# HG changeset patch # User duke # Date 1499276375 -7200 # Node ID 0d1f816217dce5e72187f167cc1816080cbeb453 # Parent 3f86282541eff4531f999c1917afc3d7ec0ce7e3# Parent a77941f176145abe24ac3c8558b1cf2107f10767 Merge diff -r a77941f17614 -r 0d1f816217dc .hgtags-top-repo --- a/.hgtags-top-repo Wed Jul 05 19:38:36 2017 +0200 +++ b/.hgtags-top-repo Wed Jul 05 19:39:35 2017 +0200 @@ -253,3 +253,4 @@ db045d8faa0924b7378102d24a1a0d850c1e3834 jdk9-b08 4a21dc7d57d1069a01f68e7182c074cb37349dfb jdk9-b09 fa13f2b926f8426876ec03e7903f3ee0ee150f2e jdk9-b10 +ab55a18a95e1990a588929d5d29db3eb9985fea0 jdk9-b11 diff -r a77941f17614 -r 0d1f816217dc common/autoconf/generated-configure.sh --- a/common/autoconf/generated-configure.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/common/autoconf/generated-configure.sh Wed Jul 05 19:39:35 2017 +0200 @@ -4243,7 +4243,7 @@ #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1398196583 +DATE_WHEN_GENERATED=1398861894 ############################################################################### # @@ -43505,9 +43505,10 @@ $as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&6;} FOUND_FREETYPE=no fi - elif test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64 && test -s "$POTENTIAL_FREETYPE_LIB_PATH/amd64/$FREETYPE_LIB_NAME"; then - # On solaris-x86_86, default is (normally) PATH/lib/amd64. Update our guess! - POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH/amd64" + elif test "x$OPENJDK_TARGET_OS" = xsolaris \ + && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then + # Found lib in isa dir, use that instead. + POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR" fi fi fi @@ -44093,9 +44094,10 @@ $as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&6;} FOUND_FREETYPE=no fi - elif test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64 && test -s "$POTENTIAL_FREETYPE_LIB_PATH/amd64/$FREETYPE_LIB_NAME"; then - # On solaris-x86_86, default is (normally) PATH/lib/amd64. Update our guess! - POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH/amd64" + elif test "x$OPENJDK_TARGET_OS" = xsolaris \ + && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then + # Found lib in isa dir, use that instead. + POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR" fi fi fi @@ -44395,9 +44397,10 @@ $as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&6;} FOUND_FREETYPE=no fi - elif test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64 && test -s "$POTENTIAL_FREETYPE_LIB_PATH/amd64/$FREETYPE_LIB_NAME"; then - # On solaris-x86_86, default is (normally) PATH/lib/amd64. Update our guess! - POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH/amd64" + elif test "x$OPENJDK_TARGET_OS" = xsolaris \ + && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then + # Found lib in isa dir, use that instead. + POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR" fi fi fi @@ -44688,9 +44691,10 @@ $as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&6;} FOUND_FREETYPE=no fi - elif test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64 && test -s "$POTENTIAL_FREETYPE_LIB_PATH/amd64/$FREETYPE_LIB_NAME"; then - # On solaris-x86_86, default is (normally) PATH/lib/amd64. Update our guess! - POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH/amd64" + elif test "x$OPENJDK_TARGET_OS" = xsolaris \ + && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then + # Found lib in isa dir, use that instead. + POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR" fi fi fi @@ -44981,9 +44985,10 @@ $as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&6;} FOUND_FREETYPE=no fi - elif test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64 && test -s "$POTENTIAL_FREETYPE_LIB_PATH/amd64/$FREETYPE_LIB_NAME"; then - # On solaris-x86_86, default is (normally) PATH/lib/amd64. Update our guess! - POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH/amd64" + elif test "x$OPENJDK_TARGET_OS" = xsolaris \ + && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then + # Found lib in isa dir, use that instead. + POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR" fi fi fi @@ -45275,9 +45280,10 @@ $as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&6;} FOUND_FREETYPE=no fi - elif test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64 && test -s "$POTENTIAL_FREETYPE_LIB_PATH/amd64/$FREETYPE_LIB_NAME"; then - # On solaris-x86_86, default is (normally) PATH/lib/amd64. Update our guess! - POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH/amd64" + elif test "x$OPENJDK_TARGET_OS" = xsolaris \ + && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then + # Found lib in isa dir, use that instead. + POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR" fi fi fi @@ -45570,9 +45576,10 @@ $as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&6;} FOUND_FREETYPE=no fi - elif test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64 && test -s "$POTENTIAL_FREETYPE_LIB_PATH/amd64/$FREETYPE_LIB_NAME"; then - # On solaris-x86_86, default is (normally) PATH/lib/amd64. Update our guess! - POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH/amd64" + elif test "x$OPENJDK_TARGET_OS" = xsolaris \ + && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then + # Found lib in isa dir, use that instead. + POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR" fi fi fi @@ -45861,9 +45868,10 @@ $as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&6;} FOUND_FREETYPE=no fi - elif test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64 && test -s "$POTENTIAL_FREETYPE_LIB_PATH/amd64/$FREETYPE_LIB_NAME"; then - # On solaris-x86_86, default is (normally) PATH/lib/amd64. Update our guess! - POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH/amd64" + elif test "x$OPENJDK_TARGET_OS" = xsolaris \ + && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then + # Found lib in isa dir, use that instead. + POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR" fi fi fi @@ -46152,9 +46160,10 @@ $as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&6;} FOUND_FREETYPE=no fi - elif test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64 && test -s "$POTENTIAL_FREETYPE_LIB_PATH/amd64/$FREETYPE_LIB_NAME"; then - # On solaris-x86_86, default is (normally) PATH/lib/amd64. Update our guess! - POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH/amd64" + elif test "x$OPENJDK_TARGET_OS" = xsolaris \ + && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then + # Found lib in isa dir, use that instead. + POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR" fi fi fi diff -r a77941f17614 -r 0d1f816217dc common/autoconf/libraries.m4 --- a/common/autoconf/libraries.m4 Wed Jul 05 19:38:36 2017 +0200 +++ b/common/autoconf/libraries.m4 Wed Jul 05 19:39:35 2017 +0200 @@ -286,9 +286,10 @@ AC_MSG_NOTICE([Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location.]) FOUND_FREETYPE=no fi - elif test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64 && test -s "$POTENTIAL_FREETYPE_LIB_PATH/amd64/$FREETYPE_LIB_NAME"; then - # On solaris-x86_86, default is (normally) PATH/lib/amd64. Update our guess! - POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH/amd64" + elif test "x$OPENJDK_TARGET_OS" = xsolaris \ + && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then + # Found lib in isa dir, use that instead. + POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR" fi fi fi diff -r a77941f17614 -r 0d1f816217dc corba/.hgtags --- a/corba/.hgtags Wed Jul 05 19:38:36 2017 +0200 +++ b/corba/.hgtags Wed Jul 05 19:39:35 2017 +0200 @@ -253,3 +253,4 @@ 2da7fead826bc27f193c7d63048c2cf100a8809c jdk9-b08 1a3a4f48515dbf1cff37279691b2fb74f228298d jdk9-b09 3bd4039dfc632fd7fc8418a25a3dcc34d1cd4019 jdk9-b10 +77ea0a2503582a28e4e66be7239a49a0d1dd313f jdk9-b11 diff -r a77941f17614 -r 0d1f816217dc hotspot/.hgtags --- a/hotspot/.hgtags Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/.hgtags Wed Jul 05 19:39:35 2017 +0200 @@ -413,3 +413,4 @@ 4dedef5e51ed3a36677a8ba82949fc517ad64162 jdk9-b08 05e8f5242c26ba45d4fa947e4f4f54c058c9b522 jdk9-b09 ebc44d040cd149d2120d69fe183a3dae7840f4b4 jdk9-b10 +783309c3a1a629a452673399dcfa83ef7eca94d8 jdk9-b11 diff -r a77941f17614 -r 0d1f816217dc hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -2003,7 +2003,7 @@ } } else { assert(MethodData::profile_return(), "either profile call args or call ret"); - update_mdp_by_constant(in_bytes(ReturnTypeEntry::size())); + update_mdp_by_constant(in_bytes(TypeEntriesAtCall::return_only_size())); } // mdp points right after the end of the diff -r a77941f17614 -r 0d1f816217dc hotspot/src/cpu/x86/vm/interp_masm_x86.cpp --- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -137,7 +137,7 @@ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp); } else { assert(MethodData::profile_return(), "either profile call args or call ret"); - update_mdp_by_constant(mdp, in_bytes(ReturnTypeEntry::size())); + update_mdp_by_constant(mdp, in_bytes(TypeEntriesAtCall::return_only_size())); } // mdp points right after the end of the diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/c1/c1_LIRGenerator.cpp --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -3188,8 +3188,8 @@ #ifdef ASSERT Bytecodes::Code code = x->method()->raw_code_at_bci(x->bci_of_invoke()); int n = x->nb_profiled_args(); - assert(MethodData::profile_parameters() && x->inlined() && - ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)), + assert(MethodData::profile_parameters() && (MethodData::profile_arguments_jsr292_only() || + (x->inlined() && ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)))), "only at JSR292 bytecodes"); #endif } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -2831,7 +2831,6 @@ } } - assert(operand_fill_index == operands->length(), "exact fill"); assert(ConstantPool::operand_array_length(operands) == attribute_array_length, "correct decode"); u1* current_end = cfs->current(); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -564,11 +564,11 @@ "--------------------------------\n"); size_t total_size = totalSizeInIndexedFreeLists(); size_t free_blocks = numFreeBlocksInIndexedFreeLists(); - gclog_or_tty->print("Total Free Space: %d\n", total_size); - gclog_or_tty->print("Max Chunk Size: %d\n", maxChunkSizeInIndexedFreeLists()); - gclog_or_tty->print("Number of Blocks: %d\n", free_blocks); + gclog_or_tty->print("Total Free Space: " SIZE_FORMAT "\n", total_size); + gclog_or_tty->print("Max Chunk Size: " SIZE_FORMAT "\n", maxChunkSizeInIndexedFreeLists()); + gclog_or_tty->print("Number of Blocks: " SIZE_FORMAT "\n", free_blocks); if (free_blocks != 0) { - gclog_or_tty->print("Av. Block Size: %d\n", total_size/free_blocks); + gclog_or_tty->print("Av. Block Size: " SIZE_FORMAT "\n", total_size/free_blocks); } } @@ -2152,7 +2152,7 @@ for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { AdaptiveFreeList* fl = &_indexedFreeList[i]; if (PrintFLSStatistics > 1) { - gclog_or_tty->print("size[%d] : ", i); + gclog_or_tty->print("size[" SIZE_FORMAT "] : ", i); } fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate); fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent)); @@ -2683,7 +2683,8 @@ _global_num_workers[i] = 0; _global_num_blocks[i] = 0; if (PrintOldPLAB) { - gclog_or_tty->print_cr("[%d]: %d", i, (size_t)_blocks_to_claim[i].average()); + gclog_or_tty->print_cr("[" SIZE_FORMAT "]: " SIZE_FORMAT, + i, (size_t)_blocks_to_claim[i].average()); } } } @@ -2722,7 +2723,7 @@ } } if (PrintOldPLAB) { - gclog_or_tty->print_cr("%d[%d]: %d/%d/%d", + gclog_or_tty->print_cr("%d[" SIZE_FORMAT "]: " SIZE_FORMAT "/" SIZE_FORMAT "/" SIZE_FORMAT, tid, i, num_retire, _num_blocks[i], (size_t)_blocks_to_claim[i].average()); } // Reset stats for next round diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -1512,6 +1512,8 @@ gclog_or_tty->print_cr("cms_allocation_rate=%g", stats().cms_allocation_rate()); gclog_or_tty->print_cr("occupancy=%3.7f", _cmsGen->occupancy()); gclog_or_tty->print_cr("initiatingOccupancy=%3.7f", _cmsGen->initiating_occupancy()); + gclog_or_tty->print_cr("cms_time_since_begin=%3.7f", stats().cms_time_since_begin()); + gclog_or_tty->print_cr("cms_time_since_end=%3.7f", stats().cms_time_since_end()); gclog_or_tty->print_cr("metadata initialized %d", MetaspaceGC::should_concurrent_collect()); } @@ -1574,6 +1576,28 @@ return true; } + // CMSTriggerInterval starts a CMS cycle if enough time has passed. + if (CMSTriggerInterval >= 0) { + if (CMSTriggerInterval == 0) { + // Trigger always + return true; + } + + // Check the CMS time since begin (we do not check the stats validity + // as we want to be able to trigger the first CMS cycle as well) + if (stats().cms_time_since_begin() >= (CMSTriggerInterval / ((double) MILLIUNITS))) { + if (Verbose && PrintGCDetails) { + if (stats().valid()) { + gclog_or_tty->print_cr("CMSCollector: collect because of trigger interval (time since last begin %3.7f secs)", + stats().cms_time_since_begin()); + } else { + gclog_or_tty->print_cr("CMSCollector: collect because of trigger interval (first collection)"); + } + } + return true; + } + } + return false; } @@ -2894,13 +2918,13 @@ // Clear the marking bit map array before starting, but, just // for kicks, first report if the given address is already marked - gclog_or_tty->print_cr("Start: Address 0x%x is%s marked", addr, + gclog_or_tty->print_cr("Start: Address " PTR_FORMAT " is%s marked", addr, _markBitMap.isMarked(addr) ? "" : " not"); if (verify_after_remark()) { MutexLockerEx x(verification_mark_bm()->lock(), Mutex::_no_safepoint_check_flag); bool result = verification_mark_bm()->isMarked(addr); - gclog_or_tty->print_cr("TransitiveMark: Address 0x%x %s marked", addr, + gclog_or_tty->print_cr("TransitiveMark: Address " PTR_FORMAT " %s marked", addr, result ? "IS" : "is NOT"); return result; } else { @@ -4569,7 +4593,7 @@ } } if (PrintCMSStatistics > 0) { - gclog_or_tty->print(" [%d iterations, %d waits, %d cards)] ", + gclog_or_tty->print(" [" SIZE_FORMAT " iterations, " SIZE_FORMAT " waits, " SIZE_FORMAT " cards)] ", loops, waited, cumworkdone); } } @@ -4721,7 +4745,7 @@ numIter++, lastNumCards = curNumCards, cumNumCards += curNumCards) { curNumCards = preclean_mod_union_table(_cmsGen, &smoac_cl); if (Verbose && PrintGCDetails) { - gclog_or_tty->print(" (modUnionTable: %d cards)", curNumCards); + gclog_or_tty->print(" (modUnionTable: " SIZE_FORMAT " cards)", curNumCards); } // Either there are very few dirty cards, so re-mark // pause will be small anyway, or our pre-cleaning isn't @@ -4743,7 +4767,7 @@ curNumCards = preclean_card_table(_cmsGen, &smoac_cl); cumNumCards += curNumCards; if (PrintGCDetails && PrintCMSStatistics != 0) { - gclog_or_tty->print_cr(" (cardTable: %d cards, re-scanned %d cards, %d iterations)", + gclog_or_tty->print_cr(" (cardTable: " SIZE_FORMAT " cards, re-scanned " SIZE_FORMAT " cards, " SIZE_FORMAT " iterations)", curNumCards, cumNumCards, numIter); } return cumNumCards; // as a measure of useful work done @@ -8205,7 +8229,7 @@ void SweepClosure::initialize_free_range(HeapWord* freeFinger, bool freeRangeInFreeLists) { if (CMSTraceSweeper) { - gclog_or_tty->print("---- Start free range at 0x%x with free block (%d)\n", + gclog_or_tty->print("---- Start free range at " PTR_FORMAT " with free block (%d)\n", freeFinger, freeRangeInFreeLists); } assert(!inFreeRange(), "Trampling existing free range"); @@ -8275,10 +8299,10 @@ pointer_delta(addr, freeFinger())); if (CMSTraceSweeper) { gclog_or_tty->print("Sweep: last chunk: "); - gclog_or_tty->print("put_free_blk 0x%x ("SIZE_FORMAT") " - "[coalesced:"SIZE_FORMAT"]\n", + gclog_or_tty->print("put_free_blk " PTR_FORMAT " ("SIZE_FORMAT") " + "[coalesced:%d]\n", freeFinger(), pointer_delta(addr, freeFinger()), - lastFreeRangeCoalesced()); + lastFreeRangeCoalesced() ? 1 : 0); } } @@ -8421,7 +8445,7 @@ // the midst of a free range, we are coalescing print_free_block_coalesced(fc); if (CMSTraceSweeper) { - gclog_or_tty->print(" -- pick up free block 0x%x (%d)\n", fc, size); + gclog_or_tty->print(" -- pick up free block " PTR_FORMAT " (" SIZE_FORMAT ")\n", fc, size); } // remove it from the free lists _sp->removeFreeChunkFromFreeLists(fc); @@ -8483,7 +8507,7 @@ // this will be swept up when we hit the end of the // free range if (CMSTraceSweeper) { - gclog_or_tty->print(" -- pick up garbage 0x%x (%d) \n", fc, size); + gclog_or_tty->print(" -- pick up garbage " PTR_FORMAT " (" SIZE_FORMAT ")\n", fc, size); } // If the chunk is being coalesced and the current free range is // in the free lists, remove the current free range so that it @@ -8576,7 +8600,7 @@ } if (CMSTraceSweeper) { - gclog_or_tty->print_cr(" -- pick up another chunk at 0x%x (%d)", fc, chunkSize); + gclog_or_tty->print_cr(" -- pick up another chunk at " PTR_FORMAT " (" SIZE_FORMAT ")", fc, chunkSize); } HeapWord* const fc_addr = (HeapWord*) fc; @@ -8705,7 +8729,7 @@ "chunk should not be in free lists yet"); } if (CMSTraceSweeper) { - gclog_or_tty->print_cr(" -- add free block 0x%x (%d) to free lists", + gclog_or_tty->print_cr(" -- add free block " PTR_FORMAT " (" SIZE_FORMAT ") to free lists", chunk, size); } // A new free range is going to be starting. The current diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -265,7 +265,7 @@ slots += _spoolHead->bufferSize - 1; blocks++; } - gclog_or_tty->print_cr(" [worker %d] promo_blocks = %d, promo_slots = %d ", + gclog_or_tty->print_cr(" [worker %d] promo_blocks = " SIZE_FORMAT ", promo_slots = " SIZE_FORMAT, worker_id, blocks, slots); } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -29,7 +29,7 @@ #include "gc_implementation/g1/g1HotCardCache.hpp" #include "runtime/java.hpp" -ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h) : +ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure) : _threads(NULL), _n_threads(0), _hot_card_cache(g1h) { @@ -61,7 +61,7 @@ ConcurrentG1RefineThread *next = NULL; for (uint i = _n_threads - 1; i != UINT_MAX; i--) { - ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, worker_id_offset, i); + ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, refine_closure, worker_id_offset, i); assert(t != NULL, "Conc refine should have been created"); if (t->osthread() == NULL) { vm_shutdown_during_initialization("Could not create ConcurrentG1RefineThread"); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -71,7 +71,7 @@ void reset_threshold_step(); public: - ConcurrentG1Refine(G1CollectedHeap* g1h); + ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure); ~ConcurrentG1Refine(); void init(); // Accomplish some initialization that has to wait. diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -33,8 +33,10 @@ ConcurrentG1RefineThread:: ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next, + CardTableEntryClosure* refine_closure, uint worker_id_offset, uint worker_id) : ConcurrentGCThread(), + _refine_closure(refine_closure), _worker_id_offset(worker_id_offset), _worker_id(worker_id), _active(false), @@ -71,6 +73,7 @@ } void ConcurrentG1RefineThread::sample_young_list_rs_lengths() { + SuspendibleThreadSetJoiner sts; G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1CollectorPolicy* g1p = g1h->g1_policy(); if (g1p->adaptive_young_list_length()) { @@ -82,8 +85,8 @@ // we try to yield every time we visit 10 regions if (regions_visited == 10) { - if (_sts.should_yield()) { - _sts.yield("G1 refine"); + if (sts.should_yield()) { + sts.yield(); // we just abandon the iteration break; } @@ -99,9 +102,7 @@ DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); _vtime_start = os::elapsedVTime(); while(!_should_terminate) { - _sts.join(); sample_young_list_rs_lengths(); - _sts.leave(); if (os::supports_vtime()) { _vtime_accum = (os::elapsedVTime() - _vtime_start); @@ -182,37 +183,37 @@ break; } - _sts.join(); + { + SuspendibleThreadSetJoiner sts; + + do { + int curr_buffer_num = (int)dcqs.completed_buffers_num(); + // If the number of the buffers falls down into the yellow zone, + // that means that the transition period after the evacuation pause has ended. + if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) { + dcqs.set_completed_queue_padding(0); + } - do { - int curr_buffer_num = (int)dcqs.completed_buffers_num(); - // If the number of the buffers falls down into the yellow zone, - // that means that the transition period after the evacuation pause has ended. - if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) { - dcqs.set_completed_queue_padding(0); - } + if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) { + // If the number of the buffer has fallen below our threshold + // we should deactivate. The predecessor will reactivate this + // thread should the number of the buffers cross the threshold again. + deactivate(); + break; + } - if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) { - // If the number of the buffer has fallen below our threshold - // we should deactivate. The predecessor will reactivate this - // thread should the number of the buffers cross the threshold again. + // Check if we need to activate the next thread. + if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) { + _next->activate(); + } + } while (dcqs.apply_closure_to_completed_buffer(_refine_closure, _worker_id + _worker_id_offset, cg1r()->green_zone())); + + // We can exit the loop above while being active if there was a yield request. + if (is_active()) { deactivate(); - break; } - - // Check if we need to activate the next thread. - if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) { - _next->activate(); - } - } while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, cg1r()->green_zone())); - - // We can exit the loop above while being active if there was a yield request. - if (is_active()) { - deactivate(); } - _sts.leave(); - if (os::supports_vtime()) { _vtime_accum = (os::elapsedVTime() - _vtime_start); } else { @@ -223,17 +224,6 @@ terminate(); } - -void ConcurrentG1RefineThread::yield() { - if (G1TraceConcRefinement) { - gclog_or_tty->print_cr("G1-Refine-yield"); - } - _sts.yield("G1 refine"); - if (G1TraceConcRefinement) { - gclog_or_tty->print_cr("G1-Refine-yield-end"); - } -} - void ConcurrentG1RefineThread::stop() { // it is ok to take late safepoints here, if needed { diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -28,6 +28,7 @@ #include "gc_implementation/shared/concurrentGCThread.hpp" // Forward Decl. +class CardTableEntryClosure; class ConcurrentG1Refine; // The G1 Concurrent Refinement Thread (could be several in the future). @@ -49,6 +50,9 @@ Monitor* _monitor; ConcurrentG1Refine* _cg1r; + // The closure applied to completed log buffers. + CardTableEntryClosure* _refine_closure; + int _thread_threshold_step; // This thread activation threshold int _threshold; @@ -64,13 +68,11 @@ void activate(); void deactivate(); - // For use by G1CollectedHeap, which is a friend. - static SuspendibleThreadSet* sts() { return &_sts; } - public: virtual void run(); // Constructor ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next, + CardTableEntryClosure* refine_closure, uint worker_id_offset, uint worker_id); void initialize(); @@ -84,8 +86,6 @@ ConcurrentG1Refine* cg1r() { return _cg1r; } - // Yield for GC - void yield(); // shutdown void stop(); }; diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -976,11 +976,11 @@ } if (concurrent()) { - ConcurrentGCThread::stsLeave(); + SuspendibleThreadSet::leave(); } _first_overflow_barrier_sync.enter(); if (concurrent()) { - ConcurrentGCThread::stsJoin(); + SuspendibleThreadSet::join(); } // at this point everyone should have synced up and not be doing any // more work @@ -1024,11 +1024,11 @@ } if (concurrent()) { - ConcurrentGCThread::stsLeave(); + SuspendibleThreadSet::leave(); } _second_overflow_barrier_sync.enter(); if (concurrent()) { - ConcurrentGCThread::stsJoin(); + SuspendibleThreadSet::join(); } // at this point everything should be re-initialized and ready to go @@ -1076,7 +1076,7 @@ double start_vtime = os::elapsedVTime(); - ConcurrentGCThread::stsJoin(); + SuspendibleThreadSet::join(); assert(worker_id < _cm->active_tasks(), "invariant"); CMTask* the_task = _cm->task(worker_id); @@ -1103,9 +1103,9 @@ if (!_cm->has_aborted() && the_task->has_aborted()) { sleep_time_ms = (jlong) (elapsed_vtime_sec * _cm->sleep_factor() * 1000.0); - ConcurrentGCThread::stsLeave(); + SuspendibleThreadSet::leave(); os::sleep(Thread::current(), sleep_time_ms, false); - ConcurrentGCThread::stsJoin(); + SuspendibleThreadSet::join(); } double end_time2_sec = os::elapsedTime(); double elapsed_time2_sec = end_time2_sec - start_time_sec; @@ -1123,7 +1123,7 @@ the_task->record_end_time(); guarantee(!the_task->has_aborted() || _cm->has_aborted(), "invariant"); - ConcurrentGCThread::stsLeave(); + SuspendibleThreadSet::leave(); double end_vtime = os::elapsedVTime(); _cm->update_accum_task_vtime(worker_id, end_vtime - start_vtime); @@ -2655,7 +2655,6 @@ str = " O"; } else { HeapRegion* hr = _g1h->heap_region_containing(obj); - guarantee(hr != NULL, "invariant"); bool over_tams = _g1h->allocated_since_marking(obj, hr, _vo); bool marked = _g1h->is_marked(obj, _vo); @@ -3302,21 +3301,17 @@ // We take a break if someone is trying to stop the world. bool ConcurrentMark::do_yield_check(uint worker_id) { - if (should_yield()) { + if (SuspendibleThreadSet::should_yield()) { if (worker_id == 0) { _g1h->g1_policy()->record_concurrent_pause(); } - cmThread()->yield(); + SuspendibleThreadSet::yield(); return true; } else { return false; } } -bool ConcurrentMark::should_yield() { - return cmThread()->should_yield(); -} - bool ConcurrentMark::containing_card_is_marked(void* p) { size_t offset = pointer_delta(p, _g1h->reserved_region().start(), 1); return _card_bm.at(offset >> CardTableModRefBS::card_shift); @@ -3417,9 +3412,8 @@ } void CMTask::setup_for_region(HeapRegion* hr) { - // Separated the asserts so that we know which one fires. assert(hr != NULL, - "claim_region() should have filtered out continues humongous regions"); + "claim_region() should have filtered out NULL regions"); assert(!hr->continuesHumongous(), "claim_region() should have filtered out continues humongous regions"); @@ -3605,7 +3599,7 @@ #endif // _MARKING_STATS_ // (4) We check whether we should yield. If we have to, then we abort. - if (_cm->should_yield()) { + if (SuspendibleThreadSet::should_yield()) { // We should yield. To do this we abort the task. The caller is // responsible for yielding. set_has_aborted(); @@ -3754,7 +3748,7 @@ if (_task_queue->size() > target_size) { if (_cm->verbose_high()) { - gclog_or_tty->print_cr("[%u] draining local queue, target size = %d", + gclog_or_tty->print_cr("[%u] draining local queue, target size = " SIZE_FORMAT, _worker_id, target_size); } @@ -3782,7 +3776,7 @@ } if (_cm->verbose_high()) { - gclog_or_tty->print_cr("[%u] drained local queue, size = %d", + gclog_or_tty->print_cr("[%u] drained local queue, size = %u", _worker_id, _task_queue->size()); } } @@ -3810,7 +3804,7 @@ if (_cm->mark_stack_size() > target_size) { if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] draining global_stack, target size %d", + gclog_or_tty->print_cr("[%u] draining global_stack, target size " SIZE_FORMAT, _worker_id, target_size); } @@ -3820,7 +3814,7 @@ } if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] drained global stack, size = %d", + gclog_or_tty->print_cr("[%u] drained global stack, size = " SIZE_FORMAT, _worker_id, _cm->mark_stack_size()); } } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -814,7 +814,6 @@ } inline bool do_yield_check(uint worker_i = 0); - inline bool should_yield(); // Called to abort the marking cycle after a Full GC takes place. void abort(); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -89,6 +89,10 @@ while (!_should_terminate) { // wait until started is set. sleepBeforeNextCycle(); + if (_should_terminate) { + break; + } + { ResourceMark rm; HandleMark hm; @@ -190,9 +194,8 @@ } else { // We don't want to update the marking status if a GC pause // is already underway. - _sts.join(); + SuspendibleThreadSetJoiner sts; g1h->set_marking_complete(); - _sts.leave(); } // Check if cleanup set the free_regions_coming flag. If it @@ -262,11 +265,12 @@ // record_concurrent_mark_cleanup_completed() (and, in fact, it's // not needed any more as the concurrent mark state has been // already reset). - _sts.join(); - if (!cm()->has_aborted()) { - g1_policy->record_concurrent_mark_cleanup_completed(); + { + SuspendibleThreadSetJoiner sts; + if (!cm()->has_aborted()) { + g1_policy->record_concurrent_mark_cleanup_completed(); + } } - _sts.leave(); if (cm()->has_aborted()) { if (G1Log::fine()) { @@ -278,36 +282,43 @@ // We now want to allow clearing of the marking bitmap to be // suspended by a collection pause. - _sts.join(); - _cm->clearNextBitmap(); - _sts.leave(); + { + SuspendibleThreadSetJoiner sts; + _cm->clearNextBitmap(); + } } // Update the number of full collections that have been // completed. This will also notify the FullGCCount_lock in case a // Java thread is waiting for a full GC to happen (e.g., it // called System.gc() with +ExplicitGCInvokesConcurrent). - _sts.join(); - g1h->increment_old_marking_cycles_completed(true /* concurrent */); - g1h->register_concurrent_cycle_end(); - _sts.leave(); + { + SuspendibleThreadSetJoiner sts; + g1h->increment_old_marking_cycles_completed(true /* concurrent */); + g1h->register_concurrent_cycle_end(); + } } assert(_should_terminate, "just checking"); terminate(); } - -void ConcurrentMarkThread::yield() { - _sts.yield("Concurrent Mark"); -} +void ConcurrentMarkThread::stop() { + { + MutexLockerEx ml(Terminator_lock); + _should_terminate = true; + } -void ConcurrentMarkThread::stop() { - // it is ok to take late safepoints here, if needed - MutexLockerEx mu(Terminator_lock); - _should_terminate = true; - while (!_has_terminated) { - Terminator_lock->wait(); + { + MutexLockerEx ml(CGC_lock, Mutex::_no_safepoint_check_flag); + CGC_lock->notify_all(); + } + + { + MutexLockerEx ml(Terminator_lock); + while (!_has_terminated) { + Terminator_lock->wait(); + } } } @@ -327,11 +338,14 @@ assert(!in_progress(), "should have been cleared"); MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); - while (!started()) { + while (!started() && !_should_terminate) { CGC_lock->wait(Mutex::_no_safepoint_check_flag); } - set_in_progress(); - clear_started(); + + if (started()) { + set_in_progress(); + clear_started(); + } } // Note: As is the case with CMS - this method, although exported diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -89,9 +89,6 @@ // that started() is set and set in_progress(). bool during_cycle() { return started() || in_progress(); } - // Yield for GC - void yield(); - // shutdown void stop(); }; diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -70,7 +70,7 @@ DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) : PtrQueueSet(notify_when_complete), - _closure(NULL), + _mut_process_closure(NULL), _shared_dirty_card_queue(this, true /*perm*/), _free_ids(NULL), _processed_buffers_mut(0), _processed_buffers_rs_thread(0) @@ -83,10 +83,11 @@ return (uint)os::processor_count(); } -void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock, +void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock, int process_completed_threshold, int max_completed_queue, Mutex* lock, PtrQueueSet* fl_owner) { + _mut_process_closure = cl; PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, max_completed_queue, fl_owner); set_buffer_size(G1UpdateBufferSize); @@ -98,18 +99,15 @@ t->dirty_card_queue().handle_zero_index(); } -void DirtyCardQueueSet::set_closure(CardTableEntryClosure* closure) { - _closure = closure; -} - -void DirtyCardQueueSet::iterate_closure_all_threads(bool consume, +void DirtyCardQueueSet::iterate_closure_all_threads(CardTableEntryClosure* cl, + bool consume, uint worker_i) { assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); for(JavaThread* t = Threads::first(); t; t = t->next()) { - bool b = t->dirty_card_queue().apply_closure(_closure, consume); + bool b = t->dirty_card_queue().apply_closure(cl, consume); guarantee(b, "Should not be interrupted."); } - bool b = shared_dirty_card_queue()->apply_closure(_closure, + bool b = shared_dirty_card_queue()->apply_closure(cl, consume, worker_i); guarantee(b, "Should not be interrupted."); @@ -143,7 +141,7 @@ bool b = false; if (worker_i != UINT_MAX) { - b = DirtyCardQueue::apply_closure_to_buffer(_closure, buf, 0, + b = DirtyCardQueue::apply_closure_to_buffer(_mut_process_closure, buf, 0, _sz, true, worker_i); if (b) Atomic::inc(&_processed_buffers_mut); @@ -218,18 +216,11 @@ return res; } -bool DirtyCardQueueSet::apply_closure_to_completed_buffer(uint worker_i, - int stop_at, - bool during_pause) { - return apply_closure_to_completed_buffer(_closure, worker_i, - stop_at, during_pause); -} - -void DirtyCardQueueSet::apply_closure_to_all_completed_buffers() { +void DirtyCardQueueSet::apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) { BufferNode* nd = _completed_buffers_head; while (nd != NULL) { bool b = - DirtyCardQueue::apply_closure_to_buffer(_closure, + DirtyCardQueue::apply_closure_to_buffer(cl, BufferNode::make_buffer_from_node(nd), 0, _sz, false); guarantee(b, "Should not stop early."); @@ -237,6 +228,24 @@ } } +void DirtyCardQueueSet::par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) { + BufferNode* nd = _cur_par_buffer_node; + while (nd != NULL) { + BufferNode* next = (BufferNode*)nd->next(); + BufferNode* actual = (BufferNode*)Atomic::cmpxchg_ptr((void*)next, (volatile void*)&_cur_par_buffer_node, (void*)nd); + if (actual == nd) { + bool b = + DirtyCardQueue::apply_closure_to_buffer(cl, + BufferNode::make_buffer_from_node(actual), + 0, _sz, false); + guarantee(b, "Should not stop early."); + nd = next; + } else { + nd = actual; + } + } +} + // Deallocates any completed log buffers void DirtyCardQueueSet::clear() { BufferNode* buffers_to_delete = NULL; diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -73,7 +73,8 @@ class DirtyCardQueueSet: public PtrQueueSet { - CardTableEntryClosure* _closure; + // The closure used in mut_process_buffer(). + CardTableEntryClosure* _mut_process_closure; DirtyCardQueue _shared_dirty_card_queue; @@ -88,10 +89,12 @@ jint _processed_buffers_mut; jint _processed_buffers_rs_thread; + // Current buffer node used for parallel iteration. + BufferNode* volatile _cur_par_buffer_node; public: DirtyCardQueueSet(bool notify_when_complete = true); - void initialize(Monitor* cbl_mon, Mutex* fl_lock, + void initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock, int process_completed_threshold, int max_completed_queue, Mutex* lock, PtrQueueSet* fl_owner = NULL); @@ -102,33 +105,15 @@ static void handle_zero_index_for_thread(JavaThread* t); - // Register "blk" as "the closure" for all queues. Only one such closure - // is allowed. The "apply_closure_to_completed_buffer" method will apply - // this closure to a completed buffer, and "iterate_closure_all_threads" - // applies it to partially-filled buffers (the latter should only be done - // with the world stopped). - void set_closure(CardTableEntryClosure* closure); - - // If there is a registered closure for buffers, apply it to all entries - // in all currently-active buffers. This should only be applied at a - // safepoint. (Currently must not be called in parallel; this should - // change in the future.) If "consume" is true, processed entries are - // discarded. - void iterate_closure_all_threads(bool consume = true, + // Apply the given closure to all entries in all currently-active buffers. + // This should only be applied at a safepoint. (Currently must not be called + // in parallel; this should change in the future.) If "consume" is true, + // processed entries are discarded. + void iterate_closure_all_threads(CardTableEntryClosure* cl, + bool consume = true, uint worker_i = 0); // If there exists some completed buffer, pop it, then apply the - // registered closure to all its elements, nulling out those elements - // processed. If all elements are processed, returns "true". If no - // completed buffers exist, returns false. If a completed buffer exists, - // but is only partially completed before a "yield" happens, the - // partially completed buffer (with its processed elements set to NULL) - // is returned to the completed buffer set, and this call returns false. - bool apply_closure_to_completed_buffer(uint worker_i = 0, - int stop_at = 0, - bool during_pause = false); - - // If there exists some completed buffer, pop it, then apply the // specified closure to all its elements, nulling out those elements // processed. If all elements are processed, returns "true". If no // completed buffers exist, returns false. If a completed buffer exists, @@ -149,7 +134,12 @@ // Applies the current closure to all completed buffers, // non-consumptively. - void apply_closure_to_all_completed_buffers(); + void apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl); + + void reset_for_par_iteration() { _cur_par_buffer_node = _completed_buffers_head; } + // Applies the current closure to all completed buffers, non-consumptively. + // Parallel version. + void par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl); DirtyCardQueue* shared_dirty_card_queue() { return &_shared_dirty_card_queue; diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -45,32 +45,27 @@ } } -FreeList G1CodeRootSet::_free_list; -size_t G1CodeRootSet::_num_chunks_handed_out = 0; - -G1CodeRootChunk* G1CodeRootSet::new_chunk() { - G1CodeRootChunk* result = _free_list.get_chunk_at_head(); - if (result == NULL) { - result = new G1CodeRootChunk(); - } - G1CodeRootSet::_num_chunks_handed_out++; - result->reset(); - return result; +G1CodeRootChunkManager::G1CodeRootChunkManager() : _free_list(), _num_chunks_handed_out(0) { + _free_list.initialize(); + _free_list.set_size(G1CodeRootChunk::word_size()); } -void G1CodeRootSet::free_chunk(G1CodeRootChunk* chunk) { - _free_list.return_chunk_at_head(chunk); - G1CodeRootSet::_num_chunks_handed_out--; +size_t G1CodeRootChunkManager::fl_mem_size() { + return _free_list.count() * _free_list.size(); } -void G1CodeRootSet::free_all_chunks(FreeList* list) { - G1CodeRootSet::_num_chunks_handed_out -= list->count(); +void G1CodeRootChunkManager::free_all_chunks(FreeList* list) { + _num_chunks_handed_out -= list->count(); _free_list.prepend(list); } -void G1CodeRootSet::purge_chunks(size_t keep_ratio) { - size_t keep = G1CodeRootSet::_num_chunks_handed_out * keep_ratio / 100; +void G1CodeRootChunkManager::free_chunk(G1CodeRootChunk* chunk) { + _free_list.return_chunk_at_head(chunk); + _num_chunks_handed_out--; +} +void G1CodeRootChunkManager::purge_chunks(size_t keep_ratio) { + size_t keep = _num_chunks_handed_out * keep_ratio / 100; if (keep >= (size_t)_free_list.count()) { return; } @@ -88,20 +83,51 @@ } } -size_t G1CodeRootSet::static_mem_size() { - return sizeof(_free_list) + sizeof(_num_chunks_handed_out); +size_t G1CodeRootChunkManager::static_mem_size() { + return sizeof(G1CodeRootChunkManager); +} + + +G1CodeRootChunk* G1CodeRootChunkManager::new_chunk() { + G1CodeRootChunk* result = _free_list.get_chunk_at_head(); + if (result == NULL) { + result = new G1CodeRootChunk(); + } + _num_chunks_handed_out++; + result->reset(); + return result; +} + +#ifndef PRODUCT + +size_t G1CodeRootChunkManager::num_chunks_handed_out() const { + return _num_chunks_handed_out; } -size_t G1CodeRootSet::fl_mem_size() { - return _free_list.count() * _free_list.size(); +size_t G1CodeRootChunkManager::num_free_chunks() const { + return (size_t)_free_list.count(); +} + +#endif + +G1CodeRootChunkManager G1CodeRootSet::_default_chunk_manager; + +void G1CodeRootSet::purge_chunks(size_t keep_ratio) { + _default_chunk_manager.purge_chunks(keep_ratio); } -void G1CodeRootSet::initialize() { - _free_list.initialize(); - _free_list.set_size(G1CodeRootChunk::word_size()); +size_t G1CodeRootSet::free_chunks_static_mem_size() { + return _default_chunk_manager.static_mem_size(); } -G1CodeRootSet::G1CodeRootSet() : _list(), _length(0) { +size_t G1CodeRootSet::free_chunks_mem_size() { + return _default_chunk_manager.fl_mem_size(); +} + +G1CodeRootSet::G1CodeRootSet(G1CodeRootChunkManager* manager) : _manager(manager), _list(), _length(0) { + if (_manager == NULL) { + _manager = &_default_chunk_manager; + } _list.initialize(); _list.set_size(G1CodeRootChunk::word_size()); } @@ -187,28 +213,38 @@ } } +size_t G1CodeRootSet::static_mem_size() { + return sizeof(G1CodeRootSet); +} + size_t G1CodeRootSet::mem_size() { - return sizeof(this) + _list.count() * _list.size(); + return G1CodeRootSet::static_mem_size() + _list.count() * _list.size(); } #ifndef PRODUCT void G1CodeRootSet::test() { - initialize(); + G1CodeRootChunkManager mgr; - assert(_free_list.count() == 0, "Free List must be empty"); - assert(_num_chunks_handed_out == 0, "No elements must have been handed out yet"); + assert(mgr.num_chunks_handed_out() == 0, "Must not have handed out chunks yet"); + + assert(G1CodeRootChunkManager::static_mem_size() > sizeof(void*), + err_msg("The chunk manager's static memory usage seems too small, is only "SIZE_FORMAT" bytes.", G1CodeRootChunkManager::static_mem_size())); // The number of chunks that we allocate for purge testing. size_t const num_chunks = 10; + { - G1CodeRootSet set1; + G1CodeRootSet set1(&mgr); assert(set1.is_empty(), "Code root set must be initially empty but is not."); + assert(G1CodeRootSet::static_mem_size() > sizeof(void*), + err_msg("The code root set's static memory usage seems too small, is only "SIZE_FORMAT" bytes", G1CodeRootSet::static_mem_size())); + set1.add((nmethod*)1); - assert(_num_chunks_handed_out == 1, + assert(mgr.num_chunks_handed_out() == 1, err_msg("Must have allocated and handed out one chunk, but handed out " - SIZE_FORMAT" chunks", _num_chunks_handed_out)); + SIZE_FORMAT" chunks", mgr.num_chunks_handed_out())); assert(set1.length() == 1, err_msg("Added exactly one element, but set contains " SIZE_FORMAT" elements", set1.length())); @@ -217,19 +253,19 @@ for (uint i = 0; i < G1CodeRootChunk::word_size() + 1; i++) { set1.add((nmethod*)1); } - assert(_num_chunks_handed_out == 1, + assert(mgr.num_chunks_handed_out() == 1, err_msg("Duplicate detection must have prevented allocation of further " - "chunks but contains "SIZE_FORMAT, _num_chunks_handed_out)); + "chunks but allocated "SIZE_FORMAT, mgr.num_chunks_handed_out())); assert(set1.length() == 1, err_msg("Duplicate detection should not have increased the set size but " "is "SIZE_FORMAT, set1.length())); size_t num_total_after_add = G1CodeRootChunk::word_size() + 1; for (size_t i = 0; i < num_total_after_add - 1; i++) { - set1.add((nmethod*)(2 + i)); + set1.add((nmethod*)(uintptr_t)(2 + i)); } - assert(_num_chunks_handed_out > 1, - "After adding more code roots, more than one chunks should have been handed out"); + assert(mgr.num_chunks_handed_out() > 1, + "After adding more code roots, more than one additional chunk should have been handed out"); assert(set1.length() == num_total_after_add, err_msg("After adding in total "SIZE_FORMAT" distinct code roots, they " "need to be in the set, but there are only "SIZE_FORMAT, @@ -242,27 +278,27 @@ assert(num_popped == num_total_after_add, err_msg("Managed to pop "SIZE_FORMAT" code roots, but only "SIZE_FORMAT" " "were added", num_popped, num_total_after_add)); - assert(_num_chunks_handed_out == 0, + assert(mgr.num_chunks_handed_out() == 0, err_msg("After popping all elements, all chunks must have been returned " - "but are still "SIZE_FORMAT, _num_chunks_handed_out)); + "but there are still "SIZE_FORMAT" additional", mgr.num_chunks_handed_out())); - purge_chunks(0); - assert(_free_list.count() == 0, + mgr.purge_chunks(0); + assert(mgr.num_free_chunks() == 0, err_msg("After purging everything, the free list must be empty but still " - "contains "SIZE_FORMAT" chunks", _free_list.count())); + "contains "SIZE_FORMAT" chunks", mgr.num_free_chunks())); // Add some more handed out chunks. size_t i = 0; - while (_num_chunks_handed_out < num_chunks) { + while (mgr.num_chunks_handed_out() < num_chunks) { set1.add((nmethod*)i); i++; } { // Generate chunks on the free list. - G1CodeRootSet set2; + G1CodeRootSet set2(&mgr); size_t i = 0; - while (_num_chunks_handed_out < num_chunks * 2) { + while (mgr.num_chunks_handed_out() < (num_chunks * 2)) { set2.add((nmethod*)i); i++; } @@ -270,45 +306,45 @@ // num_chunks elements on the free list. } - assert(_num_chunks_handed_out == num_chunks, + assert(mgr.num_chunks_handed_out() == num_chunks, err_msg("Deletion of the second set must have resulted in giving back " - "those, but there is still "SIZE_FORMAT" handed out, expecting " - SIZE_FORMAT, _num_chunks_handed_out, num_chunks)); - assert((size_t)_free_list.count() == num_chunks, + "those, but there are still "SIZE_FORMAT" additional handed out, expecting " + SIZE_FORMAT, mgr.num_chunks_handed_out(), num_chunks)); + assert(mgr.num_free_chunks() == num_chunks, err_msg("After freeing "SIZE_FORMAT" chunks, they must be on the free list " - "but there are only "SIZE_FORMAT, num_chunks, _free_list.count())); + "but there are only "SIZE_FORMAT, num_chunks, mgr.num_free_chunks())); size_t const test_percentage = 50; - purge_chunks(test_percentage); - assert(_num_chunks_handed_out == num_chunks, + mgr.purge_chunks(test_percentage); + assert(mgr.num_chunks_handed_out() == num_chunks, err_msg("Purging must not hand out chunks but there are "SIZE_FORMAT, - _num_chunks_handed_out)); - assert((size_t)_free_list.count() == (ssize_t)(num_chunks * test_percentage / 100), + mgr.num_chunks_handed_out())); + assert(mgr.num_free_chunks() == (size_t)(mgr.num_chunks_handed_out() * test_percentage / 100), err_msg("Must have purged "SIZE_FORMAT" percent of "SIZE_FORMAT" chunks" - "but there are "SSIZE_FORMAT, test_percentage, num_chunks, - _free_list.count())); + "but there are "SIZE_FORMAT, test_percentage, num_chunks, + mgr.num_free_chunks())); // Purge the remainder of the chunks on the free list. - purge_chunks(0); - assert(_free_list.count() == 0, "Free List must be empty"); - assert(_num_chunks_handed_out == num_chunks, + mgr.purge_chunks(0); + assert(mgr.num_free_chunks() == 0, "Free List must be empty"); + assert(mgr.num_chunks_handed_out() == num_chunks, err_msg("Expected to be "SIZE_FORMAT" chunks handed out from the first set " - "but there are "SIZE_FORMAT, num_chunks, _num_chunks_handed_out)); + "but there are "SIZE_FORMAT, num_chunks, mgr.num_chunks_handed_out())); // Exit of the scope of the set1 object will call the destructor that generates // num_chunks additional elements on the free list. - } + } - assert(_num_chunks_handed_out == 0, + assert(mgr.num_chunks_handed_out() == 0, err_msg("Deletion of the only set must have resulted in no chunks handed " - "out, but there is still "SIZE_FORMAT" handed out", _num_chunks_handed_out)); - assert((size_t)_free_list.count() == num_chunks, + "out, but there is still "SIZE_FORMAT" handed out", mgr.num_chunks_handed_out())); + assert(mgr.num_free_chunks() == num_chunks, err_msg("After freeing "SIZE_FORMAT" chunks, they must be on the free list " - "but there are only "SSIZE_FORMAT, num_chunks, _free_list.count())); + "but there are only "SIZE_FORMAT, num_chunks, mgr.num_free_chunks())); // Restore initial state. - purge_chunks(0); - assert(_free_list.count() == 0, "Free List must be empty"); - assert(_num_chunks_handed_out == 0, "No elements must have been handed out yet"); + mgr.purge_chunks(0); + assert(mgr.num_free_chunks() == 0, "Free List must be empty"); + assert(mgr.num_chunks_handed_out() == 0, "No additional elements must have been handed out yet"); } void TestCodeCacheRemSet_test() { diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -128,19 +128,45 @@ } }; +// Manages free chunks. +class G1CodeRootChunkManager VALUE_OBJ_CLASS_SPEC { + private: + // Global free chunk list management + FreeList _free_list; + // Total number of chunks handed out + size_t _num_chunks_handed_out; + + public: + G1CodeRootChunkManager(); + + G1CodeRootChunk* new_chunk(); + void free_chunk(G1CodeRootChunk* chunk); + // Free all elements of the given list. + void free_all_chunks(FreeList* list); + + void initialize(); + void purge_chunks(size_t keep_ratio); + + static size_t static_mem_size(); + size_t fl_mem_size(); + +#ifndef PRODUCT + size_t num_chunks_handed_out() const; + size_t num_free_chunks() const; +#endif +}; + // Implements storage for a set of code roots. // All methods that modify the set are not thread-safe except if otherwise noted. class G1CodeRootSet VALUE_OBJ_CLASS_SPEC { private: - // Global free chunk list management - static FreeList _free_list; - // Total number of chunks handed out - static size_t _num_chunks_handed_out; + // Global default free chunk manager instance. + static G1CodeRootChunkManager _default_chunk_manager; - static G1CodeRootChunk* new_chunk(); - static void free_chunk(G1CodeRootChunk* chunk); + G1CodeRootChunk* new_chunk() { return _manager->new_chunk(); } + void free_chunk(G1CodeRootChunk* chunk) { _manager->free_chunk(chunk); } // Free all elements of the given list. - static void free_all_chunks(FreeList* list); + void free_all_chunks(FreeList* list) { _manager->free_all_chunks(list); } // Return the chunk that contains the given nmethod, NULL otherwise. // Scans the list of chunks backwards, as this method is used to add new @@ -150,16 +176,18 @@ size_t _length; FreeList _list; + G1CodeRootChunkManager* _manager; public: - G1CodeRootSet(); + // If an instance is initialized with a chunk manager of NULL, use the global + // default one. + G1CodeRootSet(G1CodeRootChunkManager* manager = NULL); ~G1CodeRootSet(); - static void initialize(); static void purge_chunks(size_t keep_ratio); - static size_t static_mem_size(); - static size_t fl_mem_size(); + static size_t free_chunks_static_mem_size(); + static size_t free_chunks_mem_size(); // Search for the code blob from the recently allocated ones to find duplicates more quickly, as this // method is likely to be repeatedly called with the same nmethod. @@ -179,6 +207,8 @@ // Length in elements size_t length() const { return _length; } + // Static data memory size in bytes of this set. + static size_t static_mem_size(); // Memory size in bytes taken by this set. size_t mem_size(); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -57,6 +57,7 @@ #include "oops/oop.inline.hpp" #include "oops/oop.pcgc.inline.hpp" #include "runtime/vmThread.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/ticks.hpp" size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0; @@ -92,56 +93,54 @@ // Local to this file. class RefineCardTableEntryClosure: public CardTableEntryClosure { - SuspendibleThreadSet* _sts; - G1RemSet* _g1rs; - ConcurrentG1Refine* _cg1r; bool _concurrent; public: - RefineCardTableEntryClosure(SuspendibleThreadSet* sts, - G1RemSet* g1rs, - ConcurrentG1Refine* cg1r) : - _sts(sts), _g1rs(g1rs), _cg1r(cg1r), _concurrent(true) - {} + RefineCardTableEntryClosure() : _concurrent(true) { } + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { - bool oops_into_cset = _g1rs->refine_card(card_ptr, worker_i, false); + bool oops_into_cset = G1CollectedHeap::heap()->g1_rem_set()->refine_card(card_ptr, worker_i, false); // This path is executed by the concurrent refine or mutator threads, // concurrently, and so we do not care if card_ptr contains references // that point into the collection set. assert(!oops_into_cset, "should be"); - if (_concurrent && _sts->should_yield()) { + if (_concurrent && SuspendibleThreadSet::should_yield()) { // Caller will actually yield. return false; } // Otherwise, we finished successfully; return true. return true; } + void set_concurrent(bool b) { _concurrent = b; } }; class ClearLoggedCardTableEntryClosure: public CardTableEntryClosure { - int _calls; - G1CollectedHeap* _g1h; + size_t _num_processed; CardTableModRefBS* _ctbs; int _histo[256]; -public: + + public: ClearLoggedCardTableEntryClosure() : - _calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set()) + _num_processed(0), _ctbs(G1CollectedHeap::heap()->g1_barrier_set()) { for (int i = 0; i < 256; i++) _histo[i] = 0; } + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { - if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) { - _calls++; - unsigned char* ujb = (unsigned char*)card_ptr; - int ind = (int)(*ujb); - _histo[ind]++; - *card_ptr = -1; - } + unsigned char* ujb = (unsigned char*)card_ptr; + int ind = (int)(*ujb); + _histo[ind]++; + + *card_ptr = (jbyte)CardTableModRefBS::clean_card_val(); + _num_processed++; + return true; } - int calls() { return _calls; } + + size_t num_processed() { return _num_processed; } + void print_histo() { gclog_or_tty->print_cr("Card table value histogram:"); for (int i = 0; i < 256; i++) { @@ -152,22 +151,20 @@ } }; -class RedirtyLoggedCardTableEntryClosure: public CardTableEntryClosure { - int _calls; - G1CollectedHeap* _g1h; - CardTableModRefBS* _ctbs; -public: - RedirtyLoggedCardTableEntryClosure() : - _calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set()) {} +class RedirtyLoggedCardTableEntryClosure : public CardTableEntryClosure { + private: + size_t _num_processed; + + public: + RedirtyLoggedCardTableEntryClosure() : CardTableEntryClosure(), _num_processed(0) { } bool do_card_ptr(jbyte* card_ptr, uint worker_i) { - if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) { - _calls++; - *card_ptr = 0; - } + *card_ptr = CardTableModRefBS::dirty_card_val(); + _num_processed++; return true; } - int calls() { return _calls; } + + size_t num_processed() const { return _num_processed; } }; YoungList::YoungList(G1CollectedHeap* g1h) : @@ -431,6 +428,9 @@ void G1CollectedHeap::stop_conc_gc_threads() { _cg1r->stop(); _cmThread->stop(); + if (G1StringDedup::is_enabled()) { + G1StringDedup::stop(); + } } #ifdef ASSERT @@ -445,24 +445,18 @@ // implementation of is_scavengable() for G1 will indicate that // all nmethods must be scanned during a partial collection. bool G1CollectedHeap::is_in_partial_collection(const void* p) { - HeapRegion* hr = heap_region_containing(p); - return hr != NULL && hr->in_collection_set(); + if (p == NULL) { + return false; + } + return heap_region_containing(p)->in_collection_set(); } #endif // Returns true if the reference points to an object that // can move in an incremental collection. bool G1CollectedHeap::is_scavengable(const void* p) { - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - G1CollectorPolicy* g1p = g1h->g1_policy(); HeapRegion* hr = heap_region_containing(p); - if (hr == NULL) { - // null - assert(p == NULL, err_msg("Not NULL " PTR_FORMAT ,p)); - return false; - } else { - return !hr->isHumongous(); - } + return !hr->isHumongous(); } void G1CollectedHeap::check_ct_logs_at_safepoint() { @@ -476,9 +470,8 @@ // First clear the logged cards. ClearLoggedCardTableEntryClosure clear; - dcqs.set_closure(&clear); - dcqs.apply_closure_to_all_completed_buffers(); - dcqs.iterate_closure_all_threads(false); + dcqs.apply_closure_to_all_completed_buffers(&clear); + dcqs.iterate_closure_all_threads(&clear, false); clear.print_histo(); // Now ensure that there's no dirty cards. @@ -491,13 +484,13 @@ guarantee(count2.n() == 0, "Card table should be clean."); RedirtyLoggedCardTableEntryClosure redirty; - JavaThread::dirty_card_queue_set().set_closure(&redirty); - dcqs.apply_closure_to_all_completed_buffers(); - dcqs.iterate_closure_all_threads(false); + dcqs.apply_closure_to_all_completed_buffers(&redirty); + dcqs.iterate_closure_all_threads(&redirty, false); gclog_or_tty->print_cr("Log entries = %d, dirty cards = %d.", - clear.calls(), orig_count); - guarantee(redirty.calls() == clear.calls(), - "Or else mechanism is broken."); + clear.num_processed(), orig_count); + guarantee(redirty.num_processed() == clear.num_processed(), + err_msg("Redirtied "SIZE_FORMAT" cards, bug cleared "SIZE_FORMAT, + redirty.num_processed(), clear.num_processed())); CountNonCleanMemRegionClosure count3(this); ct_bs->mod_card_iterate(&count3); @@ -506,8 +499,6 @@ orig_count, count3.n()); guarantee(count3.n() >= orig_count, "Should have restored them all."); } - - JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl); } // Private class members. @@ -1512,9 +1503,6 @@ assert(g1_policy()->collection_set() == NULL, "must be"); g1_policy()->start_incremental_cset_building(); - // Clear the _cset_fast_test bitmap in anticipation of adding - // regions to the incremental collection set for the next - // evacuation pause. clear_cset_fast_test(); init_mutator_alloc_region(); @@ -1934,8 +1922,7 @@ _old_marking_cycles_started(0), _old_marking_cycles_completed(0), _concurrent_cycle_started(false), - _in_cset_fast_test(NULL), - _in_cset_fast_test_base(NULL), + _in_cset_fast_test(), _dirty_cards_region_list(NULL), _worker_cset_start_region(NULL), _worker_cset_start_region_time_stamp(NULL), @@ -2005,7 +1992,9 @@ Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap"); Universe::check_alignment(max_byte_size, heap_alignment, "g1 heap"); - _cg1r = new ConcurrentG1Refine(this); + _refine_cte_cl = new RefineCardTableEntryClosure(); + + _cg1r = new ConcurrentG1Refine(this, _refine_cte_cl); // Reserve the maximum. @@ -2077,20 +2066,7 @@ _g1h = this; - _in_cset_fast_test_length = max_regions(); - _in_cset_fast_test_base = - NEW_C_HEAP_ARRAY(bool, (size_t) _in_cset_fast_test_length, mtGC); - - // 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 - - ((uintx) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes); - - // Clear the _cset_fast_test bitmap in anticipation of adding - // regions to the incremental collection set for the first - // evacuation pause. - clear_cset_fast_test(); + _in_cset_fast_test.initialize(_g1_reserved.start(), _g1_reserved.end(), HeapRegion::GrainBytes); // Create the ConcurrentMark data structure and thread. // (Must do this late, so that "max_regions" is defined.) @@ -2113,25 +2089,21 @@ // Perform any initialization actions delegated to the policy. g1_policy()->init(); - _refine_cte_cl = - new RefineCardTableEntryClosure(ConcurrentG1RefineThread::sts(), - g1_rem_set(), - concurrent_g1_refine()); - JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl); - JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon, SATB_Q_FL_lock, G1SATBProcessCompletedThreshold, Shared_SATB_Q_lock); - JavaThread::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon, + JavaThread::dirty_card_queue_set().initialize(_refine_cte_cl, + DirtyCardQ_CBL_mon, DirtyCardQ_FL_lock, concurrent_g1_refine()->yellow_zone(), concurrent_g1_refine()->red_zone(), Shared_DirtyCardQ_lock); if (G1DeferredRSUpdate) { - dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon, + dirty_card_queue_set().initialize(NULL, // Should never be called by the Java code + DirtyCardQ_CBL_mon, DirtyCardQ_FL_lock, -1, // never trigger processing -1, // no limit on length @@ -2141,7 +2113,8 @@ // Initialize the card queue set used to hold cards containing // references into the collection set. - _into_cset_dirty_card_queue_set.initialize(DirtyCardQ_CBL_mon, + _into_cset_dirty_card_queue_set.initialize(NULL, // Should never be called by the Java code + DirtyCardQ_CBL_mon, DirtyCardQ_FL_lock, -1, // never trigger processing -1, // no limit on length @@ -2178,6 +2151,23 @@ return JNI_OK; } +void G1CollectedHeap::stop() { +#if 0 + // Stopping concurrent worker threads is currently disabled until + // some bugs in concurrent mark has been resolve. Without fixing + // those bugs first we risk haning during VM exit when trying to + // stop these threads. + + // Abort any ongoing concurrent root region scanning and stop all + // concurrent threads. We do this to make sure these threads do + // not continue to execute and access resources (e.g. gclog_or_tty) + // that are destroyed during shutdown. + _cm->root_regions()->abort(); + _cm->root_regions()->wait_until_scan_finished(); + stop_conc_gc_threads(); +#endif +} + size_t G1CollectedHeap::conservative_max_heap_alignment() { return HeapRegion::max_region_size(); } @@ -2963,21 +2953,16 @@ Space* G1CollectedHeap::space_containing(const void* addr) const { - Space* res = heap_region_containing(addr); - return res; + return heap_region_containing(addr); } HeapWord* G1CollectedHeap::block_start(const void* addr) const { Space* sp = space_containing(addr); - if (sp != NULL) { - return sp->block_start(addr); - } - return NULL; + return sp->block_start(addr); } size_t G1CollectedHeap::block_size(const HeapWord* addr) const { Space* sp = space_containing(addr); - assert(sp != NULL, "block_size of address outside of heap"); return sp->block_size(addr); } @@ -3212,7 +3197,7 @@ _young_ref_counter_closure.reset_count(); k->oops_do(&_young_ref_counter_closure); if (_young_ref_counter_closure.count() > 0) { - guarantee(k->has_modified_oops(), err_msg("Klass %p, has young refs but is not dirty.", k)); + guarantee(k->has_modified_oops(), err_msg("Klass " PTR_FORMAT ", has young refs but is not dirty.", k)); } } }; @@ -3296,7 +3281,7 @@ int *val; for (cur = start; cur < end; cur++) { val = (int *) cur; - gclog_or_tty->print("\t "PTR_FORMAT":"PTR_FORMAT"\n", val, *val); + gclog_or_tty->print("\t "PTR_FORMAT":%d\n", val, *val); } } } @@ -4125,9 +4110,6 @@ // Start a new incremental collection set for the next pause. g1_policy()->start_incremental_cset_building(); - // Clear the _cset_fast_test bitmap in anticipation of adding - // regions to the incremental collection set for the next - // evacuation pause. clear_cset_fast_test(); _young_list->reset_sampled_info(); @@ -4304,7 +4286,7 @@ // this point does not assume that we are the only GC thread // running. Note: of course, the actual marking work will // not start until the safepoint itself is released in - // ConcurrentGCThread::safepoint_desynchronize(). + // SuspendibleThreadSet::desynchronize(). doConcurrentMark(); } @@ -4571,7 +4553,7 @@ } G1ParGCAllocBuffer::G1ParGCAllocBuffer(size_t gclab_word_size) : - ParGCAllocBuffer(gclab_word_size), _retired(false) { } + ParGCAllocBuffer(gclab_word_size), _retired(true) { } G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp) : _g1h(g1h), @@ -4694,30 +4676,19 @@ _worker_id(par_scan_state->queue_num()) { } void G1ParCopyHelper::mark_object(oop obj) { -#ifdef ASSERT - HeapRegion* hr = _g1->heap_region_containing(obj); - assert(hr != NULL, "sanity"); - assert(!hr->in_collection_set(), "should not mark objects in the CSet"); -#endif // ASSERT + assert(!_g1->heap_region_containing(obj)->in_collection_set(), "should not mark objects in the CSet"); // We know that the object is not moving so it's safe to read its size. _cm->grayRoot(obj, (size_t) obj->size(), _worker_id); } void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) { -#ifdef ASSERT assert(from_obj->is_forwarded(), "from obj should be forwarded"); assert(from_obj->forwardee() == to_obj, "to obj should be the forwardee"); assert(from_obj != to_obj, "should not be self-forwarded"); - HeapRegion* from_hr = _g1->heap_region_containing(from_obj); - assert(from_hr != NULL, "sanity"); - assert(from_hr->in_collection_set(), "from obj should be in the CSet"); - - HeapRegion* to_hr = _g1->heap_region_containing(to_obj); - assert(to_hr != NULL, "sanity"); - assert(!to_hr->in_collection_set(), "should not mark objects in the CSet"); -#endif // ASSERT + assert(_g1->heap_region_containing(from_obj)->in_collection_set(), "from obj should be in the CSet"); + assert(!_g1->heap_region_containing(to_obj)->in_collection_set(), "should not mark objects in the CSet"); // The object might be in the process of being copied by another // worker so we cannot trust that its to-space image is @@ -4935,8 +4906,6 @@ pss->trim_queue(); } } while (!offer_termination()); - - pss->retire_alloc_buffers(); } class G1KlassScanClosure : public KlassClosure { @@ -5273,11 +5242,25 @@ } } -class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure { -public: - bool do_card_ptr(jbyte* card_ptr, uint worker_i) { - *card_ptr = CardTableModRefBS::dirty_card_val(); - return true; +class G1RedirtyLoggedCardsTask : public AbstractGangTask { + private: + DirtyCardQueueSet* _queue; + public: + G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue) : AbstractGangTask("Redirty Cards"), _queue(queue) { } + + virtual void work(uint worker_id) { + double start_time = os::elapsedTime(); + + RedirtyLoggedCardTableEntryClosure cl; + if (G1CollectedHeap::heap()->use_parallel_gc_threads()) { + _queue->par_apply_closure_to_all_completed_buffers(&cl); + } else { + _queue->apply_closure_to_all_completed_buffers(&cl); + } + + G1GCPhaseTimes* timer = G1CollectedHeap::heap()->g1_policy()->phase_times(); + timer->record_redirty_logged_cards_time_ms(worker_id, (os::elapsedTime() - start_time) * 1000.0); + timer->record_redirty_logged_cards_processed_cards(worker_id, cl.num_processed()); } }; @@ -5285,9 +5268,18 @@ guarantee(G1DeferredRSUpdate, "Must only be called when using deferred RS updates."); double redirty_logged_cards_start = os::elapsedTime(); - RedirtyLoggedCardTableEntryFastClosure redirty; - dirty_card_queue_set().set_closure(&redirty); - dirty_card_queue_set().apply_closure_to_all_completed_buffers(); + uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ? + _g1h->workers()->active_workers() : 1); + + G1RedirtyLoggedCardsTask redirty_task(&dirty_card_queue_set()); + dirty_card_queue_set().reset_for_par_iteration(); + if (use_parallel_gc_threads()) { + set_par_threads(n_workers); + workers()->run_task(&redirty_task); + set_par_threads(0); + } else { + redirty_task.work(0); + } DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set(); dcq.merge_bufferlists(&dirty_card_queue_set()); @@ -5762,10 +5754,8 @@ } _gc_tracer_stw->report_gc_reference_stats(stats); - // We have completed copying any necessary live referent objects - // (that were not copied during the actual pause) so we can - // retire any active alloc buffers - pss.retire_alloc_buffers(); + + // We have completed copying any necessary live referent objects. assert(pss.refs()->is_empty(), "both queue and overflow should be empty"); double ref_proc_time = os::elapsedTime() - ref_proc_start; @@ -6456,11 +6446,7 @@ bool G1CollectedHeap::is_in_closed_subset(const void* p) const { HeapRegion* hr = heap_region_containing(p); - if (hr == NULL) { - return false; - } else { - return hr->is_in(p); - } + return hr->is_in(p); } // Methods for the mutator alloc region diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -28,6 +28,7 @@ #include "gc_implementation/g1/concurrentMark.hpp" #include "gc_implementation/g1/evacuationInfo.hpp" #include "gc_implementation/g1/g1AllocRegion.hpp" +#include "gc_implementation/g1/g1BiasedArray.hpp" #include "gc_implementation/g1/g1HRPrinter.hpp" #include "gc_implementation/g1/g1MonitoringSupport.hpp" #include "gc_implementation/g1/g1RemSet.hpp" @@ -197,6 +198,16 @@ bool do_object_b(oop p); }; +// Instances of this class are used for quick tests on whether a reference points +// into the collection set. Each of the array's elements denotes whether the +// corresponding region is in the collection set. +class G1FastCSetBiasedMappedArray : public G1BiasedMappedArray { + protected: + bool default_value() const { return false; } + public: + void clear() { G1BiasedMappedArray::clear(); } +}; + class RefineCardTableEntryClosure; class G1CollectedHeap : public SharedHeap { @@ -353,26 +364,10 @@ // than the current allocation region. size_t _summary_bytes_used; - // 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. - uint _in_cset_fast_test_length; + // This array is used for a quick test on whether a reference points into + // the collection set or not. Each of the array's elements denotes whether the + // corresponding region is in the collection set or not. + G1FastCSetBiasedMappedArray _in_cset_fast_test; volatile unsigned _gc_time_stamp; @@ -695,12 +690,7 @@ // 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"); - uint index = r->hrs_index(); - assert(index < _in_cset_fast_test_length, "invariant"); - assert(!_in_cset_fast_test_base[index], "invariant"); - _in_cset_fast_test_base[index] = true; + _in_cset_fast_test.set_by_index(r->hrs_index(), true); } // This is a fast test on whether a reference points into the @@ -709,9 +699,7 @@ inline bool in_cset_fast_test(oop obj); void clear_cset_fast_test() { - assert(_in_cset_fast_test_base != NULL, "sanity"); - memset(_in_cset_fast_test_base, false, - (size_t) _in_cset_fast_test_length * sizeof(bool)); + _in_cset_fast_test.clear(); } // This is called at the start of either a concurrent cycle or a Full @@ -1077,6 +1065,8 @@ // specified by the policy object. jint initialize(); + virtual void stop(); + // Return the (conservative) maximum heap alignment for any G1 heap static size_t conservative_max_heap_alignment(); @@ -1390,17 +1380,15 @@ // space containing a given address, or else returns NULL. virtual Space* space_containing(const void* addr) const; - // A G1CollectedHeap will contain some number of heap regions. This - // finds the region containing a given address, or else returns NULL. + // Returns the HeapRegion that contains addr. addr must not be NULL. + template + inline HeapRegion* heap_region_containing_raw(const T addr) const; + + // Returns the HeapRegion that contains addr. addr must not be NULL. + // If addr is within a humongous continues region, it returns its humongous start region. template inline HeapRegion* heap_region_containing(const T addr) const; - // Like the above, but requires "addr" to be in the heap (to avoid a - // null-check), and unlike the above, may return an continuing humongous - // region. - template - inline HeapRegion* heap_region_containing_raw(const T addr) const; - // A CollectedHeap is divided into a dense sequence of "blocks"; that is, // each address in the (reserved) heap is a member of exactly // one block. The defining characteristic of a block is that it is @@ -1542,7 +1530,6 @@ // the region to which the object belongs. An object is dead // iff a) it was not allocated since the last mark and b) it // is not marked. - bool is_obj_dead(const oop obj, const HeapRegion* hr) const { return !hr->obj_allocated_since_prev_marking(obj) && @@ -1552,7 +1539,6 @@ // This function returns true when an object has been // around since the previous marking and hasn't yet // been marked during this marking. - bool is_obj_ill(const oop obj, const HeapRegion* hr) const { return !hr->obj_allocated_since_next_marking(obj) && @@ -1698,15 +1684,19 @@ public: G1ParGCAllocBuffer(size_t gclab_word_size); + virtual ~G1ParGCAllocBuffer() { + guarantee(_retired, "Allocation buffer has not been retired"); + } - void set_buf(HeapWord* buf) { + virtual void set_buf(HeapWord* buf) { ParGCAllocBuffer::set_buf(buf); _retired = false; } - void retire(bool end_of_gc, bool retain) { - if (_retired) + virtual void retire(bool end_of_gc, bool retain) { + if (_retired) { return; + } ParGCAllocBuffer::retire(end_of_gc, retain); _retired = true; } @@ -1776,6 +1766,7 @@ G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp); ~G1ParScanThreadState() { + retire_alloc_buffers(); FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base, mtGC); } @@ -1886,6 +1877,7 @@ return _surviving_young_words; } +private: void retire_alloc_buffers() { for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { size_t waste = _alloc_buffers[ap]->words_remaining(); @@ -1895,8 +1887,8 @@ false /* retain */); } } -private: - #define G1_PARTIAL_ARRAY_MASK 0x2 + +#define G1_PARTIAL_ARRAY_MASK 0x2 inline bool has_partial_array_mask(oop* ref) const { return ((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) == G1_PARTIAL_ARRAY_MASK; diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -42,21 +42,22 @@ template inline HeapRegion* -G1CollectedHeap::heap_region_containing(const T addr) const { - HeapRegion* hr = _hrs.addr_to_region((HeapWord*) addr); - // hr can be null if addr in perm_gen - if (hr != NULL && hr->continuesHumongous()) { - hr = hr->humongous_start_region(); - } - return hr; +G1CollectedHeap::heap_region_containing_raw(const T addr) const { + assert(addr != NULL, "invariant"); + assert(_g1_reserved.contains((const void*) addr), + err_msg("Address "PTR_FORMAT" is outside of the heap ranging from ["PTR_FORMAT" to "PTR_FORMAT")", + (void*)addr, _g1_reserved.start(), _g1_reserved.end())); + return _hrs.addr_to_region((HeapWord*) addr); } template inline HeapRegion* -G1CollectedHeap::heap_region_containing_raw(const T addr) const { - assert(_g1_reserved.contains((const void*) addr), "invariant"); - HeapRegion* res = _hrs.addr_to_region_unsafe((HeapWord*) addr); - return res; +G1CollectedHeap::heap_region_containing(const T addr) const { + HeapRegion* hr = heap_region_containing_raw(addr); + if (hr->continuesHumongous()) { + return hr->humongous_start_region(); + } + return hr; } inline void G1CollectedHeap::old_set_remove(HeapRegion* hr) { @@ -134,8 +135,7 @@ // have to keep calling heap_region_containing_raw() in the // asserts below. DEBUG_ONLY(HeapRegion* containing_hr = heap_region_containing_raw(start);) - assert(containing_hr != NULL && start != NULL && word_size > 0, - "pre-condition"); + assert(word_size > 0, "pre-condition"); assert(containing_hr->is_in(start), "it should contain start"); assert(containing_hr->is_young(), "it should be young"); assert(!containing_hr->isHumongous(), "it should not be humongous"); @@ -164,12 +164,7 @@ // collection set or not. Assume that the reference // points into the heap. inline bool G1CollectedHeap::in_cset_fast_test(oop obj) { - assert(_in_cset_fast_test != NULL, "sanity"); - assert(_g1_committed.contains((HeapWord*) obj), err_msg("Given reference outside of heap, is "PTR_FORMAT, (HeapWord*)obj)); - // no need to subtract the bottom of the heap from obj, - // _in_cset_fast_test is biased - uintx index = cast_from_oop(obj) >> HeapRegion::LogOfHRGrainBytes; - bool ret = _in_cset_fast_test[index]; + bool ret = _in_cset_fast_test.get_by_address((HeapWord*)obj); // let's make sure the result is consistent with what the slower // test returns assert( ret || !obj_in_cs(obj), "sanity"); @@ -251,8 +246,10 @@ #endif // #ifndef PRODUCT inline bool G1CollectedHeap::is_in_young(const oop obj) { - HeapRegion* hr = heap_region_containing(obj); - return hr != NULL && hr->is_young(); + if (obj == NULL) { + return false; + } + return heap_region_containing(obj)->is_young(); } // We don't need barriers for initializing stores to objects @@ -265,21 +262,17 @@ } inline bool G1CollectedHeap::is_obj_dead(const oop obj) const { - const HeapRegion* hr = heap_region_containing(obj); - if (hr == NULL) { - if (obj == NULL) return false; - else return true; + if (obj == NULL) { + return false; } - else return is_obj_dead(obj, hr); + return is_obj_dead(obj, heap_region_containing(obj)); } inline bool G1CollectedHeap::is_obj_ill(const oop obj) const { - const HeapRegion* hr = heap_region_containing(obj); - if (hr == NULL) { - if (obj == NULL) return false; - else return true; + if (obj == NULL) { + return false; } - else return is_obj_ill(obj, hr); + return is_obj_ill(obj, heap_region_containing(obj)); } template inline void G1ParScanThreadState::immediate_rs_update(HeapRegion* from, T* p, int tid) { diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -170,6 +170,8 @@ _last_gc_worker_end_times_ms(_max_gc_threads, "%.1lf", false), _last_gc_worker_times_ms(_max_gc_threads, "%.1lf"), _last_gc_worker_other_times_ms(_max_gc_threads, "%.1lf"), + _last_redirty_logged_cards_time_ms(_max_gc_threads, "%.1lf"), + _last_redirty_logged_cards_processed_cards(_max_gc_threads, SIZE_FORMAT), _cur_string_dedup_queue_fixup_worker_times_ms(_max_gc_threads, "%.1lf"), _cur_string_dedup_table_fixup_worker_times_ms(_max_gc_threads, "%.1lf") { @@ -195,6 +197,10 @@ _last_gc_worker_end_times_ms.reset(); _last_gc_worker_times_ms.reset(); _last_gc_worker_other_times_ms.reset(); + + _last_redirty_logged_cards_time_ms.reset(); + _last_redirty_logged_cards_processed_cards.reset(); + } void G1GCPhaseTimes::note_gc_end() { @@ -230,6 +236,9 @@ _last_gc_worker_times_ms.verify(); _last_gc_worker_other_times_ms.verify(); + + _last_redirty_logged_cards_time_ms.verify(); + _last_redirty_logged_cards_processed_cards.verify(); } void G1GCPhaseTimes::note_string_dedup_fixup_start() { @@ -349,6 +358,10 @@ print_stats(2, "Ref Enq", _cur_ref_enq_time_ms); if (G1DeferredRSUpdate) { print_stats(2, "Redirty Cards", _recorded_redirty_logged_cards_time_ms); + if (G1Log::finest()) { + _last_redirty_logged_cards_time_ms.print(3, "Parallel Redirty"); + _last_redirty_logged_cards_processed_cards.print(3, "Redirtied Cards"); + } } print_stats(2, "Free CSet", (_recorded_young_free_cset_time_ms + diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -151,6 +151,8 @@ double _recorded_young_cset_choice_time_ms; double _recorded_non_young_cset_choice_time_ms; + WorkerDataArray _last_redirty_logged_cards_time_ms; + WorkerDataArray _last_redirty_logged_cards_processed_cards; double _recorded_redirty_logged_cards_time_ms; double _recorded_young_free_cset_time_ms; @@ -293,6 +295,14 @@ _recorded_non_young_cset_choice_time_ms = time_ms; } + void record_redirty_logged_cards_time_ms(uint worker_i, double time_ms) { + _last_redirty_logged_cards_time_ms.set(worker_i, time_ms); + } + + void record_redirty_logged_cards_processed_cards(uint worker_i, size_t processed_buffers) { + _last_redirty_logged_cards_processed_cards.set(worker_i, processed_buffers); + } + void record_redirty_logged_cards_time_ms(double time_ms) { _recorded_redirty_logged_cards_time_ms = time_ms; } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -125,9 +125,7 @@ if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); HeapRegion* hr = _g1h->heap_region_containing((HeapWord*) obj); - if (hr != NULL) { - _cm->grayRoot(obj, obj->size(), _worker_id, hr); - } + _cm->grayRoot(obj, obj->size(), _worker_id, hr); } } @@ -154,57 +152,63 @@ template inline void G1UpdateRSOrPushRefOopClosure::do_oop_nv(T* p) { oop obj = oopDesc::load_decode_heap_oop(p); + if (obj == NULL) { + return; + } + #ifdef ASSERT // can't do because of races // assert(obj == NULL || obj->is_oop(), "expected an oop"); // Do the safe subset of is_oop - if (obj != NULL) { #ifdef CHECK_UNHANDLED_OOPS - oopDesc* o = obj.obj(); + oopDesc* o = obj.obj(); #else - oopDesc* o = obj; + oopDesc* o = obj; #endif // CHECK_UNHANDLED_OOPS - assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned"); - assert(Universe::heap()->is_in_reserved(obj), "must be in heap"); - } + assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned"); + assert(Universe::heap()->is_in_reserved(obj), "must be in heap"); #endif // ASSERT assert(_from != NULL, "from region must be non-NULL"); assert(_from->is_in_reserved(p), "p is not in from"); HeapRegion* to = _g1->heap_region_containing(obj); - if (to != NULL && _from != to) { - // The _record_refs_into_cset flag is true during the RSet - // updating part of an evacuation pause. It is false at all - // other times: - // * rebuilding the remembered sets after a full GC - // * during concurrent refinement. - // * updating the remembered sets of regions in the collection - // set in the event of an evacuation failure (when deferred - // updates are enabled). + if (_from == to) { + // Normally this closure should only be called with cross-region references. + // But since Java threads are manipulating the references concurrently and we + // reload the values things may have changed. + return; + } - if (_record_refs_into_cset && to->in_collection_set()) { - // We are recording references that point into the collection - // set and this particular reference does exactly that... - // If the referenced object has already been forwarded - // to itself, we are handling an evacuation failure and - // we have already visited/tried to copy this object - // there is no need to retry. - if (!self_forwarded(obj)) { - assert(_push_ref_cl != NULL, "should not be null"); - // Push the reference in the refs queue of the G1ParScanThreadState - // instance for this worker thread. - _push_ref_cl->do_oop(p); - } + // The _record_refs_into_cset flag is true during the RSet + // updating part of an evacuation pause. It is false at all + // other times: + // * rebuilding the remembered sets after a full GC + // * during concurrent refinement. + // * updating the remembered sets of regions in the collection + // set in the event of an evacuation failure (when deferred + // updates are enabled). - // Deferred updates to the CSet are either discarded (in the normal case), - // or processed (if an evacuation failure occurs) at the end - // of the collection. - // See G1RemSet::cleanup_after_oops_into_collection_set_do(). - return; + if (_record_refs_into_cset && to->in_collection_set()) { + // We are recording references that point into the collection + // set and this particular reference does exactly that... + // If the referenced object has already been forwarded + // to itself, we are handling an evacuation failure and + // we have already visited/tried to copy this object + // there is no need to retry. + if (!self_forwarded(obj)) { + assert(_push_ref_cl != NULL, "should not be null"); + // Push the reference in the refs queue of the G1ParScanThreadState + // instance for this worker thread. + _push_ref_cl->do_oop(p); } + // Deferred updates to the CSet are either discarded (in the normal case), + // or processed (if an evacuation failure occurs) at the end + // of the collection. + // See G1RemSet::cleanup_after_oops_into_collection_set_do(). + } else { // We either don't care about pushing references that point into the // collection set (i.e. we're not during an evacuation pause) _or_ // the reference doesn't point into the collection set. Either way diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -36,6 +36,7 @@ #include "gc_implementation/g1/heapRegionRemSet.hpp" #include "memory/iterator.hpp" #include "oops/oop.inline.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/intHisto.hpp" #define CARD_REPEAT_HISTO 0 @@ -163,7 +164,7 @@ void printCard(HeapRegion* card_region, size_t card_index, HeapWord* card_start) { gclog_or_tty->print_cr("T %u Region [" PTR_FORMAT ", " PTR_FORMAT ") " - "RS names card %p: " + "RS names card " SIZE_FORMAT_HEX ": " "[" PTR_FORMAT ", " PTR_FORMAT ")", _worker_i, card_region->bottom(), card_region->end(), @@ -209,7 +210,6 @@ #endif HeapRegion* card_region = _g1h->heap_region_containing(card_start); - assert(card_region != NULL, "Yielding cards not in the heap?"); _cards++; if (!card_region->is_on_dirty_cards_region_list()) { @@ -404,7 +404,6 @@ HeapWord* start = _ct_bs->addr_for(card_ptr); // And find the region containing it. HeapRegion* r = _g1->heap_region_containing(start); - assert(r != NULL, "unexpected null"); // Scan oops in the card looking for references into the collection set // Don't use addr_for(card_ptr + 1) which can ask for @@ -566,11 +565,6 @@ HeapWord* start = _ct_bs->addr_for(card_ptr); // And find the region containing it. HeapRegion* r = _g1->heap_region_containing(start); - if (r == NULL) { - // Again no need to return that this card contains refs that - // point into the collection set. - return false; // Not in the G1 heap (might be in perm, for example.) - } // Why do we have to check here whether a card is on a young region, // given that we dirty young regions and, as a result, the @@ -623,10 +617,6 @@ start = _ct_bs->addr_for(card_ptr); r = _g1->heap_region_containing(start); - if (r == NULL) { - // Not in the G1 heap - return false; - } // Checking whether the region we got back from the cache // is young here is inappropriate. The region could have been diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -45,26 +45,28 @@ template inline void G1RemSet::par_write_ref(HeapRegion* from, T* p, int tid) { oop obj = oopDesc::load_decode_heap_oop(p); + if (obj == NULL) { + return; + } + #ifdef ASSERT // can't do because of races // assert(obj == NULL || obj->is_oop(), "expected an oop"); // Do the safe subset of is_oop - if (obj != NULL) { #ifdef CHECK_UNHANDLED_OOPS - oopDesc* o = obj.obj(); + oopDesc* o = obj.obj(); #else - oopDesc* o = obj; + oopDesc* o = obj; #endif // CHECK_UNHANDLED_OOPS - assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned"); - assert(Universe::heap()->is_in_reserved(obj), "must be in heap"); - } + assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned"); + assert(Universe::heap()->is_in_reserved(obj), "must be in heap"); #endif // ASSERT assert(from == NULL || from->is_in_reserved(p), "p is not in from"); HeapRegion* to = _g1->heap_region_containing(obj); - if (to != NULL && from != to) { + if (from != to) { assert(to->rem_set() != NULL, "Need per-region 'into' remsets."); to->rem_set()->add_reference(p, tid); } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -44,6 +44,11 @@ } } +void G1StringDedup::stop() { + assert(is_enabled(), "String deduplication not enabled"); + G1StringDedupThread::stop(); +} + bool G1StringDedup::is_candidate_from_mark(oop obj) { if (java_lang_String::is_instance(obj)) { bool from_young = G1CollectedHeap::heap()->heap_region_containing_raw(obj)->is_young(); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -110,8 +110,12 @@ return _enabled; } + // Initialize string deduplication. static void initialize(); + // Stop the deduplication thread. + static void stop(); + // Immediately deduplicates the given String object, bypassing the // the deduplication queue. static void deduplicate(oop java_string); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1StringDedupQueue.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupQueue.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupQueue.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -35,6 +35,7 @@ G1StringDedupQueue::G1StringDedupQueue() : _cursor(0), + _cancel(false), _empty(true), _dropped(0) { _nqueues = MAX2(ParallelGCThreads, (size_t)1); @@ -55,11 +56,17 @@ void G1StringDedupQueue::wait() { MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag); - while (_queue->_empty) { + while (_queue->_empty && !_queue->_cancel) { ml.wait(Mutex::_no_safepoint_check_flag); } } +void G1StringDedupQueue::cancel_wait() { + MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag); + _queue->_cancel = true; + ml.notify(); +} + void G1StringDedupQueue::push(uint worker_id, oop java_string) { assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint"); assert(worker_id < _queue->_nqueues, "Invalid queue"); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1StringDedupQueue.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupQueue.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupQueue.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -65,6 +65,7 @@ G1StringDedupWorkerQueue* _queues; size_t _nqueues; size_t _cursor; + bool _cancel; volatile bool _empty; // Statistics counter, only used for logging. @@ -81,6 +82,9 @@ // Blocks and waits for the queue to become non-empty. static void wait(); + // Wakes up any thread blocked waiting for the queue to become non-empty. + static void cancel_wait(); + // Pushes a deduplication candidate onto a specific GC worker queue. static void push(uint worker_id, oop java_string); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -73,42 +73,60 @@ // Wait for the queue to become non-empty G1StringDedupQueue::wait(); + if (_should_terminate) { + break; + } - // Include this thread in safepoints - stsJoin(); + { + // Include thread in safepoints + SuspendibleThreadSetJoiner sts; - stat.mark_exec(); + stat.mark_exec(); - // Process the queue - for (;;) { - oop java_string = G1StringDedupQueue::pop(); - if (java_string == NULL) { - break; + // Process the queue + for (;;) { + oop java_string = G1StringDedupQueue::pop(); + if (java_string == NULL) { + break; + } + + G1StringDedupTable::deduplicate(java_string, stat); + + // Safepoint this thread if needed + if (sts.should_yield()) { + stat.mark_block(); + sts.yield(); + stat.mark_unblock(); + } } - G1StringDedupTable::deduplicate(java_string, stat); + G1StringDedupTable::trim_entry_cache(); - // Safepoint this thread if needed - if (stsShouldYield()) { - stat.mark_block(); - stsYield(NULL); - stat.mark_unblock(); - } - } + stat.mark_done(); - G1StringDedupTable::trim_entry_cache(); - - stat.mark_done(); - - // Print statistics - total_stat.add(stat); - print(gclog_or_tty, stat, total_stat); - - // Exclude this thread from safepoints - stsLeave(); + // Print statistics + total_stat.add(stat); + print(gclog_or_tty, stat, total_stat); + } } - ShouldNotReachHere(); + terminate(); +} + +void G1StringDedupThread::stop() { + { + MonitorLockerEx ml(Terminator_lock); + _thread->_should_terminate = true; + } + + G1StringDedupQueue::cancel_wait(); + + { + MonitorLockerEx ml(Terminator_lock); + while (!_thread->_has_terminated) { + ml.wait(); + } + } } void G1StringDedupThread::print(outputStream* st, const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) { diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -47,6 +47,8 @@ public: static void create(); + static void stop(); + static G1StringDedupThread* thread(); virtual void run(); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -167,7 +167,7 @@ // Mem size in bytes. size_t mem_size() const { - return sizeof(this) + _bm.size_in_words() * HeapWordSize; + return sizeof(PerRegionTable) + _bm.size_in_words() * HeapWordSize; } // Requires "from" to be in "hr()". @@ -491,7 +491,7 @@ } else { if (G1TraceHeapRegionRememberedSet) { gclog_or_tty->print_cr(" [tid %d] sparse table entry " - "overflow(f: %d, t: %d)", + "overflow(f: %d, t: %u)", tid, from_hrs_ind, cur_hrs_ind); } } @@ -610,7 +610,7 @@ _n_coarse_entries++; if (G1TraceHeapRegionRememberedSet) { gclog_or_tty->print("Coarsened entry in region [" PTR_FORMAT "...] " - "for region [" PTR_FORMAT "...] (%d coarse entries).\n", + "for region [" PTR_FORMAT "...] (" SIZE_FORMAT " coarse entries).\n", hr()->bottom(), max->hr()->bottom(), _n_coarse_entries); @@ -733,7 +733,7 @@ sum += (sizeof(PerRegionTable*) * _max_fine_entries); sum += (_coarse_map.size_in_words() * HeapWordSize); sum += (_sparse_table.mem_size()); - sum += sizeof(*this) - sizeof(_sparse_table); // Avoid double counting above. + sum += sizeof(OtherRegionsTable) - sizeof(_sparse_table); // Avoid double counting above. return sum; } @@ -768,30 +768,6 @@ clear_fcc(); } -void OtherRegionsTable::clear_incoming_entry(HeapRegion* from_hr) { - MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); - size_t hrs_ind = (size_t) from_hr->hrs_index(); - size_t ind = hrs_ind & _mod_max_fine_entries_mask; - if (del_single_region_table(ind, from_hr)) { - assert(!_coarse_map.at(hrs_ind), "Inv"); - } else { - _coarse_map.par_at_put(hrs_ind, 0); - } - // Check to see if any of the fcc entries come from here. - uint hr_ind = hr()->hrs_index(); - for (uint tid = 0; tid < HeapRegionRemSet::num_par_rem_sets(); tid++) { - int fcc_ent = FromCardCache::at(tid, hr_ind); - if (fcc_ent != FromCardCache::InvalidCard) { - HeapWord* card_addr = (HeapWord*) - (uintptr_t(fcc_ent) << CardTableModRefBS::card_shift); - if (hr()->is_in_reserved(card_addr)) { - // Clear the from card cache. - FromCardCache::set(tid, hr_ind, FromCardCache::InvalidCard); - } - } - } -} - bool OtherRegionsTable::del_single_region_table(size_t ind, HeapRegion* hr) { assert(0 <= ind && ind < _max_fine_entries, "Preconditions."); @@ -821,7 +797,6 @@ bool OtherRegionsTable::contains_reference_locked(OopOrNarrowOopStar from) const { HeapRegion* hr = _g1h->heap_region_containing_raw(from); - if (hr == NULL) return false; RegionIdx_t hr_ind = (RegionIdx_t) hr->hrs_index(); // Is this region in the coarse map? if (_coarse_map.at(hr_ind)) return true; @@ -903,10 +878,12 @@ } if (iter.n_yielded() != occupied()) { gclog_or_tty->print_cr("Yielded disagrees with occupied:"); - gclog_or_tty->print_cr(" %6d yielded (%6d coarse, %6d fine).", + gclog_or_tty->print_cr(" " SIZE_FORMAT_W(6) " yielded (" SIZE_FORMAT_W(6) + " coarse, " SIZE_FORMAT_W(6) " fine).", iter.n_yielded(), iter.n_yielded_coarse(), iter.n_yielded_fine()); - gclog_or_tty->print_cr(" %6d occ (%6d coarse, %6d fine).", + gclog_or_tty->print_cr(" " SIZE_FORMAT_W(6) " occ (" SIZE_FORMAT_W(6) + " coarse, " SIZE_FORMAT_W(6) " fine).", occupied(), occ_coarse(), occ_fine()); } guarantee(iter.n_yielded() == occupied(), @@ -1046,20 +1023,16 @@ return _code_roots.mem_size(); } -//-------------------- Iteration -------------------- - HeapRegionRemSetIterator:: HeapRegionRemSetIterator(HeapRegionRemSet* hrrs) : _hrrs(hrrs), _g1h(G1CollectedHeap::heap()), _coarse_map(&hrrs->_other_regions._coarse_map), - _fine_grain_regions(hrrs->_other_regions._fine_grain_regions), _bosa(hrrs->bosa()), _is(Sparse), // Set these values so that we increment to the first region. _coarse_cur_region_index(-1), _coarse_cur_region_cur_card(HeapRegion::CardsPerRegion-1), - _cur_region_cur_card(0), - _fine_array_index(-1), + _cur_card_in_prt(HeapRegion::CardsPerRegion), _fine_cur_prt(NULL), _n_yielded_coarse(0), _n_yielded_fine(0), @@ -1091,58 +1064,59 @@ return true; } -void HeapRegionRemSetIterator::fine_find_next_non_null_prt() { - // Otherwise, find the next bucket list in the array. - _fine_array_index++; - while (_fine_array_index < (int) OtherRegionsTable::_max_fine_entries) { - _fine_cur_prt = _fine_grain_regions[_fine_array_index]; - if (_fine_cur_prt != NULL) return; - else _fine_array_index++; - } - assert(_fine_cur_prt == NULL, "Loop post"); -} - bool HeapRegionRemSetIterator::fine_has_next(size_t& card_index) { if (fine_has_next()) { - _cur_region_cur_card = - _fine_cur_prt->_bm.get_next_one_offset(_cur_region_cur_card + 1); + _cur_card_in_prt = + _fine_cur_prt->_bm.get_next_one_offset(_cur_card_in_prt + 1); } - while (!fine_has_next()) { - if (_cur_region_cur_card == (size_t) HeapRegion::CardsPerRegion) { - _cur_region_cur_card = 0; - _fine_cur_prt = _fine_cur_prt->collision_list_next(); + if (_cur_card_in_prt == HeapRegion::CardsPerRegion) { + // _fine_cur_prt may still be NULL in case if there are not PRTs at all for + // the remembered set. + if (_fine_cur_prt == NULL || _fine_cur_prt->next() == NULL) { + return false; } - if (_fine_cur_prt == NULL) { - fine_find_next_non_null_prt(); - if (_fine_cur_prt == NULL) return false; - } - assert(_fine_cur_prt != NULL && _cur_region_cur_card == 0, - "inv."); - HeapWord* r_bot = - _fine_cur_prt->hr()->bottom(); - _cur_region_card_offset = _bosa->index_for(r_bot); - _cur_region_cur_card = _fine_cur_prt->_bm.get_next_one_offset(0); + PerRegionTable* next_prt = _fine_cur_prt->next(); + switch_to_prt(next_prt); + _cur_card_in_prt = _fine_cur_prt->_bm.get_next_one_offset(_cur_card_in_prt + 1); } - assert(fine_has_next(), "Or else we exited the loop via the return."); - card_index = _cur_region_card_offset + _cur_region_cur_card; + + card_index = _cur_region_card_offset + _cur_card_in_prt; + guarantee(_cur_card_in_prt < HeapRegion::CardsPerRegion, + err_msg("Card index "SIZE_FORMAT" must be within the region", _cur_card_in_prt)); return true; } bool HeapRegionRemSetIterator::fine_has_next() { - return - _fine_cur_prt != NULL && - _cur_region_cur_card < HeapRegion::CardsPerRegion; + return _cur_card_in_prt != HeapRegion::CardsPerRegion; +} + +void HeapRegionRemSetIterator::switch_to_prt(PerRegionTable* prt) { + assert(prt != NULL, "Cannot switch to NULL prt"); + _fine_cur_prt = prt; + + HeapWord* r_bot = _fine_cur_prt->hr()->bottom(); + _cur_region_card_offset = _bosa->index_for(r_bot); + + // The bitmap scan for the PRT always scans from _cur_region_cur_card + 1. + // To avoid special-casing this start case, and not miss the first bitmap + // entry, initialize _cur_region_cur_card with -1 instead of 0. + _cur_card_in_prt = (size_t)-1; } bool HeapRegionRemSetIterator::has_next(size_t& card_index) { switch (_is) { - case Sparse: + case Sparse: { if (_sparse_iter.has_next(card_index)) { _n_yielded_sparse++; return true; } // Otherwise, deliberate fall-through _is = Fine; + PerRegionTable* initial_fine_prt = _hrrs->_other_regions._first_all_fine_prts; + if (initial_fine_prt != NULL) { + switch_to_prt(_hrrs->_other_regions._first_all_fine_prts); + } + } case Fine: if (fine_has_next(card_index)) { _n_yielded_fine++; @@ -1274,6 +1248,11 @@ #ifndef PRODUCT void PerRegionTable::test_fl_mem_size() { PerRegionTable* dummy = alloc(NULL); + + size_t min_prt_size = sizeof(void*) + dummy->bm()->size_in_words() * HeapWordSize; + assert(dummy->mem_size() > min_prt_size, + err_msg("PerRegionTable memory usage is suspiciously small, only has "SIZE_FORMAT" bytes. " + "Should be at least "SIZE_FORMAT" bytes.", dummy->mem_size(), min_prt_size)); free(dummy); guarantee(dummy->mem_size() == fl_mem_size(), "fl_mem_size() does not return the correct element size"); // try to reset the state diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -206,9 +206,6 @@ // Specifically clear the from_card_cache. void clear_fcc(); - // "from_hr" is being cleared; remove any entries from it. - void clear_incoming_entry(HeapRegion* from_hr); - void do_cleanup_work(HRRSCleanupTask* hrrs_cleanup_task); // Declare the heap size (in # of regions) to the OtherRegionsTable. @@ -338,20 +335,20 @@ return _other_regions.mem_size() // This correction is necessary because the above includes the second // part. - + (sizeof(this) - sizeof(OtherRegionsTable)) + + (sizeof(HeapRegionRemSet) - sizeof(OtherRegionsTable)) + strong_code_roots_mem_size(); } // Returns the memory occupancy of all static data structures associated // with remembered sets. static size_t static_mem_size() { - return OtherRegionsTable::static_mem_size() + G1CodeRootSet::static_mem_size(); + return OtherRegionsTable::static_mem_size() + G1CodeRootSet::free_chunks_static_mem_size(); } // Returns the memory occupancy of all free_list data structures associated // with remembered sets. static size_t fl_mem_size() { - return OtherRegionsTable::fl_mem_size() + G1CodeRootSet::fl_mem_size(); + return OtherRegionsTable::fl_mem_size() + G1CodeRootSet::free_chunks_mem_size(); } bool contains_reference(OopOrNarrowOopStar from) const { @@ -396,7 +393,6 @@ // Declare the heap size (in # of regions) to the HeapRegionRemSet(s). // (Uses it to initialize from_card_cache). static void init_heap(uint max_regions) { - G1CodeRootSet::initialize(); OtherRegionsTable::init_from_card_cache(max_regions); } @@ -429,26 +425,24 @@ }; class HeapRegionRemSetIterator : public StackObj { - - // The region RSet over which we're iterating. + private: + // The region RSet over which we are iterating. HeapRegionRemSet* _hrrs; // Local caching of HRRS fields. const BitMap* _coarse_map; - PerRegionTable** _fine_grain_regions; G1BlockOffsetSharedArray* _bosa; G1CollectedHeap* _g1h; - // The number yielded since initialization. + // The number of cards yielded since initialization. size_t _n_yielded_fine; size_t _n_yielded_coarse; size_t _n_yielded_sparse; - // Indicates what granularity of table that we're currently iterating over. + // Indicates what granularity of table that we are currently iterating over. // We start iterating over the sparse table, progress to the fine grain // table, and then finish with the coarse table. - // See HeapRegionRemSetIterator::has_next(). enum IterState { Sparse, Fine, @@ -456,38 +450,30 @@ }; IterState _is; - // In both kinds of iteration, heap offset of first card of current - // region. + // For both Coarse and Fine remembered set iteration this contains the + // first card number of the heap region we currently iterate over. size_t _cur_region_card_offset; - // Card offset within cur region. - size_t _cur_region_cur_card; - // Coarse table iteration fields: - - // Current region index; + // Current region index for the Coarse remembered set iteration. int _coarse_cur_region_index; size_t _coarse_cur_region_cur_card; bool coarse_has_next(size_t& card_index); - // Fine table iteration fields: - - // Index of bucket-list we're working on. - int _fine_array_index; + // The PRT we are currently iterating over. + PerRegionTable* _fine_cur_prt; + // Card offset within the current PRT. + size_t _cur_card_in_prt; - // Per Region Table we're doing within current bucket list. - PerRegionTable* _fine_cur_prt; - - /* SparsePRT::*/ SparsePRTIter _sparse_iter; - - void fine_find_next_non_null_prt(); - + // Update internal variables when switching to the given PRT. + void switch_to_prt(PerRegionTable* prt); bool fine_has_next(); bool fine_has_next(size_t& card_index); -public: - // We require an iterator to be initialized before use, so the - // constructor does little. + // The Sparse remembered set iterator. + SparsePRTIter _sparse_iter; + + public: HeapRegionRemSetIterator(HeapRegionRemSet* hrrs); // If there remains one or more cards to be yielded, returns true and diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -240,7 +240,6 @@ // Asserts will fire if i is >= _length HeapWord* addr = hr->bottom(); guarantee(addr_to_region(addr) == hr, "sanity"); - guarantee(addr_to_region_unsafe(addr) == hr, "sanity"); } else { guarantee(hr->is_empty(), "sanity"); guarantee(!hr->isHumongous(), "sanity"); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -110,10 +110,6 @@ // HeapRegion, otherwise return NULL. inline HeapRegion* addr_to_region(HeapWord* addr) const; - // Return the HeapRegion that corresponds to the given - // address. Assume the address is valid. - inline HeapRegion* addr_to_region_unsafe(HeapWord* addr) const; - // Return the number of regions that have been committed in the heap. uint length() const { return _committed_length; } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -28,21 +28,17 @@ #include "gc_implementation/g1/heapRegion.hpp" #include "gc_implementation/g1/heapRegionSeq.hpp" -inline HeapRegion* HeapRegionSeq::addr_to_region_unsafe(HeapWord* addr) const { +inline HeapRegion* HeapRegionSeq::addr_to_region(HeapWord* addr) const { + assert(addr < heap_end(), + err_msg("addr: "PTR_FORMAT" end: "PTR_FORMAT, addr, heap_end())); + assert(addr >= heap_bottom(), + err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT, addr, heap_bottom())); + HeapRegion* hr = _regions.get_by_address(addr); assert(hr != NULL, "invariant"); return hr; } -inline HeapRegion* HeapRegionSeq::addr_to_region(HeapWord* addr) const { - if (addr != NULL && addr < heap_end()) { - assert(addr >= heap_bottom(), - err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT, addr, heap_bottom())); - return addr_to_region_unsafe(addr); - } - return NULL; -} - inline HeapRegion* HeapRegionSeq::at(uint index) const { assert(index < length(), "pre-condition"); HeapRegion* hr = _regions.get_by_index(index); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -370,7 +370,7 @@ } size_t RSHashTable::mem_size() const { - return sizeof(this) + + return sizeof(RSHashTable) + capacity() * (SparsePRTEntry::size() + sizeof(int)); } @@ -472,7 +472,7 @@ size_t SparsePRT::mem_size() const { // We ignore "_cur" here, because it either = _next, or else it is // on the deleted list. - return sizeof(this) + _next->mem_size(); + return sizeof(SparsePRT) + _next->mem_size(); } bool SparsePRT::add_card(RegionIdx_t region_id, CardIdx_t card_index) { diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/g1/survRateGroup.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -187,10 +187,10 @@ #ifndef PRODUCT void SurvRateGroup::print() { - gclog_or_tty->print_cr("Surv Rate Group: %s (%d entries)", + gclog_or_tty->print_cr("Surv Rate Group: %s (" SIZE_FORMAT " entries)", _name, _region_num); for (size_t i = 0; i < _region_num; ++i) { - gclog_or_tty->print_cr(" age %4d surv rate %6.2lf %% pred %6.2lf %%", + gclog_or_tty->print_cr(" age " SIZE_FORMAT_W(4) " surv rate %6.2lf %% pred %6.2lf %%", i, _surv_rate[i] * 100.0, _g1p->get_new_prediction(_surv_rate_pred[i]) * 100.0); } @@ -203,14 +203,15 @@ return; gclog_or_tty->print_cr(""); - gclog_or_tty->print_cr("%s Rate Summary (for up to age %d)", _name, length-1); + gclog_or_tty->print_cr("%s Rate Summary (for up to age " SIZE_FORMAT ")", _name, length-1); gclog_or_tty->print_cr(" age range survival rate (avg) samples (avg)"); gclog_or_tty->print_cr(" ---------------------------------------------------------"); size_t index = 0; size_t limit = MIN2((int) length, 10); while (index < limit) { - gclog_or_tty->print_cr(" %4d %6.2lf%% %6.2lf", + gclog_or_tty->print_cr(" " SIZE_FORMAT_W(4) + " %6.2lf%% %6.2lf", index, _summary_surv_rates[index]->avg() * 100.0, (double) _summary_surv_rates[index]->num()); ++index; @@ -228,7 +229,8 @@ ++index; if (index == length || num % 10 == 0) { - gclog_or_tty->print_cr(" %4d .. %4d %6.2lf%% %6.2lf", + gclog_or_tty->print_cr(" " SIZE_FORMAT_W(4) " .. " SIZE_FORMAT_W(4) + " %6.2lf%% %6.2lf", (index-1) / 10 * 10, index-1, sum / (double) num, (double) samples / (double) num); sum = 0.0; diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -143,7 +143,8 @@ if (TraceAdaptiveGCBoundary) { gclog_or_tty->print_cr("Before expansion of old gen with boundary move"); - gclog_or_tty->print_cr(" Requested change: 0x%x Attempted change: 0x%x", + gclog_or_tty->print_cr(" Requested change: " SIZE_FORMAT_HEX + " Attempted change: " SIZE_FORMAT_HEX, expand_in_bytes, change_in_bytes); if (!PrintHeapAtGC) { Universe::print_on(gclog_or_tty); @@ -201,7 +202,7 @@ if (TraceAdaptiveGCBoundary) { gclog_or_tty->print_cr("Before expansion of young gen with boundary move"); - gclog_or_tty->print_cr(" Requested change: 0x%x Attempted change: 0x%x", + gclog_or_tty->print_cr(" Requested change: " SIZE_FORMAT_HEX " Attempted change: " SIZE_FORMAT_HEX, expand_in_bytes, change_in_bytes); if (!PrintHeapAtGC) { Universe::print_on(gclog_or_tty); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -127,22 +127,22 @@ size_t result_aligned = align_size_down(result, gen_alignment); if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr("\nASPSOldGen::available_for_contraction:" - " %d K / 0x%x", result_aligned/K, result_aligned); - gclog_or_tty->print_cr(" reserved().byte_size() %d K / 0x%x ", + " " SIZE_FORMAT " K / " SIZE_FORMAT_HEX, result_aligned/K, result_aligned); + gclog_or_tty->print_cr(" reserved().byte_size() " SIZE_FORMAT " K / " SIZE_FORMAT_HEX, reserved().byte_size()/K, reserved().byte_size()); size_t working_promoted = (size_t) policy->avg_promoted()->padded_average(); - gclog_or_tty->print_cr(" padded promoted %d K / 0x%x", + gclog_or_tty->print_cr(" padded promoted " SIZE_FORMAT " K / " SIZE_FORMAT_HEX, working_promoted/K, working_promoted); - gclog_or_tty->print_cr(" used %d K / 0x%x", + gclog_or_tty->print_cr(" used " SIZE_FORMAT " K / " SIZE_FORMAT_HEX, used_in_bytes()/K, used_in_bytes()); - gclog_or_tty->print_cr(" min_gen_size() %d K / 0x%x", + gclog_or_tty->print_cr(" min_gen_size() " SIZE_FORMAT " K / " SIZE_FORMAT_HEX, min_gen_size()/K, min_gen_size()); - gclog_or_tty->print_cr(" max_contraction %d K / 0x%x", + gclog_or_tty->print_cr(" max_contraction " SIZE_FORMAT " K / " SIZE_FORMAT_HEX, max_contraction/K, max_contraction); - gclog_or_tty->print_cr(" without alignment %d K / 0x%x", + gclog_or_tty->print_cr(" without alignment " SIZE_FORMAT " K / " SIZE_FORMAT_HEX, policy->promo_increment(max_contraction)/K, policy->promo_increment(max_contraction)); - gclog_or_tty->print_cr(" alignment 0x%x", gen_alignment); + gclog_or_tty->print_cr(" alignment " SIZE_FORMAT_HEX, gen_alignment); } assert(result_aligned <= max_contraction, "arithmetic is wrong"); return result_aligned; diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -112,11 +112,11 @@ size_t result = policy->eden_increment_aligned_down(max_contraction); size_t result_aligned = align_size_down(result, gen_alignment); if (PrintAdaptiveSizePolicy && Verbose) { - gclog_or_tty->print_cr("ASPSYoungGen::available_for_contraction: %d K", + gclog_or_tty->print_cr("ASPSYoungGen::available_for_contraction: " SIZE_FORMAT " K", result_aligned/K); - gclog_or_tty->print_cr(" max_contraction %d K", max_contraction/K); - gclog_or_tty->print_cr(" eden_avail %d K", eden_avail/K); - gclog_or_tty->print_cr(" gen_avail %d K", gen_avail/K); + gclog_or_tty->print_cr(" max_contraction " SIZE_FORMAT " K", max_contraction/K); + gclog_or_tty->print_cr(" eden_avail " SIZE_FORMAT " K", eden_avail/K); + gclog_or_tty->print_cr(" gen_avail " SIZE_FORMAT " K", gen_avail/K); } return result_aligned; } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -487,7 +487,7 @@ if (TraceDynamicGCThreads) { gclog_or_tty->print_cr("GCTaskManager::set_active_gang(): " "all_workers_active() %d workers %d " - "active %d ParallelGCThreads %d ", + "active %d ParallelGCThreads " UINTX_FORMAT, all_workers_active(), workers(), active_workers(), ParallelGCThreads); } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/parallelScavenge/objectStartArray.hpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/objectStartArray.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/objectStartArray.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -128,8 +128,6 @@ // When doing MT offsets, we can't assert this. //assert(offset > *block, "Found backwards allocation"); *block = (jbyte)offset; - - // tty->print_cr("[%p]", p); } // Optimized for finding the first object that crosses into diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -264,7 +264,7 @@ cm->set_region_stack(ParCompactionManager::region_list(which_stack_index)); if (TraceDynamicGCThreads) { gclog_or_tty->print_cr("StealRegionCompactionTask::do_it " - "region_stack_index %d region_stack = 0x%x " + "region_stack_index %d region_stack = " PTR_FORMAT " " " empty (%d) use all workers %d", which_stack_index, ParCompactionManager::region_list(which_stack_index), cm->region_stack()->is_empty(), @@ -366,7 +366,7 @@ if (TraceDynamicGCThreads) { void* old_region_stack = (void*) cm->region_stack(); int old_region_stack_index = cm->region_stack_index(); - gclog_or_tty->print_cr("Pushing region stack 0x%x/%d", + gclog_or_tty->print_cr("Pushing region stack " PTR_FORMAT "/%d", old_region_stack, old_region_stack_index); } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -379,7 +379,7 @@ gclog_or_tty->print_cr( "PSAdaptiveSizePolicy::compute_eden_space_size: gc time limit" " gc_cost: %f " - " GCTimeLimit: %d", + " GCTimeLimit: " UINTX_FORMAT, gc_cost(), GCTimeLimit); } } @@ -586,7 +586,7 @@ gclog_or_tty->print_cr( "PSAdaptiveSizePolicy::compute_old_gen_free_space: gc time limit" " gc_cost: %f " - " GCTimeLimit: %d", + " GCTimeLimit: " UINTX_FORMAT, gc_cost(), GCTimeLimit); } } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -270,7 +270,8 @@ gclog_or_tty->print_cr(" collection: %d ", heap->total_collections()); if (Verbose) { - gclog_or_tty->print("old_gen_capacity: %d young_gen_capacity: %d", + gclog_or_tty->print("old_gen_capacity: " SIZE_FORMAT + " young_gen_capacity: " SIZE_FORMAT, old_gen->capacity_in_bytes(), young_gen->capacity_in_bytes()); } } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -1428,7 +1428,7 @@ "space_cap=" SIZE_FORMAT, space_live, space_used, space_capacity); - tty->print_cr("dead_wood_limiter(%6.4f, %d)=%6.4f " + tty->print_cr("dead_wood_limiter(%6.4f, " SIZE_FORMAT ")=%6.4f " "dead_wood_max=" SIZE_FORMAT " dead_wood_limit=" SIZE_FORMAT, density, min_percent_free, limiter, dead_wood_max, dead_wood_limit); @@ -2106,7 +2106,8 @@ gclog_or_tty->print_cr(" collection: %d ", heap->total_collections()); if (Verbose) { - gclog_or_tty->print("old_gen_capacity: %d young_gen_capacity: %d", + gclog_or_tty->print("old_gen_capacity: " SIZE_FORMAT + " young_gen_capacity: " SIZE_FORMAT, old_gen->capacity_in_bytes(), young_gen->capacity_in_bytes()); } } @@ -2559,7 +2560,7 @@ if (TraceParallelOldGCCompactionPhase) { if (Verbose && (fillable_regions & 7) != 0) gclog_or_tty->cr(); - gclog_or_tty->print_cr("%u initially fillable regions", fillable_regions); + gclog_or_tty->print_cr(SIZE_FORMAT " initially fillable regions", fillable_regions); } } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -330,7 +330,7 @@ #ifndef PRODUCT if (TraceScavenge) { - gclog_or_tty->print_cr("{%s %s 0x%x (%d)}", + gclog_or_tty->print_cr("{%s %s " PTR_FORMAT " (%d)}", "promotion-failure", obj->klass()->internal_name(), (void *)obj, obj->size()); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -510,7 +510,8 @@ heap->total_collections()); if (Verbose) { - gclog_or_tty->print("old_gen_capacity: %d young_gen_capacity: %d", + gclog_or_tty->print("old_gen_capacity: " SIZE_FORMAT + " young_gen_capacity: " SIZE_FORMAT, old_gen->capacity_in_bytes(), young_gen->capacity_in_bytes()); } } @@ -728,7 +729,7 @@ young_gen->object_iterate(&unforward_closure); if (PrintGC && Verbose) { - gclog_or_tty->print_cr("Restoring %d marks", _preserved_oop_stack.size()); + gclog_or_tty->print_cr("Restoring " SIZE_FORMAT " marks", _preserved_oop_stack.size()); } // Restore any saved marks. diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -31,6 +31,7 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "memory/iterator.hpp" +#include "utilities/globalDefinitions.hpp" inline void PSScavenge::save_to_space_top_before_gc() { ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); @@ -178,7 +179,7 @@ #ifndef PRODUCT if (TraceScavenge) { ResourceMark rm; - gclog_or_tty->print_cr("PSScavengeKlassClosure::do_klass %p, %s, dirty: %s", + gclog_or_tty->print_cr("PSScavengeKlassClosure::do_klass " PTR_FORMAT ", %s, dirty: %s", klass, klass->external_name(), klass->has_modified_oops() ? "true" : "false"); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -168,9 +168,9 @@ if (TraceDynamicGCThreads) { gclog_or_tty->print_cr("GCTaskManager::calc_default_active_workers() : " - "active_workers(): %d new_active_workers: %d " - "prev_active_workers: %d\n" - " active_workers_by_JT: %d active_workers_by_heap_size: %d", + "active_workers(): " UINTX_FORMAT " new_active_workers: " UINTX_FORMAT " " + "prev_active_workers: " UINTX_FORMAT "\n" + " active_workers_by_JT: " UINTX_FORMAT " active_workers_by_heap_size: " UINTX_FORMAT, active_workers, new_active_workers, prev_active_workers, active_workers_by_JT, active_workers_by_heap_size); } @@ -545,12 +545,12 @@ if (UseGCOverheadLimit && PrintGCDetails && Verbose) { if (gc_overhead_limit_exceeded()) { gclog_or_tty->print_cr(" GC is exceeding overhead limit " - "of %d%%", GCTimeLimit); + "of " UINTX_FORMAT "%%", GCTimeLimit); reset_gc_overhead_limit_count(); } else if (print_gc_overhead_limit_would_be_exceeded) { assert(gc_overhead_limit_count() > 0, "Should not be printing"); gclog_or_tty->print_cr(" GC would exceed overhead limit " - "of %d%% %d consecutive time(s)", + "of " UINTX_FORMAT "%% %d consecutive time(s)", GCTimeLimit, gc_overhead_limit_count()); } } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp --- a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -120,8 +120,9 @@ float delta_ise = (CMSExtrapolateSweep ? intra_sweep_estimate : 0.0); _desired = (ssize_t)(new_rate * (inter_sweep_estimate + delta_ise)); if (PrintFLSStatistics > 1) { - gclog_or_tty->print_cr("demand: %d, old_rate: %f, current_rate: %f, new_rate: %f, old_desired: %d, new_desired: %d", - demand, old_rate, rate, new_rate, old_desired, _desired); + gclog_or_tty->print_cr("demand: " SSIZE_FORMAT ", old_rate: %f, current_rate: %f, " + "new_rate: %f, old_desired: " SSIZE_FORMAT ", new_desired: " SSIZE_FORMAT, + demand, old_rate, rate, new_rate, old_desired, _desired); } } } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -37,21 +37,10 @@ int ConcurrentGCThread::_CGC_flag = CGC_nil; -SuspendibleThreadSet ConcurrentGCThread::_sts; - ConcurrentGCThread::ConcurrentGCThread() : _should_terminate(false), _has_terminated(false) { - _sts.initialize(); }; -void ConcurrentGCThread::safepoint_synchronize() { - _sts.suspend_all(); -} - -void ConcurrentGCThread::safepoint_desynchronize() { - _sts.resume_all(); -} - void ConcurrentGCThread::create_and_start() { if (os::create_thread(this, os::cgc_thread)) { // XXX: need to set this to low priority @@ -92,78 +81,6 @@ ThreadLocalStorage::set_thread(NULL); } - -void SuspendibleThreadSet::initialize_work() { - MutexLocker x(STS_init_lock); - if (!_initialized) { - _m = new Monitor(Mutex::leaf, - "SuspendibleThreadSetLock", true); - _async = 0; - _async_stop = false; - _async_stopped = 0; - _initialized = true; - } -} - -void SuspendibleThreadSet::join() { - initialize(); - MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); - while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag); - _async++; - assert(_async > 0, "Huh."); -} - -void SuspendibleThreadSet::leave() { - assert(_initialized, "Must be initialized."); - MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); - _async--; - assert(_async >= 0, "Huh."); - if (_async_stop) _m->notify_all(); -} - -void SuspendibleThreadSet::yield(const char* id) { - assert(_initialized, "Must be initialized."); - if (_async_stop) { - MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); - if (_async_stop) { - _async_stopped++; - assert(_async_stopped > 0, "Huh."); - if (_async_stopped == _async) { - if (ConcGCYieldTimeout > 0) { - double now = os::elapsedTime(); - guarantee((now - _suspend_all_start) * 1000.0 < - (double)ConcGCYieldTimeout, - "Long delay; whodunit?"); - } - } - _m->notify_all(); - while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag); - _async_stopped--; - assert(_async >= 0, "Huh"); - _m->notify_all(); - } - } -} - -void SuspendibleThreadSet::suspend_all() { - initialize(); // If necessary. - if (ConcGCYieldTimeout > 0) { - _suspend_all_start = os::elapsedTime(); - } - MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); - assert(!_async_stop, "Only one at a time."); - _async_stop = true; - while (_async_stopped < _async) _m->wait(Mutex::_no_safepoint_check_flag); -} - -void SuspendibleThreadSet::resume_all() { - assert(_initialized, "Must be initialized."); - MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); - assert(_async_stopped == _async, "Huh."); - _async_stop = false; - _m->notify_all(); -} - static void _sltLoop(JavaThread* thread, TRAPS) { SurrogateLockerThread* slt = (SurrogateLockerThread*)thread; slt->loop(); @@ -283,30 +200,3 @@ } assert(!_monitor.owned_by_self(), "Should unlock before exit."); } - - -// ===== STS Access From Outside CGCT ===== - -void ConcurrentGCThread::stsYield(const char* id) { - assert( Thread::current()->is_ConcurrentGC_thread(), - "only a conc GC thread can call this" ); - _sts.yield(id); -} - -bool ConcurrentGCThread::stsShouldYield() { - assert( Thread::current()->is_ConcurrentGC_thread(), - "only a conc GC thread can call this" ); - return _sts.should_yield(); -} - -void ConcurrentGCThread::stsJoin() { - assert( Thread::current()->is_ConcurrentGC_thread(), - "only a conc GC thread can call this" ); - _sts.join(); -} - -void ConcurrentGCThread::stsLeave() { - assert( Thread::current()->is_ConcurrentGC_thread(), - "only a conc GC thread can call this" ); - _sts.leave(); -} diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp --- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -26,55 +26,8 @@ #define SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS +#include "gc_implementation/shared/suspendibleThreadSet.hpp" #include "runtime/thread.hpp" -#endif // INCLUDE_ALL_GCS - -class VoidClosure; - -// A SuspendibleThreadSet is (obviously) a set of threads that can be -// suspended. A thread can join and later leave the set, and periodically -// yield. If some thread (not in the set) requests, via suspend_all, that -// the threads be suspended, then the requesting thread is blocked until -// all the threads in the set have yielded or left the set. (Threads may -// not enter the set when an attempted suspension is in progress.) The -// suspending thread later calls resume_all, allowing the suspended threads -// to continue. - -class SuspendibleThreadSet { - Monitor* _m; - int _async; - bool _async_stop; - int _async_stopped; - bool _initialized; - double _suspend_all_start; - - void initialize_work(); - - public: - SuspendibleThreadSet() : _initialized(false) {} - - // Add the current thread to the set. May block if a suspension - // is in progress. - void join(); - // Removes the current thread from the set. - void leave(); - // Returns "true" iff an suspension is in progress. - bool should_yield() { return _async_stop; } - // Suspends the current thread if a suspension is in progress (for - // the duration of the suspension.) - void yield(const char* id); - // Return when all threads in the set are suspended. - void suspend_all(); - // Allow suspended threads to resume. - void resume_all(); - // Redundant initializations okay. - void initialize() { - // Double-check dirty read idiom. - if (!_initialized) initialize_work(); - } -}; - class ConcurrentGCThread: public NamedThread { friend class VMStructs; @@ -96,9 +49,6 @@ static int set_CGC_flag(int b) { return _CGC_flag |= b; } static int reset_CGC_flag(int b) { return _CGC_flag &= ~b; } - // All instances share this one set. - static SuspendibleThreadSet _sts; - // Create and start the thread (setting it's priority high.) void create_and_start(); @@ -121,25 +71,6 @@ // Tester bool is_ConcurrentGC_thread() const { return true; } - - static void safepoint_synchronize(); - static void safepoint_desynchronize(); - - // All overridings should probably do _sts::yield, but we allow - // overriding for distinguished debugging messages. Default is to do - // nothing. - virtual void yield() {} - - bool should_yield() { return _sts.should_yield(); } - - // they are prefixed by sts since there are already yield() and - // should_yield() (non-static) methods in this class and it was an - // easy way to differentiate them. - static void stsYield(const char* id); - static bool stsShouldYield(); - static void stsJoin(); - static void stsLeave(); - }; // The SurrogateLockerThread is used by concurrent GC threads for diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -131,7 +131,7 @@ assert(_preserved_oop_stack.size() == _preserved_mark_stack.size(), "inconsistent preserved oop stacks"); if (PrintGC && Verbose) { - gclog_or_tty->print_cr("Restoring %d marks", + gclog_or_tty->print_cr("Restoring " SIZE_FORMAT " marks", _preserved_count + _preserved_oop_stack.size()); } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -888,7 +888,9 @@ for (int i = 0; i < lgrp_spaces()->length(); i++) { lgrp_spaces()->at(i)->accumulate_statistics(page_size()); } - st->print(" local/remote/unbiased/uncommitted: %dK/%dK/%dK/%dK, large/small pages: %d/%d\n", + st->print(" local/remote/unbiased/uncommitted: " SIZE_FORMAT "K/" + SIZE_FORMAT "K/" SIZE_FORMAT "K/" SIZE_FORMAT + "K, large/small pages: " SIZE_FORMAT "/" SIZE_FORMAT "\n", ls->space_stats()->_local_space / K, ls->space_stats()->_remote_space / K, ls->space_stats()->_unbiased_space / K, diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -27,6 +27,7 @@ #include "memory/sharedHeap.hpp" #include "oops/arrayOop.hpp" #include "oops/oop.inline.hpp" +#include "utilities/globalDefinitions.hpp" ParGCAllocBuffer::ParGCAllocBuffer(size_t desired_plab_sz_) : _word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL), @@ -112,7 +113,7 @@ } _used = _allocated - _wasted - _unused; size_t plab_sz = _used/(target_refills*no_of_gc_workers); - if (PrintPLAB) gclog_or_tty->print(" (plab_sz = %d ", plab_sz); + if (PrintPLAB) gclog_or_tty->print(" (plab_sz = " SIZE_FORMAT " ", plab_sz); // Take historical weighted average _filter.sample(plab_sz); // Clip from above and below, and align to object boundary @@ -120,7 +121,7 @@ plab_sz = MIN2(max_size(), plab_sz); plab_sz = align_object_size(plab_sz); // Latch the result - if (PrintPLAB) gclog_or_tty->print(" desired_plab_sz = %d) ", plab_sz); + if (PrintPLAB) gclog_or_tty->print(" desired_plab_sz = " SIZE_FORMAT ") ", plab_sz); _desired_plab_sz = plab_sz; // Now clear the accumulators for next round: // note this needs to be fixed in the case where we @@ -132,8 +133,9 @@ #ifndef PRODUCT void ParGCAllocBuffer::print() { - gclog_or_tty->print("parGCAllocBuffer: _bottom: %p _top: %p _end: %p _hard_end: %p" - "_retained: %c _retained_filler: [%p,%p)\n", + gclog_or_tty->print("parGCAllocBuffer: _bottom: " PTR_FORMAT " _top: " PTR_FORMAT + " _end: " PTR_FORMAT " _hard_end: " PTR_FORMAT " _retained: %c" + " _retained_filler: [" PTR_FORMAT "," PTR_FORMAT ")\n", _bottom, _top, _end, _hard_end, "FT"[_retained], _retained_filler.start(), _retained_filler.end()); } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp --- a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -60,6 +60,7 @@ // Initializes the buffer to be empty, but with the given "word_sz". // Must get initialized with "set_buf" for an allocation to succeed. ParGCAllocBuffer(size_t word_sz); + virtual ~ParGCAllocBuffer() {} static const size_t min_size() { return ThreadLocalAllocBuffer::min_size(); @@ -113,7 +114,7 @@ } // Sets the space of the buffer to be [buf, space+word_sz()). - void set_buf(HeapWord* buf) { + virtual void set_buf(HeapWord* buf) { _bottom = buf; _top = _bottom; _hard_end = _bottom + word_sz(); @@ -158,7 +159,7 @@ // Fills in the unallocated portion of the buffer with a garbage object. // If "end_of_gc" is TRUE, is after the last use in the GC. IF "retain" // is true, attempt to re-use the unused portion in the next GC. - void retire(bool end_of_gc, bool retain); + virtual void retire(bool end_of_gc, bool retain); void print() PRODUCT_RETURN; }; @@ -238,14 +239,14 @@ void undo_allocation(HeapWord* obj, size_t word_sz); - void set_buf(HeapWord* buf_start) { + virtual void set_buf(HeapWord* buf_start) { ParGCAllocBuffer::set_buf(buf_start); _true_end = _hard_end; _bt.set_region(MemRegion(buf_start, word_sz())); _bt.initialize_threshold(); } - void retire(bool end_of_gc, bool retain); + virtual void retire(bool end_of_gc, bool retain); MemRegion range() { return MemRegion(_top, _true_end); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -84,7 +84,7 @@ assert(ZapUnusedHeapArea, "Mangling should not be in use"); #ifdef ASSERT if(TraceZapUnusedHeapArea) { - gclog_or_tty->print("Mangling [0x%x to 0x%x)", mr.start(), mr.end()); + gclog_or_tty->print("Mangling [" PTR_FORMAT " to " PTR_FORMAT ")", mr.start(), mr.end()); } Copy::fill_to_words(mr.start(), mr.word_size(), badHeapWord); if(TraceZapUnusedHeapArea) { diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/shared/suspendibleThreadSet.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/thread.inline.hpp" + +uint SuspendibleThreadSet::_nthreads = 0; +uint SuspendibleThreadSet::_nthreads_stopped = 0; +bool SuspendibleThreadSet::_suspend_all = false; +double SuspendibleThreadSet::_suspend_all_start = 0.0; + +void SuspendibleThreadSet::join() { + MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); + while (_suspend_all) { + ml.wait(Mutex::_no_safepoint_check_flag); + } + _nthreads++; +} + +void SuspendibleThreadSet::leave() { + MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); + assert(_nthreads > 0, "Invalid"); + _nthreads--; + if (_suspend_all) { + ml.notify_all(); + } +} + +void SuspendibleThreadSet::yield() { + if (_suspend_all) { + MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); + if (_suspend_all) { + _nthreads_stopped++; + if (_nthreads_stopped == _nthreads) { + if (ConcGCYieldTimeout > 0) { + double now = os::elapsedTime(); + guarantee((now - _suspend_all_start) * 1000.0 < (double)ConcGCYieldTimeout, "Long delay"); + } + } + ml.notify_all(); + while (_suspend_all) { + ml.wait(Mutex::_no_safepoint_check_flag); + } + assert(_nthreads_stopped > 0, "Invalid"); + _nthreads_stopped--; + ml.notify_all(); + } + } +} + +void SuspendibleThreadSet::synchronize() { + assert(Thread::current()->is_VM_thread(), "Must be the VM thread"); + if (ConcGCYieldTimeout > 0) { + _suspend_all_start = os::elapsedTime(); + } + MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); + assert(!_suspend_all, "Only one at a time"); + _suspend_all = true; + while (_nthreads_stopped < _nthreads) { + ml.wait(Mutex::_no_safepoint_check_flag); + } +} + +void SuspendibleThreadSet::desynchronize() { + assert(Thread::current()->is_VM_thread(), "Must be the VM thread"); + MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); + assert(_nthreads_stopped == _nthreads, "Invalid"); + _suspend_all = false; + ml.notify_all(); +} diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP +#define SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP + +#include "memory/allocation.hpp" + +// A SuspendibleThreadSet is a set of threads that can be suspended. +// A thread can join and later leave the set, and periodically yield. +// If some thread (not in the set) requests, via synchronize(), that +// the threads be suspended, then the requesting thread is blocked +// until all the threads in the set have yielded or left the set. Threads +// may not enter the set when an attempted suspension is in progress. The +// suspending thread later calls desynchronize(), allowing the suspended +// threads to continue. +class SuspendibleThreadSet : public AllStatic { +private: + static uint _nthreads; + static uint _nthreads_stopped; + static bool _suspend_all; + static double _suspend_all_start; + +public: + // Add the current thread to the set. May block if a suspension is in progress. + static void join(); + + // Removes the current thread from the set. + static void leave(); + + // Returns true if an suspension is in progress. + static bool should_yield() { return _suspend_all; } + + // Suspends the current thread if a suspension is in progress. + static void yield(); + + // Returns when all threads in the set are suspended. + static void synchronize(); + + // Resumes all suspended threads in the set. + static void desynchronize(); +}; + +class SuspendibleThreadSetJoiner : public StackObj { +public: + SuspendibleThreadSetJoiner() { + SuspendibleThreadSet::join(); + } + + ~SuspendibleThreadSetJoiner() { + SuspendibleThreadSet::leave(); + } + + bool should_yield() { + return SuspendibleThreadSet::should_yield(); + } + + void yield() { + SuspendibleThreadSet::yield(); + } +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/gc_interface/collectedHeap.hpp --- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -208,6 +208,9 @@ // This is the correct place to place such initialization methods. virtual void post_initialize() = 0; + // Stop any onging concurrent work and prepare for exit. + virtual void stop() {} + MemRegion reserved_region() const { return _reserved; } address base() const { return (address)reserved_region().start(); } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/memory/binaryTreeDictionary.cpp --- a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -1205,13 +1205,13 @@ "------------------------------------\n"); size_t total_size = total_chunk_size(debug_only(NULL)); size_t free_blocks = num_free_blocks(); - gclog_or_tty->print("Total Free Space: %d\n", total_size); - gclog_or_tty->print("Max Chunk Size: %d\n", max_chunk_size()); - gclog_or_tty->print("Number of Blocks: %d\n", free_blocks); + gclog_or_tty->print("Total Free Space: " SIZE_FORMAT "\n", total_size); + gclog_or_tty->print("Max Chunk Size: " SIZE_FORMAT "\n", max_chunk_size()); + gclog_or_tty->print("Number of Blocks: " SIZE_FORMAT "\n", free_blocks); if (free_blocks > 0) { - gclog_or_tty->print("Av. Block Size: %d\n", total_size/free_blocks); + gclog_or_tty->print("Av. Block Size: " SIZE_FORMAT "\n", total_size/free_blocks); } - gclog_or_tty->print("Tree Height: %d\n", tree_height()); + gclog_or_tty->print("Tree Height: " SIZE_FORMAT "\n", tree_height()); } // Print census information - counts, births, deaths, etc. diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/memory/defNewGeneration.cpp --- a/hotspot/src/share/vm/memory/defNewGeneration.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -44,6 +44,7 @@ #include "runtime/java.hpp" #include "runtime/thread.inline.hpp" #include "utilities/copy.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/stack.inline.hpp" // @@ -131,7 +132,7 @@ #ifndef PRODUCT if (TraceScavenge) { ResourceMark rm; - gclog_or_tty->print_cr("KlassScanClosure::do_klass %p, %s, dirty: %s", + gclog_or_tty->print_cr("KlassScanClosure::do_klass " PTR_FORMAT ", %s, dirty: %s", klass, klass->external_name(), klass->has_modified_oops() ? "true" : "false"); @@ -511,7 +512,7 @@ HeapWord* DefNewGeneration::allocate_from_space(size_t size) { HeapWord* result = NULL; if (Verbose && PrintGCDetails) { - gclog_or_tty->print("DefNewGeneration::allocate_from_space(%u):" + gclog_or_tty->print("DefNewGeneration::allocate_from_space(" SIZE_FORMAT "):" " will_fail: %s" " heap_lock: %s" " free: " SIZE_FORMAT, @@ -756,7 +757,7 @@ void DefNewGeneration::handle_promotion_failure(oop old) { if (PrintPromotionFailure && !_promotion_failed) { - gclog_or_tty->print(" (promotion failure size = " SIZE_FORMAT ") ", + gclog_or_tty->print(" (promotion failure size = %d) ", old->size()); } _promotion_failed = true; diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/memory/generation.cpp --- a/hotspot/src/share/vm/memory/generation.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/memory/generation.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -573,8 +573,8 @@ maximum_desired_capacity / (double) K); gclog_or_tty->print_cr(" " " shrink_bytes: %.1fK" - " current_shrink_factor: %d" - " new shrink factor: %d" + " current_shrink_factor: " SIZE_FORMAT + " new shrink factor: " SIZE_FORMAT " _min_heap_delta_bytes: %.1fK", shrink_bytes / (double) K, current_shrink_factor, diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/memory/sharedHeap.cpp --- a/hotspot/src/share/vm/memory/sharedHeap.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/memory/sharedHeap.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -257,7 +257,7 @@ size_t bytes_before, size_t bytes_after, size_t capacity) { - out->print(" %d%s->%d%s(%d%s)", + out->print(" " SIZE_FORMAT "%s->" SIZE_FORMAT "%s(" SIZE_FORMAT "%s)", byte_size_in_proper_unit(bytes_before), proper_unit_for_byte_size(bytes_before), byte_size_in_proper_unit(bytes_after), diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/oops/methodData.hpp --- a/hotspot/src/share/vm/oops/methodData.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/oops/methodData.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -1012,6 +1012,11 @@ static ByteSize argument_type_offset(int i) { return in_ByteSize(argument_type_local_offset(i) * DataLayout::cell_size); } + + static ByteSize return_only_size() { + return ReturnTypeEntry::size() + in_ByteSize(header_cell_count() * DataLayout::cell_size); + } + }; // CallTypeData @@ -2143,7 +2148,6 @@ static bool profile_jsr292(methodHandle m, int bci); static int profile_arguments_flag(); - static bool profile_arguments_jsr292_only(); static bool profile_all_arguments(); static bool profile_arguments_for_invoke(methodHandle m, int bci); static int profile_return_flag(); @@ -2442,6 +2446,7 @@ static bool profile_parameters_for_method(methodHandle m); static bool profile_arguments(); + static bool profile_arguments_jsr292_only(); static bool profile_return(); static bool profile_parameters(); static bool profile_return_jsr292_only(); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/opto/superword.cpp --- a/hotspot/src/share/vm/opto/superword.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/opto/superword.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -1266,8 +1266,9 @@ memops.clear(); for (DUIterator i = upper_insert_pt->outs(); upper_insert_pt->has_out(i); i++) { Node* use = upper_insert_pt->out(i); - if (!use->is_Store()) + if (use->is_Mem() && !use->is_Store()) { memops.push(use); + } } MemNode* lower_insert_pt = last; diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -1931,6 +1931,10 @@ "not just one of the generations (e.g., G1). A value of 0 " \ "denotes 'do constant GC cycles'.") \ \ + manageable(intx, CMSTriggerInterval, -1, \ + "Commence a CMS collection cycle (at least) every so many " \ + "milliseconds (0 permanently, -1 disabled)") \ + \ product(bool, UseCMSInitiatingOccupancyOnly, false, \ "Only use occupancy as a criterion for starting a CMS collection")\ \ diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/runtime/java.cpp --- a/hotspot/src/share/vm/runtime/java.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/runtime/java.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -499,6 +499,9 @@ os::infinite_sleep(); } + // Stop any ongoing concurrent GC work + Universe::heap()->stop(); + // Terminate watcher thread - must before disenrolling any periodic task if (PeriodicTask::num_tasks() > 0) WatcherThread::stop(); diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/runtime/mutexLocker.cpp --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -69,7 +69,7 @@ Monitor* SerializePage_lock = NULL; Monitor* Threads_lock = NULL; Monitor* CGC_lock = NULL; -Mutex* STS_init_lock = NULL; +Monitor* STS_lock = NULL; Monitor* SLT_lock = NULL; Monitor* iCMS_lock = NULL; Monitor* FullGCCount_lock = NULL; @@ -173,7 +173,7 @@ def(tty_lock , Mutex , event, true ); // allow to lock in VM def(CGC_lock , Monitor, special, true ); // coordinate between fore- and background GC - def(STS_init_lock , Mutex, leaf, true ); + def(STS_lock , Monitor, leaf, true ); if (UseConcMarkSweepGC) { def(iCMS_lock , Monitor, special, true ); // CMS incremental mode start/stop notification } diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/runtime/mutexLocker.hpp --- a/hotspot/src/share/vm/runtime/mutexLocker.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -79,7 +79,7 @@ // (also used by Safepoints too to block threads creation/destruction) extern Monitor* CGC_lock; // used for coordination between // fore- & background GC threads. -extern Mutex* STS_init_lock; // coordinate initialization of SuspendibleThreadSets. +extern Monitor* STS_lock; // used for joining/leaving SuspendibleThreadSet. extern Monitor* SLT_lock; // used in CMS GC for acquiring PLL extern Monitor* iCMS_lock; // CMS incremental mode start/stop notification extern Monitor* FullGCCount_lock; // in support of "concurrent" full gc diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/runtime/safepoint.cpp --- a/hotspot/src/share/vm/runtime/safepoint.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/runtime/safepoint.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -75,7 +75,7 @@ #endif #if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" -#include "gc_implementation/shared/concurrentGCThread.hpp" +#include "gc_implementation/shared/suspendibleThreadSet.hpp" #endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_globals.hpp" @@ -110,7 +110,7 @@ // more-general mechanism below. DLD (01/05). ConcurrentMarkSweepThread::synchronize(false); } else if (UseG1GC) { - ConcurrentGCThread::safepoint_synchronize(); + SuspendibleThreadSet::synchronize(); } #endif // INCLUDE_ALL_GCS @@ -486,7 +486,7 @@ if (UseConcMarkSweepGC) { ConcurrentMarkSweepThread::desynchronize(false); } else if (UseG1GC) { - ConcurrentGCThread::safepoint_desynchronize(); + SuspendibleThreadSet::desynchronize(); } #endif // INCLUDE_ALL_GCS // record this time so VMThread can keep track how much time has elapsed diff -r a77941f17614 -r 0d1f816217dc hotspot/src/share/vm/utilities/globalDefinitions.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Wed Jul 05 19:39:35 2017 +0200 @@ -1324,10 +1324,12 @@ #define PTR_FORMAT "0x%08" PRIxPTR #endif // _LP64 -#define SSIZE_FORMAT "%" PRIdPTR -#define SIZE_FORMAT "%" PRIuPTR -#define SSIZE_FORMAT_W(width) "%" #width PRIdPTR -#define SIZE_FORMAT_W(width) "%" #width PRIuPTR +#define SSIZE_FORMAT "%" PRIdPTR +#define SIZE_FORMAT "%" PRIuPTR +#define SIZE_FORMAT_HEX "0x%" PRIxPTR +#define SSIZE_FORMAT_W(width) "%" #width PRIdPTR +#define SIZE_FORMAT_W(width) "%" #width PRIuPTR +#define SIZE_FORMAT_HEX_W(width) "0x%" #width PRIxPTR #define INTX_FORMAT "%" PRIdPTR #define UINTX_FORMAT "%" PRIuPTR diff -r a77941f17614 -r 0d1f816217dc hotspot/test/TEST.groups --- a/hotspot/test/TEST.groups Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/test/TEST.groups Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -127,10 +127,12 @@ gc/6581734/Test6581734.java \ gc/7072527/TestFullGCCount.java \ gc/g1/TestHumongousAllocInitialMark.java \ + gc/g1/TestHumongousShrinkHeap.java \ gc/arguments/TestG1HeapRegionSize.java \ gc/metaspace/TestMetaspaceMemoryPool.java \ gc/arguments/TestDynMinHeapFreeRatio.java \ gc/arguments/TestDynMaxHeapFreeRatio.java \ + gc/parallelScavenge/TestDynShrinkHeap.java \ runtime/InternalApi/ThreadCpuTimesDeadlock.java \ serviceability/threads/TestFalseDeadLock.java \ compiler/tiered/NonTieredLevelsTest.java \ diff -r a77941f17614 -r 0d1f816217dc hotspot/test/gc/g1/TestGCLogMessages.java --- a/hotspot/test/gc/g1/TestGCLogMessages.java Wed Jul 05 19:38:36 2017 +0200 +++ b/hotspot/test/gc/g1/TestGCLogMessages.java Wed Jul 05 19:39:35 2017 +0200 @@ -23,7 +23,7 @@ /* * @test TestPrintGCDetails - * @bug 8035406 8027295 8035398 + * @bug 8035406 8027295 8035398 8019342 * @summary Ensure that the PrintGCDetails output for a minor GC with G1 * includes the expected necessary messages. * @key gc @@ -48,6 +48,8 @@ OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldNotContain("[Redirty Cards"); + output.shouldNotContain("[Parallel Redirty"); + output.shouldNotContain("[Redirtied Cards"); output.shouldNotContain("[Code Root Purge"); output.shouldNotContain("[String Dedup Fixup"); output.shouldNotContain("[Young Free CSet"); @@ -63,6 +65,8 @@ output = new OutputAnalyzer(pb.start()); output.shouldContain("[Redirty Cards"); + output.shouldNotContain("[Parallel Redirty"); + output.shouldNotContain("[Redirtied Cards"); output.shouldContain("[Code Root Purge"); output.shouldContain("[String Dedup Fixup"); output.shouldNotContain("[Young Free CSet"); @@ -80,6 +84,8 @@ output = new OutputAnalyzer(pb.start()); output.shouldContain("[Redirty Cards"); + output.shouldContain("[Parallel Redirty"); + output.shouldContain("[Redirtied Cards"); output.shouldContain("[Code Root Purge"); output.shouldContain("[String Dedup Fixup"); output.shouldContain("[Young Free CSet"); diff -r a77941f17614 -r 0d1f816217dc hotspot/test/gc/g1/TestHumongousShrinkHeap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/g1/TestHumongousShrinkHeap.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test TestHumongousShrinkHeap + * @bug 8036025 + * @summary Verify that heap shrinks after GC in the presence of fragmentation due to humongous objects + * @library /testlibrary + * @run main/othervm -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=50 -XX:+UseG1GC -XX:G1HeapRegionSize=1M -verbose:gc TestHumongousShrinkHeap + */ + +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryUsage; +import java.util.ArrayList; +import java.util.List; +import sun.management.ManagementFactoryHelper; +import static com.oracle.java.testlibrary.Asserts.*; + +public class TestHumongousShrinkHeap { + + public static final String MIN_FREE_RATIO_FLAG_NAME = "MinHeapFreeRatio"; + public static final String MAX_FREE_RATIO_FLAG_NAME = "MaxHeapFreeRatio"; + + private static final ArrayList> garbage = new ArrayList<>(); + private static final int PAGE_SIZE = 1024 * 1024; // 1M + private static final int PAGES_NUM = 5; + + + public static void main(String[] args) { + new TestHumongousShrinkHeap().test(); + } + + private final void test() { + System.gc(); + MemoryUsagePrinter.printMemoryUsage("init"); + + eat(); + MemoryUsagePrinter.printMemoryUsage("eaten"); + MemoryUsage muFull = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); + + free(); + MemoryUsagePrinter.printMemoryUsage("free"); + MemoryUsage muFree = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); + + assertLessThan(muFree.getCommitted(), muFull.getCommitted(), String.format( + "committed free heap size is not less than committed full heap size, heap hasn't been shrunk?%n" + + "%s = %s%n%s = %s", + MIN_FREE_RATIO_FLAG_NAME, + ManagementFactoryHelper.getDiagnosticMXBean().getVMOption(MIN_FREE_RATIO_FLAG_NAME).getValue(), + MAX_FREE_RATIO_FLAG_NAME, + ManagementFactoryHelper.getDiagnosticMXBean().getVMOption(MAX_FREE_RATIO_FLAG_NAME).getValue() + )); + } + + private void eat() { + int HumongousObjectSize = Math.round(.9f * PAGE_SIZE); + System.out.println("Will allocate objects of size=" + + MemoryUsagePrinter.humanReadableByteCount(HumongousObjectSize, true)); + + for (int i = 0; i < PAGES_NUM; i++) { + ArrayList stuff = new ArrayList<>(); + eatList(stuff, 100, HumongousObjectSize); + MemoryUsagePrinter.printMemoryUsage("eat #" + i); + garbage.add(stuff); + } + } + + private void free() { + // do not free last one list + garbage.subList(0, garbage.size() - 1).clear(); + + // do not free last one element from last list + ArrayList stuff = garbage.get(garbage.size() - 1); + stuff.subList(0, stuff.size() - 1).clear(); + System.gc(); + } + + private static void eatList(List garbage, int count, int size) { + for (int i = 0; i < count; i++) { + garbage.add(new byte[size]); + } + } +} + +/** + * Prints memory usage to standard output + */ +class MemoryUsagePrinter { + + public static String humanReadableByteCount(long bytes, boolean si) { + int unit = si ? 1000 : 1024; + if (bytes < unit) { + return bytes + " B"; + } + int exp = (int) (Math.log(bytes) / Math.log(unit)); + String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); + return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); + } + + public static void printMemoryUsage(String label) { + MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); + float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted(); + System.out.format("[%-24s] init: %-7s, used: %-7s, comm: %-7s, freeRatio ~= %.1f%%%n", + label, + humanReadableByteCount(memusage.getInit(), true), + humanReadableByteCount(memusage.getUsed(), true), + humanReadableByteCount(memusage.getCommitted(), true), + freeratio * 100 + ); + } +} diff -r a77941f17614 -r 0d1f816217dc hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test TestDynShrinkHeap + * @bug 8016479 + * @summary Verify that the heap shrinks after full GC according to the current values of the Min/MaxHeapFreeRatio flags + * @library /testlibrary + * @run main/othervm -XX:+UseAdaptiveSizePolicyWithSystemGC -XX:+UseParallelGC -XX:MinHeapFreeRatio=0 -XX:MaxHeapFreeRatio=100 -verbose:gc TestDynShrinkHeap + */ + +import com.oracle.java.testlibrary.TestDynamicVMOption; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryUsage; +import java.util.ArrayList; +import sun.management.ManagementFactoryHelper; +import static com.oracle.java.testlibrary.Asserts.*; + +public class TestDynShrinkHeap { + + public static final String MIN_FREE_RATIO_FLAG_NAME = "MinHeapFreeRatio"; + public static final String MAX_FREE_RATIO_FLAG_NAME = "MaxHeapFreeRatio"; + + private static ArrayList list = new ArrayList<>(0); + private static final int M = 1024 * 1024; // to make heap more manageable by test code + + private final TestDynamicVMOption maxRatioOption; + private final TestDynamicVMOption minRatioOption; + + public TestDynShrinkHeap() { + minRatioOption = new TestDynamicVMOption(MIN_FREE_RATIO_FLAG_NAME); + maxRatioOption = new TestDynamicVMOption(MAX_FREE_RATIO_FLAG_NAME); + } + + private final void test() { + System.gc(); + MemoryUsagePrinter.printMemoryUsage("init"); + + eat(); + MemoryUsagePrinter.printMemoryUsage("eaten"); + MemoryUsage muFull = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); + + free(); + MemoryUsagePrinter.printMemoryUsage("free"); + MemoryUsage muFree = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); + + assertLessThan(muFree.getCommitted(), muFull.getCommitted(), String.format( + "committed free heap size is not less than committed full heap size, heap hasn't been shrunk?%n" + + "%s = %s%n%s = %s", + MIN_FREE_RATIO_FLAG_NAME, + ManagementFactoryHelper.getDiagnosticMXBean().getVMOption(MIN_FREE_RATIO_FLAG_NAME).getValue(), + MAX_FREE_RATIO_FLAG_NAME, + ManagementFactoryHelper.getDiagnosticMXBean().getVMOption(MAX_FREE_RATIO_FLAG_NAME).getValue() + )); + } + + private void eat() { + for (int i = 0; i < M; i++) { + list.add(new byte[1024]); + } + MemoryUsagePrinter.printMemoryUsage("allocated " + M + " arrays"); + + list.subList(0, M / 2).clear(); + System.gc(); + MemoryUsagePrinter.printMemoryUsage("array halved"); + } + + private void free() { + maxRatioOption.setIntValue(minRatioOption.getIntValue() + 1); + System.gc(); + MemoryUsagePrinter.printMemoryUsage("under pressure"); + } + + public static void main(String[] args) { + new TestDynShrinkHeap().test(); + } +} + +/** + * Prints memory usage to standard output + */ +class MemoryUsagePrinter { + + public static String humanReadableByteCount(long bytes, boolean si) { + int unit = si ? 1000 : 1024; + if (bytes < unit) { + return bytes + " B"; + } + int exp = (int) (Math.log(bytes) / Math.log(unit)); + String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); + return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); + } + + public static void printMemoryUsage(String label) { + MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); + float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted(); + System.out.format("[%-24s] init: %-7s, used: %-7s, comm: %-7s, freeRatio ~= %.1f%%%n", + label, + humanReadableByteCount(memusage.getInit(), true), + humanReadableByteCount(memusage.getUsed(), true), + humanReadableByteCount(memusage.getCommitted(), true), + freeratio * 100 + ); + } +} diff -r a77941f17614 -r 0d1f816217dc hotspot/test/runtime/6925573/SortMethodsTest.java --- a/hotspot/test/runtime/6925573/SortMethodsTest.java Wed Jul 05 19:38:36 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.StringWriter; - -import java.lang.reflect.Method; -import java.net.URI; -import java.util.Arrays; -import java.util.Vector; - -import javax.tools.Diagnostic; -import javax.tools.DiagnosticCollector; -import javax.tools.FileObject; -import javax.tools.ForwardingJavaFileManager; -import javax.tools.JavaCompiler; -import javax.tools.JavaCompiler.CompilationTask; -import javax.tools.JavaFileManager; -import javax.tools.JavaFileObject; -import javax.tools.JavaFileObject.Kind; -import javax.tools.SimpleJavaFileObject; -import javax.tools.StandardJavaFileManager; -import javax.tools.ToolProvider; - -/* - * @ignore 6959423 - * @test SortMethodsTest - * @bug 6925573 - * @summary verify that class loading does not need quadratic time with regard to the number of class -methods. - * @run main SortMethodsTest - * @author volker.simonis@gmail.com -*/ - -public class SortMethodsTest { - - static String createClass(String name, int nrOfMethods) { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - pw.println("public class " + name + "{"); - for (int i = 0; i < nrOfMethods; i++) { - pw.println(" public void m" + i + "() {}"); - } - pw.println(" public static String sayHello() {"); - pw.println(" return \"Hello from class \" + " + name + - ".class.getName() + \" with \" + " + name + - ".class.getDeclaredMethods().length + \" methods\";"); - pw.println(" }"); - pw.println("}"); - pw.close(); - return sw.toString(); - } - - public static void main(String args[]) { - - JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); - DiagnosticCollector diags = new DiagnosticCollector(); - final String cName = new String("ManyMethodsClass"); - Vector results = new Vector(); - - for (int i = 6; i < 600000; i*=10) { - String klass = createClass(cName, i); - JavaMemoryFileObject file = new JavaMemoryFileObject(cName, klass); - MemoryFileManager mfm = new MemoryFileManager(comp.getStandardFileManager(diags, null, null), file); - CompilationTask task = comp.getTask(null, mfm, diags, null, null, Arrays.asList(file)); - - if (task.call()) { - try { - MemoryClassLoader mcl = new MemoryClassLoader(file); - long start = System.nanoTime(); - Class c = Class.forName(cName, true, mcl); - long end = System.nanoTime(); - results.add(end - start); - Method m = c.getDeclaredMethod("sayHello", new Class[0]); - String ret = (String)m.invoke(null, new Object[0]); - System.out.println(ret + " (loaded and resloved in " + (end - start) + "ns)"); - } catch (Exception e) { - System.err.println(e); - } - } - else { - System.out.println(klass); - System.out.println(); - for (Diagnostic diag : diags.getDiagnostics()) { - System.out.println(diag.getCode() + "\n" + diag.getKind() + "\n" + diag.getPosition()); - System.out.println(diag.getSource() + "\n" + diag.getMessage(null)); - } - } - } - - long lastRatio = 0; - for (int i = 2; i < results.size(); i++) { - long normalized1 = Math.max(results.get(i-1) - results.get(0), 1); - long normalized2 = Math.max(results.get(i) - results.get(0), 1); - long ratio = normalized2/normalized1; - lastRatio = ratio; - System.out.println("10 x more methods requires " + ratio + " x more time"); - } - // The following is just vague estimation but seems to work on current x86_64 and sparcv9 machines - if (lastRatio > 80) { - throw new RuntimeException("ATTENTION: it seems that class loading needs quadratic time with regard to the number of class methods!!!"); - } - } -} - -class JavaMemoryFileObject extends SimpleJavaFileObject { - - private final String code; - private ByteArrayOutputStream byteCode; - - JavaMemoryFileObject(String name, String code) { - super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE); - this.code = code; - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return code; - } - - @Override - public OutputStream openOutputStream() { - byteCode = new ByteArrayOutputStream(); - return byteCode; - } - - byte[] getByteCode() { - return byteCode.toByteArray(); - } -} - -class MemoryClassLoader extends ClassLoader { - - private final JavaMemoryFileObject jfo; - - public MemoryClassLoader(JavaMemoryFileObject jfo) { - this.jfo = jfo; - } - - public Class findClass(String name) { - byte[] b = jfo.getByteCode(); - return defineClass(name, b, 0, b.length); - } -} - -class MemoryFileManager extends ForwardingJavaFileManager { - - private final JavaFileObject jfo; - - public MemoryFileManager(StandardJavaFileManager jfm, JavaFileObject jfo) { - super(jfm); - this.jfo = jfo; - } - - @Override - public FileObject getFileForInput(Location location, String packageName, - String relativeName) throws IOException { - return jfo; - } - - @Override - public JavaFileObject getJavaFileForOutput(Location location, String qualifiedName, - Kind kind, FileObject outputFile) throws IOException { - return jfo; - } - -} diff -r a77941f17614 -r 0d1f816217dc hotspot/test/runtime/classFileParserBug/ClassFileParserBug.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/classFileParserBug/ClassFileParserBug.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8040018 + * @library /testlibrary + * @summary Check for exception instead of assert. + * @run main ClassFileParserBug + */ + +import java.io.File; +import com.oracle.java.testlibrary.*; + +public class ClassFileParserBug { + public static void main(String args[]) throws Throwable { + + System.out.println("Regression test for bug 8040018"); + String testsrc = System.getProperty("test.src") + "/"; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-jar", testsrc + File.separator + "test.jar"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("java.lang.ClassFormatError: Bad length on BootstrapMethods"); + output.shouldHaveExitValue(1); + } +} diff -r a77941f17614 -r 0d1f816217dc hotspot/test/runtime/classFileParserBug/LambdaMath.jcod --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/classFileParserBug/LambdaMath.jcod Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This test contains a BootstrapMethods attribute with a fuzzied + * attribute_length field that is larger than it should be. This + * should cause a java.lang.ClassFormatError exception to be thrown. + */ +class LambdaMath { + 0xCAFEBABE; + 0; // minor version + 52; // version + [162] { // Constant Pool + ; // first element is empty + Method #31 #69; // #1 at 0x0A + class #70; // #2 at 0x0F + Method #2 #71; // #3 at 0x12 + Method #72 #73; // #4 at 0x17 + Field #74 #75; // #5 at 0x1C + String #76; // #6 at 0x21 + Method #77 #78; // #7 at 0x24 + InvokeDynamic 0s #84; // #8 at 0x29 + Method #30 #85; // #9 at 0x2E + String #86; // #10 at 0x33 + InvokeDynamic 1s #84; // #11 at 0x36 + String #88; // #12 at 0x3B + InvokeDynamic 2s #84; // #13 at 0x3E + String #90; // #14 at 0x43 + InvokeDynamic 3s #84; // #15 at 0x46 + String #92; // #16 at 0x4B + InvokeDynamic 4s #84; // #17 at 0x4E + InterfaceMethod #94 #95; // #18 at 0x53 + InterfaceMethod #96 #97; // #19 at 0x58 + InterfaceMethod #96 #98; // #20 at 0x5D + InterfaceMethod #99 #100; // #21 at 0x62 + class #101; // #22 at 0x67 + Method #22 #69; // #23 at 0x6A + Method #22 #102; // #24 at 0x6F + String #103; // #25 at 0x74 + Method #22 #104; // #26 at 0x77 + Method #22 #105; // #27 at 0x7C + class #106; // #28 at 0x81 + Method #2 #107; // #29 at 0x84 + class #108; // #30 at 0x89 + class #109; // #31 at 0x8C + Utf8 ""; // #32 at 0x8F + Utf8 "()V"; // #33 at 0x98 + Utf8 "Code"; // #34 at 0x9E + Utf8 "LineNumberTable"; // #35 at 0xA5 + Utf8 "LocalVariableTable"; // #36 at 0xB7 + Utf8 "this"; // #37 at 0xCC + Utf8 "LLambdaMath;"; // #38 at 0xD3 + Utf8 "main"; // #39 at 0xE2 + Utf8 "([Ljava/lang/String;)V"; // #40 at 0xE9 + Utf8 "a"; // #41 at 0x0102 + Utf8 "[Ljava/lang/String;"; // #42 at 0x0106 + Utf8 "list"; // #43 at 0x011C + Utf8 "Ljava/util/List;"; // #44 at 0x0123 + Utf8 "LocalVariableTypeTable"; // #45 at 0x0136 + Utf8 "Ljava/util/List;"; // #46 at 0x014F + Utf8 "evaluate"; // #47 at 0x0177 + Utf8 "(Ljava/util/List;Ljava/util/function/Predicate;)V"; // #48 at 0x0182 + Utf8 "n"; // #49 at 0x01B6 + Utf8 "Ljava/lang/Integer;"; // #50 at 0x01BA + Utf8 "e"; // #51 at 0x01D0 + Utf8 "Ljava/lang/Throwable;"; // #52 at 0x01D4 + Utf8 "predicate"; // #53 at 0x01EC + Utf8 "Ljava/util/function/PrediCate;"; // #54 at 0x01F8 + Utf8 "Ljava/util/function/Predicate;"; // #55 at 0x0219 + Utf8 "StackMapTable"; // #56 at 0x024F + class #110; // #57 at 0x025F + class #106; // #58 at 0x0262 + Utf8 "Signature"; // #59 at 0x0265 + Utf8 "(Ljava/util/List;Ljava/util/function/Predicate;)V"; // #60 at 0x0271 + Utf8 "lambda$main$4"; // #61 at 0x02CF + Utf8 "(Ljava/lang/Integer;)Z"; // #62 at 0x02DF + Utf8 "lambda$main$3"; // #63 at 0x02F8 + Utf8 "lambda$main$2"; // #64 at 0x0308 + Utf8 "lambda$main$1"; // #65 at 0x0318 + Utf8 "lambda$main$0"; // #66 at 0x0328 + Utf8 "SourceFile"; // #67 at 0x0338 + Utf8 "LambdaMath.java"; // #68 at 0x0345 + NameAndType #32 #33; // #69 at 0x0357 + Utf8 "java/lang/Integer"; // #70 at 0x035C + NameAndType #111 #112; // #71 at 0x0370 + class #113; // #72 at 0x0375 + NameAndType #114 #115; // #73 at 0x0378 + class #116; // #74 at 0x037D + NameAndType #117 #118; // #75 at 0x0380 + Utf8 "Print all numbers:"; // #76 at 0x0385 + class #119; // #77 at 0x039A + NameAndType #120 #121; // #78 at 0x039D + Utf8 "BootstrapMethods"; // #79 at 0x03A2 + MethodHandle 6b #122; // #80 at 0x03B5 + MethodType #123; // #81 at 0x03B9 + MethodHandle 6b #124; // #82 at 0x03BC + MethodType #62; // #83 at 0x03C0 + NameAndType #125 #126; // #84 at 0x03C3 + NameAndType #47 #48; // #85 at 0x03C8 + Utf8 "Print no numbers:"; // #86 at 0x03CD + MethodHandle 6b #127; // #87 at 0x03E1 + Utf8 "Print even numbers:"; // #88 at 0x03E5 + MethodHandle 6b #128; // #89 at 0x03FB + Utf8 "Print odd numbers:"; // #90 at 0x03FF + MethodHandle 6b #129; // #91 at 0x0414 + Utf8 "Print numbers greater than 5:"; // #92 at 0x0418 + MethodHandle 6b #130; // #93 at 0x0438 + class #131; // #94 at 0x043C + NameAndType #132 #133; // #95 at 0x043F + class #110; // #96 at 0x0444 + NameAndType #134 #135; // #97 at 0x0447 + NameAndType #136 #137; // #98 at 0x044C + class #138; // #99 at 0x0451 + NameAndType #125 #123; // #100 at 0x0454 + Utf8 "java/lang/StringFuilder"; // #101 at 0x0459 + NameAndType #139 #140; // #102 at 0x0473 + Utf8 " "; // #103 at 0x0478 + NameAndType #139 #141; // #104 at 0x047C + NameAndType #142 #143; // #105 at 0x0481 + Utf8 "java/lang/Throwable"; // #106 at 0x0486 + NameAndType #144 #145; // #107 at 0x049C + Utf8 "LambdaMath"; // #108 at 0x04A1 + Utf8 "java/lang/Object"; // #109 at 0x04AE + Utf8 "java/util/Iterator"; // #110 at 0x04C1 + Utf8 "valueOf"; // #111 at 0x04D6 + Utf8 "(I)Ljava/lang/Integer;"; // #112 at 0x04E0 + Utf8 "java/util/Arrays"; // #113 at 0x04F9 + Utf8 "asList"; // #114 at 0x050C + Utf8 "([Ljava/lang/Object;)Ljava/util/List;"; // #115 at 0x0515 + Utf8 "java/lang/System"; // #116 at 0x053D + Utf8 "out"; // #117 at 0x0550 + Utf8 "Ljava/io/PrintStream;"; // #118 at 0x0556 + Utf8 "java/io/PrintStream"; // #119 at 0x056E + Utf8 "println"; // #120 at 0x0584 + Utf8 "(Ljava/lang/String;)V"; // #121 at 0x058E + Method #146 #147; // #122 at 0x05A6 + Utf8 "(Ljava/lang/Object;)Z"; // #123 at 0x05AB + Method #30 #148; // #124 at 0x05C3 + Utf8 "test"; // #125 at 0x05C8 + Utf8 "()Ljava/util/function/Predicate;"; // #126 at 0x05CF + Method #30 #149; // #127 at 0x05F2 + Method #30 #150; // #128 at 0x05F7 + Method #30 #151; // #129 at 0x05FC + Method #30 #152; // #130 at 0x0601 + Utf8 "java/util/List"; // #131 at 0x0606 + Utf8 "iterator"; // #132 at 0x0617 + Utf8 "()Ljava/util/Iterator;"; // #133 at 0x0622 + Utf8 "hasNext"; // #134 at 0x063B + Utf8 "()Z"; // #135 at 0x0645 + Utf8 "next"; // #136 at 0x064B + Utf8 "()Ljava/lang/Object;"; // #137 at 0x0652 + Utf8 "java/util/function/Predicate"; // #138 at 0x0669 + Utf8 "append"; // #139 at 0x0688 + Utf8 "(Ljava/lang/Object;)Ljava/lang/StringBuilder;"; // #140 at 0x0691 + Utf8 "(Ljava/lang/String;)Ljava/lang/StringBuilder;"; // #141 at 0x06C1 + Utf8 "toString"; // #142 at 0x06F1 + Utf8 "()Ljava/lang/String;"; // #143 at 0x06FC + Utf8 "intValue"; // #144 at 0x0713 + Utf8 "()I"; // #145 at 0x071E + class #153; // #146 at 0x0724 + NameAndType #154 #158; // #147 at 0x0727 + NameAndType #66 #62; // #148 at 0x072C + NameAndType #65 #62; // #149 at 0x0731 + NameAndType #64 #62; // #150 at 0x0736 + NameAndType #63 #62; // #151 at 0x073B + NameAndType #61 #62; // #152 at 0x0740 + Utf8 "java/lang/invoke/LambdaMetafactory"; // #153 at 0x0745 + Utf8 "metafactory"; // #154 at 0x076A + class #160; // #155 at 0x0778 + Utf8 "Lookup"; // #156 at 0x077B + Utf8 "InnerClasses"; // #157 at 0x0784 + Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"; // #158 at 0x0793 + class #161; // #159 at 0x0862 + Utf8 "java/lang/invoke/MethodHandles$Lookup"; // #160 at 0x0865 + Utf8 "java/lang/invoke/MethodHandles"; // #161 at 0x088D + } // Constant Pool + + 0x0021; // access + #30;// this_cpx + #31;// super_cpx + + [0] { // Interfaces + } // Interfaces + + [0] { // fields + } // fields + + [8] { // methods + { // Member at 0x08BA + 0x0001; // access + #32; // name_cpx + #33; // sig_cpx + [1] { // Attributes + Attr(#34, 47) { // Code at 0x08C2 + 1; // max_stack + 1; // max_locals + Bytes[5]{ + 0x2AB70001B1; + }; + [0] { // Traps + } // end Traps + [2] { // Attributes + Attr(#35, 6) { // LineNumberTable at 0x08D9 + [1] { // LineNumberTable + 0 5; // at 0x08E5 + } + } // end LineNumberTable + ; + Attr(#36, 12) { // LocalVariableTable at 0x08E5 + [1] { // LocalVariableTable + 0 5 37 38 0; // at 0x08F7 + } + } // end LocalVariableTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x08F7 + 0x0009; // access + #39; // name_cpx + #40; // sig_cpx + [1] { // Attributes + Attr(#34, 261) { // Code at 0x08FF + 4; // max_stack + 2; // max_locals + Bytes[147]{ + 0x1007BD0002590304; + 0xB8000353590405B8; + 0x000353590506B800; + 0x0353590607B80003; + 0x53590708B8000353; + 0x59081006B8000353; + 0x5910061007B80003; + 0x53B800044CB20005; + 0x1206B600072BBA00; + 0x080000B80009B200; + 0x05120AB600072BBA; + 0x000B0000B80009B2; + 0x0005120CB600072B; + 0xBA000D0000B80009; + 0xB20005120EB60007; + 0x2BBA000F0000B800; + 0x09B200051210B600; + 0x072BBA00110000B8; + 0x0009B1; + }; + [0] { // Traps + } // end Traps + [3] { // Attributes + Attr(#35, 50) { // LineNumberTable at 0x09A4 + [12] { // LineNumberTable + 0 9; // at 0x09B0 + 61 11; // at 0x09B4 + 69 12; // at 0x09B8 + 78 14; // at 0x09BC + 86 15; // at 0x09C0 + 95 17; // at 0x09C4 + 103 18; // at 0x09C8 + 112 20; // at 0x09CC + 120 21; // at 0x09D0 + 129 23; // at 0x09D4 + 137 24; // at 0x09D8 + 146 26; // at 0x09DC + } + } // end LineNumberTable + ; + Attr(#36, 22) { // LocalVariableTable at 0x09DC + [2] { // LocalVariableTable + 0 147 41 42 0; // at 0x09EE + 61 86 43 44 1; // at 0x09F8 + } + } // end LocalVariableTable + ; + Attr(#45, 12) { // LocalVariableTypeTable at 0x09F8 + [1] { // LocalVariableTypeTable + 61 86 43 46 1; // at 0x0A0A + } + } // end LocalVariableTypeTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x0A0A + 0x0009; // access + #47; // name_cpx + #48; // sig_cpx + [2] { // Attributes + Attr(#34, 224) { // Code at 0x0A12 + 3; // max_stack + 4; // max_locals + Bytes[69]{ + 0x2AB9001201004D2C; + 0xB900130100990033; + 0x2CB900140100C200; + 0x024E2B2DB9001502; + 0x0099001CB20005BB; + 0x001659B700172DB6; + 0x00181219B6001AB6; + 0x001BB60007A7FFCA; + 0xA700044DB1; + }; + [1] { // Traps + 0 64 67 28; // at 0x0A6F + } // end Traps + [4] { // Attributes + Attr(#35, 30) { // LineNumberTable at 0x0A71 + [7] { // LineNumberTable + 0 30; // at 0x0A7D + 26 31; // at 0x0A81 + 36 32; // at 0x0A85 + 61 34; // at 0x0A89 + 64 38; // at 0x0A8D + 67 37; // at 0x0A91 + 68 39; // at 0x0A95 + } + } // end LineNumberTable + ; + Attr(#36, 42) { // LocalVariableTable at 0x0A95 + [4] { // LocalVariableTable + 26 35 49 50 3; // at 0x0AA7 + 68 0 51 52 2; // at 0x0AB1 + 0 69 43 44 0; // at 0x0ABB + 0 69 53 54 1; // at 0x0AC5 + } + } // end LocalVariableTable + ; + Attr(#45, 22) { // LocalVariableTypeTable at 0x0AC5 + [2] { // LocalVariableTypeTable + 0 69 43 46 0; // at 0x0AD7 + 0 69 53 55 1; // at 0x0AE1 + } + } // end LocalVariableTypeTable + ; + Attr(#56, 17) { // StackMapTable at 0x0AE1 + [5] { // + 252b, 7, [1]z{7b,57}; // append_frame 1 + 53b; // same_frame + 250b, 2; // chop_frame 1 + 66b, [1]z{7b,58}; // same_locals_1_stack_item_frame + 0b; // same_frame + } + } // end StackMapTable + } // Attributes + } // end Code + ; + Attr(#59, 2) { // Signature at 0x0AF8 + #60; + } // end Signature + } // Attributes + } // Member + ; + { // Member at 0x0B00 + 0x100A; // access + #61; // name_cpx + #62; // sig_cpx + [1] { // Attributes + Attr(#34, 67) { // Code at 0x0B08 + 2; // max_stack + 1; // max_locals + Bytes[14]{ + 0x2AB6001D08A40007; + 0x04A7000403AC; + }; + [0] { // Traps + } // end Traps + [3] { // Attributes + Attr(#35, 6) { // LineNumberTable at 0x0B28 + [1] { // LineNumberTable + 0 24; // at 0x0B34 + } + } // end LineNumberTable + ; + Attr(#36, 12) { // LocalVariableTable at 0x0B34 + [1] { // LocalVariableTable + 0 14 49 50 0; // at 0x0B46 + } + } // end LocalVariableTable + ; + Attr(#56, 5) { // StackMapTable at 0x0B46 + [2] { // + 12b; // same_frame + 64b, [1]z{1b}; // same_locals_1_stack_item_frame + } + } // end StackMapTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x0B51 + 0x100A; // access + #63; // name_cpx + #62; // sig_cpx + [1] { // Attributes + Attr(#34, 69) { // Code at 0x0B59 + 2; // max_stack + 1; // max_locals + Bytes[16]{ + 0x2AB6001D057004A0; + 0x000704A7000403AC; + }; + [0] { // Traps + } // end Traps + [3] { // Attributes + Attr(#35, 6) { // LineNumberTable at 0x0B7B + [1] { // LineNumberTable + 0 21; // at 0x0B87 + } + } // end LineNumberTable + ; + Attr(#36, 12) { // LocalVariableTable at 0x0B87 + [1] { // LocalVariableTable + 0 16 49 50 0; // at 0x0B99 + } + } // end LocalVariableTable + ; + Attr(#56, 5) { // StackMapTable at 0x0B99 + [2] { // + 14b; // same_frame + 64b, [1]z{1b}; // same_locals_1_stack_item_frame + } + } // end StackMapTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x0BA4 + 0x100A; // access + #64; // name_cpx + #62; // sig_cpx + [1] { // Attributes + Attr(#34, 68) { // Code at 0x0BAC + 2; // max_stack + 1; // max_locals + Bytes[15]{ + 0x2AB6001D05709A00; + 0x0704A7000403AC; + }; + [0] { // Traps + } // end Traps + [3] { // Attributes + Attr(#35, 6) { // LineNumberTable at 0x0BCD + [1] { // LineNumberTable + 0 18; // at 0x0BD9 + } + } // end LineNumberTable + ; + Attr(#36, 12) { // LocalVariableTable at 0x0BD9 + [1] { // LocalVariableTable + 0 15 49 50 0; // at 0x0BEB + } + } // end LocalVariableTable + ; + Attr(#56, 5) { // StackMapTable at 0x0BEB + [2] { // + 13b; // same_frame + 64b, [1]z{1b}; // same_locals_1_stack_item_frame + } + } // end StackMapTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x0BF6 + 0x100A; // access + #65; // name_cpx + #62; // sig_cpx + [1] { // Attributes + Attr(#34, 44) { // Code at 0x0BFE + 1; // max_stack + 1; // max_locals + Bytes[2]{ + 0x03AC; + }; + [0] { // Traps + } // end Traps + [2] { // Attributes + Attr(#35, 6) { // LineNumberTable at 0x0C12 + [1] { // LineNumberTable + 0 15; // at 0x0C1E + } + } // end LineNumberTable + ; + Attr(#36, 12) { // LocalVariableTable at 0x0C1E + [1] { // LocalVariableTable + 0 2 49 50 0; // at 0x0C30 + } + } // end LocalVariableTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x0C30 + 0x100A; // access + #66; // name_cpx + #62; // sig_cpx + [1] { // Attributes + Attr(#34, 44) { // Code at 0x0C38 + 1; // max_stack + 1; // max_locals + Bytes[2]{ + 0x04AC; + }; + [0] { // Traps + } // end Traps + [2] { // Attributes + Attr(#35, 6) { // LineNumberTable at 0x0C4C + [1] { // LineNumberTable + 0 12; // at 0x0C58 + } + } // end LineNumberTable + ; + Attr(#36, 12) { // LocalVariableTable at 0x0C58 + [1] { // LocalVariableTable + 0 2 49 50 0; // at 0x0C6A + } + } // end LocalVariableTable + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [3] { // Attributes + Attr(#67, 2) { // SourceFile at 0x0C6C + #68; + } // end SourceFile + ; + Attr(#157, 10) { // InnerClasses at 0x0C74 + [1] { // InnerClasses + #155 #159 #156 25; // at 0x0C84 + } + } // end InnerClasses + ; + Attr(#79, 52) { // BootstrapMethods at 0x0C84 + [5] { // bootstrap_methods + { // bootstrap_method + #80; // bootstrap_method_ref + [3] { // bootstrap_arguments + #81; // at 0x0C92 + #82; // at 0x0C94 + #83; // at 0x0C96 + } // bootstrap_arguments + } // bootstrap_method + ; + { // bootstrap_method + #80; // bootstrap_method_ref + [3] { // bootstrap_arguments + #81; // at 0x0C9C + #87; // at 0x0C9E + #83; // at 0x0CA0 + } // bootstrap_arguments + } // bootstrap_method + ; + { // bootstrap_method + #80; // bootstrap_method_ref + [3] { // bootstrap_arguments + #81; // at 0x0CA6 + #89; // at 0x0CA8 + #83; // at 0x0CAA + } // bootstrap_arguments + } // bootstrap_method + ; + { // bootstrap_method + #80; // bootstrap_method_ref + [3] { // bootstrap_arguments + #81; // at 0x0CB0 + #91; // at 0x0CB2 + #83; // at 0x0CB4 + } // bootstrap_arguments + } // bootstrap_method + ; + { // bootstrap_method + #80; // bootstrap_method_ref + [1] { // bootstrap_arguments + #81; // at 0x0CBA + } // bootstrap_arguments + } // bootstrap_method + } +// ======== attribute array started at 0x0C84 has 4 bytes more: + 0x005D0053; + } // end BootstrapMethods + } // Attributes +} // end class LambdaMath diff -r a77941f17614 -r 0d1f816217dc hotspot/test/runtime/classFileParserBug/test.jar Binary file hotspot/test/runtime/classFileParserBug/test.jar has changed diff -r a77941f17614 -r 0d1f816217dc jaxp/.hgtags --- a/jaxp/.hgtags Wed Jul 05 19:38:36 2017 +0200 +++ b/jaxp/.hgtags Wed Jul 05 19:39:35 2017 +0200 @@ -253,3 +253,4 @@ 3b360a77658e6b3ac150dd7cdbff1a7abe855afc jdk9-b08 f93a792fe37279d4d37aea86a99f3abbdc6fe79b jdk9-b09 4ce98701efe3b28f6ce3ab23385445731e968af7 jdk9-b10 +6b4280dceb00642f54d5bc1c2cb7d34c99a04992 jdk9-b11 diff -r a77941f17614 -r 0d1f816217dc jaxws/.hgtags --- a/jaxws/.hgtags Wed Jul 05 19:38:36 2017 +0200 +++ b/jaxws/.hgtags Wed Jul 05 19:39:35 2017 +0200 @@ -256,3 +256,4 @@ 2d9f4166e0be68aa43c5f4fd0f8d34768e11f652 jdk9-b08 c9e8bb8c1144a966ca7b481142c6b5e55d14a29c jdk9-b09 9af43f4d215f6f19b1767f6ac66da931b8ee9535 jdk9-b10 +1f953ba7db2b535e19f0354abfee6d67605e0684 jdk9-b11 diff -r a77941f17614 -r 0d1f816217dc jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/StaxBridge.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/StaxBridge.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/StaxBridge.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,12 @@ package com.sun.xml.internal.messaging.saaj.soap; +import com.sun.xml.internal.messaging.saaj.util.stax.SaajStaxWriter; + import javax.xml.namespace.QName; import javax.xml.soap.SOAPException; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; -import com.sun.xml.internal.org.jvnet.staxex.util.SaajStaxWriter; import com.sun.xml.internal.org.jvnet.staxex.util.XMLStreamReaderToXMLStreamWriter; diff -r a77941f17614 -r 0d1f816217dc jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxReaderEx.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxReaderEx.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.xml.internal.messaging.saaj.util.stax; + +import com.sun.xml.internal.org.jvnet.staxex.Base64Data; +import com.sun.xml.internal.org.jvnet.staxex.BinaryText; +import com.sun.xml.internal.org.jvnet.staxex.XMLStreamReaderEx; +import com.sun.xml.internal.org.jvnet.staxex.util.DOMStreamReader; +import org.w3c.dom.Node; +import org.w3c.dom.Text; + +import javax.xml.soap.SOAPElement; +import javax.xml.stream.XMLStreamException; +import java.util.Iterator; + +/** + * SaajStaxReaderEx + * + * @author shih-chang.chen@oracle.com + */ +public class SaajStaxReaderEx extends DOMStreamReader implements XMLStreamReaderEx { + //TODO extends com.sun.xml.internal.ws.streaming.DOMStreamReader + private BinaryText binaryText = null; + private Base64Data base64AttData = null; + + public SaajStaxReaderEx(SOAPElement se) { + super(se); + } + + @Override + public int next() throws XMLStreamException { + binaryText = null; + base64AttData = null; + while(true) { + int r = _next(); + switch (r) { + case CHARACTERS: + if (_current instanceof BinaryText) { + binaryText = (BinaryText) _current; + base64AttData = new Base64Data(); + base64AttData.set(binaryText.getDataHandler()); +//System.out.println("--------------- debug SaajStaxReaderEx binaryText " + binaryText); + } else { + // if we are currently at text node, make sure that this is a meaningful text node. + Node prev = _current.getPreviousSibling(); + if(prev!=null && prev.getNodeType()==Node.TEXT_NODE) + continue; // nope. this is just a continuation of previous text that should be invisible + + Text t = (Text)_current; + wholeText = t.getWholeText(); + if(wholeText.length()==0) + continue; // nope. this is empty text. + } + return CHARACTERS; + case START_ELEMENT: + splitAttributes(); + return START_ELEMENT; + default: + return r; + } + } + } + + @Override + public String getElementTextTrim() throws XMLStreamException { + // TODO Auto-generated method stub + return null; + } + + @Override + public CharSequence getPCDATA() throws XMLStreamException { + return (binaryText != null) ? base64AttData : getText(); + } + + @Override + public com.sun.xml.internal.org.jvnet.staxex.NamespaceContextEx getNamespaceContext() { + return new com.sun.xml.internal.org.jvnet.staxex.NamespaceContextEx() { + + @Override + public String getNamespaceURI(String prefix) { + return _current.lookupNamespaceURI(prefix); + } + + @Override + public String getPrefix(String uri) { + return _current.lookupPrefix(uri); + } + + @Override + public Iterator getPrefixes(String arg0) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Iterator iterator() { + // TODO Auto-generated method stub + return null; + } + + }; + } + + + @Override + public int getTextLength() { + return (binaryText != null) ? base64AttData.length() : super.getTextLength(); + } + + @Override + public int getTextStart() { + return (binaryText != null) ? 0: super.getTextStart(); + } + + @Override + public char[] getTextCharacters() { + if (binaryText != null) { + char[] chars = new char[base64AttData.length()]; + base64AttData.writeTo(chars, 0); + return chars; + } + return super.getTextCharacters(); + } +} diff -r a77941f17614 -r 0d1f816217dc jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxWriter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxWriter.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.xml.internal.messaging.saaj.util.stax; + +import java.util.Arrays; +import java.util.Iterator; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.soap.SOAPElement; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPMessage; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +import org.w3c.dom.Comment; +import org.w3c.dom.Node; + +/** + * SaajStaxWriter builds a SAAJ SOAPMessage by using XMLStreamWriter interface. + * + * @author shih-chang.chen@oracle.com + */ +public class SaajStaxWriter implements XMLStreamWriter { + + protected SOAPMessage soap; + protected String envURI; + protected SOAPElement currentElement; + + static final protected String Envelope = "Envelope"; + static final protected String Header = "Header"; + static final protected String Body = "Body"; + static final protected String xmlns = "xmlns"; + + private boolean isHeaderSeen = false; + + public SaajStaxWriter(final SOAPMessage msg, String uri) throws SOAPException { + soap = msg; + this.envURI = uri; + } + + public SOAPMessage getSOAPMessage() { + return soap; + } + + protected SOAPElement getEnvelope() throws SOAPException { + return soap.getSOAPPart().getEnvelope(); + } + + @Override + public void writeStartElement(final String localName) throws XMLStreamException { + try { + currentElement = currentElement.addChildElement(localName); + } catch (SOAPException e) { + throw new XMLStreamException(e); + } + } + + @Override + public void writeStartElement(final String ns, final String ln) throws XMLStreamException { + writeStartElement(null, ln, ns); + } + + @Override + public void writeStartElement(final String prefix, final String ln, final String ns) throws XMLStreamException { + try { + if (envURI.equals(ns)) { + if (Envelope.equals(ln)) { + currentElement = getEnvelope(); + fixPrefix(prefix); + return; + } else if (Header.equals(ln)) { + isHeaderSeen = true; + currentElement = soap.getSOAPHeader(); + fixPrefix(prefix); + return; + } else if (Body.equals(ln)) { + currentElement = soap.getSOAPBody(); + fixPrefix(prefix); + return; + } + } + currentElement = (prefix == null) ? + currentElement.addChildElement(new QName(ns, ln)) : + currentElement.addChildElement(ln, prefix, ns); + } catch (SOAPException e) { + throw new XMLStreamException(e); + } + } + + private void fixPrefix(final String prfx) throws XMLStreamException { + fixPrefix(prfx, currentElement); + } + + private void fixPrefix(final String prfx, SOAPElement element) throws XMLStreamException { + String oldPrfx = element.getPrefix(); + if (prfx != null && !prfx.equals(oldPrfx)) { + element.setPrefix(prfx); + } + } + + @Override + public void writeEmptyElement(final String uri, final String ln) throws XMLStreamException { + writeStartElement(null, ln, uri); + } + + @Override + public void writeEmptyElement(final String prefix, final String ln, final String uri) throws XMLStreamException { + writeStartElement(prefix, ln, uri); + } + + @Override + public void writeEmptyElement(final String ln) throws XMLStreamException { + writeStartElement(null, ln, null); + } + + @Override + public void writeEndElement() throws XMLStreamException { + if (currentElement != null) currentElement = currentElement.getParentElement(); + } + + @Override + public void writeEndDocument() throws XMLStreamException { + try { + if (!isHeaderSeen) { + SOAPElement header = soap.getSOAPHeader(); + if (header != null) { + String prefixAtHeader = header.getPrefix(); + SOAPElement env = getEnvelope(); + header.detachNode(); + if (prefixAtHeader != null && !prefixAtHeader.equals(env.getPrefix())) { + env.removeNamespaceDeclaration(prefixAtHeader); + } + } + } + } catch (SOAPException e) { + throw new XMLStreamException(e); + } + } + + @Override + public void close() throws XMLStreamException { + } + + @Override + public void flush() throws XMLStreamException { + } + + @Override + public void writeAttribute(final String ln, final String val) throws XMLStreamException { + writeAttribute(null, null, ln, val); + } + + @Override + public void writeAttribute(final String prefix, final String ns, final String ln, final String value) throws XMLStreamException { + try { + if (ns == null) { + if (prefix == null && xmlns.equals(ln)) { + currentElement.addNamespaceDeclaration("", value); + } else { + currentElement.setAttributeNS("", ln, value); + } + } else { + QName name = (prefix == null) ? new QName(ns, ln) : new QName(ns, ln, prefix); + currentElement.addAttribute(name, value); + } + } catch (SOAPException e) { + throw new XMLStreamException(e); + } + } + + @Override + public void writeAttribute(final String ns, final String ln, final String val) throws XMLStreamException { + writeAttribute(null, ns, ln, val); + } + + @Override + public void writeNamespace(String prefix, final String uri) throws XMLStreamException { + + // make prefix default if null or "xmlns" (according to javadoc) + if (prefix == null || "xmlns".equals(prefix)) { + prefix = ""; + } + + try { + currentElement.addNamespaceDeclaration(prefix, uri); + } catch (SOAPException e) { + throw new XMLStreamException(e); + } + } + + @Override + public void writeDefaultNamespace(final String uri) throws XMLStreamException { + writeNamespace("", uri); + } + + @Override + public void writeComment(final String data) throws XMLStreamException { + Comment c = soap.getSOAPPart().createComment(data); + currentElement.appendChild(c); + } + + @Override + public void writeProcessingInstruction(final String target) throws XMLStreamException { + Node n = soap.getSOAPPart().createProcessingInstruction(target, ""); + currentElement.appendChild(n); + } + + @Override + public void writeProcessingInstruction(final String target, final String data) throws XMLStreamException { + Node n = soap.getSOAPPart().createProcessingInstruction(target, data); + currentElement.appendChild(n); + } + + @Override + public void writeCData(final String data) throws XMLStreamException { + Node n = soap.getSOAPPart().createCDATASection(data); + currentElement.appendChild(n); + } + + @Override + public void writeDTD(final String dtd) throws XMLStreamException { + //TODO ... Don't do anything here + } + + @Override + public void writeEntityRef(final String name) throws XMLStreamException { + Node n = soap.getSOAPPart().createEntityReference(name); + currentElement.appendChild(n); + } + + @Override + public void writeStartDocument() throws XMLStreamException { + } + + @Override + public void writeStartDocument(final String version) throws XMLStreamException { + if (version != null) soap.getSOAPPart().setXmlVersion(version); + } + + @Override + public void writeStartDocument(final String encoding, final String version) throws XMLStreamException { + if (version != null) soap.getSOAPPart().setXmlVersion(version); + if (encoding != null) { + try { + soap.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, encoding); + } catch (SOAPException e) { + throw new XMLStreamException(e); + } + } + } + + @Override + public void writeCharacters(final String text) throws XMLStreamException { + try { + currentElement.addTextNode(text); + } catch (SOAPException e) { + throw new XMLStreamException(e); + } + } + + @Override + public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException { + char[] chr = (start == 0 && len == text.length) ? text : Arrays.copyOfRange(text, start, start + len); + try { + currentElement.addTextNode(new String(chr)); + } catch (SOAPException e) { + throw new XMLStreamException(e); + } + } + + @Override + public String getPrefix(final String uri) throws XMLStreamException { + return currentElement.lookupPrefix(uri); + } + + @Override + public void setPrefix(final String prefix, final String uri) throws XMLStreamException { + try { + this.currentElement.addNamespaceDeclaration(prefix, uri); + } catch (SOAPException e) { + throw new XMLStreamException(e); + } + } + + @Override + public void setDefaultNamespace(final String uri) throws XMLStreamException { + setPrefix("", uri); + } + + @Override + public void setNamespaceContext(final NamespaceContext context)throws XMLStreamException { + throw new UnsupportedOperationException(); + } + + @Override + public Object getProperty(final String name) throws IllegalArgumentException { + //TODO the following line is to make eclipselink happy ... they are aware of this problem - + if (javax.xml.stream.XMLOutputFactory.IS_REPAIRING_NAMESPACES.equals(name)) return Boolean.FALSE; + return null; + } + + @Override + public NamespaceContext getNamespaceContext() { + return new NamespaceContext() { + public String getNamespaceURI(final String prefix) { + return currentElement.getNamespaceURI(prefix); + } + public String getPrefix(final String namespaceURI) { + return currentElement.lookupPrefix(namespaceURI); + } + public Iterator getPrefixes(final String namespaceURI) { + return new Iterator() { + String prefix = getPrefix(namespaceURI); + public boolean hasNext() { + return (prefix != null); + } + public Object next() { + if (!hasNext()) throw new java.util.NoSuchElementException(); + String next = prefix; + prefix = null; + return next; + } + public void remove() {} + }; + } + }; + } +} diff -r a77941f17614 -r 0d1f816217dc jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxWriterEx.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxWriterEx.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.xml.internal.messaging.saaj.util.stax; + +import java.io.OutputStream; +import java.util.Arrays; +import java.util.Iterator; +import java.util.UUID; + +import javax.activation.DataHandler; +import javax.xml.bind.attachment.AttachmentMarshaller; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPMessage; +import javax.xml.stream.XMLStreamException; + +import com.sun.xml.internal.org.jvnet.staxex.Base64Data; +import com.sun.xml.internal.org.jvnet.staxex.BinaryText; +import com.sun.xml.internal.org.jvnet.staxex.MtomEnabled; +import com.sun.xml.internal.org.jvnet.staxex.NamespaceContextEx; +import com.sun.xml.internal.org.jvnet.staxex.StreamingDataHandler; +import com.sun.xml.internal.org.jvnet.staxex.XMLStreamWriterEx; +import com.sun.xml.internal.org.jvnet.staxex.util.MtomStreamWriter; +// +//import com.sun.xml.internal.ws.api.message.saaj.SaajStaxWriter; +//import com.sun.xml.internal.ws.developer.StreamingDataHandler; +//import com.sun.xml.internal.ws.streaming.MtomStreamWriter; + +/** + * SaajStaxWriterEx converts XMLStreamWriterEx calls to build an orasaaj SOAPMessage with BinaryTextImpl. + * + * @author shih-chang.chen@oracle.com + */ +public class SaajStaxWriterEx extends SaajStaxWriter implements XMLStreamWriterEx, MtomStreamWriter { + + static final protected String xopNS = "http://www.w3.org/2004/08/xop/include"; + static final protected String Include = "Include"; + static final protected String href = "href"; + + private enum State {xopInclude, others}; + private State state = State.others; + private BinaryText binaryText; + + public SaajStaxWriterEx(SOAPMessage msg, String uri) throws SOAPException { + super(msg, uri); + } + + public void writeStartElement(String prefix, String ln, String ns) throws XMLStreamException { + if (xopNS.equals(ns) && Include.equals(ln)) { + state = State.xopInclude; + return; + } else { + super.writeStartElement(prefix, ln, ns); + } + } + + @Override + public void writeEndElement() throws XMLStreamException { + if (state.equals(State.xopInclude)) { + state = State.others; + } else { + super.writeEndElement(); + } + } + + @Override + public void writeAttribute(String prefix, String ns, String ln, String value) throws XMLStreamException { + if (binaryText != null && href.equals(ln)) { + return; + } else { + super.writeAttribute(prefix, ns, ln, value); + } + } + +// @Override +// public void writeComment(String data) throws XMLStreamException { +// ((ElementImpl)currentElement).addCommentNode(data); +// } +// +// @Override +// public void writeCData(String data) throws XMLStreamException { +// CDataTextImpl cdt = new CDataTextImpl(soap.getSOAPPart(), data); +// currentElement.appendChild(cdt); +// } + + @Override + public NamespaceContextEx getNamespaceContext() { + return new NamespaceContextEx() { + public String getNamespaceURI(String prefix) { + return currentElement.getNamespaceURI(prefix); + } + public String getPrefix(String namespaceURI) { + return currentElement.lookupPrefix(namespaceURI); + } + public Iterator getPrefixes(final String namespaceURI) { + return new Iterator() { + String prefix = getPrefix(namespaceURI); + public boolean hasNext() { + return (prefix != null); + } + public Object next() { + if (prefix == null) throw new java.util.NoSuchElementException(); + String next = prefix; + prefix = null; + return next; + } + public void remove() {} + }; + } + public Iterator iterator() { + return new Iterator() { + public boolean hasNext() { return false; } + public Binding next() { return null; } + public void remove() {} + }; + } + }; + } + + @Override + public void writeBinary(DataHandler data) throws XMLStreamException { +// binaryText = BinaryTextImpl.createBinaryTextFromDataHandler((MessageImpl)soap, null, currentElement.getOwnerDocument(), data); +// currentElement.appendChild(binaryText); + addBinaryText(data); + } + + @Override + public OutputStream writeBinary(String arg0) throws XMLStreamException { + return null; + } + + @Override + public void writeBinary(byte[] data, int offset, int length, String contentType) throws XMLStreamException { +// if (mtomThreshold == -1 || mtomThreshold > length) return null; + byte[] bytes = (offset == 0 && length == data.length) ? data : Arrays.copyOfRange(data, offset, offset + length); + if (currentElement instanceof MtomEnabled) { + binaryText = ((MtomEnabled) currentElement).addBinaryText(bytes); + } else { + throw new IllegalStateException("The currentElement is not MtomEnabled " + currentElement); + } + } + + @Override + public void writePCDATA(CharSequence arg0) throws XMLStreamException { + if (arg0 instanceof Base64Data) { + // The fix of StreamReaderBufferCreator preserves this dataHandler + addBinaryText(((Base64Data) arg0).getDataHandler()); + } else { + // We should not normally get here as we expect a DataHandler, + // but this is the most general solution. If we do get + // something other than a Data Handler, create a Text node with + // the data. Another alternative would be to throw an exception, + // but in the most general case, we don't know whether this input + // is expected. + try { + currentElement.addTextNode(arg0.toString()); + } catch (SOAPException e) { + throw new XMLStreamException("Cannot add Text node", e); + } + } + } + + static private String encodeCid() { + String cid = "example.jaxws.sun.com"; + String name = UUID.randomUUID() + "@"; + return name + cid; + } + + private String addBinaryText(DataHandler data) { + String hrefOrCid = null; + if (data instanceof StreamingDataHandler) { + hrefOrCid = ((StreamingDataHandler) data).getHrefCid(); + } + if (hrefOrCid == null) hrefOrCid = encodeCid(); + + String prefixedCid = (hrefOrCid.startsWith("cid:")) ? hrefOrCid : "cid:" + hrefOrCid; + // Should we do the threshold processing on DataHandler ? But that would be + // expensive as DataHolder need to read the data again from its source + //binaryText = BinaryTextImpl.createBinaryTextFromDataHandler((MessageImpl) soap, prefixedCid, currentElement.getOwnerDocument(), data); + //currentElement.appendChild(binaryText); + if (currentElement instanceof MtomEnabled) { + binaryText = ((MtomEnabled) currentElement).addBinaryText(prefixedCid, data); + } else { + throw new IllegalStateException("The currentElement is not MtomEnabled " + currentElement); + } + return hrefOrCid; + } + + public AttachmentMarshaller getAttachmentMarshaller() { + return new AttachmentMarshaller() { + @Override + public String addMtomAttachment(DataHandler data, String ns, String ln) { +// if (mtomThreshold == -1) return null; + String hrefOrCid = addBinaryText(data); +// return binaryText.getHref(); + return hrefOrCid; + } + + @Override + public String addMtomAttachment(byte[] data, int offset, int length, String mimeType, String ns, String ln) { +// if (mtomThreshold == -1 || mtomThreshold > length) return null; + byte[] bytes = (offset == 0 && length == data.length) ? data : Arrays.copyOfRange(data, offset, offset + length); +// binaryText = (BinaryTextImpl) ((ElementImpl) currentElement).addAsBase64TextNode(bytes); + if (currentElement instanceof MtomEnabled) { + binaryText = ((MtomEnabled) currentElement).addBinaryText(bytes); + } else { + throw new IllegalStateException("The currentElement is not MtomEnabled " + currentElement); + } + return binaryText.getHref(); + } + + @Override + public String addSwaRefAttachment(DataHandler data) { + return "cid:"+encodeCid(); + } + + @Override + public boolean isXOPPackage() { + return true; + } + }; + } +} diff -r a77941f17614 -r 0d1f816217dc jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/BinaryText.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/BinaryText.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/BinaryText.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,15 +26,13 @@ package com.sun.xml.internal.org.jvnet.staxex; import javax.activation.DataHandler; -import javax.xml.soap.SOAPException; -import javax.xml.soap.Text; /** * BinaryText represents a MTOM attachment. * * @author shih-chang.chen@oracle.com */ -public interface BinaryText extends Text { +public interface BinaryText { public String getHref(); - public DataHandler getDataHandler() throws SOAPException; + public DataHandler getDataHandler(); } diff -r a77941f17614 -r 0d1f816217dc jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/StAxSOAPBody.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/StAxSOAPBody.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/StAxSOAPBody.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package com.sun.xml.internal.org.jvnet.staxex; import javax.xml.namespace.QName; -import javax.xml.soap.SOAPException; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; @@ -46,7 +45,6 @@ /** * Retrieve payload qname without materializing its contents * @return - * @throws SOAPException */ public QName getPayloadQName(); @@ -58,7 +56,7 @@ * Retrieve payload attribute value without materializing its contents * @param localName * @return - * @throws SOAPException + * @throws XMLStreamException */ public String getPayloadAttributeValue(String localName) throws XMLStreamException; @@ -66,16 +64,16 @@ * Retrieve payload attribute value without materializing its contents * @param qName * @return - * @throws SOAPException + * @throws XMLStreamException */ public String getPayloadAttributeValue(QName qName) throws XMLStreamException; - public void materialize() throws SOAPException; + public void materialize() throws XMLStreamException; } - public void setPayload(Payload src) throws SOAPException; + public void setPayload(Payload src) throws XMLStreamException; - public Payload getPayload()throws SOAPException; + public Payload getPayload()throws XMLStreamException; public boolean hasStaxPayload(); } diff -r a77941f17614 -r 0d1f816217dc jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/util/SaajStaxReaderEx.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/util/SaajStaxReaderEx.java Wed Jul 05 19:38:36 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -/* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.xml.internal.org.jvnet.staxex.util; - -import java.util.Iterator; - -import javax.xml.soap.SOAPElement; -import javax.xml.soap.SOAPException; -import javax.xml.stream.XMLStreamException; - -import com.sun.xml.internal.org.jvnet.staxex.Base64Data; -import com.sun.xml.internal.org.jvnet.staxex.XMLStreamReaderEx; -import com.sun.xml.internal.org.jvnet.staxex.BinaryText; - -import org.w3c.dom.Node; -import org.w3c.dom.Text; - -/** - * SaajStaxReaderEx - * - * @author shih-chang.chen@oracle.com - */ -public class SaajStaxReaderEx extends DOMStreamReader implements XMLStreamReaderEx { - //TODO extends com.sun.xml.internal.ws.streaming.DOMStreamReader - private BinaryText binaryText = null; - private Base64Data base64AttData = null; - - public SaajStaxReaderEx(SOAPElement se) { - super(se); - } - - @Override - public int next() throws XMLStreamException { - binaryText = null; - base64AttData = null; - while(true) { - int r = _next(); - switch (r) { - case CHARACTERS: - if (_current instanceof BinaryText) { - binaryText = (BinaryText) _current; - base64AttData = new Base64Data(); - try { - base64AttData.set(binaryText.getDataHandler()); -//System.out.println("--------------- debug SaajStaxReaderEx binaryText " + binaryText); - } catch (SOAPException e) { - throw new XMLStreamException(e); - } - } else { - // if we are currently at text node, make sure that this is a meaningful text node. - Node prev = _current.getPreviousSibling(); - if(prev!=null && prev.getNodeType()==Node.TEXT_NODE) - continue; // nope. this is just a continuation of previous text that should be invisible - - Text t = (Text)_current; - wholeText = t.getWholeText(); - if(wholeText.length()==0) - continue; // nope. this is empty text. - } - return CHARACTERS; - case START_ELEMENT: - splitAttributes(); - return START_ELEMENT; - default: - return r; - } - } - } - - @Override - public String getElementTextTrim() throws XMLStreamException { - // TODO Auto-generated method stub - return null; - } - - @Override - public CharSequence getPCDATA() throws XMLStreamException { - return (binaryText != null) ? base64AttData : getText(); - } - - @Override - public com.sun.xml.internal.org.jvnet.staxex.NamespaceContextEx getNamespaceContext() { - return new com.sun.xml.internal.org.jvnet.staxex.NamespaceContextEx() { - - @Override - public String getNamespaceURI(String prefix) { - return _current.lookupNamespaceURI(prefix); - } - - @Override - public String getPrefix(String uri) { - return _current.lookupPrefix(uri); - } - - @Override - public Iterator getPrefixes(String arg0) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Iterator iterator() { - // TODO Auto-generated method stub - return null; - } - - }; - } - - - @Override - public int getTextLength() { - return (binaryText != null) ? base64AttData.length() : super.getTextLength(); - } - - @Override - public int getTextStart() { - return (binaryText != null) ? 0: super.getTextStart(); - } - - @Override - public char[] getTextCharacters() { - if (binaryText != null) { - char[] chars = new char[base64AttData.length()]; - base64AttData.writeTo(chars, 0); - return chars; - } - return super.getTextCharacters(); - } -} diff -r a77941f17614 -r 0d1f816217dc jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/util/SaajStaxWriter.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/util/SaajStaxWriter.java Wed Jul 05 19:38:36 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,330 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.xml.internal.org.jvnet.staxex.util; - -import java.util.Arrays; -import java.util.Iterator; - -import javax.xml.namespace.NamespaceContext; -import javax.xml.namespace.QName; -import javax.xml.soap.SOAPElement; -import javax.xml.soap.SOAPException; -import javax.xml.soap.SOAPMessage; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; - -import org.w3c.dom.Comment; -import org.w3c.dom.Node; - -/** - * SaajStaxWriter builds a SAAJ SOAPMessage by using XMLStreamWriter interface. - * - * @author shih-chang.chen@oracle.com - */ -public class SaajStaxWriter implements XMLStreamWriter { - - protected SOAPMessage soap; - protected String envURI; - protected SOAPElement currentElement; - - static final protected String Envelope = "Envelope"; - static final protected String Header = "Header"; - static final protected String Body = "Body"; - static final protected String xmlns = "xmlns"; - - public SaajStaxWriter(final SOAPMessage msg, String uri) throws SOAPException { - soap = msg; - this.envURI = uri; - } - - public SOAPMessage getSOAPMessage() { - return soap; - } - - protected SOAPElement getEnvelope() throws SOAPException { - return soap.getSOAPPart().getEnvelope(); - } - - @Override - public void writeStartElement(final String localName) throws XMLStreamException { - try { - currentElement = currentElement.addChildElement(localName); - } catch (SOAPException e) { - throw new XMLStreamException(e); - } - } - - @Override - public void writeStartElement(final String ns, final String ln) throws XMLStreamException { - writeStartElement(null, ln, ns); - } - - @Override - public void writeStartElement(final String prefix, final String ln, final String ns) throws XMLStreamException { - try { - if (envURI.equals(ns)) { - if (Envelope.equals(ln)) { - currentElement = getEnvelope(); - fixPrefix(prefix); - return; - } else if (Header.equals(ln)) { - currentElement = soap.getSOAPHeader(); - fixPrefix(prefix); - return; - } else if (Body.equals(ln)) { - currentElement = soap.getSOAPBody(); - fixPrefix(prefix); - return; - } - } - currentElement = (prefix == null) ? - currentElement.addChildElement(new QName(ns, ln)) : - currentElement.addChildElement(ln, prefix, ns); - } catch (SOAPException e) { - throw new XMLStreamException(e); - } - } - - private void fixPrefix(final String prfx) throws XMLStreamException { - String oldPrfx = currentElement.getPrefix(); - if (prfx != null && !prfx.equals(oldPrfx)) { - currentElement.setPrefix(prfx); - } - } - - @Override - public void writeEmptyElement(final String uri, final String ln) throws XMLStreamException { - writeStartElement(null, ln, uri); - } - - @Override - public void writeEmptyElement(final String prefix, final String ln, final String uri) throws XMLStreamException { - writeStartElement(prefix, ln, uri); - } - - @Override - public void writeEmptyElement(final String ln) throws XMLStreamException { - writeStartElement(null, ln, null); - } - - @Override - public void writeEndElement() throws XMLStreamException { - if (currentElement != null) currentElement = currentElement.getParentElement(); - } - - @Override - public void writeEndDocument() throws XMLStreamException { - } - - @Override - public void close() throws XMLStreamException { - } - - @Override - public void flush() throws XMLStreamException { - } - - @Override - public void writeAttribute(final String ln, final String val) throws XMLStreamException { - writeAttribute(null, null, ln, val); - } - - @Override - public void writeAttribute(final String prefix, final String ns, final String ln, final String value) throws XMLStreamException { - try { - if (ns == null) { - if (prefix == null && xmlns.equals(ln)) { - currentElement.addNamespaceDeclaration("", value); - } else { - currentElement.setAttributeNS("", ln, value); - } - } else { - QName name = (prefix == null) ? new QName(ns, ln) : new QName(ns, ln, prefix); - currentElement.addAttribute(name, value); - } - } catch (SOAPException e) { - throw new XMLStreamException(e); - } - } - - @Override - public void writeAttribute(final String ns, final String ln, final String val) throws XMLStreamException { - writeAttribute(null, ns, ln, val); - } - - @Override - public void writeNamespace(String prefix, final String uri) throws XMLStreamException { - - // make prefix default if null or "xmlns" (according to javadoc) - if (prefix == null || "xmlns".equals(prefix)) { - prefix = ""; - } - - try { - currentElement.addNamespaceDeclaration(prefix, uri); - } catch (SOAPException e) { - throw new XMLStreamException(e); - } - } - - @Override - public void writeDefaultNamespace(final String uri) throws XMLStreamException { - writeNamespace("", uri); - } - - @Override - public void writeComment(final String data) throws XMLStreamException { - Comment c = soap.getSOAPPart().createComment(data); - currentElement.appendChild(c); - } - - @Override - public void writeProcessingInstruction(final String target) throws XMLStreamException { - Node n = soap.getSOAPPart().createProcessingInstruction(target, ""); - currentElement.appendChild(n); - } - - @Override - public void writeProcessingInstruction(final String target, final String data) throws XMLStreamException { - Node n = soap.getSOAPPart().createProcessingInstruction(target, data); - currentElement.appendChild(n); - } - - @Override - public void writeCData(final String data) throws XMLStreamException { - Node n = soap.getSOAPPart().createCDATASection(data); - currentElement.appendChild(n); - } - - @Override - public void writeDTD(final String dtd) throws XMLStreamException { - //TODO ... Don't do anything here - } - - @Override - public void writeEntityRef(final String name) throws XMLStreamException { - Node n = soap.getSOAPPart().createEntityReference(name); - currentElement.appendChild(n); - } - - @Override - public void writeStartDocument() throws XMLStreamException { - } - - @Override - public void writeStartDocument(final String version) throws XMLStreamException { - if (version != null) soap.getSOAPPart().setXmlVersion(version); - } - - @Override - public void writeStartDocument(final String encoding, final String version) throws XMLStreamException { - if (version != null) soap.getSOAPPart().setXmlVersion(version); - if (encoding != null) { - try { - soap.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, encoding); - } catch (SOAPException e) { - throw new XMLStreamException(e); - } - } - } - - @Override - public void writeCharacters(final String text) throws XMLStreamException { - try { - currentElement.addTextNode(text); - } catch (SOAPException e) { - throw new XMLStreamException(e); - } - } - - @Override - public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException { - char[] chr = (start == 0 && len == text.length) ? text : Arrays.copyOfRange(text, start, start + len); - try { - currentElement.addTextNode(new String(chr)); - } catch (SOAPException e) { - throw new XMLStreamException(e); - } - } - - @Override - public String getPrefix(final String uri) throws XMLStreamException { - return currentElement.lookupPrefix(uri); - } - - @Override - public void setPrefix(final String prefix, final String uri) throws XMLStreamException { - try { - this.currentElement.addNamespaceDeclaration(prefix, uri); - } catch (SOAPException e) { - throw new XMLStreamException(e); - } - } - - @Override - public void setDefaultNamespace(final String uri) throws XMLStreamException { - setPrefix("", uri); - } - - @Override - public void setNamespaceContext(final NamespaceContext context)throws XMLStreamException { - throw new UnsupportedOperationException(); - } - - @Override - public Object getProperty(final String name) throws IllegalArgumentException { - //TODO the following line is to make eclipselink happy ... they are aware of this problem - - if (javax.xml.stream.XMLOutputFactory.IS_REPAIRING_NAMESPACES.equals(name)) return Boolean.FALSE; - return null; - } - - @Override - public NamespaceContext getNamespaceContext() { - return new NamespaceContext() { - public String getNamespaceURI(final String prefix) { - return currentElement.getNamespaceURI(prefix); - } - public String getPrefix(final String namespaceURI) { - return currentElement.lookupPrefix(namespaceURI); - } - public Iterator getPrefixes(final String namespaceURI) { - return new Iterator() { - String prefix = getPrefix(namespaceURI); - public boolean hasNext() { - return (prefix != null); - } - public Object next() { - if (!hasNext()) throw new java.util.NoSuchElementException(); - String next = prefix; - prefix = null; - return next; - } - public void remove() {} - }; - } - }; - } -} diff -r a77941f17614 -r 0d1f816217dc jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/util/SaajStaxWriterEx.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/util/SaajStaxWriterEx.java Wed Jul 05 19:38:36 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,244 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.xml.internal.org.jvnet.staxex.util; - -import java.io.OutputStream; -import java.util.Arrays; -import java.util.Iterator; -import java.util.UUID; - -import javax.activation.DataHandler; -import javax.xml.bind.attachment.AttachmentMarshaller; -import javax.xml.soap.SOAPException; -import javax.xml.soap.SOAPMessage; -import javax.xml.stream.XMLStreamException; - -import com.sun.xml.internal.org.jvnet.staxex.Base64Data; -import com.sun.xml.internal.org.jvnet.staxex.BinaryText; -import com.sun.xml.internal.org.jvnet.staxex.MtomEnabled; -import com.sun.xml.internal.org.jvnet.staxex.NamespaceContextEx; -import com.sun.xml.internal.org.jvnet.staxex.StreamingDataHandler; -import com.sun.xml.internal.org.jvnet.staxex.XMLStreamWriterEx; -// -//import com.sun.xml.internal.ws.api.message.saaj.SaajStaxWriter; -//import com.sun.xml.internal.ws.developer.StreamingDataHandler; -//import com.sun.xml.internal.ws.streaming.MtomStreamWriter; - -/** - * SaajStaxWriterEx converts XMLStreamWriterEx calls to build an orasaaj SOAPMessage with BinaryTextImpl. - * - * @author shih-chang.chen@oracle.com - */ -public class SaajStaxWriterEx extends SaajStaxWriter implements XMLStreamWriterEx, MtomStreamWriter { - - static final protected String xopNS = "http://www.w3.org/2004/08/xop/include"; - static final protected String Include = "Include"; - static final protected String href = "href"; - - private enum State {xopInclude, others}; - private State state = State.others; - private BinaryText binaryText; - - public SaajStaxWriterEx(SOAPMessage msg, String uri) throws SOAPException { - super(msg, uri); - } - - public void writeStartElement(String prefix, String ln, String ns) throws XMLStreamException { - if (xopNS.equals(ns) && Include.equals(ln)) { - state = State.xopInclude; - return; - } else { - super.writeStartElement(prefix, ln, ns); - } - } - - @Override - public void writeEndElement() throws XMLStreamException { - if (state.equals(State.xopInclude)) { - state = State.others; - } else { - super.writeEndElement(); - } - } - - @Override - public void writeAttribute(String prefix, String ns, String ln, String value) throws XMLStreamException { - if (binaryText != null && href.equals(ln)) { - return; - } else { - super.writeAttribute(prefix, ns, ln, value); - } - } - -// @Override -// public void writeComment(String data) throws XMLStreamException { -// ((ElementImpl)currentElement).addCommentNode(data); -// } -// -// @Override -// public void writeCData(String data) throws XMLStreamException { -// CDataTextImpl cdt = new CDataTextImpl(soap.getSOAPPart(), data); -// currentElement.appendChild(cdt); -// } - - @Override - public NamespaceContextEx getNamespaceContext() { - return new NamespaceContextEx() { - public String getNamespaceURI(String prefix) { - return currentElement.getNamespaceURI(prefix); - } - public String getPrefix(String namespaceURI) { - return currentElement.lookupPrefix(namespaceURI); - } - public Iterator getPrefixes(final String namespaceURI) { - return new Iterator() { - String prefix = getPrefix(namespaceURI); - public boolean hasNext() { - return (prefix != null); - } - public Object next() { - if (prefix == null) throw new java.util.NoSuchElementException(); - String next = prefix; - prefix = null; - return next; - } - public void remove() {} - }; - } - public Iterator iterator() { - return new Iterator() { - public boolean hasNext() { return false; } - public Binding next() { return null; } - public void remove() {} - }; - } - }; - } - - @Override - public void writeBinary(DataHandler data) throws XMLStreamException { -// binaryText = BinaryTextImpl.createBinaryTextFromDataHandler((MessageImpl)soap, null, currentElement.getOwnerDocument(), data); -// currentElement.appendChild(binaryText); - addBinaryText(data); - } - - @Override - public OutputStream writeBinary(String arg0) throws XMLStreamException { - return null; - } - - @Override - public void writeBinary(byte[] data, int offset, int length, String contentType) throws XMLStreamException { -// if (mtomThreshold == -1 || mtomThreshold > length) return null; - byte[] bytes = (offset == 0 && length == data.length) ? data : Arrays.copyOfRange(data, offset, offset + length); - if (currentElement instanceof MtomEnabled) { - binaryText = ((MtomEnabled) currentElement).addBinaryText(bytes); - } else { - throw new IllegalStateException("The currentElement is not MtomEnabled " + currentElement); - } - } - - @Override - public void writePCDATA(CharSequence arg0) throws XMLStreamException { - if (arg0 instanceof Base64Data) { - // The fix of StreamReaderBufferCreator preserves this dataHandler - addBinaryText(((Base64Data) arg0).getDataHandler()); - } else { - // We should not normally get here as we expect a DataHandler, - // but this is the most general solution. If we do get - // something other than a Data Handler, create a Text node with - // the data. Another alternative would be to throw an exception, - // but in the most general case, we don't know whether this input - // is expected. - try { - currentElement.addTextNode(arg0.toString()); - } catch (SOAPException e) { - throw new XMLStreamException("Cannot add Text node", e); - } - } - } - - static private String encodeCid() { - String cid = "example.jaxws.sun.com"; - String name = UUID.randomUUID() + "@"; - return name + cid; - } - - private String addBinaryText(DataHandler data) { - String hrefOrCid = null; - if (data instanceof StreamingDataHandler) { - hrefOrCid = ((StreamingDataHandler) data).getHrefCid(); - } - if (hrefOrCid == null) hrefOrCid = encodeCid(); - - String prefixedCid = (hrefOrCid.startsWith("cid:")) ? hrefOrCid : "cid:" + hrefOrCid; - // Should we do the threshold processing on DataHandler ? But that would be - // expensive as DataHolder need to read the data again from its source - //binaryText = BinaryTextImpl.createBinaryTextFromDataHandler((MessageImpl) soap, prefixedCid, currentElement.getOwnerDocument(), data); - //currentElement.appendChild(binaryText); - if (currentElement instanceof MtomEnabled) { - binaryText = ((MtomEnabled) currentElement).addBinaryText(prefixedCid, data); - } else { - throw new IllegalStateException("The currentElement is not MtomEnabled " + currentElement); - } - return hrefOrCid; - } - - public AttachmentMarshaller getAttachmentMarshaller() { - return new AttachmentMarshaller() { - @Override - public String addMtomAttachment(DataHandler data, String ns, String ln) { -// if (mtomThreshold == -1) return null; - String hrefOrCid = addBinaryText(data); -// return binaryText.getHref(); - return hrefOrCid; - } - - @Override - public String addMtomAttachment(byte[] data, int offset, int length, String mimeType, String ns, String ln) { -// if (mtomThreshold == -1 || mtomThreshold > length) return null; - byte[] bytes = (offset == 0 && length == data.length) ? data : Arrays.copyOfRange(data, offset, offset + length); -// binaryText = (BinaryTextImpl) ((ElementImpl) currentElement).addAsBase64TextNode(bytes); - if (currentElement instanceof MtomEnabled) { - binaryText = ((MtomEnabled) currentElement).addBinaryText(bytes); - } else { - throw new IllegalStateException("The currentElement is not MtomEnabled " + currentElement); - } - return binaryText.getHref(); - } - - @Override - public String addSwaRefAttachment(DataHandler data) { - return "cid:"+encodeCid(); - } - - @Override - public boolean isXOPPackage() { - return true; - } - }; - } -} diff -r a77941f17614 -r 0d1f816217dc jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/saaj/SAAJFactory.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/saaj/SAAJFactory.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/saaj/SAAJFactory.java Wed Jul 05 19:39:35 2017 +0200 @@ -36,7 +36,6 @@ import javax.xml.stream.XMLStreamException; import org.xml.sax.SAXException; -import com.sun.xml.internal.org.jvnet.staxex.util.SaajStaxWriter; import com.sun.xml.internal.bind.marshaller.SAX2DOMEx; import com.sun.xml.internal.ws.api.SOAPVersion; diff -r a77941f17614 -r 0d1f816217dc jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,8 +42,6 @@ /** * SaajStaxWriter builds a SAAJ SOAPMessage by using XMLStreamWriter interface. * - * @deprecated use com.sun.xml.internal.org.jvnet.staxex.util.SaajStaxWriter - * * @author shih-chang.chen@oracle.com */ public class SaajStaxWriter implements XMLStreamWriter { @@ -57,16 +55,21 @@ static final protected String Body = "Body"; static final protected String xmlns = "xmlns"; - public SaajStaxWriter(final SOAPMessage msg) throws SOAPException { + private boolean isHeaderSeen = false; + + public SaajStaxWriter(final SOAPMessage msg, String uri) throws SOAPException { soap = msg; - currentElement = soap.getSOAPPart().getEnvelope(); - envURI = currentElement.getNamespaceURI(); + this.envURI = uri; } public SOAPMessage getSOAPMessage() { return soap; } + protected SOAPElement getEnvelope() throws SOAPException { + return soap.getSOAPPart().getEnvelope(); + } + @Override public void writeStartElement(final String localName) throws XMLStreamException { try { @@ -86,10 +89,11 @@ try { if (envURI.equals(ns)) { if (Envelope.equals(ln)) { - currentElement = soap.getSOAPPart().getEnvelope(); + currentElement = getEnvelope(); fixPrefix(prefix); return; } else if (Header.equals(ln)) { + isHeaderSeen = true; currentElement = soap.getSOAPHeader(); fixPrefix(prefix); return; @@ -108,9 +112,13 @@ } private void fixPrefix(final String prfx) throws XMLStreamException { - String oldPrfx = currentElement.getPrefix(); + fixPrefix(prfx, currentElement); + } + + private void fixPrefix(final String prfx, SOAPElement element) throws XMLStreamException { + String oldPrfx = element.getPrefix(); if (prfx != null && !prfx.equals(oldPrfx)) { - currentElement.setPrefix(prfx); + element.setPrefix(prfx); } } @@ -136,6 +144,21 @@ @Override public void writeEndDocument() throws XMLStreamException { + try { + if (!isHeaderSeen) { + SOAPElement header = soap.getSOAPHeader(); + if (header != null) { + String prefixAtHeader = header.getPrefix(); + SOAPElement env = getEnvelope(); + header.detachNode(); + if (prefixAtHeader != null && !prefixAtHeader.equals(env.getPrefix())) { + env.removeNamespaceDeclaration(prefixAtHeader); + } + } + } + } catch (SOAPException e) { + throw new XMLStreamException(e); + } } @Override diff -r a77941f17614 -r 0d1f816217dc jdk/.hgtags --- a/jdk/.hgtags Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/.hgtags Wed Jul 05 19:39:35 2017 +0200 @@ -253,3 +253,4 @@ 9e7bd44ea85c72318130379c34b98716b9c7c248 jdk9-b08 2cef452ba711b17950da275fd15931925799f07c jdk9-b09 ab06ba2894313a47e4969ca37792ff119c49e711 jdk9-b10 +47feccd164b7187a0147693a922ee47c6629643c jdk9-b11 diff -r a77941f17614 -r 0d1f816217dc jdk/make/data/jdwp/jdwp.spec --- a/jdk/make/data/jdwp/jdwp.spec Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/make/data/jdwp/jdwp.spec Wed Jul 05 19:39:35 2017 +0200 @@ -1147,7 +1147,8 @@ (ErrorSet (Error INVALID_CLASS "clazz is not the ID of a class.") (Error INVALID_OBJECT "clazz is not a known ID.") - (Error INVALID_METHODID "methodID is not the ID of a method.") + (Error INVALID_METHODID "methodID is not the ID of a static method in " + "this class type or one of its superclasses.") (Error INVALID_THREAD) (Error THREAD_NOT_SUSPENDED) (Error VM_DEAD) @@ -1250,6 +1251,83 @@ ) ) (CommandSet InterfaceType=5 + (Command InvokeMethod=1 + "Invokes a static method. " + "The method must not be a static initializer. " + "The method must be a member of the interface type. " + "

Since JDWP version 1.8 " + "

" + "The method invocation will occur in the specified thread. " + "Method invocation can occur only if the specified thread " + "has been suspended by an event. " + "Method invocation is not supported " + "when the target VM has been suspended by the front-end. " + "

" + "The specified method is invoked with the arguments in the specified " + "argument list. " + "The method invocation is synchronous; the reply packet is not " + "sent until the invoked method returns in the target VM. " + "The return value (possibly the void value) is " + "included in the reply packet. " + "If the invoked method throws an exception, the " + "exception object ID is set in the reply packet; otherwise, the " + "exception object ID is null. " + "

" + "For primitive arguments, the argument value's type must match the " + "argument's type exactly. For object arguments, there must exist a " + "widening reference conversion from the argument value's type to the " + "argument's type and the argument's type must be loaded. " + "

" + "By default, all threads in the target VM are resumed while " + "the method is being invoked if they were previously " + "suspended by an event or by a command. " + "This is done to prevent the deadlocks " + "that will occur if any of the threads own monitors " + "that will be needed by the invoked method. It is possible that " + "breakpoints or other events might occur during the invocation. " + "Note, however, that this implicit resume acts exactly like " + "the ThreadReference resume command, so if the thread's suspend " + "count is greater than 1, it will remain in a suspended state " + "during the invocation. By default, when the invocation completes, " + "all threads in the target VM are suspended, regardless their state " + "before the invocation. " + "

" + "The resumption of other threads during the invoke can be prevented " + "by specifying the INVOKE_SINGLE_THREADED " + "bit flag in the options field; however, " + "there is no protection against or recovery from the deadlocks " + "described above, so this option should be used with great caution. " + "Only the specified thread will be resumed (as described for all " + "threads above). Upon completion of a single threaded invoke, the invoking thread " + "will be suspended once again. Note that any threads started during " + "the single threaded invocation will not be suspended when the " + "invocation completes. " + "

" + "If the target VM is disconnected during the invoke (for example, through " + "the VirtualMachine dispose command) the method invocation continues. " + (Out + (interfaceType clazz "The interface type ID.") + (threadObject thread "The thread in which to invoke.") + (method methodID "The method to invoke.") + (Repeat arguments + (value arg "The argument value.") + ) + (int options "Invocation options") + ) + (Reply + (value returnValue "The returned value.") + (tagged-object exception "The thrown exception.") + ) + (ErrorSet + (Error INVALID_CLASS "clazz is not the ID of an interface.") + (Error INVALID_OBJECT "clazz is not a known ID.") + (Error INVALID_METHODID "methodID is not the ID of a static method in this " + "interface type or is the ID of a static initializer.") + (Error INVALID_THREAD) + (Error THREAD_NOT_SUSPENDED) + (Error VM_DEAD) + ) + ) ) (CommandSet Method=6 (Command LineTable=1 @@ -1543,7 +1621,7 @@ "

" "By default, all threads in the target VM are resumed while " "the method is being invoked if they were previously " - "suspended by an event or by command. " + "suspended by an event or by a command. " "This is done to prevent the deadlocks " "that will occur if any of the threads own monitors " "that will be needed by the invoked method. It is possible that " @@ -1586,7 +1664,9 @@ (Error INVALID_OBJECT) (Error INVALID_CLASS "clazz is not the ID of a reference " "type.") - (Error INVALID_METHODID "methodID is not the ID of a method.") + (Error INVALID_METHODID "methodID is not the ID of an instance method " + "in this object's type or one of its superclasses, " + "superinterfaces, or implemented interfaces.") (Error INVALID_THREAD) (Error THREAD_NOT_SUSPENDED) (Error VM_DEAD) diff -r a77941f17614 -r 0d1f816217dc jdk/make/lib/Awt2dLibraries.gmk --- a/jdk/make/lib/Awt2dLibraries.gmk Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/make/lib/Awt2dLibraries.gmk Wed Jul 05 19:39:35 2017 +0200 @@ -798,6 +798,10 @@ BUILD_LIBFONTMANAGER_ExtensionSubtables.cpp_CXXFLAGS := -fno-strict-aliasing endif +# Libfontmanager doesn't actually need X_LIBS to link, but if building +# on a Solaris machine without X installed, using a devkit, linking +# to libawt_xawt will fail without the -L parameters from X_LIBS. Filter +# out the -R parameters since they aren't needed. $(eval $(call SetupNativeCompilation,BUILD_LIBFONTMANAGER, \ LIBRARY := fontmanager, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ @@ -816,7 +820,8 @@ $(call SET_SHARED_LIBRARY_ORIGIN), \ LDFLAGS_SUFFIX := $(BUILD_LIBFONTMANAGER_FONTLIB), \ LDFLAGS_SUFFIX_linux := -lawt $(LIBM) $(LIBCXX) -ljava -ljvm -lc, \ - LDFLAGS_SUFFIX_solaris := -lawt -lawt_xawt -lc $(LIBM) $(LIBCXX) -ljava -ljvm, \ + LDFLAGS_SUFFIX_solaris := $(filter-out -R%, $(X_LIBS)) \ + -lawt -lawt_xawt -lc $(LIBM) $(LIBCXX) -ljava -ljvm, \ LDFLAGS_SUFFIX_aix := -lawt -lawt_xawt $(LIBM) $(LIBCXX) -ljava -ljvm,\ LDFLAGS_SUFFIX_macosx := -lawt $(LIBM) $(LIBCXX) -undefined dynamic_lookup \ -ljava -ljvm, \ diff -r a77941f17614 -r 0d1f816217dc jdk/make/mapfiles/libjava/mapfile-vers diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/classes/apple/laf/JRSUIConstants.java --- a/jdk/src/macosx/classes/apple/laf/JRSUIConstants.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/classes/apple/laf/JRSUIConstants.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,13 @@ import java.lang.annotation.Native; public final class JRSUIConstants { + + /** + * There is no way to get width of focus border, so it is hardcoded here. + * All components, which can be focused should take care about it. + */ + public static final int FOCUS_SIZE = 4; + private static native long getPtrForConstant(final int constant); static class Key { diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/classes/com/apple/laf/AquaButtonExtendedTypes.java --- a/jdk/src/macosx/classes/com/apple/laf/AquaButtonExtendedTypes.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/classes/com/apple/laf/AquaButtonExtendedTypes.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,8 @@ import com.apple.laf.AquaUtilControlSize.*; import com.apple.laf.AquaUtils.RecyclableSingleton; +import static apple.laf.JRSUIConstants.FOCUS_SIZE; + /** * All the "magic numbers" in this class should go away once * "default font" and sizes for controls in Java Aqua Look and Feel @@ -145,7 +147,8 @@ protected static Map getAllTypes() { final Map specifiersByName = new HashMap(); - final Insets focusInsets = new Insets(4, 4, 4, 4); + final Insets focusInsets = new Insets(FOCUS_SIZE, FOCUS_SIZE, + FOCUS_SIZE, FOCUS_SIZE); final TypeSpecifier[] specifiers = { new TypeSpecifier("toolbar", true) { diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/classes/com/apple/laf/AquaIcon.java --- a/jdk/src/macosx/classes/com/apple/laf/AquaIcon.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/classes/com/apple/laf/AquaIcon.java Wed Jul 05 19:39:35 2017 +0200 @@ -44,7 +44,8 @@ } static UIResource getIconFor(final JRSUIControlSpec spec, final int width, final int height) { - return new CachableJRSUIIcon(width, height) { + return new ScalingJRSUIIcon(width, height) { + @Override public void initIconPainter(final AquaPainter painter) { spec.initIconPainter(painter); } @@ -128,35 +129,12 @@ if (image != null) return image; if (!GraphicsEnvironment.isHeadless()) { - image = getOptimizedImage(); + image = createImage(); } return image; } - private Image getOptimizedImage() { - final Image img = createImage(); - // TODO: no RuntimeOptions for now - //if (RuntimeOptions.getRenderer(null) != RuntimeOptions.Sun) return img; - return getProgressiveOptimizedImage(img, getIconWidth(), getIconHeight()); - } - - static Image getProgressiveOptimizedImage(final Image img, final int w, final int h) { - if (img == null) return null; - - final int halfImgW = img.getWidth(null) / 2; - final int halfImgH = img.getHeight(null) / 2; - if (w * 2 > halfImgW && h * 2 > halfImgH) return img; - - final BufferedImage halfImage = new BufferedImage(halfImgW, halfImgH, BufferedImage.TYPE_INT_ARGB); - final Graphics g = halfImage.getGraphics(); - ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - g.drawImage(img, 0, 0, halfImgW, halfImgH, null); - g.dispose(); - - return getProgressiveOptimizedImage(halfImage, w, h); - } - abstract Image createImage(); public boolean hasIconRef() { @@ -189,24 +167,50 @@ } - static abstract class CachableJRSUIIcon extends CachingScalingIcon implements UIResource { - public CachableJRSUIIcon(final int width, final int height) { - super(width, height); + static abstract class ScalingJRSUIIcon implements Icon, UIResource { + final int width; + final int height; + + public ScalingJRSUIIcon(final int width, final int height) { + this.width = width; + this.height = height; } - Image createImage() { - final AquaPainter painter = AquaPainter.create(JRSUIState.getInstance()); + @Override + public void paintIcon(final Component c, Graphics g, + final int x, final int y) { + if (GraphicsEnvironment.isHeadless()) { + return; + } + + g = g.create(); + + if (g instanceof Graphics2D) { + // improves icon rendering quality in Quartz + ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_QUALITY); + } + + final AquaPainter painter = + AquaPainter.create(JRSUIState.getInstance()); initIconPainter(painter); - final BufferedImage img = new BufferedImage(getIconWidth(), getIconHeight(), BufferedImage.TYPE_INT_ARGB_PRE); - final Graphics g = img.getGraphics(); - g.setClip(new Rectangle(0, 0, getIconWidth(), getIconHeight())); - painter.paint(g, null, 0, 0, getIconWidth(), getIconHeight()); + g.setClip(new Rectangle(x, y, width, height)); + painter.paint(g, c, x, y, width, height); g.dispose(); - return img; } public abstract void initIconPainter(final AquaPainter painter); + + @Override + public int getIconWidth() { + return width; + } + + @Override + public int getIconHeight() { + return height; + } } static class FileIcon extends CachingScalingIcon { diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/classes/com/apple/laf/AquaInternalFrameUI.java --- a/jdk/src/macosx/classes/com/apple/laf/AquaInternalFrameUI.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/classes/com/apple/laf/AquaInternalFrameUI.java Wed Jul 05 19:39:35 2017 +0200 @@ -787,8 +787,9 @@ } static final RecyclableSingleton RESIZE_ICON = new RecyclableSingleton() { + @Override protected Icon getInstance() { - return new AquaIcon.CachableJRSUIIcon(11, 11) { + return new AquaIcon.ScalingJRSUIIcon(11, 11) { public void initIconPainter(final AquaPainter iconState) { iconState.state.set(Widget.GROW_BOX_TEXTURED); iconState.state.set(WindowType.UTILITY); diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/classes/com/apple/laf/AquaPainter.java --- a/jdk/src/macosx/classes/com/apple/laf/AquaPainter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/classes/com/apple/laf/AquaPainter.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -141,40 +141,71 @@ paintFromSingleCachedImage(g, control, stateToPaint, boundsRect); } + /** + * Paints a native control, which identified by its size and a set of + * additional arguments using a cached image. + * + * @param g Graphics to draw the control + * @param control the reference to the native control + * @param controlState the state of the native control + * @param bounds the rectangle where the native part should be drawn. + * Note: the focus can/will be drawn outside of this bounds. + */ static void paintFromSingleCachedImage(final Graphics2D g, - final JRSUIControl control, final JRSUIState controlState, - final Rectangle bounds) { + final JRSUIControl control, + final JRSUIState controlState, + final Rectangle bounds) { if (bounds.width <= 0 || bounds.height <= 0) { return; } - int scale = 1; - if (g instanceof SunGraphics2D) { - scale = ((SunGraphics2D) g).surfaceData.getDefaultScale(); + int focus = 0; + if (controlState.is(JRSUIConstants.Focused.YES)) { + focus = JRSUIConstants.FOCUS_SIZE; } + + final int imgX = bounds.x - focus; + final int imgY = bounds.y - focus; + final int imgW = bounds.width + (focus << 1); + final int imgH = bounds.height + (focus << 1); final GraphicsConfiguration config = g.getDeviceConfiguration(); final ImageCache cache = ImageCache.getInstance(); - final int imgW = bounds.width * scale; - final int imgH = bounds.height * scale; - AquaPixelsKey key = new AquaPixelsKey(config, - imgW, imgH, scale, controlState); - BufferedImage img = (BufferedImage) cache.getImage(key); + final AquaPixelsKey key = new AquaPixelsKey(config, imgW, imgH, + bounds, controlState); + Image img = cache.getImage(key); if (img == null) { - img = new BufferedImage(imgW, imgH, BufferedImage.TYPE_INT_ARGB_PRE); + + Image baseImage = createImage(imgX, imgY, imgW, imgH, bounds, + control, controlState); + + img = new MultiResolutionBufferedImage(baseImage, + (rvWidth, rvHeight) -> createImage(imgX, imgY, + rvWidth, rvHeight, bounds, control, controlState)); + if (!controlState.is(JRSUIConstants.Animating.YES)) { cache.setImage(key, img); } - - final WritableRaster raster = img.getRaster(); - final DataBufferInt buffer = (DataBufferInt) raster.getDataBuffer(); - - control.set(controlState); - control.paint(SunWritableRaster.stealData(buffer, 0), - imgW, imgH, 0, 0, bounds.width, bounds.height); - SunWritableRaster.markDirty(buffer); } - g.drawImage(img, bounds.x, bounds.y, bounds.width, bounds.height, null); + g.drawImage(img, imgX, imgY, imgW, imgH, null); + } + + private static Image createImage(int imgX, int imgY, int imgW, int imgH, + final Rectangle bounds, + final JRSUIControl control, + JRSUIState controlState) { + BufferedImage img = new BufferedImage(imgW, imgH, + BufferedImage.TYPE_INT_ARGB_PRE); + + final WritableRaster raster = img.getRaster(); + final DataBufferInt buffer = (DataBufferInt) raster.getDataBuffer(); + + control.set(controlState); + control.paint(SunWritableRaster.stealData(buffer, 0), imgW, imgH, + bounds.x - imgX, bounds.y - imgY, bounds.width, + bounds.height); + SunWritableRaster.markDirty(buffer); + return img; } } @@ -187,21 +218,22 @@ private final GraphicsConfiguration config; private final int w; private final int h; - private final int scale; + private final Rectangle bounds; private final JRSUIState state; AquaPixelsKey(final GraphicsConfiguration config, - final int w, final int h, final int scale, + final int w, final int h, final Rectangle bounds, final JRSUIState state) { this.pixelCount = w * h; this.config = config; this.w = w; this.h = h; - this.scale = scale; + this.bounds = bounds; this.state = state; this.hash = hash(); } + @Override public int getPixelCount() { return pixelCount; } @@ -210,7 +242,7 @@ int hash = config != null ? config.hashCode() : 0; hash = 31 * hash + w; hash = 31 * hash + h; - hash = 31 * hash + scale; + hash = 31 * hash + bounds.hashCode(); hash = 31 * hash + state.hashCode(); return hash; } @@ -225,7 +257,7 @@ if (obj instanceof AquaPixelsKey) { AquaPixelsKey key = (AquaPixelsKey) obj; return config == key.config && w == key.w && h == key.h - && scale == key.scale && state.equals(key.state); + && bounds.equals(key.bounds) && state.equals(key.state); } return false; } diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed Jul 05 19:39:35 2017 +0200 @@ -44,6 +44,7 @@ import sun.awt.*; import sun.awt.datatransfer.DataTransferer; +import sun.java2d.opengl.OGLRenderQueue; import sun.lwawt.*; import sun.lwawt.LWWindowPeer.PeerType; import sun.security.action.GetBooleanAction; @@ -410,7 +411,11 @@ @Override public void sync() { - // TODO Auto-generated method stub + // flush the OGL pipeline (this is a no-op if OGL is not enabled) + OGLRenderQueue.sync(); + // setNeedsDisplay() selector was sent to the appropriate CALayer so now + // we have to flush the native selectors queue. + flushNativeSelectors(); } @Override @@ -813,6 +818,11 @@ private native boolean nativeSyncQueue(long timeout); + /** + * Just spin a single empty block synchronously. + */ + private static native void flushNativeSelectors(); + @Override public Clipboard createPlatformClipboard() { return new CClipboard("System"); diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/native/com/apple/laf/JRSUIController.m --- a/jdk/src/macosx/native/com/apple/laf/JRSUIController.m Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/native/com/apple/laf/JRSUIController.m Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -199,7 +199,7 @@ CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); CGContextRef cgRef = CGBitmapContextCreate(rawPixelData, imgW, imgH, 8, imgW * 4, colorspace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); CGColorSpaceRelease(colorspace); - CGContextScaleCTM(cgRef, imgW/w , imgH/h); + CGContextScaleCTM(cgRef, imgW/(w + x + x) , imgH/(h + y + y)); jint status = doPaintCGContext(cgRef, controlPtr, oldProperties, newProperties, x, y, w, h); CGContextRelease(cgRef); diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/native/sun/awt/AWTWindow.m --- a/jdk/src/macosx/native/sun/awt/AWTWindow.m Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m Wed Jul 05 19:39:35 2017 +0200 @@ -762,6 +762,10 @@ return lastKeyWindow; } +- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame { + return !NSEqualSizes(self.nsWindow.frame.size, newFrame.size); +} + @end // AWTWindow diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/native/sun/awt/CClipboard.h --- a/jdk/src/macosx/native/sun/awt/CClipboard.h Wed Jul 05 19:38:36 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#import -#import "jni.h" - -@interface CClipboard : NSObject { - jobject fClipboardOwner; - - // Track pasteboard changes. Initialized once at the start, and then updated - // on an application resume event. If it's different than the last time we claimed - // the clipboard that means we lost the clipboard to someone else. - NSInteger fChangeCount; -} - -+ (CClipboard *) sharedClipboard; - -- (void) javaDeclareTypes:(NSArray *)inTypes withOwner:(jobject)inClipboard jniEnv:(JNIEnv *)inEnv; -- (void) javaSetData:(NSData *)inData forType:(NSString *) inFormat; - -- (NSArray *) javaGetTypes; -- (NSData *) javaGetDataForType:(NSString *)inFormat; - -@end diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/native/sun/awt/CClipboard.m --- a/jdk/src/macosx/native/sun/awt/CClipboard.m Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/native/sun/awt/CClipboard.m Wed Jul 05 19:39:35 2017 +0200 @@ -23,70 +23,28 @@ * questions. */ -#import "CClipboard.h" #import "CDataTransferer.h" #import "ThreadUtilities.h" #import "jni_util.h" #import #import -static CClipboard *sClipboard = nil; - -// -// CClipboardUpdate is used for mulitple calls to setData that happen before -// the model and AppKit can get back in sync. -// - -@interface CClipboardUpdate : NSObject { - NSData *fData; - NSString *fFormat; -} - -- (id)initWithData:(NSData *)inData withFormat:(NSString *)inFormat; -- (NSData *)data; -- (NSString *)format; - -@end - -@implementation CClipboardUpdate - -- (id)initWithData:(NSData *)inData withFormat:(NSString *)inFormat -{ - self = [super init]; +@interface CClipboard : NSObject { } +@property NSInteger changeCount; +@property jobject clipboardOwner; - if (self != nil) { - fData = [inData retain]; - fFormat = [inFormat retain]; - } - - return self; -} - -- (void)dealloc -{ - [fData release]; - fData = nil; - - [fFormat release]; - fFormat = nil; - - [super dealloc]; -} - -- (NSData *)data { - return fData; -} - -- (NSString *)format { - return fFormat; -} ++ (CClipboard*)sharedClipboard; +- (void)declareTypes:(NSArray *)types withOwner:(jobject)owner jniEnv:(JNIEnv*)env; +- (void)checkPasteboard:(id)sender; @end @implementation CClipboard +@synthesize changeCount = _changeCount; +@synthesize clipboardOwner = _clipboardOwner; -// Clipboard creation is synchronized at the Java level. -+ (CClipboard *) sharedClipboard -{ +// Clipboard creation is synchronized at the Java level ++ (CClipboard*)sharedClipboard { + static CClipboard* sClipboard = nil; if (sClipboard == nil) { sClipboard = [[CClipboard alloc] init]; [[NSNotificationCenter defaultCenter] addObserver:sClipboard selector: @selector(checkPasteboard:) @@ -97,90 +55,38 @@ return sClipboard; } -- (id) init -{ - self = [super init]; - - if (self != nil) { - fChangeCount = [[NSPasteboard generalPasteboard] changeCount]; +- (id)init { + if (self = [super init]) { + self.changeCount = [[NSPasteboard generalPasteboard] changeCount]; } - return self; } -- (void) javaDeclareTypes:(NSArray *)inTypes withOwner:(jobject)inClipboard jniEnv:(JNIEnv *)inEnv { - +- (void)declareTypes:(NSArray*)types withOwner:(jobject)owner jniEnv:(JNIEnv*)env { @synchronized(self) { - if (inClipboard != NULL) { - if (fClipboardOwner != NULL) { - JNFDeleteGlobalRef(inEnv, fClipboardOwner); + if (owner != NULL) { + if (self.clipboardOwner != NULL) { + JNFDeleteGlobalRef(env, self.clipboardOwner); } - fClipboardOwner = JNFNewGlobalRef(inEnv, inClipboard); + self.clipboardOwner = JNFNewGlobalRef(env, owner); } } - [ThreadUtilities performOnMainThread:@selector(_nativeDeclareTypes:) on:self withObject:inTypes waitUntilDone:YES]; -} - -- (void) _nativeDeclareTypes:(NSArray *)inTypes { - AWT_ASSERT_APPKIT_THREAD; - - fChangeCount = [[NSPasteboard generalPasteboard] declareTypes:inTypes owner:self]; -} - - -- (NSArray *) javaGetTypes { - - NSMutableArray *args = [NSMutableArray arrayWithCapacity:1]; - [ThreadUtilities performOnMainThread:@selector(_nativeGetTypes:) on:self withObject:args waitUntilDone:YES]; - return [args lastObject]; -} - -- (void) _nativeGetTypes:(NSMutableArray *)args { - AWT_ASSERT_APPKIT_THREAD; - - [args addObject:[[NSPasteboard generalPasteboard] types]]; + [ThreadUtilities performOnMainThreadWaiting:YES block:^() { + self.changeCount = [[NSPasteboard generalPasteboard] declareTypes:types owner:self]; + }]; } -- (void) javaSetData:(NSData *)inData forType:(NSString *) inFormat { - - CClipboardUpdate *newUpdate = [[CClipboardUpdate alloc] initWithData:inData withFormat:inFormat]; - [ThreadUtilities performOnMainThread:@selector(_nativeSetData:) on:self withObject:newUpdate waitUntilDone:YES]; - [newUpdate release]; -} - -- (void) _nativeSetData:(CClipboardUpdate *)newUpdate { - AWT_ASSERT_APPKIT_THREAD; - - [[NSPasteboard generalPasteboard] setData:[newUpdate data] forType:[newUpdate format]]; -} - -- (NSData *) javaGetDataForType:(NSString *) inFormat { +- (void)checkPasteboard:(id)sender { - NSMutableArray *args = [NSMutableArray arrayWithObject:inFormat]; - [ThreadUtilities performOnMainThread:@selector(_nativeGetDataForType:) on:self withObject:args waitUntilDone:YES]; - return [args lastObject]; -} - -- (void) _nativeGetDataForType:(NSMutableArray *) args { - AWT_ASSERT_APPKIT_THREAD; - - NSData *returnValue = [[NSPasteboard generalPasteboard] dataForType:[args objectAtIndex:0]]; - - if (returnValue) [args replaceObjectAtIndex:0 withObject:returnValue]; - else [args removeLastObject]; -} - -- (void) checkPasteboard:(id)application { - AWT_ASSERT_APPKIT_THREAD; - // This is called via NSApplicationDidBecomeActiveNotification. // If the change count on the general pasteboard is different than when we set it // someone else put data on the clipboard. That means the current owner lost ownership. + NSInteger newChangeCount = [[NSPasteboard generalPasteboard] changeCount]; - - if (fChangeCount != newChangeCount) { - fChangeCount = newChangeCount; + + if (self.changeCount != newChangeCount) { + self.changeCount = newChangeCount; // Notify that the content might be changed static JNF_CLASS_CACHE(jc_CClipboard, "sun/lwawt/macosx/CClipboard"); @@ -191,11 +97,11 @@ // If we have a Java pasteboard owner, tell it that it doesn't own the pasteboard anymore. static JNF_MEMBER_CACHE(jm_lostOwnership, jc_CClipboard, "notifyLostOwnership", "()V"); @synchronized(self) { - if (fClipboardOwner) { + if (self.clipboardOwner) { JNIEnv *env = [ThreadUtilities getJNIEnv]; - JNFCallVoidMethod(env, fClipboardOwner, jm_lostOwnership); // AWT_THREADING Safe (event) - JNFDeleteGlobalRef(env, fClipboardOwner); - fClipboardOwner = NULL; + JNFCallVoidMethod(env, self.clipboardOwner, jm_lostOwnership); // AWT_THREADING Safe (event) + JNFDeleteGlobalRef(env, self.clipboardOwner); + self.clipboardOwner = NULL; } } } @@ -225,7 +131,7 @@ } (*env)->ReleasePrimitiveArrayCritical(env, inTypes, elements, JNI_ABORT); - [[CClipboard sharedClipboard] javaDeclareTypes:formatArray withOwner:inJavaClip jniEnv:env]; + [[CClipboard sharedClipboard] declareTypes:formatArray withOwner:inJavaClip jniEnv:env]; JNF_COCOA_EXIT(env); } @@ -248,7 +154,9 @@ NSData *bytesAsData = [NSData dataWithBytes:rawBytes length:nBytes]; (*env)->ReleasePrimitiveArrayCritical(env, inBytes, rawBytes, JNI_ABORT); NSString *format = formatForIndex(inFormat); - [[CClipboard sharedClipboard] javaSetData:bytesAsData forType:format]; + [ThreadUtilities performOnMainThreadWaiting:YES block:^() { + [[NSPasteboard generalPasteboard] setData:bytesAsData forType:format]; + }]; JNF_COCOA_EXIT(env); } @@ -263,7 +171,12 @@ jlongArray returnValue = NULL; JNF_COCOA_ENTER(env); - NSArray *dataTypes = [[CClipboard sharedClipboard] javaGetTypes]; + __block NSArray* dataTypes; + [ThreadUtilities performOnMainThreadWaiting:YES block:^() { + dataTypes = [[[NSPasteboard generalPasteboard] types] retain]; + }]; + [dataTypes autorelease]; + NSUInteger nFormats = [dataTypes count]; NSUInteger knownFormats = 0; NSUInteger i; @@ -320,11 +233,16 @@ JNF_COCOA_ENTER(env); NSString *formatAsString = formatForIndex(format); - NSData *clipData = [[CClipboard sharedClipboard] javaGetDataForType:formatAsString]; - + __block NSData* clipData; + [ThreadUtilities performOnMainThreadWaiting:YES block:^() { + clipData = [[[NSPasteboard generalPasteboard] dataForType:formatAsString] retain]; + }]; + if (clipData == NULL) { [JNFException raise:env as:"java/io/IOException" reason:"Font transform has NaN position"]; return NULL; + } else { + [clipData autorelease]; } NSUInteger dataSize = [clipData length]; @@ -350,13 +268,13 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CClipboard_checkPasteboard (JNIEnv *env, jobject inObject ) { - JNF_COCOA_ENTER(env); +JNF_COCOA_ENTER(env); [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ [[CClipboard sharedClipboard] checkPasteboard:nil]; }]; - JNF_COCOA_EXIT(env); +JNF_COCOA_EXIT(env); } diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/native/sun/awt/CImage.m --- a/jdk/src/macosx/native/sun/awt/CImage.m Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/native/sun/awt/CImage.m Wed Jul 05 19:39:35 2017 +0200 @@ -379,7 +379,7 @@ return getOrder(size1.width <= size2.width && size1.height <= size2.height); }]; - NSMutableArray *sortedPixelSizes = [[NSMutableArray alloc] init]; + NSMutableArray *sortedPixelSizes = [[[NSMutableArray alloc] init] autorelease]; NSSize lastSize = [[sortedImageRepresentations lastObject] size]; NSUInteger i = [sortedImageRepresentations indexOfObjectPassingTest: diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/native/sun/awt/CTextPipe.m --- a/jdk/src/macosx/native/sun/awt/CTextPipe.m Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/native/sun/awt/CTextPipe.m Wed Jul 05 19:39:35 2017 +0200 @@ -147,7 +147,7 @@ CGAffineTransform invTx = CGAffineTransformInvert(strike->fTx); - NSUInteger i; + NSInteger i; for (i = 0; i < length; i++) { CGGlyph glyph = glyphs[i]; @@ -355,19 +355,31 @@ static JNF_CLASS_CACHE(jc_StandardGlyphVector_GlyphTransformInfo, "sun/font/StandardGlyphVector$GlyphTransformInfo"); static JNF_MEMBER_CACHE(jm_StandardGlyphVector_GlyphTransformInfo_transforms, jc_StandardGlyphVector_GlyphTransformInfo, "transforms", "[D"); jdoubleArray g_gtiTransformsArray = JNFGetObjectField(env, gti, jm_StandardGlyphVector_GlyphTransformInfo_transforms); //(*env)->GetObjectField(env, gti, g_gtiTransforms); + if (g_gtiTransformsArray == NULL) { + return; + } jdouble *g_gvTransformsAsDoubles = (*env)->GetPrimitiveArrayCritical(env, g_gtiTransformsArray, NULL); + if (g_gvTransformsAsDoubles == NULL) { + (*env)->DeleteLocalRef(env, g_gtiTransformsArray); + return; + } static JNF_MEMBER_CACHE(jm_StandardGlyphVector_GlyphTransformInfo_indices, jc_StandardGlyphVector_GlyphTransformInfo, "indices", "[I"); jintArray g_gtiTXIndicesArray = JNFGetObjectField(env, gti, jm_StandardGlyphVector_GlyphTransformInfo_indices); jint *g_gvTXIndicesAsInts = (*env)->GetPrimitiveArrayCritical(env, g_gtiTXIndicesArray, NULL); - + if (g_gvTXIndicesAsInts == NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTransformsArray, g_gvTransformsAsDoubles, JNI_ABORT); + (*env)->DeleteLocalRef(env, g_gtiTransformsArray); + (*env)->DeleteLocalRef(env, g_gtiTXIndicesArray); + return; + } // slowest case, we have per-glyph transforms, and possibly glyph substitution as well JavaCT_DrawGlyphVector(qsdo, strike, useSubstituion, uniChars, glyphs, advances, g_gvTXIndicesAsInts, g_gvTransformsAsDoubles, length); (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTransformsArray, g_gvTransformsAsDoubles, JNI_ABORT); - (*env)->DeleteLocalRef(env, g_gtiTransformsArray); + (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTXIndicesArray, g_gvTXIndicesAsInts, JNI_ABORT); - (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTXIndicesArray, g_gvTXIndicesAsInts, JNI_ABORT); + (*env)->DeleteLocalRef(env, g_gtiTransformsArray); (*env)->DeleteLocalRef(env, g_gtiTXIndicesArray); } @@ -403,6 +415,9 @@ { // fill the glyph buffer jint *glyphsAsInts = (*env)->GetPrimitiveArrayCritical(env, glyphsArray, NULL); + if (glyphsAsInts == NULL) { + return; + } // if a glyph code from Java is negative, that means it is really a unicode value // which we can use in CoreText to strike the character in another font @@ -429,11 +444,15 @@ // fill the advance buffer static JNF_MEMBER_CACHE(jm_StandardGlyphVector_positions, jc_StandardGlyphVector, "positions", "[F"); jfloatArray posArray = JNFGetObjectField(env, gVector, jm_StandardGlyphVector_positions); - if (posArray != NULL) - { + jfloat *positions = NULL; + if (posArray != NULL) { // in this case, the positions have already been pre-calculated for us on the Java side - - jfloat *positions = (*env)->GetPrimitiveArrayCritical(env, posArray, NULL); + positions = (*env)->GetPrimitiveArrayCritical(env, posArray, NULL); + if (positions == NULL) { + (*env)->DeleteLocalRef(env, posArray); + } + } + if (positions != NULL) { CGPoint prev; prev.x = positions[0]; prev.y = positions[1]; diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m --- a/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m Wed Jul 05 19:39:35 2017 +0200 @@ -242,11 +242,15 @@ jsize count = [ignoredKeys count]; JNIEnv *env = [ThreadUtilities getJNIEnv]; - jclass clazz = (*env)->FindClass(env, "java/lang/String"); - result = (*env)->NewObjectArray(env, count, clazz, NULL); // AWT_THREADING Safe (known object) - (*env)->DeleteLocalRef(env, clazz); - NSUInteger i; + static JNF_CLASS_CACHE(jc_String, "java/lang/String"); + result = JNFNewObjectArray(env, &jc_String, count); + if (!result) { + NSLog(@"In %s, can't create Java array of String objects", __FUNCTION__); + return; + } + + NSInteger i; for (i = 0; i < count; i++) { jstring jString = JNFNSToJavaString(env, [ignoredKeys objectAtIndex:i]); (*env)->SetObjectArrayElement(env, result, i, jString); @@ -281,7 +285,7 @@ jsize arrayLen = (*env)->GetArrayLength(env, jchildrenAndRoles); NSMutableArray *children = [NSMutableArray arrayWithCapacity:arrayLen/2]; //childrenAndRoles array contains two elements (child, role) for each child - NSUInteger i; + NSInteger i; NSUInteger childIndex = (whichChildren >= 0) ? whichChildren : 0; // if we're getting one particular child, make sure to set its index correctly for(i = 0; i < arrayLen; i+=2) { @@ -377,8 +381,13 @@ // Get all the other accessibility attributes states we need in one swell foop. // javaRole isn't pulled in because we need protected access to AccessibleRole.key jbooleanArray attributeStates = JNFCallStaticObjectMethod(env, jm_getInitialAttributeStates, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) - if (attributeStates == NULL) return NULL; + if (attributeStates == NULL) return nil; jboolean *attributeStatesArray = (*env)->GetBooleanArrayElements(env, attributeStates, 0); + if (attributeStatesArray == NULL) { + // Note: Java will not be on the stack here so a java exception can't happen and no need to call ExceptionCheck. + NSLog(@"%s failed calling GetBooleanArrayElements", __FUNCTION__); + return nil; + } // if there's a component, it can be enabled and it has a size/position if (attributeStatesArray[0]) { @@ -1206,7 +1215,7 @@ // Go through the tabs and find selAccessible _numTabs = [tabs count]; JavaComponentAccessibility *aTab; - NSUInteger i; + NSInteger i; for (i = 0; i < _numTabs; i++) { aTab = (JavaComponentAccessibility *)[tabs objectAtIndex:i]; if ([aTab isAccessibleWithEnv:env forAccessible:selAccessible]) { @@ -1233,7 +1242,7 @@ NSString *tabJavaRole = JNFJavaToNSString(env, JNFGetObjectField(env, jtabJavaRole, sjf_key)); - NSUInteger i; + NSInteger i; NSUInteger tabIndex = (whichTabs >= 0) ? whichTabs : 0; // if we're getting one particular child, make sure to set its index correctly for(i = 0; i < arrayLen; i+=2) { jobject jtab = (*env)->GetObjectArrayElement(env, jtabsAndRoles, i); diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/native/sun/awt/JavaTextAccessibility.m --- a/jdk/src/macosx/native/sun/awt/JavaTextAccessibility.m Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/native/sun/awt/JavaTextAccessibility.m Wed Jul 05 19:39:35 2017 +0200 @@ -40,6 +40,11 @@ */ NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) { jint *values = (*env)->GetIntArrayElements(env, array, 0); + if (values == NULL) { + // Note: Java will not be on the stack here so a java exception can't happen and no need to call ExceptionCheck. + NSLog(@"%s failed calling GetIntArrayElements", __FUNCTION__); + return nil; + }; NSValue *value = [NSValue valueWithRange:NSMakeRange(values[0], values[1] - values[0])]; (*env)->ReleaseIntArrayElements(env, array, values, 0); return value; @@ -285,6 +290,11 @@ // We cheat because we know that the array is 4 elements long (x, y, width, height) jdouble *values = (*env)->GetDoubleArrayElements(env, axBounds, 0); + if (values == NULL) { + // Note: Java will not be on the stack here so a java exception can't happen and no need to call ExceptionCheck. + NSLog(@"%s failed calling GetDoubleArrayElements", __FUNCTION__); + return nil; + }; NSRect bounds; bounds.origin.x = values[0]; bounds.origin.y = [[[[self view] window] screen] frame].size.height - values[1] - values[3]; //values[1] is y-coord from top-left of screen. Flip. Account for the height (values[3]) when flipping diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/native/sun/awt/LWCToolkit.m --- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m Wed Jul 05 19:39:35 2017 +0200 @@ -144,6 +144,18 @@ return JNI_FALSE; } +/* + * Class: sun_lwawt_macosx_LWCToolkit + * Method: flushNativeSelectors + * Signature: ()J + */ +JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_flushNativeSelectors +(JNIEnv *env, jclass clz) +{ +JNF_COCOA_ENTER(env); + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){}]; +JNF_COCOA_EXIT(env); +} static JNF_CLASS_CACHE(jc_Component, "java/awt/Component"); static JNF_MEMBER_CACHE(jf_Component_appContext, jc_Component, "appContext", "Lsun/awt/AppContext;"); diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/native/sun/awt/splashscreen/splashscreen_sys.m --- a/jdk/src/macosx/native/sun/awt/splashscreen/splashscreen_sys.m Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/native/sun/awt/splashscreen/splashscreen_sys.m Wed Jul 05 19:39:35 2017 +0200 @@ -142,9 +142,16 @@ splash->screenFormat.byteOrder = 1 ? BYTE_ORDER_LSBFIRST : BYTE_ORDER_MSBFIRST; splash->screenFormat.depthBytes = 4; - [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^() { - [NSApplicationAWT runAWTLoopWithApp:[NSApplicationAWT sharedApplication]]; - }]; + // If this property is present we are running SWT and should not start a runLoop + // Can't check if running SWT in webstart, so splash screen in webstart SWT + // applications is not supported + char envVar[80]; + snprintf(envVar, sizeof(envVar), "JAVA_STARTED_ON_FIRST_THREAD_%d", getpid()); + if (getenv(envVar) == NULL) { + [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^() { + [NSApplicationAWT runAWTLoopWithApp:[NSApplicationAWT sharedApplication]]; + }]; + } } void diff -r a77941f17614 -r 0d1f816217dc jdk/src/macosx/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c --- a/jdk/src/macosx/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/macosx/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c Wed Jul 05 19:39:35 2017 +0200 @@ -154,7 +154,10 @@ if (pmStr != NULL) { CFStringGetCString(pmStr, buf, BUFLEN, kCFStringEncodingUTF8); CFRelease(pmStr); - (*env)->SetObjectArrayElement(env, ampms, 1, (*env)->NewStringUTF(env, buf)); + tmp_string = (*env)->NewStringUTF(env, buf); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, ampms, 1, tmp_string); + } } } CFRelease(df); diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/back/InterfaceTypeImpl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/back/InterfaceTypeImpl.c Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "util.h" +#include "InterfaceTypeImpl.h" +#include "inStream.h" +#include "outStream.h" + +static jboolean +invokeStatic(PacketInputStream *in, PacketOutputStream *out) +{ + return sharedInvoke(in, out); +} + +void *InterfaceType_Cmds[] = { (void *)0x1 + , (void *)invokeStatic +}; diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/back/InterfaceTypeImpl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/back/InterfaceTypeImpl.h Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +extern void *InterfaceType_Cmds[]; diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/back/VirtualMachineImpl.c --- a/jdk/src/share/back/VirtualMachineImpl.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/back/VirtualMachineImpl.c Wed Jul 05 19:39:35 2017 +0200 @@ -36,7 +36,7 @@ static char *versionName = "Java Debug Wire Protocol (Reference Implementation)"; static int majorVersion = 1; /* JDWP major version */ -static int minorVersion = 6; /* JDWP minor version */ +static int minorVersion = 8; /* JDWP minor version */ static jboolean version(PacketInputStream *in, PacketOutputStream *out) diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/back/debugDispatch.c --- a/jdk/src/share/back/debugDispatch.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/back/debugDispatch.c Wed Jul 05 19:39:35 2017 +0200 @@ -29,6 +29,7 @@ #include "VirtualMachineImpl.h" #include "ReferenceTypeImpl.h" #include "ClassTypeImpl.h" +#include "InterfaceTypeImpl.h" #include "ArrayTypeImpl.h" #include "FieldImpl.h" #include "MethodImpl.h" @@ -67,6 +68,7 @@ l1Array[JDWP_COMMAND_SET(VirtualMachine)] = (void *)VirtualMachine_Cmds; l1Array[JDWP_COMMAND_SET(ReferenceType)] = (void *)ReferenceType_Cmds; l1Array[JDWP_COMMAND_SET(ClassType)] = (void *)ClassType_Cmds; + l1Array[JDWP_COMMAND_SET(InterfaceType)] = (void *)InterfaceType_Cmds; l1Array[JDWP_COMMAND_SET(ArrayType)] = (void *)ArrayType_Cmds; l1Array[JDWP_COMMAND_SET(Field)] = (void *)Field_Cmds; diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/back/util.c --- a/jdk/src/share/back/util.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/back/util.c Wed Jul 05 19:39:35 2017 +0200 @@ -591,6 +591,8 @@ invokeType = INVOKE_CONSTRUCTOR; } else if (inStream_command(in) == JDWP_COMMAND(ClassType, InvokeMethod)) { invokeType = INVOKE_STATIC; + } else if (inStream_command(in) == JDWP_COMMAND(InterfaceType, InvokeMethod)) { + invokeType = INVOKE_STATIC; } else if (inStream_command(in) == JDWP_COMMAND(ObjectReference, InvokeMethod)) { invokeType = INVOKE_INSTANCE; } else { diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/beans/util/Cache.java --- a/jdk/src/share/classes/com/sun/beans/util/Cache.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/com/sun/beans/util/Cache.java Wed Jul 05 19:39:35 2017 +0200 @@ -119,13 +119,13 @@ synchronized (this.queue) { // synchronized search improves stability // we must create and add new value if there are no needed entry - int index = index(hash, this.table); - current = getEntryValue(key, hash, this.table[index]); + current = getEntryValue(key, hash, this.table[index(hash, this.table)]); if (current != null) { return current; } V value = create(key); Objects.requireNonNull(value, "value"); + int index = index(hash, this.table); this.table[index] = new CacheEntry<>(hash, key, value, this.table[index]); if (++this.size >= this.threshold) { if (this.table.length == MAXIMUM_CAPACITY) { diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifScrollBarUI.java --- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifScrollBarUI.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifScrollBarUI.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,17 +24,19 @@ */ package com.sun.java.swing.plaf.motif; -import javax.swing.*; -import javax.swing.event.*; -import javax.swing.plaf.*; -import javax.swing.border.*; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JScrollBar; +import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicScrollBarUI; -import java.awt.Dimension; -import java.awt.Insets; -import java.awt.Rectangle; -import java.awt.Graphics; -import java.awt.Color; +import static sun.swing.SwingUtilities2.drawHLine; +import static sun.swing.SwingUtilities2.drawVLine; /** @@ -74,17 +76,13 @@ return new MotifScrollBarButton(orientation); } - public void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) { g.setColor(trackColor); g.fillRect(trackBounds.x, trackBounds.y, trackBounds.width, trackBounds.height); } - - public void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) - { - - if(thumbBounds.isEmpty() || !scrollbar.isEnabled()) { + public void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { + if (thumbBounds.isEmpty() || !scrollbar.isEnabled()) { return; } @@ -93,15 +91,15 @@ g.translate(thumbBounds.x, thumbBounds.y); g.setColor(thumbColor); - g.fillRect(0, 0, w-1, h-1); + g.fillRect(0, 0, w - 1, h - 1); g.setColor(thumbHighlightColor); - g.drawLine(0, 0, 0, h-1); - g.drawLine(1, 0, w-1, 0); + drawVLine(g, 0, 0, h - 1); + drawHLine(g, 1, w - 1, 0); g.setColor(thumbLightShadowColor); - g.drawLine(1, h-1, w-1, h-1); - g.drawLine(w-1, 1, w-1, h-2); + drawHLine(g, 1, w - 1, h - 1); + drawVLine(g, w - 1, 1, h - 2); g.translate(-thumbBounds.x, -thumbBounds.y); } diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifSliderUI.java --- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifSliderUI.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifSliderUI.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,14 +25,17 @@ package com.sun.java.swing.plaf.motif; -import java.awt.*; -import java.awt.event.*; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Rectangle; -import javax.swing.*; -import javax.swing.event.*; -import javax.swing.plaf.*; +import javax.swing.JComponent; +import javax.swing.JSlider; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicSliderUI; -import javax.swing.plaf.basic.BasicSliderUI; +import static sun.swing.SwingUtilities2.drawHLine; +import static sun.swing.SwingUtilities2.drawVLine; /** * Motif Slider @@ -123,15 +126,15 @@ // highlight g.setColor(getHighlightColor()); - g.drawLine(0, 1, w - 1, 1); // top - g.drawLine(0, 1, 0, h); // left - g.drawLine(w/2, 2, w/2, h-1); // center + drawHLine(g, 0, w - 1, 1); // top + drawVLine(g, 0, 1, h); // left + drawVLine(g, w / 2, 2, h - 1); // center // shadow g.setColor(getShadowColor()); - g.drawLine(0, h, w - 1, h); // bottom - g.drawLine(w - 1, 1, w - 1, h); // right - g.drawLine(w/2 - 1, 2, w/2 - 1, h); // center + drawHLine(g, 0, w - 1, h); // bottom + drawVLine(g, w - 1, 1, h); // right + drawVLine(g, w / 2 - 1, 2, h); // center g.translate(-x, -(knobBounds.y-1)); } @@ -143,15 +146,15 @@ // highlight g.setColor(getHighlightColor()); - g.drawLine(1, y, w, y); // top - g.drawLine(1, y+1, 1, y+h-1); // left - g.drawLine(2, y+h/2, w-1, y+h/2); // center + drawHLine(g, 1, w, y); // top + drawVLine(g, 1, y + 1, y + h - 1); // left + drawHLine(g, 2, w - 1, y + h / 2); // center // shadow g.setColor(getShadowColor()); - g.drawLine(2, y+h-1, w, y+h-1); // bottom - g.drawLine(w, y+h-1, w, y); // right - g.drawLine(2, y+h/2-1, w-1, y+h/2-1); // center + drawHLine(g, 2, w, y + h - 1); // bottom + drawVLine(g, w, y + h - 1, y); // right + drawHLine(g, 2, w - 1, y + h / 2 - 1);// center g.translate(-(knobBounds.x-1), 0); } diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/jdi/ClassType.java --- a/jdk/src/share/classes/com/sun/jdi/ClassType.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/com/sun/jdi/ClassType.java Wed Jul 05 19:39:35 2017 +0200 @@ -103,7 +103,7 @@ *

* Object values must be assignment compatible with the field type * (This implies that the field type must be loaded through the - * enclosing class's class loader). Primitive values must be + * enclosing class' class loader). Primitive values must be * either assignment compatible with the field type or must be * convertible to the field type without loss of information. * See JLS section 5.2 for more information on assignment @@ -153,7 +153,7 @@ *

* Object arguments must be assignment compatible with the argument type * (This implies that the argument type must be loaded through the - * enclosing class's class loader). Primitive arguments must be + * enclosing class' class loader). Primitive arguments must be * either assignment compatible with the argument type or must be * convertible to the argument type without loss of information. * If the method being called accepts a variable number of arguments, @@ -216,7 +216,7 @@ * @return a {@link Value} mirror of the invoked method's return value. * @throws java.lang.IllegalArgumentException if the method is not * a member of this class or a superclass, if the size of the argument list - * does not match the number of declared arguemnts for the method, or + * does not match the number of declared arguments for the method, or * if the method is an initializer, constructor or static intializer. * @throws {@link InvalidTypeException} if any argument in the * argument list is not assignable to the corresponding method argument @@ -230,7 +230,7 @@ * @throws InvalidTypeException If the arguments do not meet this requirement -- * Object arguments must be assignment compatible with the argument * type. This implies that the argument type must be - * loaded through the enclosing class's class loader. + * loaded through the enclosing class' class loader. * Primitive arguments must be either assignment compatible with the * argument type or must be convertible to the argument type without loss * of information. See JLS section 5.2 for more information on assignment @@ -267,7 +267,7 @@ *

* Object arguments must be assignment compatible with the argument type * (This implies that the argument type must be loaded through the - * enclosing class's class loader). Primitive arguments must be + * enclosing class' class loader). Primitive arguments must be * either assignment compatible with the argument type or must be * convertible to the argument type without loss of information. * If the method being called accepts a variable number of arguments, @@ -335,7 +335,7 @@ * @throws InvalidTypeException If the arguments do not meet this requirement -- * Object arguments must be assignment compatible with the argument * type. This implies that the argument type must be - * loaded through the enclosing class's class loader. + * loaded through the enclosing class' class loader. * Primitive arguments must be either assignment compatible with the * argument type or must be convertible to the argument type without loss * of information. See JLS section 5.2 for more information on assignment diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/jdi/InterfaceType.java --- a/jdk/src/share/classes/com/sun/jdi/InterfaceType.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/com/sun/jdi/InterfaceType.java Wed Jul 05 19:39:35 2017 +0200 @@ -79,4 +79,123 @@ * If none exist, returns a zero length List. */ List implementors(); + + /** + * Invokes the specified static {@link Method} in the + * target VM. The + * specified method must be defined in this interface. + * The method must be a static method + * but not a static initializer. + *

+ * The method invocation will occur in the specified thread. + * Method invocation can occur only if the specified thread + * has been suspended by an event which occurred in that thread. + * Method invocation is not supported + * when the target VM has been suspended through + * {@link VirtualMachine#suspend} or when the specified thread + * is suspended through {@link ThreadReference#suspend}. + *

+ * The specified method is invoked with the arguments in the specified + * argument list. The method invocation is synchronous; this method + * does not return until the invoked method returns in the target VM. + * If the invoked method throws an exception, this method will throw + * an {@link InvocationException} which contains a mirror to the exception + * object thrown. + *

+ * Object arguments must be assignment compatible with the argument type + * (This implies that the argument type must be loaded through the + * enclosing class' class loader). Primitive arguments must be + * either assignment compatible with the argument type or must be + * convertible to the argument type without loss of information. + * If the method being called accepts a variable number of arguments, + * then the last argument type is an array of some component type. + * The argument in the matching position can be omitted, or can be null, + * an array of the same component type, or an argument of the + * component type followed by any number of other arguments of the same + * type. If the argument is omitted, then a 0 length array of the + * component type is passed. The component type can be a primitive type. + * Autoboxing is not supported. + * + * See Section 5.2 of + * The Java™ Language Specification + * for more information on assignment compatibility. + *

+ * By default, all threads in the target VM are resumed while + * the method is being invoked if they were previously + * suspended by an event or by {@link VirtualMachine#suspend} or + * {@link ThreadReference#suspend}. This is done to prevent the deadlocks + * that will occur if any of the threads own monitors + * that will be needed by the invoked method. + * Note, however, that this implicit resume acts exactly like + * {@link ThreadReference#resume}, so if the thread's suspend + * count is greater than 1, it will remain in a suspended state + * during the invocation and thus a deadlock could still occur. + * By default, when the invocation completes, + * all threads in the target VM are suspended, regardless their state + * before the invocation. + * It is possible that + * breakpoints or other events might occur during the invocation. + * This can cause deadlocks as described above. It can also cause a deadlock + * if invokeMethod is called from the client's event handler thread. In this + * case, this thread will be waiting for the invokeMethod to complete and + * won't read the EventSet that comes in for the new event. If this + * new EventSet is SUSPEND_ALL, then a deadlock will occur because no + * one will resume the EventSet. To avoid this, all EventRequests should + * be disabled before doing the invokeMethod, or the invokeMethod should + * not be done from the client's event handler thread. + *

+ * The resumption of other threads during the invocation can be prevented + * by specifying the {@link #INVOKE_SINGLE_THREADED} + * bit flag in the options argument; however, + * there is no protection against or recovery from the deadlocks + * described above, so this option should be used with great caution. + * Only the specified thread will be resumed (as described for all + * threads above). Upon completion of a single threaded invoke, the invoking thread + * will be suspended once again. Note that any threads started during + * the single threaded invocation will not be suspended when the + * invocation completes. + *

+ * If the target VM is disconnected during the invoke (for example, through + * {@link VirtualMachine#dispose}) the method invocation continues. + * + * @param thread the thread in which to invoke. + * @param method the {@link Method} to invoke. + * @param arguments the list of {@link Value} arguments bound to the + * invoked method. Values from the list are assigned to arguments + * in the order they appear in the method signature. + * @param options the integer bit flag options. + * @return a {@link Value} mirror of the invoked method's return value. + * @throws java.lang.IllegalArgumentException if the method is not + * a member of this interface, if the size of the argument list + * does not match the number of declared arguments for the method, or + * if the method is not static or is a static initializer. + * @throws {@link InvalidTypeException} if any argument in the + * argument list is not assignable to the corresponding method argument + * type. + * @throws ClassNotLoadedException if any argument type has not yet been loaded + * through the appropriate class loader. + * @throws IncompatibleThreadStateException if the specified thread has not + * been suspended by an event. + * @throws InvocationException if the method invocation resulted in + * an exception in the target VM. + * @throws InvalidTypeException If the arguments do not meet this requirement -- + * Object arguments must be assignment compatible with the argument + * type. This implies that the argument type must be + * loaded through the enclosing class' class loader. + * Primitive arguments must be either assignment compatible with the + * argument type or must be convertible to the argument type without loss + * of information. See JLS section 5.2 for more information on assignment + * compatibility. + * @throws VMCannotBeModifiedException if the VirtualMachine is read-only - see {@link VirtualMachine#canBeModified()}. + * + * @since 1.8 + */ + default Value invokeMethod(ThreadReference thread, Method method, + List arguments, int options) + throws InvalidTypeException, + ClassNotLoadedException, + IncompatibleThreadStateException, + InvocationException { + throw new UnsupportedOperationException(); + } } diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/jdi/Method.java --- a/jdk/src/share/classes/com/sun/jdi/Method.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/com/sun/jdi/Method.java Wed Jul 05 19:39:35 2017 +0200 @@ -138,6 +138,18 @@ boolean isAbstract(); /** + * Determine if this method is a default method + * + * @return true if the method is declared default; + * false otherwise + * + * @since 1.8 + */ + default boolean isDefault() { + throw new UnsupportedOperationException(); + } + + /** * Determine if this method is synchronized. * * @return true if the method is declared synchronized; diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/jdi/ObjectReference.java --- a/jdk/src/share/classes/com/sun/jdi/ObjectReference.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/com/sun/jdi/ObjectReference.java Wed Jul 05 19:39:35 2017 +0200 @@ -194,10 +194,10 @@ * {@link #INVOKE_NONVIRTUAL} bit flag in the options * argument. If this flag is set, the specified method is invoked * whether or not it is overridden for this object's runtime type. - * The method, in this case, must not belong to an interface and - * must not be abstract. This option is useful for performing method - * invocations like those done with the super keyword in - * the Java programming language. + * The method, in this case, must have an implementation, either in a class + * or an interface. This option is useful for performing method invocations + * like those done with the super keyword in the Java programming + * language. *

* By default, all threads in the target VM are resumed while * the method is being invoked if they were previously @@ -246,10 +246,10 @@ * @return a {@link Value} mirror of the invoked method's return value. * @throws java.lang.IllegalArgumentException if the method is not * a member of this object's class, if the size of the argument list - * does not match the number of declared arguemnts for the method, + * does not match the number of declared arguments for the method, * if the method is a constructor or static intializer, or * if {@link #INVOKE_NONVIRTUAL} is specified and the method is - * either abstract or an interface member. + * either abstract or a non-default interface member. * @throws {@link InvalidTypeException} if any argument in the * argument list is not assignable to the corresponding method argument * type. diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/media/sound/SoftEnvelopeGenerator.java --- a/jdk/src/share/classes/com/sun/media/sound/SoftEnvelopeGenerator.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/com/sun/media/sound/SoftEnvelopeGenerator.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,6 +118,7 @@ return null; } + @SuppressWarnings("fallthrough") public void processControlLogic() { for (int i = 0; i < used_count; i++) { @@ -170,6 +171,7 @@ this.delay[i][0] / 1200.0) / control_time); if (stage_ix[i] < 0) stage_ix[i] = 0; + // Fallthrough case EG_DELAY: if (stage_ix[i] == 0) { double attack = this.attack[i][0]; diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/tools/example/debug/expr/LValue.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/expr/LValue.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/expr/LValue.java Wed Jul 05 19:39:35 2017 +0200 @@ -559,6 +559,9 @@ } else if (refType instanceof ClassType) { ClassType clazz = (ClassType)refType; return jdiValue = clazz.invokeMethod(thread, matchingMethod, methodArguments, 0); + } else if (refType instanceof InterfaceType) { + InterfaceType iface = (InterfaceType)refType; + return jdiValue = iface.invokeMethod(thread, matchingMethod, methodArguments, 0); } else { throw new InvalidTypeException("Cannot invoke static method on " + refType.name()); diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java Wed Jul 05 19:39:35 2017 +0200 @@ -29,9 +29,27 @@ import java.util.*; -public class ClassTypeImpl extends ReferenceTypeImpl +final public class ClassTypeImpl extends InvokableTypeImpl implements ClassType { + private static class IResult implements InvocationResult { + final private JDWP.ClassType.InvokeMethod rslt; + + public IResult(JDWP.ClassType.InvokeMethod rslt) { + this.rslt = rslt; + } + + @Override + public ObjectReferenceImpl getException() { + return rslt.exception; + } + + @Override + public ValueImpl getResult() { + return rslt.returnValue; + } + } + private boolean cachedSuperclass = false; private ClassType superclass = null; private int lastLine = -1; @@ -65,6 +83,7 @@ return superclass; } + @Override public List interfaces() { if (interfaces == null) { interfaces = getInterfaces(); @@ -72,26 +91,9 @@ return interfaces; } - void addInterfaces(List list) { - List immediate = interfaces(); - list.addAll(interfaces()); - - Iterator iter = immediate.iterator(); - while (iter.hasNext()) { - InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); - interfaze.addSuperinterfaces(list); - } - - ClassTypeImpl superclass = (ClassTypeImpl)superclass(); - if (superclass != null) { - superclass.addInterfaces(list); - } - } - - public List allInterfaces() { - List all = new ArrayList(); - addInterfaces(all); - return all; + @Override + public List allInterfaces() { + return getAllInterfaces(); } public List subclasses() { @@ -159,28 +161,6 @@ } } - PacketStream sendInvokeCommand(final ThreadReferenceImpl thread, - final MethodImpl method, - final ValueImpl[] args, - final int options) { - CommandSender sender = - new CommandSender() { - public PacketStream send() { - return JDWP.ClassType.InvokeMethod.enqueueCommand( - vm, ClassTypeImpl.this, thread, - method.ref(), args, options); - } - }; - - PacketStream stream; - if ((options & INVOKE_SINGLE_THREADED) != 0) { - stream = thread.sendResumingCommand(sender); - } else { - stream = vm.sendResumingCommand(sender); - } - return stream; - } - PacketStream sendNewInstanceCommand(final ThreadReferenceImpl thread, final MethodImpl method, final ValueImpl[] args, @@ -203,52 +183,6 @@ return stream; } - public Value invokeMethod(ThreadReference threadIntf, Method methodIntf, - List origArguments, int options) - throws InvalidTypeException, - ClassNotLoadedException, - IncompatibleThreadStateException, - InvocationException { - validateMirror(threadIntf); - validateMirror(methodIntf); - validateMirrorsOrNulls(origArguments); - - MethodImpl method = (MethodImpl)methodIntf; - ThreadReferenceImpl thread = (ThreadReferenceImpl)threadIntf; - - validateMethodInvocation(method); - - List arguments = method.validateAndPrepareArgumentsForInvoke(origArguments); - - ValueImpl[] args = arguments.toArray(new ValueImpl[0]); - JDWP.ClassType.InvokeMethod ret; - try { - PacketStream stream = - sendInvokeCommand(thread, method, args, options); - ret = JDWP.ClassType.InvokeMethod.waitForReply(vm, stream); - } catch (JDWPException exc) { - if (exc.errorCode() == JDWP.Error.INVALID_THREAD) { - throw new IncompatibleThreadStateException(); - } else { - throw exc.toJDIException(); - } - } - - /* - * There is an implict VM-wide suspend at the conclusion - * of a normal (non-single-threaded) method invoke - */ - if ((options & INVOKE_SINGLE_THREADED) == 0) { - vm.notifySuspend(); - } - - if (ret.exception != null) { - throw new InvocationException(ret.exception); - } else { - return ret.returnValue; - } - } - public ObjectReference newInstance(ThreadReference threadIntf, Method methodIntf, List origArguments, @@ -311,58 +245,6 @@ return method; } - public List allMethods() { - ArrayList list = new ArrayList(methods()); - - ClassType clazz = superclass(); - while (clazz != null) { - list.addAll(clazz.methods()); - clazz = clazz.superclass(); - } - - /* - * Avoid duplicate checking on each method by iterating through - * duplicate-free allInterfaces() rather than recursing - */ - for (InterfaceType interfaze : allInterfaces()) { - list.addAll(interfaze.methods()); - } - - return list; - } - - List inheritedTypes() { - List inherited = new ArrayList(); - if (superclass() != null) { - inherited.add(0, (ReferenceType)superclass()); /* insert at front */ - } - for (ReferenceType rt : interfaces()) { - inherited.add(rt); - } - return inherited; - } - - void validateMethodInvocation(Method method) - throws InvalidTypeException, - InvocationException { - /* - * Method must be in this class or a superclass. - */ - ReferenceTypeImpl declType = (ReferenceTypeImpl)method.declaringType(); - if (!declType.isAssignableFrom(this)) { - throw new IllegalArgumentException("Invalid method"); - } - - /* - * Method must be a static and not a static initializer - */ - if (!method.isStatic()) { - throw new IllegalArgumentException("Cannot invoke instance method on a class type"); - } else if (method.isStaticInitializer()) { - throw new IllegalArgumentException("Cannot invoke static initializer"); - } - } - void validateConstructorInvocation(Method method) throws InvalidTypeException, InvocationException { @@ -382,51 +264,33 @@ } } - @Override - void addVisibleMethods(Map methodMap, Set seenInterfaces) { - /* - * Add methods from - * parent types first, so that the methods in this class will - * overwrite them in the hash table - */ - - Iterator iter = interfaces().iterator(); - while (iter.hasNext()) { - InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); - if (!seenInterfaces.contains(interfaze)) { - interfaze.addVisibleMethods(methodMap, seenInterfaces); - seenInterfaces.add(interfaze); - } - } - - ClassTypeImpl clazz = (ClassTypeImpl)superclass(); - if (clazz != null) { - clazz.addVisibleMethods(methodMap, seenInterfaces); - } - - addToMethodMap(methodMap, methods()); - } - - boolean isAssignableTo(ReferenceType type) { - ClassTypeImpl superclazz = (ClassTypeImpl)superclass(); - if (this.equals(type)) { - return true; - } else if ((superclazz != null) && superclazz.isAssignableTo(type)) { - return true; - } else { - List interfaces = interfaces(); - Iterator iter = interfaces.iterator(); - while (iter.hasNext()) { - InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); - if (interfaze.isAssignableTo(type)) { - return true; - } - } - return false; - } - } public String toString() { return "class " + name() + " (" + loaderString() + ")"; } + + @Override + CommandSender getInvokeMethodSender(ThreadReferenceImpl thread, + MethodImpl method, + ValueImpl[] args, + int options) { + return () -> + JDWP.ClassType.InvokeMethod.enqueueCommand(vm, + ClassTypeImpl.this, + thread, + method.ref(), + args, + options); + } + + @Override + InvocationResult waitForReply(PacketStream stream) throws JDWPException { + return new IResult(JDWP.ClassType.InvokeMethod.waitForReply(vm, stream)); + } + + @Override + boolean canInvoke(Method method) { + // Method must be in this class or a superclass. + return ((ReferenceTypeImpl)method.declaringType()).isAssignableFrom(this); + } } diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java Wed Jul 05 19:39:35 2017 +0200 @@ -29,14 +29,31 @@ import java.util.List; import java.util.ArrayList; -import java.util.Map; -import java.util.Iterator; import java.util.Collections; import java.util.Set; import java.lang.ref.SoftReference; -public class InterfaceTypeImpl extends ReferenceTypeImpl - implements InterfaceType { +final public class InterfaceTypeImpl extends InvokableTypeImpl + implements InterfaceType { + + private static class IResult implements InvocationResult { + final private JDWP.InterfaceType.InvokeMethod rslt; + + public IResult(JDWP.InterfaceType.InvokeMethod rslt) { + this.rslt = rslt; + } + + @Override + public ObjectReferenceImpl getException() { + return rslt.exception; + } + + @Override + public ValueImpl getResult() { + return rslt.returnValue; + } + + } private SoftReference> superinterfacesRef = null; @@ -81,102 +98,6 @@ return implementors; } - @Override - void addVisibleMethods(Map methodMap, Set seenInterfaces) { - /* - * Add methods from - * parent types first, so that the methods in this class will - * overwrite them in the hash table - */ - - for (InterfaceType interfaze : superinterfaces()) { - if (!seenInterfaces.contains(interfaze)) { - ((InterfaceTypeImpl)interfaze).addVisibleMethods(methodMap, seenInterfaces); - seenInterfaces.add(interfaze); - } - } - - addToMethodMap(methodMap, methods()); - } - - public List allMethods() { - ArrayList list = new ArrayList(methods()); - - /* - * It's more efficient if don't do this - * recursively. - */ - for (InterfaceType interfaze : allSuperinterfaces()) { - list.addAll(interfaze.methods()); - } - - return list; - } - - List allSuperinterfaces() { - ArrayList list = new ArrayList(); - addSuperinterfaces(list); - return list; - } - - void addSuperinterfaces(List list) { - /* - * This code is a little strange because it - * builds the list with a more suitable order than the - * depth-first approach a normal recursive solution would - * take. Instead, all direct superinterfaces precede all - * indirect ones. - */ - - /* - * Get a list of direct superinterfaces that's not already in the - * list being built. - */ - List immediate = new ArrayList(superinterfaces()); - Iterator iter = immediate.iterator(); - while (iter.hasNext()) { - InterfaceType interfaze = iter.next(); - if (list.contains(interfaze)) { - iter.remove(); - } - } - - /* - * Add all new direct superinterfaces - */ - list.addAll(immediate); - - /* - * Recurse for all new direct superinterfaces. - */ - iter = immediate.iterator(); - while (iter.hasNext()) { - InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); - interfaze.addSuperinterfaces(list); - } - } - - boolean isAssignableTo(ReferenceType type) { - - // Exact match? - if (this.equals(type)) { - return true; - } else { - // Try superinterfaces. - for (InterfaceType interfaze : superinterfaces()) { - if (((InterfaceTypeImpl)interfaze).isAssignableTo(type)) { - return true; - } - } - - return false; - } - } - - List inheritedTypes() { - return superinterfaces(); - } - public boolean isInitialized() { return isPrepared(); } @@ -184,4 +105,39 @@ public String toString() { return "interface " + name() + " (" + loaderString() + ")"; } -} + + @Override + InvocationResult waitForReply(PacketStream stream) throws JDWPException { + return new IResult(JDWP.InterfaceType.InvokeMethod.waitForReply(vm, stream)); + } + + @Override + CommandSender getInvokeMethodSender(final ThreadReferenceImpl thread, + final MethodImpl method, + final ValueImpl[] args, + final int options) { + return () -> + JDWP.InterfaceType.InvokeMethod.enqueueCommand(vm, + InterfaceTypeImpl.this, + thread, + method.ref(), + args, + options); + } + + @Override + ClassType superclass() { + return null; + } + + @Override + List interfaces() { + return superinterfaces(); + } + + @Override + boolean canInvoke(Method method) { + // method must be directly in this interface + return this.equals(method.declaringType()); + } +} \ No newline at end of file diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/tools/jdi/InvokableTypeImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tools/jdi/InvokableTypeImpl.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.jdi; + +import com.sun.jdi.ClassNotLoadedException; +import com.sun.jdi.ClassType; +import com.sun.jdi.IncompatibleThreadStateException; +import com.sun.jdi.InterfaceType; +import com.sun.jdi.InvalidTypeException; +import com.sun.jdi.InvocationException; +import com.sun.jdi.Method; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.ThreadReference; +import com.sun.jdi.Value; +import com.sun.jdi.VirtualMachine; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * A supertype for ReferenceTypes allowing method invocations + */ +abstract class InvokableTypeImpl extends ReferenceTypeImpl { + /** + * The invocation result wrapper + * It is necessary because both ClassType and InterfaceType + * use their own type to represent the invocation result + */ + static interface InvocationResult { + ObjectReferenceImpl getException(); + ValueImpl getResult(); + } + + InvokableTypeImpl(VirtualMachine aVm, long aRef) { + super(aVm, aRef); + } + + /** + * Method invocation support. + * Shared by ClassType and InterfaceType + * @param threadIntf the thread in which to invoke. + * @param methodIntf method the {@link Method} to invoke. + * @param origArguments the list of {@link Value} arguments bound to the + * invoked method. Values from the list are assigned to arguments + * in the order they appear in the method signature. + * @param options the integer bit flag options. + * @return a {@link Value} mirror of the invoked method's return value. + * @throws java.lang.IllegalArgumentException if the method is not + * a member of this type, if the size of the argument list + * does not match the number of declared arguments for the method, or + * if the method is not static or is a static initializer. + * @throws {@link InvalidTypeException} if any argument in the + * argument list is not assignable to the corresponding method argument + * type. + * @throws ClassNotLoadedException if any argument type has not yet been loaded + * through the appropriate class loader. + * @throws IncompatibleThreadStateException if the specified thread has not + * been suspended by an event. + * @throws InvocationException if the method invocation resulted in + * an exception in the target VM. + * @throws InvalidTypeException If the arguments do not meet this requirement -- + * Object arguments must be assignment compatible with the argument + * type. This implies that the argument type must be + * loaded through the enclosing class's class loader. + * Primitive arguments must be either assignment compatible with the + * argument type or must be convertible to the argument type without loss + * of information. See JLS section 5.2 for more information on assignment + * compatibility. + * @throws VMCannotBeModifiedException if the VirtualMachine is read-only - see {@link VirtualMachine#canBeModified()}. + */ + final public Value invokeMethod(ThreadReference threadIntf, Method methodIntf, + List origArguments, int options) + throws InvalidTypeException, + ClassNotLoadedException, + IncompatibleThreadStateException, + InvocationException { + validateMirror(threadIntf); + validateMirror(methodIntf); + validateMirrorsOrNulls(origArguments); + MethodImpl method = (MethodImpl) methodIntf; + ThreadReferenceImpl thread = (ThreadReferenceImpl) threadIntf; + validateMethodInvocation(method); + List arguments = method.validateAndPrepareArgumentsForInvoke(origArguments); + ValueImpl[] args = arguments.toArray(new ValueImpl[0]); + InvocationResult ret; + try { + PacketStream stream = sendInvokeCommand(thread, method, args, options); + ret = waitForReply(stream); + } catch (JDWPException exc) { + if (exc.errorCode() == JDWP.Error.INVALID_THREAD) { + throw new IncompatibleThreadStateException(); + } else { + throw exc.toJDIException(); + } + } + /* + * There is an implict VM-wide suspend at the conclusion + * of a normal (non-single-threaded) method invoke + */ + if ((options & ClassType.INVOKE_SINGLE_THREADED) == 0) { + vm.notifySuspend(); + } + if (ret.getException() != null) { + throw new InvocationException(ret.getException()); + } else { + return ret.getResult(); + } + } + + @Override + boolean isAssignableTo(ReferenceType type) { + ClassTypeImpl superclazz = (ClassTypeImpl) superclass(); + if (this.equals(type)) { + return true; + } else if ((superclazz != null) && superclazz.isAssignableTo(type)) { + return true; + } else { + List interfaces = interfaces(); + Iterator iter = interfaces.iterator(); + while (iter.hasNext()) { + InterfaceTypeImpl interfaze = (InterfaceTypeImpl) iter.next(); + if (interfaze.isAssignableTo(type)) { + return true; + } + } + return false; + } + } + + @Override + final void addVisibleMethods(Map methodMap, Set seenInterfaces) { + /* + * Add methods from + * parent types first, so that the methods in this class will + * overwrite them in the hash table + */ + Iterator iter = interfaces().iterator(); + while (iter.hasNext()) { + InterfaceTypeImpl interfaze = (InterfaceTypeImpl) iter.next(); + if (!seenInterfaces.contains(interfaze)) { + interfaze.addVisibleMethods(methodMap, seenInterfaces); + seenInterfaces.add(interfaze); + } + } + ClassTypeImpl clazz = (ClassTypeImpl) superclass(); + if (clazz != null) { + clazz.addVisibleMethods(methodMap, seenInterfaces); + } + addToMethodMap(methodMap, methods()); + } + + final void addInterfaces(List list) { + List immediate = interfaces(); + list.addAll(interfaces()); + Iterator iter = immediate.iterator(); + while (iter.hasNext()) { + InterfaceTypeImpl interfaze = (InterfaceTypeImpl) iter.next(); + interfaze.addInterfaces(list); + } + ClassTypeImpl superclass = (ClassTypeImpl) superclass(); + if (superclass != null) { + superclass.addInterfaces(list); + } + } + + /** + * Returns all the implemented interfaces recursively + * @return A list of all the implemented interfaces (recursively) + */ + final List getAllInterfaces() { + List all = new ArrayList<>(); + addInterfaces(all); + return all; + } + + /** + * Shared implementation of {@linkplain ClassType#allMethods()} and + * {@linkplain InterfaceType#allMethods()} + * @return A list of all methods (recursively) + */ + public final List allMethods() { + ArrayList list = new ArrayList<>(methods()); + ClassType clazz = superclass(); + while (clazz != null) { + list.addAll(clazz.methods()); + clazz = clazz.superclass(); + } + /* + * Avoid duplicate checking on each method by iterating through + * duplicate-free allInterfaces() rather than recursing + */ + for (InterfaceType interfaze : getAllInterfaces()) { + list.addAll(interfaze.methods()); + } + return list; + } + + @Override + final List inheritedTypes() { + List inherited = new ArrayList<>(); + if (superclass() != null) { + inherited.add(0, superclass()); /* insert at front */ + } + for (ReferenceType rt : interfaces()) { + inherited.add(rt); + } + return inherited; + } + + private PacketStream sendInvokeCommand(final ThreadReferenceImpl thread, + final MethodImpl method, + final ValueImpl[] args, + final int options) { + CommandSender sender = getInvokeMethodSender(thread, method, args, options); + PacketStream stream; + if ((options & ClassType.INVOKE_SINGLE_THREADED) != 0) { + stream = thread.sendResumingCommand(sender); + } else { + stream = vm.sendResumingCommand(sender); + } + return stream; + } + + private void validateMethodInvocation(Method method) + throws InvalidTypeException, + InvocationException { + if (!canInvoke(method)) { + throw new IllegalArgumentException("Invalid method"); + } + /* + * Method must be a static and not a static initializer + */ + if (!method.isStatic()) { + throw new IllegalArgumentException("Cannot invoke instance method on a class/interface type"); + } else if (method.isStaticInitializer()) { + throw new IllegalArgumentException("Cannot invoke static initializer"); + } + } + + /** + * A subclass will provide specific {@linkplain CommandSender} + * @param thread the current invocation thread + * @param method the method to invoke + * @param args the arguments to pass to the method + * @param options the integer bit flag options + * @return the specific {@literal CommandSender} instance + */ + abstract CommandSender getInvokeMethodSender(ThreadReferenceImpl thread, + MethodImpl method, + ValueImpl[] args, + int options); + + /** + * Waits for the reply to the last sent command + * @param stream the stream to listen for the reply on + * @return the {@linkplain InvocationResult} instance + * @throws JDWPException when something goes wrong in JDWP + */ + abstract InvocationResult waitForReply(PacketStream stream) throws JDWPException; + + /** + * Get the {@linkplain ReferenceType} superclass + * @return the superclass or null + */ + abstract ClassType superclass(); + + /** + * Get the implemented/extended interfaces + * @return the list of implemented/extended interfaces + */ + abstract List interfaces(); + + /** + * Checks the provided method whether it can be invoked + * @param method the method to check + * @return {@code TRUE} if the implementation knows how to invoke the method, + * {@code FALSE} otherwise + */ + abstract boolean canInvoke(Method method); +} diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/tools/jdi/MethodImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/MethodImpl.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/com/sun/tools/jdi/MethodImpl.java Wed Jul 05 19:39:35 2017 +0200 @@ -187,6 +187,13 @@ return isModifierSet(VMModifiers.ABSTRACT); } + public boolean isDefault() { + return !isModifierSet(VMModifiers.ABSTRACT) && + !isModifierSet(VMModifiers.STATIC) && + !isModifierSet(VMModifiers.PRIVATE) && + declaringType() instanceof InterfaceType; + } + public boolean isSynchronized() { return isModifierSet(VMModifiers.SYNCHRONIZED); } diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java Wed Jul 05 19:39:35 2017 +0200 @@ -277,7 +277,6 @@ void validateMethodInvocation(Method method, int options) throws InvalidTypeException, InvocationException { - /* * Method must be in this object's class, a superclass, or * implemented interface @@ -287,6 +286,19 @@ throw new IllegalArgumentException("Invalid method"); } + if (declType instanceof ClassTypeImpl) { + validateClassMethodInvocation(method, options); + } else if (declType instanceof InterfaceTypeImpl) { + validateIfaceMethodInvocation(method, options); + } else { + throw new InvalidTypeException(); + } + } + + void validateClassMethodInvocation(Method method, int options) + throws InvalidTypeException, + InvocationException { + ClassTypeImpl clazz = invokableReferenceType(method); /* @@ -300,9 +312,7 @@ * For nonvirtual invokes, method must have a body */ if ((options & INVOKE_NONVIRTUAL) != 0) { - if (method.declaringType() instanceof InterfaceType) { - throw new IllegalArgumentException("Interface method"); - } else if (method.isAbstract()) { + if (method.isAbstract()) { throw new IllegalArgumentException("Abstract method"); } } @@ -324,7 +334,7 @@ */ Method invoker = clazz.concreteMethodByName(method.name(), method.signature()); - // isAssignableFrom check above guarantees non-null + // invoker is supposed to be non-null under normal circumstances invokedClass = (ClassTypeImpl)invoker.declaringType(); } /* The above code is left over from previous versions. @@ -332,6 +342,17 @@ */ } + void validateIfaceMethodInvocation(Method method, int options) + throws InvalidTypeException, + InvocationException { + /* + * Only default methods allowed for nonvirtual invokes + */ + if (!method.isDefault()) { + throw new IllegalArgumentException("Not a default method"); + } + } + PacketStream sendInvokeCommand(final ThreadReferenceImpl thread, final ClassTypeImpl refType, final MethodImpl method, @@ -370,7 +391,10 @@ ThreadReferenceImpl thread = (ThreadReferenceImpl)threadIntf; if (method.isStatic()) { - if (referenceType() instanceof ClassType) { + if (referenceType() instanceof InterfaceType) { + InterfaceType type = (InterfaceType)referenceType(); + return type.invokeMethod(thread, method, origArguments, options); + } else if (referenceType() instanceof ClassType) { ClassType type = (ClassType)referenceType(); return type.invokeMethod(thread, method, origArguments, options); } else { diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java Wed Jul 05 19:39:35 2017 +0200 @@ -48,7 +48,7 @@ private ResourceBundle messages = null; private int vmSequenceNumber = 0; private static final int majorVersion = 1; - private static final int minorVersion = 6; + private static final int minorVersion = 8; private static final Object lock = new Object(); private static VirtualMachineManagerImpl vmm; diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/awt/Container.java --- a/jdk/src/share/classes/java/awt/Container.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/awt/Container.java Wed Jul 05 19:39:35 2017 +0200 @@ -263,6 +263,16 @@ boolean ignoreEnabled) { return cont.findComponentAt(x, y, ignoreEnabled); } + + @Override + public void startLWModal(Container cont) { + cont.startLWModal(); + } + + @Override + public void stopLWModal(Container cont) { + cont.stopLWModal(); + } }); } diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/awt/datatransfer/Clipboard.java --- a/jdk/src/share/classes/java/awt/datatransfer/Clipboard.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/awt/datatransfer/Clipboard.java Wed Jul 05 19:39:35 2017 +0200 @@ -27,14 +27,13 @@ import java.awt.EventQueue; +import java.util.Objects; import java.util.Set; import java.util.HashSet; import java.util.Arrays; import java.io.IOException; -import sun.awt.EventListenerAggregate; - /** * A class that implements a mechanism to transfer data using * cut/copy/paste operations. @@ -68,7 +67,7 @@ * * @since 1.5 */ - private EventListenerAggregate flavorListeners; + private Set flavorListeners; /** * A set of DataFlavors that is available on @@ -131,11 +130,7 @@ this.contents = contents; if (oldOwner != null && oldOwner != owner) { - EventQueue.invokeLater(new Runnable() { - public void run() { - oldOwner.lostOwnership(Clipboard.this, oldContents); - } - }); + EventQueue.invokeLater(() -> oldOwner.lostOwnership(Clipboard.this, oldContents)); } fireFlavorsChanged(); } @@ -261,10 +256,12 @@ if (listener == null) { return; } + if (flavorListeners == null) { + flavorListeners = new HashSet<>(); currentDataFlavors = getAvailableDataFlavorSet(); - flavorListeners = new EventListenerAggregate(FlavorListener.class); } + flavorListeners.add(listener); } @@ -306,7 +303,7 @@ */ public synchronized FlavorListener[] getFlavorListeners() { return flavorListeners == null ? new FlavorListener[0] : - (FlavorListener[])flavorListeners.getListenersCopy(); + flavorListeners.toArray(new FlavorListener[flavorListeners.size()]); } /** @@ -320,21 +317,15 @@ if (flavorListeners == null) { return; } + Set prevDataFlavors = currentDataFlavors; currentDataFlavors = getAvailableDataFlavorSet(); - if (prevDataFlavors.equals(currentDataFlavors)) { + if (Objects.equals(prevDataFlavors, currentDataFlavors)) { return; } - FlavorListener[] flavorListenerArray = - (FlavorListener[])flavorListeners.getListenersInternal(); - for (int i = 0; i < flavorListenerArray.length; i++) { - final FlavorListener listener = flavorListenerArray[i]; - EventQueue.invokeLater(new Runnable() { - public void run() { - listener.flavorsChanged(new FlavorEvent(Clipboard.this)); - } - }); - } + flavorListeners.forEach(listener -> + EventQueue.invokeLater(() -> + listener.flavorsChanged(new FlavorEvent(Clipboard.this)))); } /** diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java --- a/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java Wed Jul 05 19:39:35 2017 +0200 @@ -25,13 +25,28 @@ package java.awt.datatransfer; -import java.io.*; -import java.nio.*; -import java.util.*; - import sun.awt.datatransfer.DataTransferer; import sun.reflect.misc.ReflectUtil; +import java.io.ByteArrayInputStream; +import java.io.CharArrayReader; +import java.io.Externalizable; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.OptionalDataException; +import java.io.Reader; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Objects; + import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION; /** @@ -92,7 +107,7 @@ * As such, asking a {@code Transferable} for either {@code DataFlavor} returns * the same results. *

- * For more information on the using data transfer with Swing see + * For more information on using data transfer with Swing see * the * How to Use Drag and Drop and Data Transfer, * section in Java Tutorial. @@ -390,7 +405,7 @@ * If the mimeType is * "application/x-java-serialized-object; class=<representation class>", * the result is the same as calling - * new DataFlavor(Class:forName(<representation class>). + * new DataFlavor(Class.forName(<representation class>). *

* Otherwise: *

@@ -398,7 +413,7 @@
      *     mimeType            = mimeType
      * 
* @param mimeType the string used to identify the MIME type for this flavor; - * if the the mimeType does not specify a + * if the mimeType does not specify a * "class=" parameter, or if the class is not successfully * loaded, then an IllegalArgumentException * is thrown @@ -433,7 +448,7 @@ * If the mimeType is * "application/x-java-serialized-object; class=<representation class>", * the result is the same as calling - * new DataFlavor(Class:forName(<representation class>). + * new DataFlavor(Class.forName(<representation class>). *

* Otherwise: *

@@ -501,7 +516,7 @@
     * @throws ClassNotFoundException
     * @throws  NullPointerException if mimeType is null
     *
-    * @see tryToLoadClass
+    * @see #tryToLoadClass
     */
     private void initialize(String mimeType, String humanPresentableName, ClassLoader classLoader) throws MimeTypeParseException, ClassNotFoundException {
         if (mimeType == null) {
@@ -986,14 +1001,8 @@
             return true;
         }
 
-        if (representationClass == null) {
-            if (that.getRepresentationClass() != null) {
-                return false;
-            }
-        } else {
-            if (!representationClass.equals(that.getRepresentationClass())) {
-                return false;
-            }
+        if (!Objects.equals(this.getRepresentationClass(), that.getRepresentationClass())) {
+            return false;
         }
 
         if (mimeType == null) {
@@ -1006,34 +1015,22 @@
             }
 
             if ("text".equals(getPrimaryType())) {
-                if (DataTransferer.doesSubtypeSupportCharset(this) &&
-                    representationClass != null &&
-                    !(isRepresentationClassReader() ||
-                        String.class.equals(representationClass) ||
-                        isRepresentationClassCharBuffer() ||
-                        char[].class.equals(representationClass)))
-                {
+                if (DataTransferer.doesSubtypeSupportCharset(this)
+                        && representationClass != null
+                        && !isStandardTextRepresentationClass()) {
                     String thisCharset =
-                        DataTransferer.canonicalName(getParameter("charset"));
+                            DataTransferer.canonicalName(this.getParameter("charset"));
                     String thatCharset =
-                        DataTransferer.canonicalName(that.getParameter("charset"));
-                    if (thisCharset == null) {
-                        if (thatCharset != null) {
-                            return false;
-                        }
-                    } else {
-                        if (!thisCharset.equals(thatCharset)) {
-                            return false;
-                        }
+                            DataTransferer.canonicalName(that.getParameter("charset"));
+                    if (!Objects.equals(thisCharset, thatCharset)) {
+                        return false;
                     }
                 }
 
-                if ("html".equals(getSubType()) &&
-                        this.getParameter("document") != null )
-                {
-                   if (!this.getParameter("document").
-                            equals(that.getParameter("document")))
-                    {
+                if ("html".equals(getSubType())) {
+                    String thisDocument = this.getParameter("document");
+                    String thatDocument = that.getParameter("document");
+                    if (!Objects.equals(thisDocument, thatDocument)) {
                         return false;
                     }
                 }
@@ -1090,18 +1087,21 @@
             // MimeType.match which reports a match if one or both of the
             // subTypes is '*', regardless of the other subType.
 
-            if ("text".equals(primaryType) &&
-                DataTransferer.doesSubtypeSupportCharset(this) &&
-                representationClass != null &&
-                !(isRepresentationClassReader() ||
-                  String.class.equals(representationClass) ||
-                  isRepresentationClassCharBuffer() ||
-                  char[].class.equals(representationClass)))
-            {
-                String charset =
-                    DataTransferer.canonicalName(getParameter("charset"));
-                if (charset != null) {
-                    total += charset.hashCode();
+            if ("text".equals(primaryType)) {
+                if (DataTransferer.doesSubtypeSupportCharset(this)
+                        && representationClass != null
+                        && !isStandardTextRepresentationClass()) {
+                    String charset = DataTransferer.canonicalName(getParameter("charset"));
+                    if (charset != null) {
+                        total += charset.hashCode();
+                    }
+                }
+
+                if ("html".equals(getSubType())) {
+                    String document = this.getParameter("document");
+                    if (document != null) {
+                        total += document.hashCode();
+                    }
                 }
             }
         }
@@ -1177,6 +1177,20 @@
         return mimeType.match(mtype);
     }
 
+    /**
+     * Checks if the representation class is one of the standard text
+     * representation classes.
+     *
+     * @return true if the representation class is one of the standard text
+     *              representation classes, otherwise false
+     */
+    private boolean isStandardTextRepresentationClass() {
+        return isRepresentationClassReader()
+                || String.class.equals(representationClass)
+                || isRepresentationClassCharBuffer()
+                || char[].class.equals(representationClass);
+    }
+
    /**
     * Does the DataFlavor represent a serialized object?
     * @return whether or not a serialized object is represented
diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/awt/dnd/DragSourceContext.java
--- a/jdk/src/share/classes/java/awt/dnd/DragSourceContext.java	Wed Jul 05 19:38:36 2017 +0200
+++ b/jdk/src/share/classes/java/awt/dnd/DragSourceContext.java	Wed Jul 05 19:39:35 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -472,7 +472,7 @@
      *               ENTER, OVER,
      *               CHANGED
      */
-
+    @SuppressWarnings("fallthrough")
     protected synchronized void updateCurrentCursor(int sourceAct, int targetAct, int status) {
 
         // if the cursor has been previously set then don't do any defaults
@@ -576,9 +576,9 @@
             throw new InvalidObjectException("Null trigger component");
         }
 
-        int DGRActions = newTrigger.getSourceAsDragGestureRecognizer().getSourceActions()
+        int newSourceActions = f.get("sourceActions", 0)
                 & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK);
-        if (DGRActions == DnDConstants.ACTION_NONE) {
+        if (newSourceActions == DnDConstants.ACTION_NONE) {
             throw new InvalidObjectException("Invalid source actions");
         }
         int triggerActions = newTrigger.getDragAction();
@@ -591,8 +591,7 @@
 
         cursor = (Cursor)f.get("cursor", null);
         useCustomCursor = f.get("useCustomCursor", false);
-        sourceActions = f.get("sourceActions", 0)
-                & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK);
+        sourceActions = newSourceActions;
 
         transferable = (Transferable)s.readObject();
         listener = (DragSourceListener)s.readObject();
diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/awt/geom/Line2D.java
--- a/jdk/src/share/classes/java/awt/geom/Line2D.java	Wed Jul 05 19:38:36 2017 +0200
+++ b/jdk/src/share/classes/java/awt/geom/Line2D.java	Wed Jul 05 19:39:35 2017 +0200
@@ -35,7 +35,7 @@
  * default coordinate system called user space in which the y-axis
  * values increase downward and x-axis values increase to the right.  For
  * more information on the user space coordinate system, see the
- * 
+ * 
  * Coordinate Systems section of the Java 2D Programmer's Guide.
  * 

* This class is only the abstract superclass for all objects that diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/beans/Introspector.java --- a/jdk/src/share/classes/java/beans/Introspector.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/beans/Introspector.java Wed Jul 05 19:39:35 2017 +0200 @@ -848,7 +848,7 @@ } private static boolean isAssignable(Class current, Class candidate) { - return current == null ? candidate == null : current.isAssignableFrom(candidate); + return ((current == null) || (candidate == null)) ? current == candidate : current.isAssignableFrom(candidate); } private PropertyDescriptor mergePropertyWithIndexedProperty(PropertyDescriptor pd, IndexedPropertyDescriptor ipd) { diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/nio/package.html --- a/jdk/src/share/classes/java/nio/package.html Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/nio/package.html Wed Jul 05 19:39:35 2017 +0200 @@ -121,7 +121,7 @@ available.

  • A byte buffer provides access to its content as either a heterogeneous - or homogeneous sequence of binary data + or homogeneous sequence of binary data of any non-boolean primitive type, in either big-endian or little-endian byte order.

  • diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/sql/package.html --- a/jdk/src/share/classes/java/sql/package.html Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/sql/package.html Wed Jul 05 19:39:35 2017 +0200 @@ -323,10 +323,10 @@ diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/ArrayList.java --- a/jdk/src/share/classes/java/util/ArrayList.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/ArrayList.java Wed Jul 05 19:39:35 2017 +0200 @@ -30,33 +30,33 @@ import java.util.function.UnaryOperator; /** - * Resizable-array implementation of the List interface. Implements + * Resizable-array implementation of the {@code List} interface. Implements * all optional list operations, and permits all elements, including - * null. In addition to implementing the List interface, + * {@code null}. In addition to implementing the {@code List} interface, * this class provides methods to manipulate the size of the array that is * used internally to store the list. (This class is roughly equivalent to - * Vector, except that it is unsynchronized.) + * {@code Vector}, except that it is unsynchronized.) * - *

    The size, isEmpty, get, set, - * iterator, and listIterator operations run in constant - * time. The add operation runs in amortized constant time, + *

    The {@code size}, {@code isEmpty}, {@code get}, {@code set}, + * {@code iterator}, and {@code listIterator} operations run in constant + * time. The {@code add} operation runs in amortized constant time, * that is, adding n elements requires O(n) time. All of the other operations * run in linear time (roughly speaking). The constant factor is low compared - * to that for the LinkedList implementation. + * to that for the {@code LinkedList} implementation. * - *

    Each ArrayList instance has a capacity. The capacity is + *

    Each {@code ArrayList} instance has a capacity. The capacity is * the size of the array used to store the elements in the list. It is always * at least as large as the list size. As elements are added to an ArrayList, * its capacity grows automatically. The details of the growth policy are not * specified beyond the fact that adding an element has constant amortized * time cost. * - *

    An application can increase the capacity of an ArrayList instance - * before adding a large number of elements using the ensureCapacity + *

    An application can increase the capacity of an {@code ArrayList} instance + * before adding a large number of elements using the {@code ensureCapacity} * operation. This may reduce the amount of incremental reallocation. * *

    Note that this implementation is not synchronized. - * If multiple threads access an ArrayList instance concurrently, + * If multiple threads access an {@code ArrayList} instance concurrently, * and at least one of the threads modifies the list structurally, it * must be synchronized externally. (A structural modification is * any operation that adds or deletes one or more elements, or explicitly @@ -70,9 +70,9 @@ * unsynchronized access to the list:

      *   List list = Collections.synchronizedList(new ArrayList(...));
    * - *

    + *

    * The iterators returned by this class's {@link #iterator() iterator} and - * {@link #listIterator(int) listIterator} methods are fail-fast: + * {@link #listIterator(int) listIterator} methods are fail-fast: * if the list is structurally modified at any time after the iterator is * created, in any way except through the iterator's own * {@link ListIterator#remove() remove} or @@ -94,6 +94,8 @@ * * Java Collections Framework. * + * @param the type of elements in this list + * * @author Josh Bloch * @author Neal Gafter * @see Collection @@ -119,10 +121,17 @@ private static final Object[] EMPTY_ELEMENTDATA = {}; /** + * Shared empty array instance used for default sized empty instances. We + * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when + * first element is added. + */ + private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; + + /** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. Any - * empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to - * DEFAULT_CAPACITY when the first element is added. + * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA + * will be expanded to DEFAULT_CAPACITY when the first element is added. */ transient Object[] elementData; // non-private to simplify nested class access @@ -141,19 +150,21 @@ * is negative */ public ArrayList(int initialCapacity) { - super(); - if (initialCapacity < 0) + if (initialCapacity > 0) { + this.elementData = new Object[initialCapacity]; + } else if (initialCapacity == 0) { + this.elementData = EMPTY_ELEMENTDATA; + } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); - this.elementData = new Object[initialCapacity]; + } } /** * Constructs an empty list with an initial capacity of ten. */ public ArrayList() { - super(); - this.elementData = EMPTY_ELEMENTDATA; + this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } /** @@ -166,37 +177,43 @@ */ public ArrayList(Collection c) { elementData = c.toArray(); - size = elementData.length; - // c.toArray might (incorrectly) not return Object[] (see 6260652) - if (elementData.getClass() != Object[].class) - elementData = Arrays.copyOf(elementData, size, Object[].class); + if ((size = elementData.length) != 0) { + // c.toArray might (incorrectly) not return Object[] (see 6260652) + if (elementData.getClass() != Object[].class) + elementData = Arrays.copyOf(elementData, size, Object[].class); + } else { + // replace with empty array. + this.elementData = EMPTY_ELEMENTDATA; + } } /** - * Trims the capacity of this ArrayList instance to be the + * Trims the capacity of this {@code ArrayList} instance to be the * list's current size. An application can use this operation to minimize - * the storage of an ArrayList instance. + * the storage of an {@code ArrayList} instance. */ public void trimToSize() { modCount++; if (size < elementData.length) { - elementData = Arrays.copyOf(elementData, size); + elementData = (size == 0) + ? EMPTY_ELEMENTDATA + : Arrays.copyOf(elementData, size); } } /** - * Increases the capacity of this ArrayList instance, if + * Increases the capacity of this {@code ArrayList} instance, if * necessary, to ensure that it can hold at least the number of elements * specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity */ public void ensureCapacity(int minCapacity) { - int minExpand = (elementData != EMPTY_ELEMENTDATA) - // any size if real element table + int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) + // any size if not default element table ? 0 - // larger than default for empty table. It's already supposed to be - // at default size. + // larger than default for default empty table. It's already + // supposed to be at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { @@ -205,7 +222,7 @@ } private void ensureCapacityInternal(int minCapacity) { - if (elementData == EMPTY_ELEMENTDATA) { + if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } @@ -264,22 +281,22 @@ } /** - * Returns true if this list contains no elements. + * Returns {@code true} if this list contains no elements. * - * @return true if this list contains no elements + * @return {@code true} if this list contains no elements */ public boolean isEmpty() { return size == 0; } /** - * Returns true if this list contains the specified element. - * More formally, returns true if and only if this list contains - * at least one element e such that + * Returns {@code true} if this list contains the specified element. + * More formally, returns {@code true} if and only if this list contains + * at least one element {@code e} such that * (o==null ? e==null : o.equals(e)). * * @param o element whose presence in this list is to be tested - * @return true if this list contains the specified element + * @return {@code true} if this list contains the specified element */ public boolean contains(Object o) { return indexOf(o) >= 0; @@ -288,7 +305,7 @@ /** * Returns the index of the first occurrence of the specified element * in this list, or -1 if this list does not contain the element. - * More formally, returns the lowest index i such that + * More formally, returns the lowest index {@code i} such that * (o==null ? get(i)==null : o.equals(get(i))), * or -1 if there is no such index. */ @@ -308,7 +325,7 @@ /** * Returns the index of the last occurrence of the specified element * in this list, or -1 if this list does not contain the element. - * More formally, returns the highest index i such that + * More formally, returns the highest index {@code i} such that * (o==null ? get(i)==null : o.equals(get(i))), * or -1 if there is no such index. */ @@ -326,10 +343,10 @@ } /** - * Returns a shallow copy of this ArrayList instance. (The + * Returns a shallow copy of this {@code ArrayList} instance. (The * elements themselves are not copied.) * - * @return a clone of this ArrayList instance + * @return a clone of this {@code ArrayList} instance */ public Object clone() { try { @@ -372,7 +389,7 @@ *

    If the list fits in the specified array with room to spare * (i.e., the array has more elements than the list), the element in * the array immediately following the end of the collection is set to - * null. (This is useful in determining the length of the + * {@code null}. (This is useful in determining the length of the * list only if the caller knows that the list does not contain * any null elements.) * @@ -437,7 +454,7 @@ * Appends the specified element to the end of this list. * * @param e element to be appended to this list - * @return true (as specified by {@link Collection#add}) + * @return {@code true} (as specified by {@link Collection#add}) */ public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! @@ -492,14 +509,14 @@ * Removes the first occurrence of the specified element from this list, * if it is present. If the list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index - * i such that + * {@code i} such that * (o==null ? get(i)==null : o.equals(get(i))) - * (if such an element exists). Returns true if this list + * (if such an element exists). Returns {@code true} if this list * contained the specified element (or equivalently, if this list * changed as a result of the call). * * @param o element to be removed from this list, if present - * @return true if this list contained the specified element + * @return {@code true} if this list contained the specified element */ public boolean remove(Object o) { if (o == null) { @@ -555,7 +572,7 @@ * list is nonempty.) * * @param c collection containing elements to be added to this list - * @return true if this list changed as a result of the call + * @return {@code true} if this list changed as a result of the call * @throws NullPointerException if the specified collection is null */ public boolean addAll(Collection c) { @@ -578,7 +595,7 @@ * @param index index at which to insert the first element from the * specified collection * @param c collection containing elements to be added to this list - * @return true if this list changed as a result of the call + * @return {@code true} if this list changed as a result of the call * @throws IndexOutOfBoundsException {@inheritDoc} * @throws NullPointerException if the specified collection is null */ @@ -736,12 +753,12 @@ } /** - * Save the state of the ArrayList instance to a stream (that + * Save the state of the {@code ArrayList} instance to a stream (that * is, serialize it). * - * @serialData The length of the array backing the ArrayList + * @serialData The length of the array backing the {@code ArrayList} * instance is emitted (int), followed by all of its elements - * (each an Object) in the proper order. + * (each an {@code Object}) in the proper order. */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{ @@ -763,7 +780,7 @@ } /** - * Reconstitute the ArrayList instance from a stream (that is, + * Reconstitute the {@code ArrayList} instance from a stream (that is, * deserialize it). */ private void readObject(java.io.ObjectInputStream s) diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/Arrays.java --- a/jdk/src/share/classes/java/util/Arrays.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/Arrays.java Wed Jul 05 19:39:35 2017 +0200 @@ -2561,7 +2561,7 @@ * arrays contain the same number of elements, and all corresponding pairs * of elements in the two arrays are equal. In other words, two arrays * are equal if they contain the same elements in the same order. Also, - * two array references are considered equal if both are null.

    + * two array references are considered equal if both are null. * * @param a one array to be tested for equality * @param a2 the other array to be tested for equality @@ -2590,7 +2590,7 @@ * arrays contain the same number of elements, and all corresponding pairs * of elements in the two arrays are equal. In other words, two arrays * are equal if they contain the same elements in the same order. Also, - * two array references are considered equal if both are null.

    + * two array references are considered equal if both are null. * * @param a one array to be tested for equality * @param a2 the other array to be tested for equality @@ -2619,7 +2619,7 @@ * arrays contain the same number of elements, and all corresponding pairs * of elements in the two arrays are equal. In other words, two arrays * are equal if they contain the same elements in the same order. Also, - * two array references are considered equal if both are null.

    + * two array references are considered equal if both are null. * * @param a one array to be tested for equality * @param a2 the other array to be tested for equality @@ -2648,7 +2648,7 @@ * arrays contain the same number of elements, and all corresponding pairs * of elements in the two arrays are equal. In other words, two arrays * are equal if they contain the same elements in the same order. Also, - * two array references are considered equal if both are null.

    + * two array references are considered equal if both are null. * * @param a one array to be tested for equality * @param a2 the other array to be tested for equality @@ -2677,7 +2677,7 @@ * arrays contain the same number of elements, and all corresponding pairs * of elements in the two arrays are equal. In other words, two arrays * are equal if they contain the same elements in the same order. Also, - * two array references are considered equal if both are null.

    + * two array references are considered equal if both are null. * * @param a one array to be tested for equality * @param a2 the other array to be tested for equality @@ -2706,7 +2706,7 @@ * arrays contain the same number of elements, and all corresponding pairs * of elements in the two arrays are equal. In other words, two arrays * are equal if they contain the same elements in the same order. Also, - * two array references are considered equal if both are null.

    + * two array references are considered equal if both are null. * * @param a one array to be tested for equality * @param a2 the other array to be tested for equality @@ -2735,7 +2735,7 @@ * arrays contain the same number of elements, and all corresponding pairs * of elements in the two arrays are equal. In other words, two arrays * are equal if they contain the same elements in the same order. Also, - * two array references are considered equal if both are null.

    + * two array references are considered equal if both are null. * * Two doubles d1 and d2 are considered equal if: *

        new Double(d1).equals(new Double(d2))
    @@ -2770,7 +2770,7 @@ * arrays contain the same number of elements, and all corresponding pairs * of elements in the two arrays are equal. In other words, two arrays * are equal if they contain the same elements in the same order. Also, - * two array references are considered equal if both are null.

    + * two array references are considered equal if both are null. * * Two floats f1 and f2 are considered equal if: *

        new Float(f1).equals(new Float(f2))
    @@ -2807,7 +2807,7 @@ * and e2 are considered equal if (e1==null ? e2==null * : e1.equals(e2)). In other words, the two arrays are equal if * they contain the same elements in the same order. Also, two array - * references are considered equal if both are null.

    + * references are considered equal if both are null. * * @param a one array to be tested for equality * @param a2 the other array to be tested for equality diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/Locale.java --- a/jdk/src/share/classes/java/util/Locale.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/Locale.java Wed Jul 05 19:39:35 2017 +0200 @@ -951,7 +951,6 @@ * functionality, this method should only be used if the caller is * prepared to reinitialize locale-sensitive code running within the * same Java Virtual Machine. - *

    * * @param category - the specified category to set the default locale * @param newLocale - the new default locale diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/Properties.java --- a/jdk/src/share/classes/java/util/Properties.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/Properties.java Wed Jul 05 19:39:35 2017 +0200 @@ -754,7 +754,6 @@ *

    * After the entries have been written, the output stream is flushed. * The output stream remains open after this method returns. - *

    * * @param writer an output character stream writer. * @param comments a description of the property list. @@ -802,7 +801,7 @@ *

    * After the entries have been written, the output stream is flushed. * The output stream remains open after this method returns. - *

    + * * @param out an output stream. * @param comments a description of the property list. * @exception IOException if writing this property list to the specified diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/PropertyPermission.java --- a/jdk/src/share/classes/java/util/PropertyPermission.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/PropertyPermission.java Wed Jul 05 19:39:35 2017 +0200 @@ -193,7 +193,7 @@ /** * Checks two PropertyPermission objects for equality. Checks that obj is * a PropertyPermission, and has the same name and actions as this object. - *

    + * * @param obj the object we are testing for equality with this object. * @return true if obj is a PropertyPermission, and has the same name and * actions as this PropertyPermission object. @@ -369,7 +369,6 @@ /** * Returns a new PermissionCollection object for storing * PropertyPermission objects. - *

    * * @return a new PermissionCollection object suitable for storing * PropertyPermissions. diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/Vector.java --- a/jdk/src/share/classes/java/util/Vector.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/Vector.java Wed Jul 05 19:39:35 2017 +0200 @@ -45,9 +45,9 @@ * capacity of a vector before inserting a large number of * components; this reduces the amount of incremental reallocation. * - *

    + *

    * The iterators returned by this class's {@link #iterator() iterator} and - * {@link #listIterator(int) listIterator} methods are fail-fast: + * {@link #listIterator(int) listIterator} methods are fail-fast: * if the vector is structurally modified at any time after the iterator is * created, in any way except through the iterator's own * {@link ListIterator#remove() remove} or diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java --- a/jdk/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java Wed Jul 05 19:39:35 2017 +0200 @@ -80,7 +80,6 @@ * {@link ReadLock#tryLock()} and {@link WriteLock#tryLock()} methods * do not honor this fair setting and will immediately acquire the lock * if it is possible, regardless of waiting threads.) - *

    * * *

  • Reentrancy diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/jar/Pack200.java --- a/jdk/src/share/classes/java/util/jar/Pack200.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/jar/Pack200.java Wed Jul 05 19:39:35 2017 +0200 @@ -224,7 +224,7 @@ * Note: Unless otherwise noted, passing a null argument to a * constructor or method in this class will cause a {@link NullPointerException} * to be thrown. - *

    + * * @since 1.5 */ public interface Packer { diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/jar/package.html --- a/jdk/src/share/classes/java/util/jar/package.html Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/jar/package.html Wed Jul 05 19:39:35 2017 +0200 @@ -43,8 +43,7 @@ file format. See java.util.zip package description.

    - In JAR files, all file names must be encoded in the UTF-8 encoding. -

    + In JAR files, all file names must be encoded in the UTF-8 encoding.

  • Manifest and Signature Specification - The manifest format specification. diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/logging/ConsoleHandler.java --- a/jdk/src/share/classes/java/util/logging/ConsoleHandler.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/logging/ConsoleHandler.java Wed Jul 05 19:39:35 2017 +0200 @@ -62,7 +62,7 @@ *
  • com.foo.MyHandler.level=INFO
  • *
  • com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter
  • * - *

    + * * @since 1.4 */ public class ConsoleHandler extends StreamHandler { @@ -86,7 +86,7 @@ *

    * The logging request was made initially to a Logger object, * which initialized the LogRecord and forwarded it here. - *

    + * * @param record description of the log event. A null record is * silently ignored and is not published */ diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/logging/FileHandler.java --- a/jdk/src/share/classes/java/util/logging/FileHandler.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/logging/FileHandler.java Wed Jul 05 19:39:35 2017 +0200 @@ -243,7 +243,7 @@ /** * Construct a default FileHandler. This will be configured * entirely from LogManager properties (or their default values). - *

    + * * @exception IOException if there are IO problems opening the files. * @exception SecurityException if a security manager exists and if * the caller does not have LoggingPermission("control")). diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/logging/Formatter.java --- a/jdk/src/share/classes/java/util/logging/Formatter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/logging/Formatter.java Wed Jul 05 19:39:35 2017 +0200 @@ -105,7 +105,6 @@ * java.text.MessageFormat is used to format the string. *

  • Otherwise no formatting is performed. * - *

    * * @param record the log record containing the raw message * @return a localized and formatted message diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/logging/Handler.java --- a/jdk/src/share/classes/java/util/logging/Handler.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/logging/Handler.java Wed Jul 05 19:39:35 2017 +0200 @@ -158,7 +158,7 @@ *

    * Some Handlers may not use Formatters, in * which case the Formatter will be remembered, but not used. - *

    + * * @param newFormatter the Formatter to use (may not be null) * @exception SecurityException if a security manager exists and if * the caller does not have LoggingPermission("control"). @@ -329,7 +329,7 @@ * may make other Handler specific checks that might prevent a * handler from logging the LogRecord. It will return false if * the LogRecord is null. - *

    + * * @param record a LogRecord * @return true if the LogRecord would be logged. * diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/logging/Level.java --- a/jdk/src/share/classes/java/util/logging/Level.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/logging/Level.java Wed Jul 05 19:39:35 2017 +0200 @@ -195,7 +195,7 @@ /** * Create a named Level with a given integer value and a * given localization resource name. - *

    + * * @param name the name of the Level, for example "SEVERE". * @param value an integer value for the level. * @param resourceBundleName name of a resource bundle to use in diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/logging/LogManager.java --- a/jdk/src/share/classes/java/util/logging/LogManager.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/logging/LogManager.java Wed Jul 05 19:39:35 2017 +0200 @@ -1130,7 +1130,7 @@ * is no strong reference to the Logger. The caller of this method * must check the return value for null in order to properly handle * the case where the Logger has been garbage collected. - *

    + * * @param name name of the logger * @return matching logger or null if none is found */ @@ -1151,7 +1151,7 @@ * return value from {@code LogManager.getLogger()} for null to properly * handle the case where the Logger has been garbage collected in the * time since its name was returned by this method. - *

    + * * @return enumeration of logger name strings */ public Enumeration getLoggerNames() { diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/logging/Logger.java --- a/jdk/src/share/classes/java/util/logging/Logger.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/logging/Logger.java Wed Jul 05 19:39:35 2017 +0200 @@ -338,7 +338,7 @@ * suitable per-Logger granularity. Developers also need to keep a * strong reference to their Logger objects to prevent them from * being garbage collected. - *

    + * * @deprecated Initialization of this field is prone to deadlocks. * The field must be initialized by the Logger class initialization * which may cause deadlocks with the LogManager class initialization. @@ -526,7 +526,7 @@ * name is used. If the named Logger already exists and has * a different resource bundle name then an IllegalArgumentException * is thrown. - *

    + * * @param name A name for the logger. This should * be a dot-separated name and should normally * be based on the package name or class name @@ -595,7 +595,6 @@ * from the root logger. Changing its parent via the * {@link #setParent(java.util.logging.Logger) setParent} method * will still require the security permission specified by that method. - *

    * * @return a newly created private Logger */ @@ -621,7 +620,7 @@ * from the root logger. Changing its parent via the * {@link #setParent(java.util.logging.Logger) setParent} method * will still require the security permission specified by that method. - *

    + * * @param resourceBundleName name of ResourceBundle to be used for localizing * messages for this logger. * May be null if none of the messages require localization. @@ -776,7 +775,7 @@ * If the logger is currently enabled for the given message * level then the given message is forwarded to all the * registered output Handler objects. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param msg The string message (or a key in the message catalog) */ @@ -796,7 +795,7 @@ * level then the message is constructed by invoking the provided * supplier function and forwarded to all the registered output * Handler objects. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param msgSupplier A function, which when called, produces the * desired log message @@ -815,7 +814,7 @@ * If the logger is currently enabled for the given message * level then a corresponding LogRecord is created and forwarded * to all the registered output Handler objects. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param msg The string message (or a key in the message catalog) * @param param1 parameter to the message @@ -836,7 +835,7 @@ * If the logger is currently enabled for the given message * level then a corresponding LogRecord is created and forwarded * to all the registered output Handler objects. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param msg The string message (or a key in the message catalog) * @param params array of parameters to the message @@ -861,7 +860,7 @@ * property, rather than the LogRecord parameters property. Thus it is * processed specially by output Formatters and is not treated * as a formatting parameter to the LogRecord message property. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param msg The string message (or a key in the message catalog) * @param thrown Throwable associated with log message. @@ -887,7 +886,7 @@ * property, rather than the LogRecord parameters property. Thus it is * processed specially by output Formatters and is not treated * as a formatting parameter to the LogRecord message property. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param thrown Throwable associated with log message. * @param msgSupplier A function, which when called, produces the @@ -914,7 +913,7 @@ * If the logger is currently enabled for the given message * level then the given message is forwarded to all the * registered output Handler objects. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request @@ -938,7 +937,7 @@ * level then the message is constructed by invoking the provided * supplier function and forwarded to all the registered output * Handler objects. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request @@ -964,7 +963,7 @@ * If the logger is currently enabled for the given message * level then a corresponding LogRecord is created and forwarded * to all the registered output Handler objects. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request @@ -991,7 +990,7 @@ * If the logger is currently enabled for the given message * level then a corresponding LogRecord is created and forwarded * to all the registered output Handler objects. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request @@ -1022,7 +1021,7 @@ * property, rather than the LogRecord parameters property. Thus it is * processed specially by output Formatters and is not treated * as a formatting parameter to the LogRecord message property. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request @@ -1054,7 +1053,7 @@ * property, rather than the LogRecord parameters property. Thus it is * processed specially by output Formatters and is not treated * as a formatting parameter to the LogRecord message property. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request @@ -1113,7 +1112,7 @@ * The msg string is localized using the named resource bundle. If the * resource bundle name is null, or an empty String or invalid * then the msg string is not localized. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request @@ -1147,7 +1146,7 @@ * The msg string is localized using the named resource bundle. If the * resource bundle name is null, or an empty String or invalid * then the msg string is not localized. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request @@ -1184,7 +1183,7 @@ * The msg string is localized using the named resource bundle. If the * resource bundle name is null, or an empty String or invalid * then the msg string is not localized. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request @@ -1220,7 +1219,7 @@ * The {@code msg} string is localized using the given resource bundle. * If the resource bundle is {@code null}, then the {@code msg} string is not * localized. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass Name of the class that issued the logging request * @param sourceMethod Name of the method that issued the logging request @@ -1260,7 +1259,7 @@ * property, rather than the LogRecord parameters property. Thus it is * processed specially by output Formatters and is not treated * as a formatting parameter to the LogRecord message property. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request @@ -1301,7 +1300,7 @@ * property, rather than the LogRecord parameters property. Thus it is * processed specially by output Formatters and is not treated * as a formatting parameter to the LogRecord message property. - *

    + * * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass Name of the class that issued the logging request * @param sourceMethod Name of the method that issued the logging request @@ -1333,7 +1332,7 @@ * This is a convenience method that can be used to log entry * to a method. A LogRecord with message "ENTRY", log level * FINER, and the given sourceMethod and sourceClass is logged. - *

    + * * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that is being entered */ @@ -1348,7 +1347,7 @@ * to a method. A LogRecord with message "ENTRY {0}", log level * FINER, and the given sourceMethod, sourceClass, and parameter * is logged. - *

    + * * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that is being entered * @param param1 parameter to the method being entered @@ -1365,7 +1364,7 @@ * format {N} indicator for each entry in the parameter array), * log level FINER, and the given sourceMethod, sourceClass, and * parameters is logged. - *

    + * * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that is being entered * @param params array of parameters to the method being entered @@ -1389,7 +1388,7 @@ * This is a convenience method that can be used to log returning * from a method. A LogRecord with message "RETURN", log level * FINER, and the given sourceMethod and sourceClass is logged. - *

    + * * @param sourceClass name of class that issued the logging request * @param sourceMethod name of the method */ @@ -1405,7 +1404,7 @@ * from a method. A LogRecord with message "RETURN {0}", log level * FINER, and the gives sourceMethod, sourceClass, and result * object is logged. - *

    + * * @param sourceClass name of class that issued the logging request * @param sourceMethod name of the method * @param result Object that is being returned @@ -1430,7 +1429,7 @@ * property, rather than the LogRecord parameters property. Thus it is * processed specially by output Formatters and is not treated * as a formatting parameter to the LogRecord message property. - *

    + * * @param sourceClass name of class that issued the logging request * @param sourceMethod name of the method. * @param thrown The Throwable that is being thrown. @@ -1456,7 +1455,7 @@ * If the logger is currently enabled for the SEVERE message * level then the given message is forwarded to all the * registered output Handler objects. - *

    + * * @param msg The string message (or a key in the message catalog) */ public void severe(String msg) { @@ -1469,7 +1468,7 @@ * If the logger is currently enabled for the WARNING message * level then the given message is forwarded to all the * registered output Handler objects. - *

    + * * @param msg The string message (or a key in the message catalog) */ public void warning(String msg) { @@ -1482,7 +1481,7 @@ * If the logger is currently enabled for the INFO message * level then the given message is forwarded to all the * registered output Handler objects. - *

    + * * @param msg The string message (or a key in the message catalog) */ public void info(String msg) { @@ -1495,7 +1494,7 @@ * If the logger is currently enabled for the CONFIG message * level then the given message is forwarded to all the * registered output Handler objects. - *

    + * * @param msg The string message (or a key in the message catalog) */ public void config(String msg) { @@ -1508,7 +1507,7 @@ * If the logger is currently enabled for the FINE message * level then the given message is forwarded to all the * registered output Handler objects. - *

    + * * @param msg The string message (or a key in the message catalog) */ public void fine(String msg) { @@ -1521,7 +1520,7 @@ * If the logger is currently enabled for the FINER message * level then the given message is forwarded to all the * registered output Handler objects. - *

    + * * @param msg The string message (or a key in the message catalog) */ public void finer(String msg) { @@ -1534,7 +1533,7 @@ * If the logger is currently enabled for the FINEST message * level then the given message is forwarded to all the * registered output Handler objects. - *

    + * * @param msg The string message (or a key in the message catalog) */ public void finest(String msg) { @@ -1554,7 +1553,7 @@ * level then the message is constructed by invoking the provided * supplier function and forwarded to all the registered output * Handler objects. - *

    + * * @param msgSupplier A function, which when called, produces the * desired log message * @since 1.8 @@ -1571,7 +1570,7 @@ * level then the message is constructed by invoking the provided * supplier function and forwarded to all the registered output * Handler objects. - *

    + * * @param msgSupplier A function, which when called, produces the * desired log message * @since 1.8 @@ -1588,7 +1587,7 @@ * level then the message is constructed by invoking the provided * supplier function and forwarded to all the registered output * Handler objects. - *

    + * * @param msgSupplier A function, which when called, produces the * desired log message * @since 1.8 @@ -1605,7 +1604,7 @@ * level then the message is constructed by invoking the provided * supplier function and forwarded to all the registered output * Handler objects. - *

    + * * @param msgSupplier A function, which when called, produces the * desired log message * @since 1.8 @@ -1622,7 +1621,7 @@ * level then the message is constructed by invoking the provided * supplier function and forwarded to all the registered output * Handler objects. - *

    + * * @param msgSupplier A function, which when called, produces the * desired log message * @since 1.8 @@ -1639,7 +1638,7 @@ * level then the message is constructed by invoking the provided * supplier function and forwarded to all the registered output * Handler objects. - *

    + * * @param msgSupplier A function, which when called, produces the * desired log message * @since 1.8 @@ -1656,7 +1655,7 @@ * level then the message is constructed by invoking the provided * supplier function and forwarded to all the registered output * Handler objects. - *

    + * * @param msgSupplier A function, which when called, produces the * desired log message * @since 1.8 @@ -1769,7 +1768,7 @@ /** * Get the Handlers associated with this logger. - *

    + * * @return an array of all registered Handlers */ public Handler[] getHandlers() { @@ -2015,7 +2014,7 @@ * the LogManager to update a Logger when the namespace changes. *

    * It should not be called from application code. - *

    + * * @param parent the new parent logger * @throws SecurityException if a security manager exists and if * the caller does not have LoggingPermission("control"). diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/logging/MemoryHandler.java --- a/jdk/src/share/classes/java/util/logging/MemoryHandler.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/logging/MemoryHandler.java Wed Jul 05 19:39:35 2017 +0200 @@ -82,7 +82,7 @@ *

  • com.foo.MyHandler.level=INFO
  • *
  • com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter
  • * - *

    + * * @since 1.4 */ @@ -267,7 +267,7 @@ * whether it satisfies any Filter. However it does not * check whether the LogRecord would result in a "push" of the * buffer contents. It will return false if the LogRecord is null. - *

    + * * @param record a LogRecord * @return true if the LogRecord would be logged. * diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/logging/StreamHandler.java --- a/jdk/src/share/classes/java/util/logging/StreamHandler.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/logging/StreamHandler.java Wed Jul 05 19:39:35 2017 +0200 @@ -71,7 +71,7 @@ *

  • com.foo.MyHandler.level=INFO
  • *
  • com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter
  • * - *

    + * * @since 1.4 */ @@ -91,7 +91,7 @@ /** * Create a StreamHandler with a given Formatter * and output stream. - *

    + * * @param out the target output stream * @param formatter Formatter to be used to format output */ @@ -224,7 +224,7 @@ * This method checks if the LogRecord has an appropriate level and * whether it satisfies any Filter. It will also return false if * no output stream has been assigned yet or the LogRecord is null. - *

    + * * @param record a LogRecord * @return true if the LogRecord would be logged. * diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/logging/package.html --- a/jdk/src/share/classes/java/util/logging/package.html Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/logging/package.html Wed Jul 05 19:39:35 2017 +0200 @@ -54,18 +54,18 @@ When a problem occurs in the field, it may be necessary to return the captured logging information to the original development team for diagnosis. This logging information may be extremely detailed and fairly inscrutable. Such information might include - detailed tracing on the internal execution of particular subsystems. + detailed tracing on the internal execution of particular subsystems.

  • Problem diagnosis by developers. The Logging APIs may also be used to help debug an application under development. This may include logging information generated by the target application - as well as logging information generated by lower-level libraries. + as well as logging information generated by lower-level libraries. Note however that while this use is perfectly reasonable, the logging APIs are not intended to replace the normal debugging and profiling tools that may already exist in the development environment. -

    +

    The key elements of this package include:

    • Logger: The main entity on which applications make @@ -111,7 +111,7 @@ log, logp, logrb, severe, throwing, and warning methods) will accept null values for all arguments except for the initial Level argument (if any). -

      +

      Related Documentation

      For an overview of control flow, diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/prefs/PreferenceChangeListener.java --- a/jdk/src/share/classes/java/util/prefs/PreferenceChangeListener.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/prefs/PreferenceChangeListener.java Wed Jul 05 19:39:35 2017 +0200 @@ -39,7 +39,7 @@ /** * This method gets called when a preference is added, removed or when * its value is changed. - *

      + * * @param evt A PreferenceChangeEvent object describing the event source * and the preference that has changed. */ diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/regex/Matcher.java --- a/jdk/src/share/classes/java/util/regex/Matcher.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/regex/Matcher.java Wed Jul 05 19:39:35 2017 +0200 @@ -830,7 +830,7 @@ * *

      The replacement string may contain references to subsequences * captured during the previous match: Each occurrence of - * $g will be replaced by the result of + * $g will be replaced by the result of * evaluating {@link #group(int) group}(g). * The first number after the $ is always treated as part of * the group reference. Subsequent numbers are incorporated into g if diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/stream/Collectors.java --- a/jdk/src/share/classes/java/util/stream/Collectors.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/stream/Collectors.java Wed Jul 05 19:39:35 2017 +0200 @@ -120,17 +120,63 @@ private Collectors() { } /** - * Returns a merge function, suitable for use in - * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or - * {@link #toMap(Function, Function, BinaryOperator) toMap()}, which always - * throws {@code IllegalStateException}. This can be used to enforce the - * assumption that the elements being collected are distinct. + * Construct an {@code IllegalStateException} with appropriate message. + * + * @param k the duplicate key + * @param u 1st value to be accumulated/merged + * @param v 2nd value to be accumulated/merged + */ + private static IllegalStateException duplicateKeyException( + Object k, Object u, Object v) { + return new IllegalStateException(String.format( + "Duplicate key %s (attempted merging values %s and %s)", + k, u, v)); + } + + /** + * {@code BinaryOperator} that merges the contents of its right + * argument into its left argument, throwing {@code IllegalStateException} + * if duplicate keys are encountered. * - * @param the type of input arguments to the merge function - * @return a merge function which always throw {@code IllegalStateException} + * @param type of the map keys + * @param type of the map values + * @param type of the map + * @return a merge function for two maps */ - private static BinaryOperator throwingMerger() { - return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); }; + private static > + BinaryOperator uniqKeysMapMerger() { + return (m1, m2) -> { + for (Map.Entry e : m2.entrySet()) { + K k = e.getKey(); + V v = Objects.requireNonNull(e.getValue()); + V u = m1.putIfAbsent(k, v); + if (u != null) throw duplicateKeyException(k, u, v); + } + return m1; + }; + } + + /** + * {@code BiConsumer} that accumulates (key, value) pairs + * extracted from elements into the map, throwing {@code IllegalStateException} + * if duplicate keys are encountered. + * + * @param keyMapper a function that maps an element into a key + * @param valueMapper a function that maps an element into a value + * @param type of elements + * @param type of map keys + * @param type of map values + * @return an accumulating consumer + */ + private static + BiConsumer, T> uniqKeysMapAccumulator(Function keyMapper, + Function valueMapper) { + return (map, element) -> { + K k = keyMapper.apply(element); + V v = Objects.requireNonNull(valueMapper.apply(element)); + V u = map.putIfAbsent(k, v); + if (u != null) throw duplicateKeyException(k, u, v); + }; } @SuppressWarnings("unchecked") @@ -1209,7 +1255,10 @@ public static Collector> toMap(Function keyMapper, Function valueMapper) { - return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new); + return new CollectorImpl<>(HashMap::new, + uniqKeysMapAccumulator(keyMapper, valueMapper), + uniqKeysMapMerger(), + CH_ID); } /** @@ -1372,7 +1421,10 @@ public static Collector> toConcurrentMap(Function keyMapper, Function valueMapper) { - return toConcurrentMap(keyMapper, valueMapper, throwingMerger(), ConcurrentHashMap::new); + return new CollectorImpl<>(ConcurrentHashMap::new, + uniqKeysMapAccumulator(keyMapper, valueMapper), + uniqKeysMapMerger(), + CH_CONCURRENT_ID); } /** diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/java/util/zip/package.html --- a/jdk/src/share/classes/java/util/zip/package.html Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/java/util/zip/package.html Wed Jul 05 19:39:35 2017 +0200 @@ -39,45 +39,35 @@

      Package Specification

      - diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/sql/PooledConnection.java --- a/jdk/src/share/classes/javax/sql/PooledConnection.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/sql/PooledConnection.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,7 +83,6 @@ * ConnectionPool method addStatementEventListener. * Thus, when an application closes its PreparedStatement, * the underlying prepared statement is recycled rather than being closed. - *

      * * @since 1.4 */ @@ -154,10 +153,10 @@ * wish to be notified when PreparedStatements created by the * connection are closed or are detected to be invalid may use this method * to register a StatementEventListener with this PooledConnection object. - *

      + * * @param listener an component which implements the StatementEventListener * interface that is to be registered with this PooledConnection object - *

      + * * @since 1.6 */ public void addStatementEventListener(StatementEventListener listener); @@ -166,11 +165,11 @@ * Removes the specified StatementEventListener from the list of * components that will be notified when the driver detects that a * PreparedStatement has been closed or is invalid. - *

      + * * @param listener the component which implements the * StatementEventListener interface that was previously * registered with this PooledConnection object - *

      + * * @since 1.6 */ public void removeStatementEventListener(StatementEventListener listener); diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/sql/StatementEvent.java --- a/jdk/src/share/classes/javax/sql/StatementEvent.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/sql/StatementEvent.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ * registered with a PooledConnection. This occurs when the driver determines that a * PreparedStatement that is associated with the PooledConnection has been closed or the driver determines * is invalid. - *

      + * * @since 1.6 */ public class StatementEvent extends EventObject { @@ -50,11 +50,11 @@ * Constructs a StatementEvent with the specified PooledConnection and * PreparedStatement. The SQLException contained in the event defaults to * null. - *

      + * * @param con The PooledConnection that the closed or invalid * PreparedStatementis associated with. * @param statement The PreparedStatement that is being closed or is invalid - *

      + * * @throws IllegalArgumentException if con is null. * * @since 1.6 @@ -71,7 +71,7 @@ /** * Constructs a StatementEvent with the specified PooledConnection, * PreparedStatement and SQLException - *

      + * * @param con The PooledConnection that the closed or invalid PreparedStatement * is associated with. * @param statement The PreparedStatement that is being closed or is invalid @@ -79,7 +79,7 @@ * the application * * @throws IllegalArgumentException if con is null. - *

      + * * @since 1.6 */ public StatementEvent(PooledConnection con, @@ -94,9 +94,9 @@ /** * Returns the PreparedStatement that is being closed or is invalid - *

      + * * @return The PreparedStatement that is being closed or is invalid - *

      + * * @since 1.6 */ public PreparedStatement getStatement() { @@ -106,9 +106,9 @@ /** * Returns the SQLException the driver is about to throw - *

      + * * @return The SQLException the driver is about to throw - *

      + * * @since 1.6 */ public SQLException getSQLException() { diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/sql/StatementEventListener.java --- a/jdk/src/share/classes/javax/sql/StatementEventListener.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/sql/StatementEventListener.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ *

      * Methods which allow a component to register a StatementEventListener with a * PooledConnection have been added to the PooledConnection interface. - *

      + * * @since 1.6 */ public interface StatementEventListener extends java.util.EventListener{ @@ -72,13 +72,13 @@ * PreparedStatement is invalid. The driver calls this method * just before it throws the SQLException, * contained in the given event, to the application. - *

      - * @param event an event object describing the source of the event, - * the statement that is invalid and the exception the - * driver is about to throw. The source of the event is - * the PooledConnection which the invalid PreparedStatement - * is associated with. - *

      + * + * @param event an event object describing the source of the event, + * the statement that is invalid and the exception the + * driver is about to throw. The source of the event is + * the PooledConnection which the invalid PreparedStatement + * is associated with. + * * @since 1.6 */ void statementErrorOccurred(StatementEvent event); diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/sql/package.html --- a/jdk/src/share/classes/javax/sql/package.html Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/sql/package.html Wed Jul 05 19:39:35 2017 +0200 @@ -2,7 +2,7 @@ javax.sql.rowset.spi - + @@ -46,7 +46,7 @@ it with the SyncFactory singleton. (See the class comment for SyncProvider for a full explanation of the registration process and the naming convention to be used.) -

      +

      Table of Contents

      -

      1.0 Package Specification

      +

      1.0 Package Specification

      The following classes and interfaces make up the javax.sql.rowset.spi package: @@ -155,7 +155,7 @@ using locks; rather, it checks to see if there is a conflict before trying to synchronize the RowSet object and the data source. If there is a conflict, it does nothing, meaning that - changes to the RowSet object are not persisted to the data + changes to the RowSet object are not persisted to the data source.

    • RIXMLProvider
      A synchronization provider that can be used with a @@ -201,10 +201,8 @@ synchronization mechanisms. A vendor can make its implementation available by registering the fully qualified class name with Oracle Corporation at jdbc@sun.com. This process is discussed in further detail below. -

      -

      2.0 Service Provider Interface Architecture

      -
        +

        2.0 Service Provider Interface Architecture

        2.1 Overview

        The Service Provider Interface provides a pluggable mechanism by which @@ -229,13 +227,13 @@ properties are set at run time and apply system-wide per invocation of the Java application. See the section "Related Documentation" further related information. -

        +

      • Property Files - Properties specified in a standard property file. This can be specified using a System Property or by modifying a standard property file located in the platform run-time. The reference implementation of this technology includes a standard property file than can be edited to add additional SyncProvider objects. -

        +

      • JNDI Context - Available providers can be registered on a JNDI context. The SyncFactory will attempt to load SyncProvider objects bound to the context and register them with the factory. This @@ -258,20 +256,19 @@
      • If a SyncProvider object is specified and the SyncFactory contains no reference to the provider, a SyncFactoryException is thrown. -

        +

      • If a SyncProvider object is specified and the SyncFactory contains a reference to the provider, the requested provider is supplied. -

        +

      • If no SyncProvider object is specified, the reference implementation provider RIOptimisticProvider is supplied.

      These policies are explored in more detail in the SyncFactory class. -

    -
  • 3.0 SyncProvider Implementer's Guide

    -
      +

      3.0 SyncProvider Implementer's Guide

      + 3.1 Requirements

      A compliant SyncProvider implementation that is fully pluggable @@ -300,7 +297,7 @@ underlying data source, overwriting whatever is there. No attempt is made to compare original values with current values to see if there is a conflict. The RIXMLProvider is implemented with this grade. -

      +

    • GRADE_CHECK_MODIFIED_AT_COMMIT - A low grade of optimistic synchronization. A SyncProvider implementation returning this grade will check for conflicts in rows that have changed between the last synchronization @@ -309,20 +306,20 @@ object. If there are no conflicts, changes in the RowSet object will be written to the data source. If there are conflicts, no changes are written. The RIOptimisticProvider implementation uses this grade. -

      +

    • GRADE_CHECK_ALL_AT_COMMIT - A high grade of optimistic synchronization. A SyncProvider implementation returning this grade will check all rows, including rows that have not changed in the disconnected RowSet object. In this way, any changes to rows in the underlying data source will be reflected in the disconnected RowSet object when the synchronization finishes successfully. -

      +

    • GRADE_LOCK_WHEN_MODIFIED - A pessimistic grade of synchronization. SyncProvider implementations returning this grade will lock the row in the originating data source that corresponds to the row being changed in the RowSet object to reduce the possibility of other processes modifying the same data in the data source. -

      +

    • GRADE_LOCK_WHEN_LOADED - A higher pessimistic synchronization grade. A SyncProvider implementation returning this grade will lock the entire view and/or table affected by the original query used to @@ -347,13 +344,13 @@
    • DATASOURCE_NO_LOCK - No locks remain on the originating data source. This is the default lock setting for all SyncProvider implementations unless otherwise directed by a RowSet object. -

      +

    • DATASOURCE_ROW_LOCK - A lock is placed on the rows that are touched by the original SQL query used to populate the RowSet object. -

      +

    • DATASOURCE_TABLE_LOCK - A lock is placed on all tables that are touched by the query that was used to populate the RowSet object. -

      +

    • DATASOURCE_DB_LOCK A lock is placed on the entire data source that is used by the RowSet object. @@ -369,7 +366,7 @@ Indicates that a SyncProvider implementation supports synchronization to the table or tables from which the SQL VIEW used to populate a a RowSet object is derived. -

      +

    • NONUPDATABLE_VIEW_SYNC Indicates that a SyncProvider implementation does not support synchronization to the table or tables from which the SQL VIEW @@ -381,7 +378,7 @@ In the example below, the reference CachedRowSetImpl implementation reconfigures its current SyncProvider object by calling the setSyncProvider method.
      - +
           CachedRowSetImpl crs = new CachedRowSetImpl();
           crs.setSyncProvider("com.foo.bar.HASyncProvider");
      @@ -412,7 +409,7 @@
             // No synchronization with the originating data source provided
           break;
           }
      -	  
      +
           switch (sync.getDataSourcLock() {
             case: SyncProvider.DATASOURCE_DB_LOCK
              // A lock is placed on the entire datasource that is used by the
      @@ -439,14 +436,13 @@
           It is also possible using the static utility method in the
       SyncFactory class to determine the list of SyncProvider
       implementations currently registered with the SyncFactory.
      -       
      +
       
      -	Enumeration e = SyncFactory.getRegisteredProviders();
      -
      + Enumeration e = SyncFactory.getRegisteredProviders(); +
      -
    -

    4.0 Resolving Synchronization Conflicts

    +

    4.0 Resolving Synchronization Conflicts

    The interface SyncResolver provides a way for an application to decide manually what to do when a conflict occurs. When the CachedRowSet @@ -491,18 +487,18 @@

    The comment for the SyncResolver interface has more detail. -

    5.0 Related Specifications

    +

    5.0 Related Specifications

    -

    6.0 Related Documentation

    +

    6.0 Related Documentation

    diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/BufferStrategyPaintManager.java --- a/jdk/src/share/classes/javax/swing/BufferStrategyPaintManager.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/swing/BufferStrategyPaintManager.java Wed Jul 05 19:39:35 2017 +0200 @@ -27,13 +27,10 @@ import java.awt.*; import java.awt.event.*; import java.awt.image.*; -import java.lang.reflect.*; import java.lang.ref.WeakReference; import java.util.*; import com.sun.java.swing.SwingUtilities3; -import java.util.logging.Level; -import java.util.logging.Logger; import sun.awt.AWTAccessor; import sun.awt.SubRegionShowable; diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/JOptionPane.java --- a/jdk/src/share/classes/javax/swing/JOptionPane.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/swing/JOptionPane.java Wed Jul 05 19:39:35 2017 +0200 @@ -56,6 +56,7 @@ import javax.swing.event.InternalFrameAdapter; import javax.accessibility.*; import static javax.swing.ClientPropertyKey.PopupFactory_FORCE_HEAVYWEIGHT_POPUP; +import sun.awt.AWTAccessor; /** * JOptionPane makes it easy to pop up a standard dialog box that @@ -1306,17 +1307,7 @@ } } - // Use reflection to get Container.startLWModal. - try { - Method method = AccessController.doPrivileged(new ModalPrivilegedAction( - Container.class, "startLWModal")); - if (method != null) { - method.invoke(dialog, (Object[])null); - } - } catch (IllegalAccessException ex) { - } catch (IllegalArgumentException ex) { - } catch (InvocationTargetException ex) { - } + AWTAccessor.getContainerAccessor().startLWModal(dialog); if (parentComponent instanceof JInternalFrame) { try { @@ -1451,17 +1442,7 @@ } } - // Use reflection to get Container.startLWModal. - try { - Method method = AccessController.doPrivileged(new ModalPrivilegedAction( - Container.class, "startLWModal")); - if (method != null) { - method.invoke(dialog, (Object[])null); - } - } catch (IllegalAccessException ex) { - } catch (IllegalArgumentException ex) { - } catch (InvocationTargetException ex) { - } + AWTAccessor.getContainerAccessor().startLWModal(dialog); if (parentComponent instanceof JInternalFrame) { try { @@ -1535,18 +1516,7 @@ if (iFrame.isVisible() && event.getSource() == JOptionPane.this && event.getPropertyName().equals(VALUE_PROPERTY)) { - // Use reflection to get Container.stopLWModal(). - try { - Method method = AccessController.doPrivileged( - new ModalPrivilegedAction( - Container.class, "stopLWModal")); - if (method != null) { - method.invoke(iFrame, (Object[])null); - } - } catch (IllegalAccessException ex) { - } catch (IllegalArgumentException ex) { - } catch (InvocationTargetException ex) { - } + AWTAccessor.getContainerAccessor().stopLWModal(iFrame); try { iFrame.setClosed(true); @@ -2512,33 +2482,6 @@ ",wantsInput=" + wantsInputString; } - /** - * Retrieves a method from the provided class and makes it accessible. - */ - private static class ModalPrivilegedAction implements PrivilegedAction { - private Class clazz; - private String methodName; - - public ModalPrivilegedAction(Class clazz, String methodName) { - this.clazz = clazz; - this.methodName = methodName; - } - - public Method run() { - Method method = null; - try { - method = clazz.getDeclaredMethod(methodName, (Class[])null); - } catch (NoSuchMethodException ex) { - } - if (method != null) { - method.setAccessible(true); - } - return method; - } - } - - - /////////////////// // Accessibility support /////////////////// diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/JTable.java --- a/jdk/src/share/classes/javax/swing/JTable.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/swing/JTable.java Wed Jul 05 19:39:35 2017 +0200 @@ -34,7 +34,6 @@ import java.beans.*; -import java.io.Serializable; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.io.IOException; @@ -4043,7 +4042,7 @@ } // Restore the lead int viewLeadIndex = modelSelection.getLeadSelectionIndex(); - if (viewLeadIndex != -1) { + if (viewLeadIndex != -1 && !modelSelection.isSelectionEmpty()) { viewLeadIndex = convertRowIndexToView(viewLeadIndex); } SwingUtilities2.setLeadAnchorWithoutSelection( @@ -5307,14 +5306,6 @@ return retValue; } - private void setLazyValue(Hashtable h, Class c, LazyClass lazyClass) { - h.put(c, new TableLazyValue(lazyClass)); - } - - private void setLazyRenderer(Class c, LazyClass lazyClass) { - setLazyValue(defaultRenderersByColumnClass, c, lazyClass); - } - /** * Creates default cell renderers for objects, numbers, doubles, dates, * booleans, and icons. @@ -5325,24 +5316,32 @@ defaultRenderersByColumnClass = new UIDefaults(8, 0.75f); // Objects - setLazyRenderer(Object.class, LazyClass.UIResource); + defaultRenderersByColumnClass.put(Object.class, (UIDefaults.LazyValue) + t -> new DefaultTableCellRenderer.UIResource()); // Numbers - setLazyRenderer(Number.class, LazyClass.NumberRenderer); + defaultRenderersByColumnClass.put(Number.class, (UIDefaults.LazyValue) + t -> new NumberRenderer()); // Doubles and Floats - setLazyRenderer(Float.class, LazyClass.DoubleRenderer); - setLazyRenderer(Double.class, LazyClass.DoubleRenderer); + defaultRenderersByColumnClass.put(Float.class, (UIDefaults.LazyValue) + t -> new DoubleRenderer()); + defaultRenderersByColumnClass.put(Double.class, (UIDefaults.LazyValue) + t -> new DoubleRenderer()); // Dates - setLazyRenderer(Date.class, LazyClass.DateRenderer); + defaultRenderersByColumnClass.put(Date.class, (UIDefaults.LazyValue) + t -> new DateRenderer()); // Icons and ImageIcons - setLazyRenderer(Icon.class, LazyClass.IconRenderer); - setLazyRenderer(ImageIcon.class, LazyClass.IconRenderer); + defaultRenderersByColumnClass.put(Icon.class, (UIDefaults.LazyValue) + t -> new IconRenderer()); + defaultRenderersByColumnClass.put(ImageIcon.class, (UIDefaults.LazyValue) + t -> new IconRenderer()); // Booleans - setLazyRenderer(Boolean.class, LazyClass.BooleanRenderer); + defaultRenderersByColumnClass.put(Boolean.class, (UIDefaults.LazyValue) + t -> new BooleanRenderer()); } /** @@ -5420,10 +5419,6 @@ } } - private void setLazyEditor(Class c, LazyClass lazyClass) { - setLazyValue(defaultEditorsByColumnClass, c, lazyClass); - } - /** * Creates default cell editors for objects, numbers, and boolean values. * @see DefaultCellEditor @@ -5432,13 +5427,16 @@ defaultEditorsByColumnClass = new UIDefaults(3, 0.75f); // Objects - setLazyEditor(Object.class, LazyClass.GenericEditor); + defaultEditorsByColumnClass.put(Object.class, (UIDefaults.LazyValue) + t -> new GenericEditor()); // Numbers - setLazyEditor(Number.class, LazyClass.NumberEditor); + defaultEditorsByColumnClass.put(Number.class, (UIDefaults.LazyValue) + t -> new NumberEditor()); // Booleans - setLazyEditor(Boolean.class, LazyClass.BooleanEditor); + defaultEditorsByColumnClass.put(Boolean.class, (UIDefaults.LazyValue) + t -> new BooleanEditor()); } /** @@ -6544,54 +6542,6 @@ } } - private enum LazyClass { - - UIResource, - NumberRenderer, - DoubleRenderer, - DateRenderer, - IconRenderer, - BooleanRenderer, - GenericEditor, - NumberEditor, - BooleanEditor, - } - - private static class TableLazyValue implements UIDefaults.LazyValue { - - private LazyClass type; - - public TableLazyValue(LazyClass type) { - this.type = type; - } - - @Override - public Object createValue(UIDefaults table) { - switch (type) { - case UIResource: - return new DefaultTableCellRenderer.UIResource(); - case NumberRenderer: - return new NumberRenderer(); - case DoubleRenderer: - return new DoubleRenderer(); - case DateRenderer: - return new DateRenderer(); - case IconRenderer: - return new IconRenderer(); - case BooleanRenderer: - return new BooleanRenderer(); - case GenericEditor: - return new GenericEditor(); - case NumberEditor: - return new NumberEditor(); - case BooleanEditor: - return new BooleanEditor(); - default: - return null; - } - } - } - ///////////////// // Accessibility support //////////////// @@ -6636,8 +6586,8 @@ TableColumnModelListener, CellEditorListener, PropertyChangeListener, AccessibleExtendedTable { - int lastSelectedRow; - int lastSelectedCol; + int previousFocusedRow; + int previousFocusedCol; /** * AccessibleJTable constructor @@ -6652,8 +6602,10 @@ tcm.addColumnModelListener(this); tcm.getSelectionModel().addListSelectionListener(this); JTable.this.getModel().addTableModelListener(this); - lastSelectedRow = JTable.this.getSelectedRow(); - lastSelectedCol = JTable.this.getSelectedColumn(); + previousFocusedRow = JTable.this.getSelectionModel(). + getLeadSelectionIndex(); + previousFocusedCol = JTable.this.getColumnModel(). + getSelectionModel().getLeadSelectionIndex(); } // Listeners to track model, etc. changes to as to re-place the other @@ -6979,20 +6931,23 @@ */ public void valueChanged(ListSelectionEvent e) { firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY, - Boolean.valueOf(false), Boolean.valueOf(true)); - - int selectedRow = JTable.this.getSelectedRow(); - int selectedCol = JTable.this.getSelectedColumn(); - if (selectedRow != lastSelectedRow || - selectedCol != lastSelectedCol) { - Accessible oldA = getAccessibleAt(lastSelectedRow, - lastSelectedCol); - Accessible newA = getAccessibleAt(selectedRow, selectedCol); + Boolean.valueOf(false), Boolean.valueOf(true)); + + // Using lead selection index to cover both cases: node selected and node + // is focused but not selected (Ctrl+up/down) + int focusedRow = JTable.this.getSelectionModel().getLeadSelectionIndex(); + int focusedCol = JTable.this.getColumnModel().getSelectionModel(). + getLeadSelectionIndex(); + + if (focusedRow != previousFocusedRow || + focusedCol != previousFocusedCol) { + Accessible oldA = getAccessibleAt(previousFocusedRow, previousFocusedCol); + Accessible newA = getAccessibleAt(focusedRow, focusedCol); firePropertyChange(AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY, - oldA, newA); - lastSelectedRow = selectedRow; - lastSelectedCol = selectedCol; - } + oldA, newA); + previousFocusedRow = focusedRow; + previousFocusedCol = focusedCol; + } } diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/JTree.java --- a/jdk/src/share/classes/javax/swing/JTree.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/swing/JTree.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1664,6 +1664,14 @@ leadPath = newPath; firePropertyChange(LEAD_SELECTION_PATH_PROPERTY, oldValue, newPath); + + // Fire the active descendant property change here since the + // leadPath got set, this is triggered both in case node + // selection changed and node focus changed + if (accessibleContext != null){ + ((AccessibleJTree)accessibleContext). + fireActiveDescendantPropertyChange(oldValue, newPath); + } } /** @@ -4129,26 +4137,9 @@ * */ public void valueChanged(TreeSelectionEvent e) { - // Fixes 4546503 - JTree is sending incorrect active - // descendant events - TreePath oldLeadSelectionPath = e.getOldLeadSelectionPath(); - leadSelectionPath = e.getNewLeadSelectionPath(); - - if (oldLeadSelectionPath != leadSelectionPath) { - // Set parent to null so AccessibleJTreeNode computes - // its parent. - Accessible oldLSA = leadSelectionAccessible; - leadSelectionAccessible = (leadSelectionPath != null) - ? new AccessibleJTreeNode(JTree.this, - leadSelectionPath, - null) // parent - : null; - firePropertyChange(AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY, - oldLSA, leadSelectionAccessible); - } - firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY, - Boolean.valueOf(false), Boolean.valueOf(true)); - } + firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY, + Boolean.valueOf(false), Boolean.valueOf(true)); + } /** * Fire a visible data property change notification. @@ -4249,6 +4240,34 @@ } } + /** + * Fire an active descendant property change notification. + * The active descendant is used for objects such as list, + * tree, and table, which may have transient children. + * It notifies screen readers the active child of the component + * has been changed so user can be notified from there. + * + * @param oldPath - lead path of previous active child + * @param newPath - lead path of current active child + * + */ + void fireActiveDescendantPropertyChange(TreePath oldPath, TreePath newPath){ + if(oldPath != newPath){ + Accessible oldLSA = (oldPath != null) + ? new AccessibleJTreeNode(JTree.this, + oldPath, + null) + : null; + + Accessible newLSA = (newPath != null) + ? new AccessibleJTreeNode(JTree.this, + newPath, + null) + : null; + firePropertyChange(AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY, + oldLSA, newLSA); + } + } private AccessibleContext getCurrentAccessibleContext() { Component c = getCurrentComponent(); diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/plaf/ComponentUI.java --- a/jdk/src/share/classes/javax/swing/plaf/ComponentUI.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/swing/plaf/ComponentUI.java Wed Jul 05 19:39:35 2017 +0200 @@ -297,7 +297,7 @@ } /** - * Returns an enum indicating how the baseline of he component + * Returns an enum indicating how the baseline of the component * changes as the size changes. This method is primarily meant for * layout managers and GUI builders. *

    diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,10 @@ import javax.swing.event.*; import javax.swing.plaf.*; +import static sun.swing.SwingUtilities2.drawHLine; +import static sun.swing.SwingUtilities2.drawRect; +import static sun.swing.SwingUtilities2.drawVLine; + /** * Implementation of ScrollBarUI for the Basic Look and Feel @@ -572,17 +576,17 @@ g.translate(thumbBounds.x, thumbBounds.y); g.setColor(thumbDarkShadowColor); - g.drawRect(0, 0, w-1, h-1); + drawRect(g, 0, 0, w - 1, h - 1); g.setColor(thumbColor); - g.fillRect(0, 0, w-1, h-1); + g.fillRect(0, 0, w - 1, h - 1); g.setColor(thumbHighlightColor); - g.drawLine(1, 1, 1, h-2); - g.drawLine(2, 1, w-3, 1); + drawVLine(g, 1, 1, h - 2); + drawHLine(g, 2, w - 3, 1); g.setColor(thumbLightShadowColor); - g.drawLine(2, h-2, w-2, h-2); - g.drawLine(w-2, 1, w-2, h-3); + drawHLine(g, 2, w - 2, h - 2); + drawVLine(g, w - 2, 1, h - 3); g.translate(-thumbBounds.x, -thumbBounds.y); } diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java --- a/jdk/src/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java Wed Jul 05 19:39:35 2017 +0200 @@ -34,13 +34,10 @@ import javax.swing.text.DefaultEditorKit; import java.awt.Color; -import java.awt.event.KeyEvent; -import java.lang.reflect.*; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.security.AccessController; -import java.security.PrivilegedAction; import sun.awt.*; import sun.security.action.GetPropertyAction; @@ -460,11 +457,9 @@ LazyValue textFieldBorder = t -> MetalBorders.getTextFieldBorder(); - Object dialogBorder = new MetalLazyValue( - "javax.swing.plaf.metal.MetalBorders$DialogBorder"); + LazyValue dialogBorder = t -> new MetalBorders.DialogBorder(); - Object questionDialogBorder = new MetalLazyValue( - "javax.swing.plaf.metal.MetalBorders$QuestionDialogBorder"); + LazyValue questionDialogBorder = t -> new MetalBorders.QuestionDialogBorder(); Object fieldInputMap = new UIDefaults.LazyInputMap(new Object[] { "ctrl C", DefaultEditorKit.copyAction, @@ -1470,12 +1465,8 @@ "ToolBar.floatingBackground", menuBackground, "ToolBar.dockingForeground", primaryControlDarkShadow, "ToolBar.floatingForeground", primaryControl, - "ToolBar.rolloverBorder", new MetalLazyValue( - "javax.swing.plaf.metal.MetalBorders", - "getToolBarRolloverBorder"), - "ToolBar.nonrolloverBorder", new MetalLazyValue( - "javax.swing.plaf.metal.MetalBorders", - "getToolBarNonrolloverBorder"), + "ToolBar.rolloverBorder", (LazyValue) t -> MetalBorders.getToolBarRolloverBorder(), + "ToolBar.nonrolloverBorder", (LazyValue) t -> MetalBorders.getToolBarNonrolloverBorder(), "ToolBar.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { "UP", "navigateUp", @@ -1489,17 +1480,14 @@ }), // RootPane - "RootPane.frameBorder", new MetalLazyValue( - "javax.swing.plaf.metal.MetalBorders$FrameBorder"), + "RootPane.frameBorder", (LazyValue) t -> new MetalBorders.FrameBorder(), "RootPane.plainDialogBorder", dialogBorder, "RootPane.informationDialogBorder", dialogBorder, - "RootPane.errorDialogBorder", new MetalLazyValue( - "javax.swing.plaf.metal.MetalBorders$ErrorDialogBorder"), + "RootPane.errorDialogBorder", (LazyValue) t -> new MetalBorders.ErrorDialogBorder(), "RootPane.colorChooserDialogBorder", questionDialogBorder, "RootPane.fileChooserDialogBorder", questionDialogBorder, "RootPane.questionDialogBorder", questionDialogBorder, - "RootPane.warningDialogBorder", new MetalLazyValue( - "javax.swing.plaf.metal.MetalBorders$WarningDialogBorder"), + "RootPane.warningDialogBorder", (LazyValue) t -> new MetalBorders.WarningDialogBorder(), // These bindings are only enabled when there is a default // button set on the rootpane. "RootPane.defaultButtonWindowKeyBindings", new Object[] { @@ -2151,61 +2139,6 @@ /** - * MetalLazyValue is a slimmed down version of ProxyLaxyValue. - * The code is duplicate so that it can get at the package private - * classes in metal. - */ - private static class MetalLazyValue implements UIDefaults.LazyValue { - /** - * Name of the class to create. - */ - private String className; - private String methodName; - - MetalLazyValue(String name) { - this.className = name; - } - - MetalLazyValue(String name, String methodName) { - this(name); - this.methodName = methodName; - } - - public Object createValue(UIDefaults table) { - try { - final Class c = Class.forName(className); - - if (methodName == null) { - return c.newInstance(); - } - Method method = AccessController.doPrivileged( - new PrivilegedAction() { - public Method run() { - Method[] methods = c.getDeclaredMethods(); - for (int counter = methods.length - 1; counter >= 0; - counter--) { - if (methods[counter].getName().equals(methodName)){ - methods[counter].setAccessible(true); - return methods[counter]; - } - } - return null; - } - }); - if (method != null) { - return method.invoke(null, (Object[])null); - } - } catch (ClassNotFoundException cnfe) { - } catch (InstantiationException ie) { - } catch (IllegalAccessException iae) { - } catch (InvocationTargetException ite) { - } - return null; - } - } - - - /** * FontActiveValue redirects to the appropriate metal theme method. */ private static class FontActiveValue implements UIDefaults.ActiveValue { diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/plaf/metal/MetalScrollBarUI.java --- a/jdk/src/share/classes/javax/swing/plaf/metal/MetalScrollBarUI.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/swing/plaf/metal/MetalScrollBarUI.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,33 +25,23 @@ package javax.swing.plaf.metal; -import java.awt.Component; -import java.awt.Container; -import java.awt.LayoutManager; -import java.awt.Adjustable; -import java.awt.event.AdjustmentListener; -import java.awt.event.AdjustmentEvent; -import java.awt.event.ActionListener; -import java.awt.event.ActionEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.Graphics; +import java.awt.Color; import java.awt.Dimension; +import java.awt.Graphics; import java.awt.Rectangle; -import java.awt.Point; -import java.awt.Insets; -import java.awt.Color; -import java.awt.IllegalComponentStateException; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; -import java.beans.*; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JScrollBar; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicScrollBarUI; -import javax.swing.*; -import javax.swing.event.*; - -import javax.swing.plaf.*; -import javax.swing.plaf.basic.BasicScrollBarUI; +import static sun.swing.SwingUtilities2.drawHLine; +import static sun.swing.SwingUtilities2.drawRect; +import static sun.swing.SwingUtilities2.drawVLine; /** @@ -158,21 +148,21 @@ if ( c.isEnabled() ) { g.setColor( darkShadowColor ); - g.drawLine( 0, 0, 0, trackBounds.height - 1 ); - g.drawLine( trackBounds.width - 2, 0, trackBounds.width - 2, trackBounds.height - 1 ); - g.drawLine( 2, trackBounds.height - 1, trackBounds.width - 1, trackBounds.height - 1); - g.drawLine( 2, 0, trackBounds.width - 2, 0 ); + drawVLine(g, 0, 0, trackBounds.height - 1); + drawVLine(g, trackBounds.width - 2, 0, trackBounds.height - 1); + drawHLine(g, 2, trackBounds.width - 1, trackBounds.height - 1); + drawHLine(g, 2, trackBounds.width - 2, 0); g.setColor( shadowColor ); // g.setColor( Color.red); - g.drawLine( 1, 1, 1, trackBounds.height - 2 ); - g.drawLine( 1, 1, trackBounds.width - 3, 1 ); + drawVLine(g, 1, 1, trackBounds.height - 2); + drawHLine(g, 1, trackBounds.width - 3, 1); if (scrollbar.getValue() != scrollbar.getMaximum()) { // thumb shadow int y = thumbRect.y + thumbRect.height - trackBounds.y; - g.drawLine( 1, y, trackBounds.width-1, y); + drawHLine(g, 1, trackBounds.width - 1, y); } g.setColor(highlightColor); - g.drawLine( trackBounds.width - 1, 0, trackBounds.width - 1, trackBounds.height - 1 ); + drawVLine(g, trackBounds.width - 1, 0, trackBounds.height - 1); } else { MetalUtils.drawDisabledBorder(g, 0, 0, trackBounds.width, trackBounds.height ); } @@ -192,19 +182,19 @@ if ( c.isEnabled() ) { g.setColor( darkShadowColor ); - g.drawLine( 0, 0, trackBounds.width - 1, 0 ); // top - g.drawLine( 0, 2, 0, trackBounds.height - 2 ); // left - g.drawLine( 0, trackBounds.height - 2, trackBounds.width - 1, trackBounds.height - 2 ); // bottom - g.drawLine( trackBounds.width - 1, 2, trackBounds.width - 1, trackBounds.height - 1 ); // right + drawHLine(g, 0, trackBounds.width - 1, 0); // top + drawVLine(g, 0, 2, trackBounds.height - 2); // left + drawHLine(g, 0, trackBounds.width - 1, trackBounds.height - 2 ); // bottom + drawVLine(g, trackBounds.width - 1, 2, trackBounds.height - 1 ); // right g.setColor( shadowColor ); // g.setColor( Color.red); - g.drawLine( 1, 1, trackBounds.width - 2, 1 ); // top - g.drawLine( 1, 1, 1, trackBounds.height - 3 ); // left - g.drawLine( 0, trackBounds.height - 1, trackBounds.width - 1, trackBounds.height - 1 ); // bottom + drawHLine(g, 1, trackBounds.width - 2, 1 ); // top + drawVLine(g, 1, 1, trackBounds.height - 3 ); // left + drawHLine(g, 0, trackBounds.width - 1, trackBounds.height - 1 ); // bottom if (scrollbar.getValue() != scrollbar.getMaximum()) { // thumb shadow int x = thumbRect.x + thumbRect.width - trackBounds.x; - g.drawLine( x, 1, x, trackBounds.height-1); + drawVLine(g, x, 1, trackBounds.height-1); } } else { MetalUtils.drawDisabledBorder(g, 0, 0, trackBounds.width, trackBounds.height ); @@ -246,11 +236,11 @@ g.fillRect( 0, 0, thumbBounds.width - 2, thumbBounds.height - 1 ); g.setColor( thumbShadow ); - g.drawRect( 0, 0, thumbBounds.width - 2, thumbBounds.height - 1 ); + drawRect(g, 0, 0, thumbBounds.width - 2, thumbBounds.height - 1); g.setColor( thumbHighlightColor ); - g.drawLine( 1, 1, thumbBounds.width - 3, 1 ); - g.drawLine( 1, 1, 1, thumbBounds.height - 2 ); + drawHLine(g, 1, thumbBounds.width - 3, 1); + drawVLine(g, 1, 1, thumbBounds.height - 2); bumps.setBumpArea( thumbBounds.width - 6, thumbBounds.height - 7 ); bumps.paintIcon( c, g, 3, 4 ); @@ -272,11 +262,11 @@ g.fillRect( 0, 0, thumbBounds.width - 1, thumbBounds.height - 2 ); g.setColor( thumbShadow ); - g.drawRect( 0, 0, thumbBounds.width - 1, thumbBounds.height - 2 ); + drawRect(g, 0, 0, thumbBounds.width - 1, thumbBounds.height - 2); g.setColor( thumbHighlightColor ); - g.drawLine( 1, 1, thumbBounds.width - 3, 1 ); - g.drawLine( 1, 1, 1, thumbBounds.height - 3 ); + drawHLine(g, 1, thumbBounds.width - 3, 1); + drawVLine(g, 1, 1, thumbBounds.height - 3); bumps.setBumpArea( thumbBounds.width - 7, thumbBounds.height - 6 ); bumps.paintIcon( c, g, 4, 3 ); @@ -309,11 +299,11 @@ } g.setColor(thumbShadow); - g.drawRect(0, 0, thumbBounds.width - 2, thumbBounds.height - 1); + drawRect(g, 0, 0, thumbBounds.width - 2, thumbBounds.height - 1); g.setColor(thumbHighlightColor); - g.drawLine(1, 1, thumbBounds.width - 3, 1); - g.drawLine(1, 1, 1, thumbBounds.height - 2); + drawHLine(g, 1, thumbBounds.width - 3, 1); + drawVLine(g, 1, 1, thumbBounds.height - 2); MetalUtils.drawGradient(c, g, "ScrollBar.gradient", 2, 2, thumbBounds.width - 4, @@ -351,11 +341,11 @@ } g.setColor(thumbShadow); - g.drawRect(0, 0, thumbBounds.width - 1, thumbBounds.height - 2); + drawRect(g, 0, 0, thumbBounds.width - 1, thumbBounds.height - 2); g.setColor(thumbHighlightColor); - g.drawLine(1, 1, thumbBounds.width - 2, 1); - g.drawLine(1, 1, 1, thumbBounds.height - 3); + drawHLine(g, 1, thumbBounds.width - 2, 1); + drawVLine(g, 1, 1, thumbBounds.height - 3); MetalUtils.drawGradient(c, g, "ScrollBar.gradient", 2, 2, thumbBounds.width - 3, diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/text/EditorKit.java --- a/jdk/src/share/classes/javax/swing/text/EditorKit.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/swing/text/EditorKit.java Wed Jul 05 19:39:35 2017 +0200 @@ -39,9 +39,9 @@ * A kit can safely store editing state as an instance * of the kit will be dedicated to a text component. * New kits will normally be created by cloning a - * prototype kit. The kit will have it's + * prototype kit. The kit will have its * setComponent method called to establish - * it's relationship with a JTextComponent. + * its relationship with a JTextComponent. * * @author Timothy Prinzing */ diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/text/JTextComponent.java --- a/jdk/src/share/classes/javax/swing/text/JTextComponent.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/swing/text/JTextComponent.java Wed Jul 05 19:39:35 2017 +0200 @@ -24,18 +24,16 @@ */ package javax.swing.text; -import java.lang.reflect.Method; +import com.sun.beans.util.Cache; import java.security.AccessController; import java.security.PrivilegedAction; import java.beans.Transient; -import java.util.Collections; import java.util.HashMap; import java.util.Hashtable; import java.util.Enumeration; import java.util.Vector; -import java.util.Map; import java.util.concurrent.*; @@ -1194,47 +1192,6 @@ } /** - * Returns true if klass is NOT a JTextComponent and it or - * one of its superclasses (stoping at JTextComponent) overrides - * processInputMethodEvent. It is assumed this will be - * invoked from within a doPrivileged, and it is also - * assumed klass extends JTextComponent. - */ - private static Boolean isProcessInputMethodEventOverridden(Class klass) { - if (klass == JTextComponent.class) { - return Boolean.FALSE; - } - Boolean retValue = overrideMap.get(klass.getName()); - - if (retValue != null) { - return retValue; - } - Boolean sOverriden = isProcessInputMethodEventOverridden( - klass.getSuperclass()); - - if (sOverriden.booleanValue()) { - // If our superclass has overriden it, then by definition klass - // overrides it. - overrideMap.put(klass.getName(), sOverriden); - return sOverriden; - } - // klass's superclass didn't override it, check for an override in - // klass. - try { - Class[] classes = new Class[1]; - classes[0] = InputMethodEvent.class; - - Method m = klass.getDeclaredMethod("processInputMethodEvent", - classes); - retValue = Boolean.TRUE; - } catch (NoSuchMethodException nsme) { - retValue = Boolean.FALSE; - } - overrideMap.put(klass.getName(), retValue); - return retValue; - } - - /** * Fetches the current color used to render the * caret. * @@ -3916,7 +3873,33 @@ * Maps from class name to Boolean indicating if * processInputMethodEvent has been overriden. */ - private static Map overrideMap; + private static Cache,Boolean> METHOD_OVERRIDDEN + = new Cache,Boolean>(Cache.Kind.WEAK, Cache.Kind.STRONG) { + /** + * Returns {@code true} if the specified {@code type} extends {@link JTextComponent} + * and the {@link JTextComponent#processInputMethodEvent} method is overridden. + */ + @Override + public Boolean create(final Class type) { + if (JTextComponent.class == type) { + return Boolean.FALSE; + } + if (get(type.getSuperclass())) { + return Boolean.TRUE; + } + return AccessController.doPrivileged( + new PrivilegedAction() { + public Boolean run() { + try { + type.getDeclaredMethod("processInputMethodEvent", InputMethodEvent.class); + return Boolean.TRUE; + } catch (NoSuchMethodException exception) { + return Boolean.FALSE; + } + } + }); + } + }; /** * Returns a string representation of this JTextComponent. @@ -4941,39 +4924,16 @@ */ private boolean shouldSynthensizeKeyEvents() { if (!checkedInputOverride) { + // Checks whether the client code overrides processInputMethodEvent. + // If it is overridden, need not to generate KeyTyped events for committed text. + // If it's not, behave as an passive input method client. + needToSendKeyTypedEvent = !METHOD_OVERRIDDEN.get(getClass()); checkedInputOverride = true; - needToSendKeyTypedEvent = - !isProcessInputMethodEventOverridden(); } return needToSendKeyTypedEvent; } // - // Checks whether the client code overrides processInputMethodEvent. If it is overridden, - // need not to generate KeyTyped events for committed text. If it's not, behave as an - // passive input method client. - // - private boolean isProcessInputMethodEventOverridden() { - if (overrideMap == null) { - overrideMap = Collections.synchronizedMap(new HashMap()); - } - Boolean retValue = overrideMap.get(getClass().getName()); - - if (retValue != null) { - return retValue.booleanValue(); - } - Boolean ret = AccessController.doPrivileged(new - PrivilegedAction() { - public Boolean run() { - return isProcessInputMethodEventOverridden( - JTextComponent.this.getClass()); - } - }); - - return ret.booleanValue(); - } - - // // Checks whether a composed text in this text component // boolean composedTextExists() { diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/text/html/HTMLEditorKit.java --- a/jdk/src/share/classes/javax/swing/text/html/HTMLEditorKit.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/swing/text/html/HTMLEditorKit.java Wed Jul 05 19:39:35 2017 +0200 @@ -26,7 +26,6 @@ import sun.awt.AppContext; -import java.lang.reflect.Method; import java.awt.*; import java.awt.event.*; import java.io.*; @@ -34,12 +33,13 @@ import java.net.URL; import javax.swing.text.*; import javax.swing.*; -import javax.swing.border.*; import javax.swing.event.*; import javax.swing.plaf.TextUI; import java.util.*; import javax.accessibility.*; import java.lang.ref.*; +import java.security.AccessController; +import java.security.PrivilegedAction; /** * The Swing JEditorPane text component supports different kinds @@ -415,14 +415,13 @@ * HTMLEditorKit class * @return a stream representing the resource */ - static InputStream getResourceAsStream(String name) { - try { - return ResourceLoader.getResourceAsStream(name); - } catch (Throwable e) { - // If the class doesn't exist or we have some other - // problem we just try to call getResourceAsStream directly. - return HTMLEditorKit.class.getResourceAsStream(name); - } + static InputStream getResourceAsStream(final String name) { + return AccessController.doPrivileged( + new PrivilegedAction() { + public InputStream run() { + return HTMLEditorKit.class.getResourceAsStream(name); + } + }); } /** diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/text/html/ResourceLoader.java --- a/jdk/src/share/classes/javax/swing/text/html/ResourceLoader.java Wed Jul 05 19:38:36 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package javax.swing.text.html; - -import java.io.InputStream; - -/** - * Simple class to load resources using the 1.2 - * security model. Since the html support is loaded - * lazily, it's resources are potentially fetched with - * applet code in the call stack. By providing this - * functionality in a class that is only built on 1.2, - * reflection can be used from the code that is also - * built on 1.1 to call this functionality (and avoid - * the evils of preprocessing). This functionality - * is called from HTMLEditorKit.getResourceAsStream. - * - * @author Timothy Prinzing - */ -class ResourceLoader implements java.security.PrivilegedAction { - - ResourceLoader(String name) { - this.name = name; - } - - public Object run() { - Object o = HTMLEditorKit.class.getResourceAsStream(name); - return o; - } - - public static InputStream getResourceAsStream(String name) { - java.security.PrivilegedAction a = new ResourceLoader(name); - return (InputStream) java.security.AccessController.doPrivileged(a); - } - - private String name; -} diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java --- a/jdk/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java Wed Jul 05 19:39:35 2017 +0200 @@ -22,7 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package javax.swing.text.html.parser; import sun.awt.AppContext; @@ -35,6 +34,8 @@ import java.io.ObjectInputStream; import java.io.Reader; import java.io.Serializable; +import java.security.AccessController; +import java.security.PrivilegedAction; /** * Responsible for starting up a new DocumentParser @@ -110,14 +111,13 @@ * ParserDelegator class. * @returns a stream representing the resource */ - static InputStream getResourceAsStream(String name) { - try { - return ResourceLoader.getResourceAsStream(name); - } catch (Throwable e) { - // If the class doesn't exist or we have some other - // problem we just try to call getResourceAsStream directly. - return ParserDelegator.class.getResourceAsStream(name); - } + static InputStream getResourceAsStream(final String name) { + return AccessController.doPrivileged( + new PrivilegedAction() { + public InputStream run() { + return ParserDelegator.class.getResourceAsStream(name); + } + }); } private void readObject(ObjectInputStream s) diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/text/html/parser/ResourceLoader.java --- a/jdk/src/share/classes/javax/swing/text/html/parser/ResourceLoader.java Wed Jul 05 19:38:36 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package javax.swing.text.html.parser; - -import java.io.InputStream; - -/** - * Simple class to load resources using the 1.2 - * security model. Since the html support is loaded - * lazily, it's resources are potentially fetched with - * applet code in the call stack. By providing this - * functionality in a class that is only built on 1.2, - * reflection can be used from the code that is also - * built on 1.1 to call this functionality (and avoid - * the evils of preprocessing). This functionality - * is called from ParserDelegator.getResourceAsStream. - * - * @author Timothy Prinzing - */ -class ResourceLoader implements java.security.PrivilegedAction { - - ResourceLoader(String name) { - this.name = name; - } - - public Object run() { - Object o = ParserDelegator.class.getResourceAsStream(name); - return o; - } - - public static InputStream getResourceAsStream(String name) { - java.security.PrivilegedAction a = new ResourceLoader(name); - return (InputStream) java.security.AccessController.doPrivileged(a); - } - - private String name; -} diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/text/rtf/RTFReader.java --- a/jdk/src/share/classes/javax/swing/text/rtf/RTFReader.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/swing/text/rtf/RTFReader.java Wed Jul 05 19:39:35 2017 +0200 @@ -27,9 +27,9 @@ import java.lang.*; import java.util.*; import java.io.*; -import java.awt.Font; import java.awt.Color; - +import java.security.AccessController; +import java.security.PrivilegedAction; import javax.swing.text.*; /** @@ -558,16 +558,14 @@ { char[] set = characterSets.get(name); if (set == null) { - InputStream charsetStream; - charsetStream = java.security.AccessController. - doPrivileged(new java.security.PrivilegedAction() { - public InputStream run() { - return RTFReader.class.getResourceAsStream - ("charsets/" + name + ".txt"); - } - }); - set = readCharset(charsetStream); - defineCharacterSet(name, set); + InputStream charsetStream = AccessController.doPrivileged( + new PrivilegedAction() { + public InputStream run() { + return RTFReader.class.getResourceAsStream("charsets/" + name + ".txt"); + } + }); + set = readCharset(charsetStream); + defineCharacterSet(name, set); } return set; } diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/javax/swing/tree/DefaultTreeCellRenderer.java --- a/jdk/src/share/classes/javax/swing/tree/DefaultTreeCellRenderer.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/javax/swing/tree/DefaultTreeCellRenderer.java Wed Jul 05 19:39:35 2017 +0200 @@ -191,7 +191,7 @@ if (!inited || (getClosedIcon() instanceof UIResource)) { setClosedIcon(DefaultLookup.getIcon(this, ui, "Tree.closedIcon")); } - if (!inited || (getOpenIcon() instanceof UIManager)) { + if (!inited || (getOpenIcon() instanceof UIResource)) { setOpenIcon(DefaultLookup.getIcon(this, ui, "Tree.openIcon")); } if (!inited || (getTextSelectionColor() instanceof UIResource)) { diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/sun/awt/AWTAccessor.java --- a/jdk/src/share/classes/sun/awt/AWTAccessor.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java Wed Jul 05 19:39:35 2017 +0200 @@ -272,6 +272,16 @@ * bypasses disabled Components during the search. */ Component findComponentAt(Container cont, int x, int y, boolean ignoreEnabled); + + /** + * Starts LW Modal. + */ + void startLWModal(Container cont); + + /** + * Starts LW Modal. + */ + void stopLWModal(Container cont); } /* diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/sun/awt/EventListenerAggregate.java --- a/jdk/src/share/classes/sun/awt/EventListenerAggregate.java Wed Jul 05 19:38:36 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.awt; - -import java.lang.reflect.Array; -import java.util.EventListener; - - -/** - * A class that assists in managing {@link java.util.EventListener}s of - * the specified type. Its instance holds an array of listeners of the same - * type and allows to perform the typical operations on the listeners. - * This class is thread-safe. - * - * @author Alexander Gerasimov - * - * @since 1.5 - */ -public class EventListenerAggregate { - - private EventListener[] listenerList; - - /** - * Constructs an EventListenerAggregate object. - * - * @param listenerClass the type of the listeners to be managed by this object - * - * @throws NullPointerException if listenerClass is - * null - * @throws ClassCastException if listenerClass is not - * assignable to java.util.EventListener - */ - public EventListenerAggregate(Class listenerClass) { - if (listenerClass == null) { - throw new NullPointerException("listener class is null"); - } - - listenerList = (EventListener[])Array.newInstance(listenerClass, 0); - } - - private Class getListenerClass() { - return listenerList.getClass().getComponentType(); - } - - /** - * Adds the listener to this aggregate. - * - * @param listener the listener to be added - * - * @throws ClassCastException if listener is not - * an instatce of listenerClass specified - * in the constructor - */ - public synchronized void add(EventListener listener) { - Class listenerClass = getListenerClass(); - - if (!listenerClass.isInstance(listener)) { // null is not an instance of any class - throw new ClassCastException("listener " + listener + " is not " + - "an instance of listener class " + listenerClass); - } - - EventListener[] tmp = (EventListener[])Array.newInstance(listenerClass, listenerList.length + 1); - System.arraycopy(listenerList, 0, tmp, 0, listenerList.length); - tmp[listenerList.length] = listener; - listenerList = tmp; - } - - /** - * Removes a listener that is equal to the given one from this aggregate. - * equals() method is used to compare listeners. - * - * @param listener the listener to be removed - * - * @return true if this aggregate contained the specified - * listener; false otherwise - * - * @throws ClassCastException if listener is not - * an instatce of listenerClass specified - * in the constructor - */ - public synchronized boolean remove(EventListener listener) { - Class listenerClass = getListenerClass(); - - if (!listenerClass.isInstance(listener)) { // null is not an instance of any class - throw new ClassCastException("listener " + listener + " is not " + - "an instance of listener class " + listenerClass); - } - - for (int i = 0; i < listenerList.length; i++) { - if (listenerList[i].equals(listener)) { - EventListener[] tmp = (EventListener[])Array.newInstance(listenerClass, - listenerList.length - 1); - System.arraycopy(listenerList, 0, tmp, 0, i); - System.arraycopy(listenerList, i + 1, tmp, i, listenerList.length - i - 1); - listenerList = tmp; - - return true; - } - } - - return false; - } - - /** - * Returns an array of all the listeners contained in this aggregate. - * The array is the data structure in which listeners are stored internally. - * The runtime type of the returned array is "array of listenerClass" - * (listenerClass has been specified as a parameter to - * the constructor of this class). - * - * @return all the listeners contained in this aggregate (an empty - * array if there are no listeners) - */ - public synchronized EventListener[] getListenersInternal() { - return listenerList; - } - - /** - * Returns an array of all the listeners contained in this aggregate. - * The array is a copy of the data structure in which listeners are stored - * internally. - * The runtime type of the returned array is "array of listenerClass" - * (listenerClass has been specified as a parameter to - * the constructor of this class). - * - * @return a copy of all the listeners contained in this aggregate (an empty - * array if there are no listeners) - */ - public synchronized EventListener[] getListenersCopy() { - return (listenerList.length == 0) ? listenerList : listenerList.clone(); - } - - /** - * Returns the number of lisetners in this aggregate. - * - * @return the number of lisetners in this aggregate - */ - public synchronized int size() { - return listenerList.length; - } - - /** - * Returns true if this aggregate contains no listeners, - * false otherwise. - * - * @return true if this aggregate contains no listeners, - * false otherwise - */ - public synchronized boolean isEmpty() { - return listenerList.length == 0; - } -} diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/sun/awt/datatransfer/SunClipboard.java --- a/jdk/src/share/classes/sun/awt/datatransfer/SunClipboard.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/sun/awt/datatransfer/SunClipboard.java Wed Jul 05 19:39:35 2017 +0200 @@ -40,7 +40,7 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.util.Iterator; +import java.util.Objects; import java.util.Set; import java.util.HashSet; @@ -49,7 +49,6 @@ import sun.awt.AppContext; import sun.awt.PeerEvent; import sun.awt.SunToolkit; -import sun.awt.EventListenerAggregate; /** @@ -107,11 +106,7 @@ setContentsNative(contents); } finally { if (oldOwner != null && oldOwner != owner) { - EventQueue.invokeLater(new Runnable() { - public void run() { - oldOwner.lostOwnership(SunClipboard.this, oldContents); - } - }); + EventQueue.invokeLater(() -> oldOwner.lostOwnership(SunClipboard.this, oldContents)); } } } @@ -355,13 +350,12 @@ return; } AppContext appContext = AppContext.getAppContext(); - EventListenerAggregate contextFlavorListeners = (EventListenerAggregate) - appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY); - if (contextFlavorListeners == null) { - contextFlavorListeners = new EventListenerAggregate(FlavorListener.class); - appContext.put(CLIPBOARD_FLAVOR_LISTENER_KEY, contextFlavorListeners); + Set flavorListeners = getFlavorListeners(appContext); + if (flavorListeners == null) { + flavorListeners = new HashSet<>(); + appContext.put(CLIPBOARD_FLAVOR_LISTENER_KEY, flavorListeners); } - contextFlavorListeners.add(listener); + flavorListeners.add(listener); if (numberOfFlavorListeners++ == 0) { long[] currentFormats = null; @@ -382,25 +376,26 @@ if (listener == null) { return; } - AppContext appContext = AppContext.getAppContext(); - EventListenerAggregate contextFlavorListeners = (EventListenerAggregate) - appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY); - if (contextFlavorListeners == null){ + Set flavorListeners = getFlavorListeners(AppContext.getAppContext()); + if (flavorListeners == null){ //else we throw NullPointerException, but it is forbidden return; } - if (contextFlavorListeners.remove(listener) && - --numberOfFlavorListeners == 0) { + if (flavorListeners.remove(listener) && --numberOfFlavorListeners == 0) { unregisterClipboardViewerChecked(); currentDataFlavors = null; } } + @SuppressWarnings("unchecked") + private Set getFlavorListeners(AppContext appContext) { + return (Set)appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY); + } + public synchronized FlavorListener[] getFlavorListeners() { - EventListenerAggregate contextFlavorListeners = (EventListenerAggregate) - AppContext.getAppContext().get(CLIPBOARD_FLAVOR_LISTENER_KEY); - return contextFlavorListeners == null ? new FlavorListener[0] : - (FlavorListener[])contextFlavorListeners.getListenersCopy(); + Set flavorListeners = getFlavorListeners(AppContext.getAppContext()); + return flavorListeners == null ? new FlavorListener[0] + : flavorListeners.toArray(new FlavorListener[flavorListeners.size()]); } public boolean areFlavorListenersRegistered() { @@ -425,42 +420,26 @@ Set prevDataFlavors = currentDataFlavors; currentDataFlavors = formatArrayAsDataFlavorSet(formats); - if ((prevDataFlavors != null) && (currentDataFlavors != null) && - prevDataFlavors.equals(currentDataFlavors)) { + if (Objects.equals(prevDataFlavors, currentDataFlavors)) { // we've been able to successfully get available on the clipboard // DataFlavors this and previous time and they are coincident; // don't notify return; } - class SunFlavorChangeNotifier implements Runnable { - private final FlavorListener flavorListener; - - SunFlavorChangeNotifier(FlavorListener flavorListener) { - this.flavorListener = flavorListener; - } - - public void run() { - if (flavorListener != null) { - flavorListener.flavorsChanged(new FlavorEvent(SunClipboard.this)); - } - } - }; - - for (Iterator it = AppContext.getAppContexts().iterator(); it.hasNext();) { - AppContext appContext = (AppContext)it.next(); + for (AppContext appContext : AppContext.getAppContexts()) { if (appContext == null || appContext.isDisposed()) { continue; } - EventListenerAggregate flavorListeners = (EventListenerAggregate) - appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY); + Set flavorListeners = getFlavorListeners(appContext); if (flavorListeners != null) { - FlavorListener[] flavorListenerArray = - (FlavorListener[])flavorListeners.getListenersInternal(); - for (int i = 0; i < flavorListenerArray.length; i++) { - SunToolkit.postEvent(appContext, new PeerEvent(this, - new SunFlavorChangeNotifier(flavorListenerArray[i]), - PeerEvent.PRIORITY_EVENT)); + for (FlavorListener listener : flavorListeners) { + if (listener != null) { + PeerEvent peerEvent = new PeerEvent(this, + () -> listener.flavorsChanged(new FlavorEvent(SunClipboard.this)), + PeerEvent.PRIORITY_EVENT); + SunToolkit.postEvent(appContext, peerEvent); + } } } } diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/sun/awt/image/GifImageDecoder.java --- a/jdk/src/share/classes/sun/awt/image/GifImageDecoder.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/sun/awt/image/GifImageDecoder.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,6 +114,7 @@ /** * produce an image from the stream. */ + @SuppressWarnings("fallthrough") public void produceImage() throws IOException, ImageFormatException { try { readHeader(); @@ -238,7 +239,7 @@ if (frameno == 0) { return; } - // NOBREAK + // Fall through case TERMINATOR: if (nloops == 0 || nloops-- >= 0) { diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java --- a/jdk/src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java Wed Jul 05 19:39:35 2017 +0200 @@ -24,6 +24,7 @@ */ package sun.awt.image; +import java.awt.Dimension; import java.awt.Image; import java.awt.Graphics; import java.awt.geom.Dimension2D; @@ -43,6 +44,13 @@ private int availableInfo; public MultiResolutionBufferedImage(Image baseImage, + BiFunction mapper) { + this(baseImage, new Dimension[]{new Dimension( + baseImage.getWidth(null), baseImage.getHeight(null)) + }, mapper); + } + + public MultiResolutionBufferedImage(Image baseImage, Dimension2D[] sizes, BiFunction mapper) { super(baseImage.getWidth(null), baseImage.getHeight(null), BufferedImage.TYPE_INT_ARGB_PRE); @@ -115,7 +123,7 @@ } private static void preload(Image image, int availableInfo) { - if (image instanceof ToolkitImage) { + if (availableInfo != 0 && image instanceof ToolkitImage) { ((ToolkitImage) image).preload(new ImageObserver() { int flags = availableInfo; diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/sun/awt/image/PixelConverter.java --- a/jdk/src/share/classes/sun/awt/image/PixelConverter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/sun/awt/image/PixelConverter.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,6 +53,7 @@ protected PixelConverter() {} + @SuppressWarnings("fallthrough") public int rgbToPixel(int rgb, ColorModel cm) { Object obj = cm.getDataElements(rgb, null); switch (cm.getTransferType()) { diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/sun/java2d/pipe/DrawImage.java --- a/jdk/src/share/classes/sun/java2d/pipe/DrawImage.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/sun/java2d/pipe/DrawImage.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -310,11 +310,19 @@ return false; } - /* - * Return a BufferedImage of the requested type with the indicated - * subimage of the original image located at 0,0 in the new image. - * If a bgColor is supplied, composite the original image over that - * color with a SrcOver operation, otherwise make a SrcNoEa copy. + /** + * Return a non-accelerated BufferedImage of the requested type with the + * indicated subimage of the original image located at 0,0 in the new image. + * If a bgColor is supplied, composite the original image over that color + * with a SrcOver operation, otherwise make a SrcNoEa copy. + *

    + * Returned BufferedImage is not accelerated for two reasons: + *

      + *
    • Types of the image and surface are predefined, because these types + * correspond to the TransformHelpers, which we know we have. And + * acceleration can change the type of the surface + *
    • Image will be used only once and acceleration caching wouldn't help + *
    */ BufferedImage makeBufferedImage(Image img, Color bgColor, int type, int sx1, int sy1, int sx2, int sy2) @@ -324,6 +332,7 @@ final BufferedImage bimg = new BufferedImage(width, height, type); final SunGraphics2D g2d = (SunGraphics2D) bimg.createGraphics(); g2d.setComposite(AlphaComposite.Src); + bimg.setAccelerationPriority(0); if (bgColor != null) { g2d.setColor(bgColor); g2d.fillRect(0, 0, width, height); diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/sun/misc/VMSupport.java diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java --- a/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import java.util.Base64; import java.util.HashMap; import sun.net.www.HeaderParser; +import sun.util.logging.PlatformLogger; import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE; import static sun.net.www.protocol.http.AuthScheme.KERBEROS; @@ -44,6 +45,7 @@ class NegotiateAuthentication extends AuthenticationInfo { private static final long serialVersionUID = 100L; + private static final PlatformLogger logger = HttpURLConnection.getHttpLogger(); final private HttpCallerInfo hci; @@ -79,6 +81,31 @@ } /** + * Find out if the HttpCallerInfo supports Negotiate protocol. + * @return true if supported + */ + public static boolean isSupported(HttpCallerInfo hci) { + ClassLoader loader = null; + try { + loader = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException se) { + if (logger.isLoggable(PlatformLogger.Level.FINER)) { + logger.finer("NegotiateAuthentication: " + + "Attempt to get the context class loader failed - " + se); + } + } + + if (loader != null) { + // Lock on the class loader instance to avoid the deadlock engaging + // the lock in "ClassLoader.loadClass(String, boolean)" method. + synchronized (loader) { + return isSupportedImpl(hci); + } + } + return isSupportedImpl(hci); + } + + /** * Find out if the HttpCallerInfo supports Negotiate protocol. In order to * find out yes or no, an initialization of a Negotiator object against it * is tried. The generated object will be cached under the name of ths @@ -89,7 +116,7 @@ * * @return true if supported */ - synchronized public static boolean isSupported(HttpCallerInfo hci) { + private static synchronized boolean isSupportedImpl(HttpCallerInfo hci) { if (supported == null) { supported = new HashMap (); cache = new HashMap (); diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/sun/nio/ch/PendingFuture.java --- a/jdk/src/share/classes/sun/nio/ch/PendingFuture.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/sun/nio/ch/PendingFuture.java Wed Jul 05 19:39:35 2017 +0200 @@ -35,8 +35,6 @@ */ final class PendingFuture implements Future { - private static final CancellationException CANCELLED = - new CancellationException(); private final AsynchronousChannel channel; private final CompletionHandler handler; @@ -180,7 +178,7 @@ latch.await(); } if (exc != null) { - if (exc == CANCELLED) + if (exc instanceof CancellationException) throw new CancellationException(); throw new ExecutionException(exc); } @@ -197,7 +195,7 @@ if (!latch.await(timeout, unit)) throw new TimeoutException(); } if (exc != null) { - if (exc == CANCELLED) + if (exc instanceof CancellationException) throw new CancellationException(); throw new ExecutionException(exc); } @@ -205,7 +203,7 @@ } Throwable exception() { - return (exc != CANCELLED) ? exc : null; + return (exc instanceof CancellationException) ? null : exc; } V value() { @@ -214,7 +212,7 @@ @Override public boolean isCancelled() { - return (exc == CANCELLED); + return (exc instanceof CancellationException); } @Override @@ -233,7 +231,7 @@ ((Cancellable)channel()).onCancel(this); // set result and cancel timer - exc = CANCELLED; + exc = new CancellationException(); haveResult = true; if (timeoutTask != null) timeoutTask.cancel(false); diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java --- a/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -113,7 +113,6 @@ try { Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); - // Cannot generate key here, please don't use Cipher.UNWRAP_MODE! cipher.init(Cipher.UNWRAP_MODE, privateKey, new TlsRsaPremasterSecretParameterSpec( maxVersion.v, currentVersion.v), diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/classes/sun/swing/SwingUtilities2.java --- a/jdk/src/share/classes/sun/swing/SwingUtilities2.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/classes/sun/swing/SwingUtilities2.java Wed Jul 05 19:39:35 2017 +0200 @@ -25,13 +25,11 @@ package sun.swing; -import java.security.*; import java.lang.reflect.*; import java.awt.*; import static java.awt.RenderingHints.*; import java.awt.event.*; import java.awt.font.*; -import java.awt.geom.*; import java.awt.print.PrinterGraphics; import java.text.CharacterIterator; import java.text.AttributedCharacterIterator; @@ -48,11 +46,8 @@ import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; -import sun.swing.PrintColorUIResource; -import sun.swing.ImageIconUIResource; import sun.print.ProxyPrintGraphics; import sun.awt.*; -import sun.security.action.GetPropertyAction; import java.io.*; import java.util.*; import sun.font.FontDesignMetrics; @@ -924,6 +919,77 @@ return retVal; } + /** + * This method should be used for drawing a borders over a filled rectangle. + * Draws vertical line, using the current color, between the points {@code + * (x, y1)} and {@code (x, y2)} in graphics context's coordinate system. + * Note: it use {@code Graphics.fillRect()} internally. + * + * @param g Graphics to draw the line to. + * @param x the x coordinate. + * @param y1 the first point's y coordinate. + * @param y2 the second point's y coordinate. + */ + public static void drawVLine(Graphics g, int x, int y1, int y2) { + if (y2 < y1) { + final int temp = y2; + y2 = y1; + y1 = temp; + } + g.fillRect(x, y1, 1, y2 - y1 + 1); + } + + /** + * This method should be used for drawing a borders over a filled rectangle. + * Draws horizontal line, using the current color, between the points {@code + * (x1, y)} and {@code (x2, y)} in graphics context's coordinate system. + * Note: it use {@code Graphics.fillRect()} internally. + * + * @param g Graphics to draw the line to. + * @param x1 the first point's x coordinate. + * @param x2 the second point's x coordinate. + * @param y the y coordinate. + */ + public static void drawHLine(Graphics g, int x1, int x2, int y) { + if (x2 < x1) { + final int temp = x2; + x2 = x1; + x1 = temp; + } + g.fillRect(x1, y, x2 - x1 + 1, 1); + } + + /** + * This method should be used for drawing a borders over a filled rectangle. + * Draws the outline of the specified rectangle. The left and right edges of + * the rectangle are at {@code x} and {@code x + w}. The top and bottom + * edges are at {@code y} and {@code y + h}. The rectangle is drawn using + * the graphics context's current color. Note: it use {@code + * Graphics.fillRect()} internally. + * + * @param g Graphics to draw the rectangle to. + * @param x the x coordinate of the rectangle to be drawn. + * @param y the y coordinate of the rectangle to be drawn. + * @param w the w of the rectangle to be drawn. + * @param h the h of the rectangle to be drawn. + * @see SwingUtilities2#drawVLine(java.awt.Graphics, int, int, int) + * @see SwingUtilities2#drawHLine(java.awt.Graphics, int, int, int) + */ + public static void drawRect(Graphics g, int x, int y, int w, int h) { + if (w < 0 || h < 0) { + return; + } + + if (h == 0 || w == 0) { + g.fillRect(x, y, w + 1, h + 1); + } else { + g.fillRect(x, y, w, 1); + g.fillRect(x + w, y, 1, h); + g.fillRect(x + 1, y + h, w, 1); + g.fillRect(x, y + 1, 1, h); + } + } + private static TextLayout createTextLayout(JComponent c, String s, Font f, FontRenderContext frc) { Object shaper = (c == null ? diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/javavm/export/jvm.h diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/native/sun/java2d/loops/TransformHelper.c --- a/jdk/src/share/native/sun/java2d/loops/TransformHelper.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/native/sun/java2d/loops/TransformHelper.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -384,6 +384,7 @@ return; } Region_IntersectBounds(&clipInfo, &dstInfo.bounds); + Transform_GetInfo(env, itxform, &itxInfo); numedges = (((jlong) dstInfo.bounds.y2) - ((jlong) dstInfo.bounds.y1)); if (numedges <= 0) { @@ -423,7 +424,6 @@ return; } - Transform_GetInfo(env, itxform, &itxInfo); if (!Region_IsEmpty(&clipInfo)) { srcOps->GetRasInfo(env, srcOps, &srcInfo); diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/native/sun/java2d/opengl/OGLSurfaceData.c --- a/jdk/src/share/native/sun/java2d/opengl/OGLSurfaceData.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/share/native/sun/java2d/opengl/OGLSurfaceData.c Wed Jul 05 19:39:35 2017 +0200 @@ -543,7 +543,9 @@ } JNU_SetFieldByName(env, NULL, sdObject, "nativeWidth", "I", width); - JNU_SetFieldByName(env, NULL, sdObject, "nativeHeight", "I", height); + if (!((*env)->ExceptionOccurred(env))) { + JNU_SetFieldByName(env, NULL, sdObject, "nativeHeight", "I", height); + } (*env)->DeleteLocalRef(env, sdObject); } diff -r a77941f17614 -r 0d1f816217dc jdk/src/share/native/sun/misc/VMSupport.c diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java --- a/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java Wed Jul 05 19:39:35 2017 +0200 @@ -548,6 +548,7 @@ } } + @SuppressWarnings("fallthrough") public void handleEvent(java.awt.AWTEvent e) { if ((e instanceof InputEvent) && !((InputEvent)e).isConsumed() && target.isEnabled()) { if (e instanceof MouseEvent) { diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/classes/sun/awt/X11/XWM.java --- a/jdk/src/solaris/classes/sun/awt/X11/XWM.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/classes/sun/awt/X11/XWM.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1112,6 +1112,7 @@ * Therefore, a compound state is just ICONIFIED | anything else. * */ + @SuppressWarnings("fallthrough") boolean supportsExtendedState(int state) { switch (state) { case Frame.MAXIMIZED_VERT: @@ -1131,6 +1132,7 @@ return true; } } + /* FALLTROUGH */ default: return false; } diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/CUPSfuncs.c --- a/jdk/src/solaris/native/sun/awt/CUPSfuncs.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/CUPSfuncs.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -213,6 +213,8 @@ name = (*env)->GetStringUTFChars(env, printer, NULL); if (name == NULL) { + (*env)->ExceptionClear(env); + JNU_ThrowOutOfMemoryError(env, "Could not create printer name"); return NULL; } @@ -220,12 +222,10 @@ // unlink() must be caled to remove the file when finished using it. filename = j2d_cupsGetPPD(name); (*env)->ReleaseStringUTFChars(env, printer, name); + CHECK_NULL_RETURN(filename, NULL); cls = (*env)->FindClass(env, "java/lang/String"); - - if (filename == NULL) { - return NULL; - } + CHECK_NULL_RETURN(cls, NULL); if ((ppd = j2d_ppdOpenFile(filename)) == NULL) { unlink(filename); @@ -249,6 +249,7 @@ unlink(filename); j2d_ppdClose(ppd); DPRINTF("CUPSfuncs::bad alloc new array\n", "") + (*env)->ExceptionClear(env); JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); return NULL; } @@ -323,6 +324,11 @@ ppd_size_t *size; const char *name = (*env)->GetStringUTFChars(env, printer, NULL); + if (name == NULL) { + (*env)->ExceptionClear(env); + JNU_ThrowOutOfMemoryError(env, "Could not create printer name"); + return NULL; + } const char *filename; int i; jobjectArray sizeArray = NULL; @@ -332,9 +338,7 @@ // unlink() must be called to remove the file after using it. filename = j2d_cupsGetPPD(name); (*env)->ReleaseStringUTFChars(env, printer, name); - if (filename == NULL) { - return NULL; - } + CHECK_NULL_RETURN(filename, NULL); if ((ppd = j2d_ppdOpenFile(filename)) == NULL) { unlink(filename); DPRINTF("unable to open PPD %s\n", filename) @@ -350,11 +354,19 @@ unlink(filename); j2d_ppdClose(ppd); DPRINTF("CUPSfuncs::bad alloc new float array\n", "") + (*env)->ExceptionClear(env); JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); return NULL; } dims = (*env)->GetFloatArrayElements(env, sizeArray, NULL); + if (dims == NULL) { + unlink(filename); + j2d_ppdClose(ppd); + (*env)->ExceptionClear(env); + JNU_ThrowOutOfMemoryError(env, "Could not create printer name"); + return NULL; + } for (i = 0; inum_choices; i++) { choice = (option->choices)+i; size = j2d_ppdPageSize(ppd, choice->choice); diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/X11Color.c --- a/jdk/src/solaris/native/sun/awt/X11Color.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/X11Color.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -892,11 +892,10 @@ jmethodID mid; clazz = (*env)->FindClass(env,"java/awt/color/ColorSpace"); + CHECK_NULL_RETURN(clazz, NULL); mid = (*env)->GetStaticMethodID(env, clazz, "getInstance", "(I)Ljava/awt/color/ColorSpace;"); - if (mid == NULL) { - return NULL; - } + CHECK_NULL_RETURN(mid, NULL); /* SECURITY: This is safe, because static methods cannot * be overridden, and this method does not invoke @@ -919,6 +918,11 @@ (aData->awt_depth >= 15)) { clazz = (*env)->FindClass(env,"java/awt/image/DirectColorModel"); + if (clazz == NULL) { + (*env)->PopLocalFrame(env, 0); + return NULL; + } + if (!aData->isTranslucencySupported) { mid = (*env)->GetMethodID(env,clazz,"","(IIIII)V"); @@ -1005,6 +1009,10 @@ } clazz = (*env)->FindClass(env,"java/awt/image/ComponentColorModel"); + if (clazz == NULL) { + (*env)->PopLocalFrame(env, 0); + return NULL; + } mid = (*env)->GetMethodID(env,clazz,"", "(Ljava/awt/color/ColorSpace;[IZZII)V"); @@ -1253,6 +1261,7 @@ if (!JNU_IsNull(env,this)) { SYSCLR_class = (*env)->FindClass(env, "java/awt/SystemColor"); + CHECK_NULL_RETURN(SYSCLR_class, 0); if ((*env)->IsInstanceOf(env, this, SYSCLR_class)) { /* SECURITY: This is safe, because there is no way @@ -1264,6 +1273,7 @@ ,this ,"getRGB" ,"()I").i; + JNU_CHECK_EXCEPTION_RETURN(env, 0); } else { col = (int)(*env)->GetIntField(env,this,colorValueID); } @@ -1370,6 +1380,8 @@ AWT_UNLOCK (); } sysColors = (*env)->FindClass (env, "java/awt/SystemColor"); + CHECK_NULL(sysColors); + if (lock) { AWT_LOCK (); } @@ -1377,6 +1389,13 @@ "systemColors", "[I"); + if (colorID == NULL) { + if (lock) { + AWT_UNLOCK(); + } + return; + } + colors = (jintArray) (*env)->GetStaticObjectField (env, sysColors, colorID); diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/awt.h --- a/jdk/src/solaris/native/sun/awt/awt.h Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/awt.h Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,8 +77,22 @@ #define AWT_LOCK_IMPL() \ (*env)->CallStaticVoidMethod(env, tkClass, awtLockMID) + #define AWT_NOFLUSH_UNLOCK_IMPL() \ - (*env)->CallStaticVoidMethod(env, tkClass, awtUnlockMID) + do { \ + jthrowable pendingException; \ + if ((pendingException = (*env)->ExceptionOccurred(env)) != NULL) { \ + (*env)->ExceptionClear(env); \ + } \ + (*env)->CallStaticVoidMethod(env, tkClass, awtUnlockMID); \ + if (pendingException) { \ + if ((*env)->ExceptionCheck(env)) { \ + (*env)->ExceptionDescribe(env); \ + (*env)->ExceptionClear(env); \ + } \ + (*env)->Throw(env, pendingException); \ + } \ + } while (0) #define AWT_WAIT_IMPL(tm) \ (*env)->CallStaticVoidMethod(env, tkClass, awtWaitMID, (jlong)(tm)) #define AWT_NOTIFY_IMPL() \ diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/awt_AWTEvent.c --- a/jdk/src/solaris/native/sun/awt/awt_AWTEvent.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/awt_AWTEvent.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,22 +49,22 @@ JNIEXPORT void JNICALL Java_java_awt_AWTEvent_initIDs(JNIEnv *env, jclass cls) { - awtEventIDs.bdata = (*env)->GetFieldID(env, cls, "bdata", "[B"); - awtEventIDs.consumed = (*env)->GetFieldID(env, cls, "consumed", "Z"); - awtEventIDs.id = (*env)->GetFieldID(env, cls, "id", "I"); + CHECK_NULL(awtEventIDs.bdata = (*env)->GetFieldID(env, cls, "bdata", "[B")); + CHECK_NULL(awtEventIDs.consumed = (*env)->GetFieldID(env, cls, "consumed", "Z")); + CHECK_NULL(awtEventIDs.id = (*env)->GetFieldID(env, cls, "id", "I")); } JNIEXPORT void JNICALL Java_java_awt_event_InputEvent_initIDs(JNIEnv *env, jclass cls) { - inputEventIDs.modifiers = (*env)->GetFieldID(env, cls, "modifiers", "I"); + CHECK_NULL(inputEventIDs.modifiers = (*env)->GetFieldID(env, cls, "modifiers", "I")); } JNIEXPORT void JNICALL Java_java_awt_event_KeyEvent_initIDs(JNIEnv *env, jclass cls) { - keyEventIDs.keyCode = (*env)->GetFieldID(env, cls, "keyCode", "I"); - keyEventIDs.keyChar = (*env)->GetFieldID(env, cls, "keyChar", "C"); + CHECK_NULL(keyEventIDs.keyCode = (*env)->GetFieldID(env, cls, "keyCode", "I")); + CHECK_NULL(keyEventIDs.keyChar = (*env)->GetFieldID(env, cls, "keyChar", "C")); } JNIEXPORT void JNICALL diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/awt_DrawingSurface.c --- a/jdk/src/solaris/native/sun/awt/awt_DrawingSurface.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/awt_DrawingSurface.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,6 +78,8 @@ /* Make sure the target is a java.awt.Component */ componentClass = (*env)->FindClass(env, "java/awt/Component"); + CHECK_NULL_RETURN(componentClass, (jint)JAWT_LOCK_ERROR); + if (!(*env)->IsInstanceOf(env, target, componentClass)) { #ifdef DEBUG fprintf(stderr, "Target is not a component\n"); @@ -126,6 +128,8 @@ /* Make sure the target is a java.awt.Component */ componentClass = (*env)->FindClass(env, "java/awt/Component"); + CHECK_NULL_RETURN(componentClass, (int32_t) 0); + if (!(*env)->IsInstanceOf(env, target, componentClass)) { #ifdef DEBUG fprintf(stderr, "DrawingSurface target must be a component\n"); @@ -195,6 +199,8 @@ /* Make sure the target is a java.awt.Component */ componentClass = (*env)->FindClass(env, "java/awt/Component"); + CHECK_NULL_RETURN(componentClass, NULL); + if (!(*env)->IsInstanceOf(env, target, componentClass)) { #ifdef DEBUG fprintf(stderr, "DrawingSurface target must be a component\n"); @@ -292,6 +298,8 @@ /* Make sure the target component is a java.awt.Component */ componentClass = (*env)->FindClass(env, "java/awt/Component"); + CHECK_NULL_RETURN(componentClass, NULL); + if (!(*env)->IsInstanceOf(env, target, componentClass)) { #ifdef DEBUG fprintf(stderr, @@ -354,6 +362,10 @@ if (window != None) { peer = JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XToolkit", "windowToXWindow", "(J)Lsun/awt/X11/XBaseWindow;", (jlong)window).l; + if ((*env)->ExceptionCheck(env)) { + AWT_UNLOCK(); + return (jobject)NULL; + } } if ((peer != NULL) && (JNU_IsInstanceOfByName(env, peer, "sun/awt/X11/XWindow") == 1)) { @@ -361,6 +373,7 @@ } if (target == NULL) { + (*env)->ExceptionClear(env); JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return (jobject)NULL; diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/awt_Font.c --- a/jdk/src/solaris/native/sun/awt/awt_Font.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/awt_Font.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,14 +86,13 @@ #ifndef HEADLESS /** We call "NoClientCode" methods because they won't invoke client code on the privileged toolkit thread **/ - fontIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J"); - fontIDs.style = (*env)->GetFieldID(env, cls, "style", "I"); - fontIDs.size = (*env)->GetFieldID(env, cls, "size", "I"); - fontIDs.getPeer = (*env)->GetMethodID(env, cls, "getPeer_NoClientCode", - "()Ljava/awt/peer/FontPeer;"); - fontIDs.getFamily = - (*env)->GetMethodID(env, cls, "getFamily_NoClientCode", - "()Ljava/lang/String;"); + CHECK_NULL(fontIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J")); + CHECK_NULL(fontIDs.style = (*env)->GetFieldID(env, cls, "style", "I")); + CHECK_NULL(fontIDs.size = (*env)->GetFieldID(env, cls, "size", "I")); + CHECK_NULL(fontIDs.getPeer = (*env)->GetMethodID(env, cls, "getPeer_NoClientCode", + "()Ljava/awt/peer/FontPeer;")); + CHECK_NULL(fontIDs.getFamily = (*env)->GetMethodID(env, cls, "getFamily_NoClientCode", + "()Ljava/lang/String;")); #endif /* !HEADLESS */ } @@ -120,12 +119,10 @@ (JNIEnv *env, jclass cls) { #ifndef HEADLESS - fontDescriptorIDs.nativeName = - (*env)->GetFieldID(env, cls, "nativeName", - "Ljava/lang/String;"); - fontDescriptorIDs.charsetName = - (*env)->GetFieldID(env, cls, "charsetName", - "Ljava/lang/String;"); + CHECK_NULL(fontDescriptorIDs.nativeName = + (*env)->GetFieldID(env, cls, "nativeName", "Ljava/lang/String;")); + CHECK_NULL(fontDescriptorIDs.charsetName = + (*env)->GetFieldID(env, cls, "charsetName", "Ljava/lang/String;")); #endif /* !HEADLESS */ } @@ -144,20 +141,18 @@ (JNIEnv *env, jclass cls) { #ifndef HEADLESS - platformFontIDs.componentFonts = - (*env)->GetFieldID(env, cls, "componentFonts", - "[Lsun/awt/FontDescriptor;"); - platformFontIDs.fontConfig = - (*env)->GetFieldID(env,cls, "fontConfig", - "Lsun/awt/FontConfiguration;"); - - platformFontIDs.makeConvertedMultiFontString = - (*env)->GetMethodID(env, cls, "makeConvertedMultiFontString", - "(Ljava/lang/String;)[Ljava/lang/Object;"); - - platformFontIDs.makeConvertedMultiFontChars = - (*env)->GetMethodID(env, cls, "makeConvertedMultiFontChars", - "([CII)[Ljava/lang/Object;"); + CHECK_NULL(platformFontIDs.componentFonts = + (*env)->GetFieldID(env, cls, "componentFonts", + "[Lsun/awt/FontDescriptor;")); + CHECK_NULL(platformFontIDs.fontConfig = + (*env)->GetFieldID(env,cls, "fontConfig", + "Lsun/awt/FontConfiguration;")); + CHECK_NULL(platformFontIDs.makeConvertedMultiFontString = + (*env)->GetMethodID(env, cls, "makeConvertedMultiFontString", + "(Ljava/lang/String;)[Ljava/lang/Object;")); + CHECK_NULL(platformFontIDs.makeConvertedMultiFontChars = + (*env)->GetMethodID(env, cls, "makeConvertedMultiFontChars", + "([CII)[Ljava/lang/Object;")); #endif /* !HEADLESS */ } @@ -385,6 +380,11 @@ return 0; } cname = (char *) JNU_GetStringPlatformChars(env, name, NULL); + if (cname == NULL) { + (*env)->ExceptionClear(env); + JNU_ThrowOutOfMemoryError(env, "Could not create font name"); + return 0; + } /* additional default font names */ if (strcmp(cname, "serif") == 0) { @@ -448,6 +448,8 @@ } if (!JNU_IsNull(env, font) && awtJNI_IsMultiFont(env, font)) { + JNU_CHECK_EXCEPTION_RETURN(env, NULL); + struct FontData *fdata = NULL; int32_t i, size; char *fontsetname = NULL; @@ -492,7 +494,12 @@ if (!JNU_IsNull(env, fontDescriptorName)) { nativename = (char *) JNU_GetStringPlatformChars(env, fontDescriptorName, NULL); - doFree = TRUE; + if (nativename == NULL) { + nativename = ""; + doFree = FALSE; + } else { + doFree = TRUE; + } } else { nativename = ""; doFree = FALSE; @@ -516,6 +523,11 @@ fdata->flist[i].charset_name = (char *) JNU_GetStringPlatformChars(env, charsetName, NULL); + if (fdata->flist[i].charset_name == NULL) { + (*env)->ExceptionClear(env); + JNU_ThrowOutOfMemoryError(env, "Could not create charset name"); + return NULL; + } /* We are done with the objects. */ (*env)->DeleteLocalRef(env, fontDescriptor); @@ -543,6 +555,19 @@ fdata->xfont = fdata->flist[i].xfont; fdata->flist[i].index_length = 1; } else { + /* Free any already allocated storage and fonts */ + int j = i; + for (j = 0; j <= i; j++) { + free((void *)fdata->flist[j].xlfd); + JNU_ReleaseStringPlatformChars(env, NULL, + fdata->flist[j].charset_name); + if (fdata->flist[j].load) { + XFreeFont(awt_display, fdata->flist[j].xfont); + } + } + free((void *)fdata->flist); + free((void *)fdata); + if (errmsg != NULL) { *errmsg = "java/lang" "NullPointerException"; } diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c --- a/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -152,8 +152,11 @@ x11GraphicsConfigIDs.screen = NULL; x11GraphicsConfigIDs.aData = (*env)->GetFieldID (env, cls, "aData", "J"); + CHECK_NULL(x11GraphicsConfigIDs.aData); x11GraphicsConfigIDs.bitsPerPixel = (*env)->GetFieldID (env, cls, "bitsPerPixel", "I"); + CHECK_NULL(x11GraphicsConfigIDs.bitsPerPixel); x11GraphicsConfigIDs.screen = (*env)->GetFieldID (env, cls, "screen", "Lsun/awt/X11GraphicsDevice;"); + CHECK_NULL(x11GraphicsConfigIDs.screen); if (x11GraphicsConfigIDs.aData == NULL || x11GraphicsConfigIDs.bitsPerPixel == NULL || @@ -1346,7 +1349,6 @@ /* Make Color Model object for this GraphicsConfiguration */ colorModel = awtJNI_GetColorModel (env, adata); - AWT_UNLOCK (); return colorModel; @@ -1374,6 +1376,7 @@ JNU_GetLongFieldAsPtr(env, this, x11GraphicsConfigIDs.aData); clazz = (*env)->FindClass(env, "java/awt/Rectangle"); + CHECK_NULL_RETURN(clazz, NULL); mid = (*env)->GetMethodID(env, clazz, "", "(IIII)V"); if (mid != NULL) { if (usingXinerama) { @@ -1543,7 +1546,7 @@ clazz = (*env)->GetObjectClass(env, this); midAddVisual = (*env)->GetMethodID(env, clazz, "addDoubleBufferVisual", "(I)V"); - + CHECK_NULL(midAddVisual); AWT_LOCK(); rootWindow = RootWindow(awt_display, xinawareScreen); visScreenInfo = XdbeGetVisualInfo(awt_display, &rootWindow, &n); @@ -1739,6 +1742,7 @@ jint validRefreshRate = refreshRate; displayModeClass = (*env)->FindClass(env, "java/awt/DisplayMode"); + CHECK_NULL_RETURN(displayModeClass, NULL); if (JNU_IsNull(env, displayModeClass)) { JNU_ThrowInternalError(env, "Could not get display mode class"); @@ -1746,6 +1750,7 @@ } cid = (*env)->GetMethodID(env, displayModeClass, "", "(IIII)V"); + CHECK_NULL_RETURN(cid, NULL); if (cid == NULL) { JNU_ThrowInternalError(env, "Could not get display mode constructor"); @@ -1779,6 +1784,7 @@ } mid = (*env)->GetMethodID(env, arrayListClass, "add", "(Ljava/lang/Object;)Z"); + CHECK_NULL(mid); if (mid == NULL) { JNU_ThrowInternalError(env, "Could not get method java.util.ArrayList.add()"); @@ -1955,6 +1961,9 @@ size.height, BIT_DEPTH_MULTI, rates[j]); + if ((*env)->ExceptionCheck(env)) { + break; + } } } } diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/awt_InputMethod.c --- a/jdk/src/solaris/native/sun/awt/awt_InputMethod.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/awt_InputMethod.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -319,6 +319,7 @@ JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod, "flushText", "()V"); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); /* IMPORTANT: The order of the following calls is critical since "imInstance" may point to the global reference itself, if "freeX11InputMethodData" is called @@ -1120,6 +1121,9 @@ if (text->string.multi_byte != NULL) { if (pre_draw->text->encoding_is_wchar == False) { javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte); + if (javastr == NULL) { + goto finally; + } } else { char *mbstr = wcstombsdmp(text->string.wide_char, text->length); if (mbstr == NULL) { @@ -1127,6 +1131,9 @@ } javastr = JNU_NewStringPlatform(env, (const char *)mbstr); free(mbstr); + if (javastr == NULL) { + goto finally; + } } } if (text->feedback != NULL) { @@ -1135,6 +1142,7 @@ style = (*env)->NewIntArray(env, text->length); if (JNU_IsNull(env, style)) { + (*env)->ExceptionClear(env); THROW_OUT_OF_MEMORY_ERROR(); goto finally; } @@ -1395,14 +1403,17 @@ pX11IMData->lookup_buf = 0; pX11IMData->lookup_buf_len = 0; - if (createXIC(env, pX11IMData, (Window)window) - == False) { + if (createXIC(env, pX11IMData, (Window)window) == False) { destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData); pX11IMData = (X11InputMethodData *) NULL; + if ((*env)->ExceptionCheck(env)) { + goto finally; + } } setX11InputMethodData(env, this, pX11IMData); +finally: AWT_UNLOCK(); return (pX11IMData != NULL); } diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/awt_Insets.c --- a/jdk/src/solaris/native/sun/awt/awt_Insets.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/awt_Insets.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,8 +34,8 @@ JNIEXPORT void JNICALL Java_java_awt_Insets_initIDs(JNIEnv *env, jclass cls) { - insetsIDs.top = (*env)->GetFieldID(env, cls, "top", "I"); - insetsIDs.bottom = (*env)->GetFieldID(env, cls, "bottom", "I"); - insetsIDs.left = (*env)->GetFieldID(env, cls, "left", "I"); - insetsIDs.right = (*env)->GetFieldID(env, cls, "right", "I"); + CHECK_NULL(insetsIDs.top = (*env)->GetFieldID(env, cls, "top", "I")); + CHECK_NULL(insetsIDs.bottom = (*env)->GetFieldID(env, cls, "bottom", "I")); + CHECK_NULL(insetsIDs.left = (*env)->GetFieldID(env, cls, "left", "I")); + CHECK_NULL(insetsIDs.right = (*env)->GetFieldID(env, cls, "right", "I")); } diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/awt_LoadLibrary.c --- a/jdk/src/solaris/native/sun/awt/awt_LoadLibrary.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/awt_LoadLibrary.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,11 +77,16 @@ return isHeadless; } +#define CHECK_EXCEPTION_FATAL(env, message) \ + if ((*env)->ExceptionCheck(env)) { \ + (*env)->ExceptionClear(env); \ + (*env)->FatalError(env, message); \ + } + /* * Pathnames to the various awt toolkits */ - #ifdef MACOSX #define LWAWT_PATH "/libawt_lwawt.dylib" #define DEFAULT_PATH LWAWT_PATH @@ -125,6 +130,8 @@ */ fmProp = (*env)->NewStringUTF(env, "sun.font.fontmanager"); + CHECK_EXCEPTION_FATAL(env, "Could not allocate font manager property"); + #ifdef MACOSX fmanager = (*env)->NewStringUTF(env, "sun.font.CFontManager"); tk = LWAWT_PATH; @@ -132,10 +139,13 @@ fmanager = (*env)->NewStringUTF(env, "sun.awt.X11FontManager"); tk = XAWT_PATH; #endif + CHECK_EXCEPTION_FATAL(env, "Could not allocate font manager name"); + if (fmanager && fmProp) { JNU_CallStaticMethodByName(env, NULL, "java/lang/System", "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", fmProp, fmanager); + CHECK_EXCEPTION_FATAL(env, "Could not allocate set properties"); } #ifndef MACOSX @@ -154,9 +164,11 @@ (*env)->DeleteLocalRef(env, fmanager); } + jstring jbuf = JNU_NewStringPlatform(env, buf); + CHECK_EXCEPTION_FATAL(env, "Could not allocate library name"); JNU_CallStaticMethodByName(env, NULL, "java/lang/System", "load", "(Ljava/lang/String;)V", - JNU_NewStringPlatform(env, buf)); + jbuf); awtHandle = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL); diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/awt_Robot.c --- a/jdk/src/solaris/native/sun/awt/awt_Robot.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/awt_Robot.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -175,10 +175,13 @@ num_buttons = numberOfButtons; tmp = (*env)->GetIntArrayElements(env, buttonDownMasks, JNI_FALSE); + CHECK_NULL(tmp); + masks = (jint *)SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(jint), num_buttons); if (masks == (jint *) NULL) { + (*env)->ExceptionClear(env); + (*env)->ReleaseIntArrayElements(env, buttonDownMasks, tmp, 0); JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL); - (*env)->ReleaseIntArrayElements(env, buttonDownMasks, tmp, 0); return; } for (i = 0; i < num_buttons; i++) { diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/awt_UNIXToolkit.c --- a/jdk/src/solaris/native/sun/awt/awt_UNIXToolkit.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/awt_UNIXToolkit.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,6 +98,7 @@ (*env)->GetObjectClass(env, this)); icon_upcall_method = (*env)->GetMethodID(env, this_class, "loadIconCallback", "([BIIIIIZ)V"); + CHECK_NULL_RETURN(icon_upcall_method, JNI_FALSE); } if (pixbuf != NULL) @@ -112,6 +113,8 @@ /* Copy the data array into a Java structure so we can pass it back. */ jbyteArray data = (*env)->NewByteArray(env, (row_stride * height)); + JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); + (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height), (jbyte *)pixbuf_data); diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/awt_util.c --- a/jdk/src/solaris/native/sun/awt/awt_util.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/awt_util.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif -void +jboolean awtJNI_ThreadYield(JNIEnv *env) { static jclass threadClass = NULL; @@ -76,6 +76,7 @@ Boolean err = FALSE; if (threadClass == NULL) { jclass tc = (*env)->FindClass(env, "java/lang/Thread"); + CHECK_NULL_RETURN(tc, JNI_FALSE); threadClass = (*env)->NewGlobalRef(env, tc); (*env)->DeleteLocalRef(env, tc); if (threadClass != NULL) { @@ -91,10 +92,11 @@ err = TRUE; } if (err) { - return; + return JNI_FALSE; } } /* threadClass == NULL*/ (*env)->CallStaticVoidMethod(env, threadClass, yieldMethodID); DASSERT(!((*env)->ExceptionOccurred(env))); + return JNI_TRUE; } /* awtJNI_ThreadYield() */ diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/awt_util.h --- a/jdk/src/solaris/native/sun/awt/awt_util.h Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/awt_util.h Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,7 +78,7 @@ int32_t echoC; }; -extern void awtJNI_ThreadYield(JNIEnv *env); +extern jboolean awtJNI_ThreadYield(JNIEnv *env); /* * Functions for accessing fields by name and signature diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/fontpath.c --- a/jdk/src/solaris/native/sun/awt/fontpath.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/fontpath.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -161,17 +161,22 @@ if (! isLocalSet) { jclass geCls = (*env)->FindClass(env, "java/awt/GraphicsEnvironment"); + CHECK_NULL_RETURN(geCls, JNI_FALSE); jmethodID getLocalGE = (*env)->GetStaticMethodID(env, geCls, "getLocalGraphicsEnvironment", "()Ljava/awt/GraphicsEnvironment;"); + CHECK_NULL_RETURN(getLocalGE, JNI_FALSE); jobject ge = (*env)->CallStaticObjectMethod(env, geCls, getLocalGE); + JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); jclass sgeCls = (*env)->FindClass(env, "sun/java2d/SunGraphicsEnvironment"); + CHECK_NULL_RETURN(sgeCls, JNI_FALSE); if ((*env)->IsInstanceOf(env, ge, sgeCls)) { jmethodID isDisplayLocal = (*env)->GetMethodID(env, sgeCls, "isDisplayLocal", "()Z"); + JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); isLocal = (*env)->CallBooleanMethod(env, ge, isDisplayLocal); } else { isLocal = True; @@ -1005,50 +1010,38 @@ jmethodID fcFontCons; char* debugMinGlyphsStr = getenv("J2D_DEBUG_MIN_GLYPHS"); + CHECK_NULL(fcInfoObj); + CHECK_NULL(fcCompFontArray); + jclass fcInfoClass = (*env)->FindClass(env, "sun/font/FontConfigManager$FontConfigInfo"); + CHECK_NULL(fcInfoClass); jclass fcCompFontClass = (*env)->FindClass(env, "sun/font/FontConfigManager$FcCompFont"); + CHECK_NULL(fcCompFontClass); jclass fcFontClass = (*env)->FindClass(env, "sun/font/FontConfigManager$FontConfigFont"); - - if (fcInfoObj == NULL || fcCompFontArray == NULL || fcInfoClass == NULL || - fcCompFontClass == NULL || fcFontClass == NULL) { - return; - } - - fcVersionID = (*env)->GetFieldID(env, fcInfoClass, "fcVersion", "I"); + CHECK_NULL(fcFontClass); - fcCacheDirsID = (*env)->GetFieldID(env, fcInfoClass, "cacheDirs", - "[Ljava/lang/String;"); - - fcNameID = (*env)->GetFieldID(env, fcCompFontClass, - "fcName", "Ljava/lang/String;"); - fcFirstFontID = - (*env)->GetFieldID(env, fcCompFontClass, "firstFont", - "Lsun/font/FontConfigManager$FontConfigFont;"); - fcAllFontsID = - (*env)->GetFieldID(env, fcCompFontClass, "allFonts", - "[Lsun/font/FontConfigManager$FontConfigFont;"); - - fcFontCons = (*env)->GetMethodID(env, fcFontClass, "", "()V"); - - familyNameID = (*env)->GetFieldID(env, fcFontClass, - "familyName", "Ljava/lang/String;"); - styleNameID = (*env)->GetFieldID(env, fcFontClass, - "styleStr", "Ljava/lang/String;"); - fullNameID = (*env)->GetFieldID(env, fcFontClass, - "fullName", "Ljava/lang/String;"); - fontFileID = (*env)->GetFieldID(env, fcFontClass, - "fontFile", "Ljava/lang/String;"); - - if (fcVersionID == NULL || fcCacheDirsID == NULL || fcNameID == NULL || - fcFirstFontID == NULL || fcAllFontsID == NULL || fcFontCons == NULL || - familyNameID == NULL || styleNameID == NULL || fullNameID == NULL || - fontFileID == NULL) { - return; - } + CHECK_NULL(fcVersionID = (*env)->GetFieldID(env, fcInfoClass, "fcVersion", "I")); + CHECK_NULL(fcCacheDirsID = (*env)->GetFieldID(env, fcInfoClass, "cacheDirs", + "[Ljava/lang/String;")); + CHECK_NULL(fcNameID = (*env)->GetFieldID(env, fcCompFontClass, + "fcName", "Ljava/lang/String;")); + CHECK_NULL(fcFirstFontID = (*env)->GetFieldID(env, fcCompFontClass, "firstFont", + "Lsun/font/FontConfigManager$FontConfigFont;")); + CHECK_NULL(fcAllFontsID = (*env)->GetFieldID(env, fcCompFontClass, "allFonts", + "[Lsun/font/FontConfigManager$FontConfigFont;")); + CHECK_NULL(fcFontCons = (*env)->GetMethodID(env, fcFontClass, "", "()V")); + CHECK_NULL(familyNameID = (*env)->GetFieldID(env, fcFontClass, + "familyName", "Ljava/lang/String;")); + CHECK_NULL(styleNameID = (*env)->GetFieldID(env, fcFontClass, + "styleStr", "Ljava/lang/String;")); + CHECK_NULL(fullNameID = (*env)->GetFieldID(env, fcFontClass, + "fullName", "Ljava/lang/String;")); + CHECK_NULL(fontFileID = (*env)->GetFieldID(env, fcFontClass, + "fontFile", "Ljava/lang/String;")); if ((libfontconfig = openFontConfig()) == NULL) { return; @@ -1129,6 +1122,8 @@ if (cacheDirs != NULL) { while ((cnt < max) && (cacheDir = (*FcStrListNext)(cacheDirs))) { jstr = (*env)->NewStringUTF(env, (const char*)cacheDir); + JNU_CHECK_EXCEPTION(env); + (*env)->SetObjectArrayElement(env, cacheDirArray, cnt++, jstr); } (*FcStrListDone)(cacheDirs); @@ -1136,6 +1131,11 @@ } locale = (*env)->GetStringUTFChars(env, localeStr, 0); + if (locale == NULL) { + (*env)->ExceptionClear(env); + JNU_ThrowOutOfMemoryError(env, "Could not create locale"); + return; + } arrlen = (*env)->GetArrayLength(env, fcCompFontArray); for (i=0; iGetFieldID(env, clazz, "value", "I"); - - if(colorValueID == NULL) - JNU_ThrowNullPointerException (env, "Can't get java/awt/Color.value fieldID"); } JNIEXPORT void JNICALL diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/multi_font.c --- a/jdk/src/solaris/native/sun/awt/multi_font.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/multi_font.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,7 +74,7 @@ jobject temp = NULL; jboolean validRet = JNI_FALSE; - if ((*env)->EnsureLocalCapacity(env, 2) < 0) + if ((*env)->EnsureLocalCapacity(env, 2) < 0 || (*env)->ExceptionCheck(env)) goto done; peer = (*env)->CallObjectMethod(env,font,fontIDs.getPeer); @@ -162,7 +162,7 @@ font = JNU_CallMethodByName(env, NULL, this, "getFont_NoClientCode", "()Ljava/awt/Font;").l; - if (JNU_IsNull(env, font)) { + if (JNU_IsNull(env, font) || (*env)->ExceptionCheck(env)) { return JNI_FALSE; } @@ -318,6 +318,10 @@ } fdata = awtJNI_GetFontData(env, font, &err); + if ((*env)->ExceptionCheck(env)) { + (*env)->DeleteLocalRef(env, dataArray); + return 0; + } stringCount = (*env)->GetArrayLength(env, dataArray); @@ -336,6 +340,11 @@ } j = awtJNI_GetFontDescriptorNumber(env, font, fontDescriptor); + if ((*env)->ExceptionCheck(env)) { + (*env)->DeleteLocalRef(env, fontDescriptor); + (*env)->DeleteLocalRef(env, data); + break; + } if (fdata->flist[j].load == 0) { xf = loadFont(awt_display, @@ -356,6 +365,14 @@ stringData = (unsigned char *)(*env)->GetPrimitiveArrayCritical(env, data,NULL); + if (stringData == NULL) { + (*env)->DeleteLocalRef(env, fontDescriptor); + (*env)->DeleteLocalRef(env, data); + (*env)->ExceptionClear(env); + JNU_ThrowOutOfMemoryError(env, "Could not get string data"); + break; + } + length = (stringData[0] << 24) | (stringData[1] << 16) | (stringData[2] << 8) | stringData[3]; offsetStringData = (char *)(stringData + (4 * sizeof(char))); diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c --- a/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,10 +45,12 @@ filenameFilterCallbackMethodID = (*env)->GetMethodID(env, cx, "filenameFilterCallback", "(Ljava/lang/String;)Z"); DASSERT(filenameFilterCallbackMethodID != NULL); + CHECK_NULL(filenameFilterCallbackMethodID); setFileInternalMethodID = (*env)->GetMethodID(env, cx, "setFileInternal", "(Ljava/lang/String;[Ljava/lang/String;)V"); DASSERT(setFileInternalMethodID != NULL); + CHECK_NULL(setFileInternalMethodID); widgetFieldID = (*env)->GetFieldID(env, cx, "widget", "J"); DASSERT(widgetFieldID != NULL); @@ -63,6 +65,7 @@ env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); filename = (*env)->NewStringUTF(env, filter_info->filename); + JNU_CHECK_EXCEPTION_RETURN(env, FALSE); return (*env)->CallBooleanMethod(env, obj, filenameFilterCallbackMethodID, filename); @@ -173,13 +176,14 @@ stringCls = (*env)->FindClass(env, "java/lang/String"); if (stringCls == NULL) { + (*env)->ExceptionClear(env); JNU_ThrowInternalError(env, "Could not get java.lang.String class"); return NULL; } - array = (*env)->NewObjectArray(env, fp_gtk_g_slist_length(list), stringCls, - NULL); + array = (*env)->NewObjectArray(env, fp_gtk_g_slist_length(list), stringCls, NULL); if (array == NULL) { + (*env)->ExceptionClear(env); JNU_ThrowInternalError(env, "Could not instantiate array files array"); return NULL; } @@ -189,7 +193,9 @@ entry = (char*) iterator->data; entry = strrchr(entry, '/') + 1; str = (*env)->NewStringUTF(env, entry); - (*env)->SetObjectArrayElement(env, array, i, str); + if (str && !(*env)->ExceptionCheck(env)) { + (*env)->SetObjectArrayElement(env, array, i, str); + } i++; } @@ -215,13 +221,14 @@ stringCls = (*env)->FindClass(env, "java/lang/String"); if (stringCls == NULL) { + (*env)->ExceptionClear(env); JNU_ThrowInternalError(env, "Could not get java.lang.String class"); return NULL; } - array = (*env)->NewObjectArray(env, fp_gtk_g_slist_length(list), stringCls, - NULL); + array = (*env)->NewObjectArray(env, fp_gtk_g_slist_length(list), stringCls, NULL); if (array == NULL) { + (*env)->ExceptionClear(env); JNU_ThrowInternalError(env, "Could not instantiate array files array"); return NULL; } @@ -236,7 +243,9 @@ } str = (*env)->NewStringUTF(env, entry); - (*env)->SetObjectArrayElement(env, array, i, str); + if (str && !(*env)->ExceptionCheck(env)) { + (*env)->SetObjectArrayElement(env, array, i, str); + } i++; } @@ -268,16 +277,17 @@ if (full_path_names) { //This is a hack for use with "Recent Folders" in gtk where each //file could have its own directory. + jfilenames = toPathAndFilenamesArray(env, filenames); jcurrent_folder = (*env)->NewStringUTF(env, "/"); - jfilenames = toPathAndFilenamesArray(env, filenames); } else { - jcurrent_folder = (*env)->NewStringUTF(env, current_folder); jfilenames = toFilenamesArray(env, filenames); + jcurrent_folder = (*env)->NewStringUTF(env, current_folder); } - (*env)->CallVoidMethod(env, obj, setFileInternalMethodID, jcurrent_folder, - jfilenames); + if (!(*env)->ExceptionCheck(env)) { + (*env)->CallVoidMethod(env, obj, setFileInternalMethodID, + jcurrent_folder, jfilenames); + } fp_g_free(current_folder); - quit(env, (jobject)obj, TRUE); } @@ -296,11 +306,17 @@ if (jvm == NULL) { (*env)->GetJavaVM(env, &jvm); + JNU_CHECK_EXCEPTION(env); } fp_gdk_threads_enter(); const char *title = jtitle == NULL? "": (*env)->GetStringUTFChars(env, jtitle, 0); + if (title == NULL) { + (*env)->ExceptionClear(env); + JNU_ThrowOutOfMemoryError(env, "Could not get title"); + return; + } if (mode == java_awt_FileDialog_SAVE) { /* Save action */ @@ -328,6 +344,11 @@ /* Set the directory */ if (jdir != NULL) { const char *dir = (*env)->GetStringUTFChars(env, jdir, 0); + if (dir == NULL) { + (*env)->ExceptionClear(env); + JNU_ThrowOutOfMemoryError(env, "Could not get dir"); + return; + } fp_gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir); (*env)->ReleaseStringUTFChars(env, jdir, dir); } @@ -335,6 +356,11 @@ /* Set the filename */ if (jfile != NULL) { const char *filename = (*env)->GetStringUTFChars(env, jfile, 0); + if (filename == NULL) { + (*env)->ExceptionClear(env); + JNU_ThrowOutOfMemoryError(env, "Could not get filename"); + return; + } if (mode == java_awt_FileDialog_SAVE) { fp_gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename); } else { diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/xawt/XToolkit.c --- a/jdk/src/solaris/native/sun/xawt/XToolkit.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/xawt/XToolkit.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ #include "awt_Component.h" #include "awt_MenuComponent.h" #include "awt_Font.h" +#include "awt_util.h" #include "sun_awt_X11_XToolkit.h" #include "java_awt_SystemColor.h" @@ -76,6 +77,8 @@ #ifndef HEADLESS extern Display* awt_init_Display(JNIEnv *env, jobject this); +extern void freeNativeStringArray(char **array, long length); +extern char** stringArrayToNative(JNIEnv *env, jobjectArray array, jsize * ret_length); struct XFontPeerIDs xFontPeerIDs; @@ -103,9 +106,11 @@ (JNIEnv *env, jclass clazz) { jfieldID fid = (*env)->GetStaticFieldID(env, clazz, "numLockMask", "I"); + CHECK_NULL(fid); awt_NumLockMask = (*env)->GetStaticIntField(env, clazz, fid); DTRACE_PRINTLN1("awt_NumLockMask = %u", awt_NumLockMask); fid = (*env)->GetStaticFieldID(env, clazz, "modLockIsShiftLock", "I"); + CHECK_NULL(fid); awt_ModLockIsShiftLock = (*env)->GetStaticIntField(env, clazz, fid) != 0 ? True : False; } @@ -173,21 +178,31 @@ componentIDs.x = (*env)->GetFieldID(env, cls, "x", "I"); + CHECK_NULL(componentIDs.x); componentIDs.y = (*env)->GetFieldID(env, cls, "y", "I"); + CHECK_NULL(componentIDs.y); componentIDs.width = (*env)->GetFieldID(env, cls, "width", "I"); + CHECK_NULL(componentIDs.width); componentIDs.height = (*env)->GetFieldID(env, cls, "height", "I"); + CHECK_NULL(componentIDs.height); componentIDs.isPacked = (*env)->GetFieldID(env, cls, "isPacked", "Z"); + CHECK_NULL(componentIDs.isPacked); componentIDs.peer = (*env)->GetFieldID(env, cls, "peer", "Ljava/awt/peer/ComponentPeer;"); + CHECK_NULL(componentIDs.peer); componentIDs.background = (*env)->GetFieldID(env, cls, "background", "Ljava/awt/Color;"); + CHECK_NULL(componentIDs.background); componentIDs.foreground = (*env)->GetFieldID(env, cls, "foreground", "Ljava/awt/Color;"); + CHECK_NULL(componentIDs.foreground); componentIDs.graphicsConfig = (*env)->GetFieldID(env, cls, "graphicsConfig", "Ljava/awt/GraphicsConfiguration;"); + CHECK_NULL(componentIDs.graphicsConfig); componentIDs.name = (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;"); + CHECK_NULL(componentIDs.name); /* Use _NoClientCode() methods for trusted methods, so that we * know that we are not invoking client code on trusted threads @@ -195,19 +210,20 @@ componentIDs.getParent = (*env)->GetMethodID(env, cls, "getParent_NoClientCode", "()Ljava/awt/Container;"); + CHECK_NULL(componentIDs.getParent); componentIDs.getLocationOnScreen = (*env)->GetMethodID(env, cls, "getLocationOnScreen_NoTreeLock", "()Ljava/awt/Point;"); + CHECK_NULL(componentIDs.getLocationOnScreen); keyclass = (*env)->FindClass(env, "java/awt/event/KeyEvent"); - if (JNU_IsNull(env, keyclass)) { - return; - } + CHECK_NULL(keyclass); componentIDs.isProxyActive = (*env)->GetFieldID(env, keyclass, "isProxyActive", "Z"); + CHECK_NULL(componentIDs.isProxyActive); componentIDs.appContext = (*env)->GetFieldID(env, cls, "appContext", @@ -339,7 +355,7 @@ static void waitForEvents(JNIEnv *, jlong); static void awt_pipe_init(); static void processOneEvent(XtInputMask iMask); -static void performPoll(JNIEnv *, jlong); +static Boolean performPoll(JNIEnv *, jlong); static void wakeUp(); static void update_poll_timeout(int timeout_control); static uint32_t get_poll_timeout(jlong nextTaskTime); @@ -608,11 +624,13 @@ */ void waitForEvents(JNIEnv *env, jlong nextTaskTime) { - performPoll(env, nextTaskTime); - if ((awt_next_flush_time > 0) && (awtJNI_TimeMillis() >= awt_next_flush_time)) { - XFlush(awt_display); - awt_last_flush_time = awt_next_flush_time; - awt_next_flush_time = 0LL; + if (performPoll(env, nextTaskTime) + && (awt_next_flush_time > 0) + && (awtJNI_TimeMillis() >= awt_next_flush_time)) { + + XFlush(awt_display); + awt_last_flush_time = awt_next_flush_time; + awt_next_flush_time = 0LL; } } /* waitForEvents() */ @@ -646,7 +664,7 @@ * * The fdAWTPipe will be empty when this returns. */ -static void +static Boolean performPoll(JNIEnv *env, jlong nextTaskTime) { static Bool pollFdsInited = False; static char read_buf[AWT_POLL_BUFSIZE + 1]; /* dummy buf to empty pipe */ @@ -673,7 +691,9 @@ /* ACTUALLY DO THE POLL() */ if (timeout == 0) { // be sure other threads get a chance - awtJNI_ThreadYield(env); + if (!awtJNI_ThreadYield(env)) { + return FALSE; + } } if (tracing) poll_sleep_time = awtJNI_TimeMillis(); @@ -701,7 +721,7 @@ update_poll_timeout(TIMEOUT_EVENTS); PRINT2("performPoll(): TIMEOUT_EVENTS curPollTimeout = %d \n", curPollTimeout); } - return; + return TRUE; } /* performPoll() */ @@ -856,23 +876,25 @@ xawt_root_window = get_xawt_root_shell(env); if ( xawt_root_window == None ) { + AWT_UNLOCK(); JNU_ThrowNullPointerException(env, "AWT root shell is unrealized"); - AWT_UNLOCK(); return; } command = (char *) JNU_GetStringPlatformChars(env, jcommand, NULL); - c[0] = (char *)command; - status = XmbTextListToTextProperty(awt_display, c, 1, - XStdICCTextStyle, &text_prop); + if (command != NULL) { + c[0] = (char *)command; + status = XmbTextListToTextProperty(awt_display, c, 1, + XStdICCTextStyle, &text_prop); - if (status == Success || status > 0) { - XSetTextProperty(awt_display, xawt_root_window, - &text_prop, XA_WM_COMMAND); - if (text_prop.value != NULL) - XFree(text_prop.value); + if (status == Success || status > 0) { + XSetTextProperty(awt_display, xawt_root_window, + &text_prop, XA_WM_COMMAND); + if (text_prop.value != NULL) + XFree(text_prop.value); + } + JNU_ReleaseStringPlatformChars(env, jcommand, command); } - JNU_ReleaseStringPlatformChars(env, jcommand, command); AWT_UNLOCK(); } @@ -886,96 +908,56 @@ * name. It's not! It's just a plain function. */ JNIEXPORT void JNICALL -Java_sun_awt_motif_XsessionWMcommand_New(JNIEnv *env, jobjectArray jargv) +Java_sun_awt_motif_XsessionWMcommand_New(JNIEnv *env, jobjectArray jarray) { - static const char empty[] = ""; - - int argc; - const char **cargv; + jsize length; + char ** array; XTextProperty text_prop; int status; - int i; Window xawt_root_window; AWT_LOCK(); xawt_root_window = get_xawt_root_shell(env); if (xawt_root_window == None) { + AWT_UNLOCK(); JNU_ThrowNullPointerException(env, "AWT root shell is unrealized"); - AWT_UNLOCK(); return; } - argc = (int)(*env)->GetArrayLength(env, jargv); - if (argc == 0) { - AWT_UNLOCK(); - return; - } - - /* array of C strings */ - cargv = (const char **)calloc(argc, sizeof(char *)); - if (cargv == NULL) { - JNU_ThrowOutOfMemoryError(env, "Unable to allocate cargv"); - AWT_UNLOCK(); - return; - } - - /* fill C array with platform chars of java strings */ - for (i = 0; i < argc; ++i) { - jstring js; - const char *cs; - - cs = NULL; - js = (*env)->GetObjectArrayElement(env, jargv, i); - if (js != NULL) { - cs = JNU_GetStringPlatformChars(env, js, NULL); - } - if (cs == NULL) { - cs = empty; - } - cargv[i] = cs; - (*env)->DeleteLocalRef(env, js); - } + array = stringArrayToNative(env, jarray, &length); - /* grr, X prototype doesn't declare cargv as const, thought it really is */ - status = XmbTextListToTextProperty(awt_display, (char **)cargv, argc, - XStdICCTextStyle, &text_prop); - if (status < 0) { - switch (status) { - case XNoMemory: - JNU_ThrowOutOfMemoryError(env, - "XmbTextListToTextProperty: XNoMemory"); - break; - case XLocaleNotSupported: - JNU_ThrowInternalError(env, - "XmbTextListToTextProperty: XLocaleNotSupported"); - break; - case XConverterNotFound: - JNU_ThrowNullPointerException(env, - "XmbTextListToTextProperty: XConverterNotFound"); - break; - default: - JNU_ThrowInternalError(env, - "XmbTextListToTextProperty: unknown error"); + if (array != NULL) { + status = XmbTextListToTextProperty(awt_display, array, length, + XStdICCTextStyle, &text_prop); + if (status < 0) { + switch (status) { + case XNoMemory: + JNU_ThrowOutOfMemoryError(env, + "XmbTextListToTextProperty: XNoMemory"); + break; + case XLocaleNotSupported: + JNU_ThrowInternalError(env, + "XmbTextListToTextProperty: XLocaleNotSupported"); + break; + case XConverterNotFound: + JNU_ThrowNullPointerException(env, + "XmbTextListToTextProperty: XConverterNotFound"); + break; + default: + JNU_ThrowInternalError(env, + "XmbTextListToTextProperty: unknown error"); + } + } else { + XSetTextProperty(awt_display, xawt_root_window, + &text_prop, XA_WM_COMMAND); } - } else { - - XSetTextProperty(awt_display, xawt_root_window, - &text_prop, XA_WM_COMMAND); - } - - for (i = 0; i < argc; ++i) { - jstring js; - if (cargv[i] == empty) - continue; + if (text_prop.value != NULL) + XFree(text_prop.value); - js = (*env)->GetObjectArrayElement(env, jargv, i); - JNU_ReleaseStringPlatformChars(env, js, cargv[i]); - (*env)->DeleteLocalRef(env, js); + freeNativeStringArray(array, length); } - if (text_prop.value != NULL) - XFree(text_prop.value); AWT_UNLOCK(); } diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/xawt/XWindow.c --- a/jdk/src/solaris/native/sun/xawt/XWindow.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/xawt/XWindow.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1242,9 +1242,13 @@ { char *ptr = NULL; windowID = (*env)->GetFieldID(env, clazz, "window", "J"); + CHECK_NULL(windowID); targetID = (*env)->GetFieldID(env, clazz, "target", "Ljava/awt/Component;"); + CHECK_NULL(targetID); graphicsConfigID = (*env)->GetFieldID(env, clazz, "graphicsConfig", "Lsun/awt/X11GraphicsConfig;"); + CHECK_NULL(graphicsConfigID); drawStateID = (*env)->GetFieldID(env, clazz, "drawState", "I"); + CHECK_NULL(drawStateID); ptr = getenv("_AWT_USE_TYPE4_PATCH"); if( ptr != NULL && ptr[0] != 0 ) { if( strncmp("true", ptr, 4) == 0 ) { diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/xawt/XlibWrapper.c --- a/jdk/src/solaris/native/sun/xawt/XlibWrapper.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/xawt/XlibWrapper.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,7 @@ #include "utility/rect.h" #include + #if defined(DEBUG) || defined(INTERNAL_BUILD) static jmethodID lockIsHeldMID = NULL; @@ -59,17 +60,94 @@ lockIsHeldMID = (*env)->GetStaticMethodID(env, tkClass, "isAWTLockHeldByCurrentThread", "()Z"); + if (lockIsHeldMID == NULL) return; } if (!(*env)->CallStaticBooleanMethod(env, tkClass, lockIsHeldMID)) { JNU_ThrowInternalError(env, "Current thread does not hold AWT_LOCK!"); } } -#define AWT_CHECK_HAVE_LOCK() CheckHaveAWTLock(env) +#define AWT_CHECK_HAVE_LOCK() \ + do { \ + CheckHaveAWTLock(env); \ + if ((*env)->ExceptionCheck(env)) { \ + return; \ + } \ + } while (0); \ + +#define AWT_CHECK_HAVE_LOCK_RETURN(ret) \ + do { \ + CheckHaveAWTLock(env); \ + if ((*env)->ExceptionCheck(env)) { \ + return (ret); \ + } \ + } while (0); \ + #else #define AWT_CHECK_HAVE_LOCK() +#define AWT_CHECK_HAVE_LOCK_RETURN(ret) #endif +void freeNativeStringArray(char **array, jsize length) { + int i; + if (array == NULL) { + return; + } + for (i = 0; i < length; i++) { + free(array[i]); + } + free(array); +} + +char** stringArrayToNative(JNIEnv *env, jobjectArray array, jsize * ret_length) { + Bool err = FALSE; + char ** strings; + int index, str_index = 0; + jsize length = (*env)->GetArrayLength(env, array); + + if (length == 0) { + return NULL; + } + + strings = (char**) calloc(length, sizeof (char*)); + + if (strings == NULL) { + JNU_ThrowOutOfMemoryError(env, ""); + return NULL; + } + + for (index = 0; index < length; index++) { + jstring str = (*env)->GetObjectArrayElement(env, array, index); + if (str != NULL) { + const char * str_char = JNU_GetStringPlatformChars(env, str, NULL); + if (str_char != NULL) { + char * dup_str = strdup(str_char); + if (dup_str != NULL) { + strings[str_index++] = dup_str; + } else { + JNU_ThrowOutOfMemoryError(env, ""); + err = TRUE; + } + JNU_ReleaseStringPlatformChars(env, str, str_char); + } else { + err = TRUE; + } + (*env)->DeleteLocalRef(env, str); + if (err) { + break; + } + } + } + + if (err) { + freeNativeStringArray(strings, str_index); + strings = NULL; + str_index = -1; + } + *ret_length = str_index; + + return strings; +} /* * Class: XlibWrapper @@ -81,7 +159,7 @@ (JNIEnv *env, jclass clazz, jlong display_name) { Display *dp; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); dp = XOpenDisplay((char *) jlong_to_ptr(display_name)); return ptr_to_jlong(dp); @@ -97,7 +175,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XDisplayString(JNIEnv *env, jclass clazz, jlong display) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return ptr_to_jlong(XDisplayString((Display*) jlong_to_ptr(display))); } @@ -115,7 +193,7 @@ */ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_DefaultScreen (JNIEnv *env, jclass clazz, jlong display) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return (jlong) DefaultScreen((Display *) jlong_to_ptr(display)); } @@ -125,7 +203,7 @@ * Signature: (JJ)J */ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_ScreenOfDisplay(JNIEnv *env, jclass clazz, jlong display, jlong screen_number) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return ptr_to_jlong(ScreenOfDisplay((Display *) jlong_to_ptr(display), screen_number)); } @@ -136,7 +214,7 @@ * Signature: (J)I */ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_DoesBackingStore(JNIEnv *env, jclass clazz, jlong screen) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return (jint) DoesBackingStore((Screen*) jlong_to_ptr(screen)); } @@ -148,7 +226,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_DisplayWidth (JNIEnv *env, jclass clazz, jlong display, jlong screen) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return (jlong) DisplayWidth((Display *) jlong_to_ptr(display),screen); } @@ -160,7 +238,7 @@ */ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_DisplayWidthMM (JNIEnv *env, jclass clazz, jlong display, jlong screen) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return (jlong) DisplayWidthMM((Display *) jlong_to_ptr(display),screen); } @@ -172,7 +250,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_DisplayHeight (JNIEnv *env, jclass clazz, jlong display, jlong screen) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return (jlong) DisplayHeight((Display *) jlong_to_ptr(display),screen); } /* @@ -182,7 +260,7 @@ */ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_DisplayHeightMM (JNIEnv *env, jclass clazz, jlong display, jlong screen) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return (jlong) DisplayHeightMM((Display *) jlong_to_ptr(display),screen); } @@ -193,7 +271,7 @@ */ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_RootWindow (JNIEnv *env , jclass clazz, jlong display, jlong screen_number) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return (jlong) RootWindow((Display *) jlong_to_ptr(display), screen_number); } @@ -203,7 +281,7 @@ */ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_ScreenCount (JNIEnv *env , jclass clazz, jlong display) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return ScreenCount((Display *) jlong_to_ptr(display)); } @@ -218,7 +296,7 @@ jint x, jint y, jint w, jint h , jint border_width, jint depth, jlong wclass, jlong visual, jlong valuemask, jlong attributes) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XCreateWindow((Display *) jlong_to_ptr(display),(Window) window, x, y, w, h, border_width, depth, wclass, (Visual *) jlong_to_ptr(visual), valuemask, (XSetWindowAttributes *) jlong_to_ptr(attributes)); @@ -360,7 +438,7 @@ Window focusOwner; int revert_to; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); XGetInputFocus( (Display *)jlong_to_ptr(display), &focusOwner, &revert_to); return focusOwner; } @@ -383,7 +461,7 @@ jint owner_events, jint event_mask, jint pointer_mode, jint keyboard_mode, jlong confine_to, jlong cursor, jlong time) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XGrabPointer( (Display *)jlong_to_ptr(display), (Window) window, (Bool) owner_events, (unsigned int) event_mask, (int) pointer_mode, (int) keyboard_mode, (Window) confine_to, (Cursor) cursor, (Time) time); @@ -401,7 +479,7 @@ jint owner_events, jint pointer_mode, jint keyboard_mode, jlong time) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XGrabKeyboard( (Display *)jlong_to_ptr(display), (Window) window, (Bool) owner_events, (int) pointer_mode, (int) keyboard_mode, (Time) time); @@ -474,7 +552,7 @@ (JNIEnv *env, jclass clazz, jlong display, jlong opcode_rtrn, jlong event_rtrn, jlong error_rtrn, jlong major_in_out, jlong minor_in_out) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); return XkbQueryExtension( (Display *) jlong_to_ptr(display), (int *) jlong_to_ptr(opcode_rtrn), (int *) jlong_to_ptr(event_rtrn), @@ -485,7 +563,7 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XkbLibraryVersion (JNIEnv *env, jclass clazz, jlong lib_major_in_out, jlong lib_minor_in_out) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); *((int *)jlong_to_ptr(lib_major_in_out)) = XkbMajorVersion; *((int *)jlong_to_ptr(lib_minor_in_out)) = XkbMinorVersion; return XkbLibraryVersion((int *)jlong_to_ptr(lib_major_in_out), (int *)jlong_to_ptr(lib_minor_in_out)); @@ -494,7 +572,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XkbGetMap (JNIEnv *env, jclass clazz, jlong display, jlong which, jlong device_spec) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return (jlong) XkbGetMap( (Display *) jlong_to_ptr(display), (unsigned int) which, (unsigned int) device_spec); @@ -502,7 +580,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XkbGetUpdatedMap (JNIEnv *env, jclass clazz, jlong display, jlong which, jlong xkb) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return (jlong) XkbGetUpdatedMap( (Display *) jlong_to_ptr(display), (unsigned int) which, (XkbDescPtr) jlong_to_ptr(xkb)); @@ -516,6 +594,7 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XkbTranslateKeyCode (JNIEnv *env, jclass clazz, jlong xkb, jint keycode, jlong mods, jlong mods_rtrn, jlong keysym_rtrn) { + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); Bool b; b = XkbTranslateKeyCode((XkbDescPtr)xkb, (unsigned int)keycode, (unsigned int)mods, (unsigned int *)jlong_to_ptr(mods_rtrn), @@ -578,7 +657,7 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XFilterEvent (JNIEnv *env, jclass clazz, jlong ptr, jlong window) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); return (jboolean) XFilterEvent((XEvent *) jlong_to_ptr(ptr), (Window) window); } @@ -590,7 +669,7 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XSupportsLocale (JNIEnv *env, jclass clazz) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); return (jboolean)XSupportsLocale(); } @@ -607,9 +686,10 @@ if (!JNU_IsNull(env, jstr)) { modifier_list = (char *)JNU_GetStringPlatformChars(env, jstr, NULL); + CHECK_NULL_RETURN(modifier_list, NULL); } - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(NULL); if (modifier_list) { ret = XSetLocaleModifiers(modifier_list); JNU_ReleaseStringPlatformChars(env, jstr, (const char *) modifier_list); @@ -722,7 +802,7 @@ jlong src_x, jlong src_y, jlong dest_x_return, jlong dest_y_return, jlong child_return) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XTranslateCoordinates( (Display *) jlong_to_ptr(display), src_w, dest_w, src_x, src_y, (int *) jlong_to_ptr(dest_x_return), @@ -733,7 +813,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XEventsQueued (JNIEnv *env, jclass clazz, jlong display, jint mode) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XEventsQueued((Display *) jlong_to_ptr(display), mode); } @@ -758,6 +838,7 @@ #else cname = (char *) JNU_GetStringPlatformChars(env, jstr, NULL); #endif + CHECK_NULL(cname); } else { cname = ""; } @@ -814,8 +895,9 @@ jlong type, jint format, jint mode, jstring value) { jboolean iscopy; + AWT_CHECK_HAVE_LOCK(); const char * chars = JNU_GetStringPlatformChars(env, value, &iscopy); - AWT_CHECK_HAVE_LOCK(); + CHECK_NULL(chars); XChangeProperty((Display*)jlong_to_ptr(display), window, (Atom)property, (Atom)type, format, mode, (unsigned char*)chars, strlen(chars)); if (iscopy) { @@ -833,7 +915,7 @@ jlong long_length, jlong delete, jlong req_type, jlong actual_type, jlong actual_format, jlong nitems_ptr, jlong bytes_after, jlong data_ptr) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XGetWindowProperty((Display*) jlong_to_ptr(display), window, property, long_offset, long_length, delete, (Atom) req_type, (Atom*) jlong_to_ptr(actual_type), (int *) jlong_to_ptr(actual_format), (unsigned long *) jlong_to_ptr(nitems_ptr), @@ -857,23 +939,22 @@ unsigned long nitems; unsigned long bytes_after; unsigned char * string; - jstring res; - AWT_CHECK_HAVE_LOCK(); + jstring res = NULL; + AWT_CHECK_HAVE_LOCK_RETURN(NULL); status = XGetWindowProperty((Display*)jlong_to_ptr(display), window, atom, 0, 0xFFFF, False, XA_STRING, &actual_type, &actual_format, &nitems, &bytes_after, &string); + if (status != Success || string == NULL) { - return NULL; + return NULL; } - if (actual_type != XA_STRING || actual_format != 8) { - XFree(string); - return NULL; + if (actual_type == XA_STRING && actual_format == 8) { + res = JNU_NewStringPlatform(env,(char*) string); } - - // Memory leak??? - return JNU_NewStringPlatform(env,(char*) string); + XFree(string); + return res; } /* @@ -887,13 +968,15 @@ char *cname; unsigned long atom; + AWT_CHECK_HAVE_LOCK_RETURN(0); + if (!JNU_IsNull(env, jstr)) { cname = (char *)JNU_GetStringPlatformChars(env, jstr, NULL); + CHECK_NULL_RETURN(cname, 0); } else { cname = ""; } - AWT_CHECK_HAVE_LOCK(); atom = XInternAtom((Display *) jlong_to_ptr(display), cname, ife); if (!JNU_IsNull(env, jstr)) { @@ -906,7 +989,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XCreateFontCursor (JNIEnv *env, jclass clazz, jlong display, jint shape) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XCreateFontCursor((Display *) jlong_to_ptr(display), (int) shape); } @@ -919,7 +1002,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XCreatePixmapCursor (JNIEnv *env , jclass clazz, jlong display, jlong source, jlong mask, jlong fore, jlong back, jint x , jint y) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return (jlong) XCreatePixmapCursor((Display *) jlong_to_ptr(display), (Pixmap) source, (Pixmap) mask, (XColor *) jlong_to_ptr(fore), (XColor *) jlong_to_ptr(back), x, y); } @@ -935,7 +1018,7 @@ Status status; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); status = XQueryBestCursor((Display *) jlong_to_ptr(display), (Drawable) drawable, width,height, (unsigned int *) jlong_to_ptr(width_return), (unsigned int *) jlong_to_ptr(height_return)); @@ -966,15 +1049,14 @@ Bool b; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); b = XQueryPointer((Display *) jlong_to_ptr(display), (Window) w, (Window *) jlong_to_ptr(root_return), (Window *) jlong_to_ptr(child_return), (int *) jlong_to_ptr(root_x_return), (int *) jlong_to_ptr(root_y_return), (int *) jlong_to_ptr(win_x_return), (int *) jlong_to_ptr(win_y_return), (unsigned int *) jlong_to_ptr(mask_return)); - if (b == True) return JNI_TRUE; - else return JNI_FALSE; + return b ? JNI_TRUE : JNI_FALSE; } /* @@ -1042,7 +1124,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XGetPointerMapping (JNIEnv *env, jclass clazz, jlong display, jlong map, jint buttonNumber) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XGetPointerMapping((Display*)jlong_to_ptr(display), (unsigned char*) jlong_to_ptr(map), buttonNumber); } @@ -1061,31 +1143,26 @@ if (!JNU_IsNull(env, program)) { c_program = (char *)JNU_GetStringPlatformChars(env, program, NULL); } + CHECK_NULL_RETURN(c_program, NULL); + if (!JNU_IsNull(env, option)) { c_option = (char *)JNU_GetStringPlatformChars(env, option, NULL); } - if (c_program == NULL || c_option == NULL) { - if (!JNU_IsNull(env, program)) { - JNU_ReleaseStringPlatformChars(env, program, (const char *) c_program); - } - if (!JNU_IsNull(env, option)) { - JNU_ReleaseStringPlatformChars(env, option, (const char *) c_option); - } + if (c_option == NULL) { + JNU_ReleaseStringPlatformChars(env, program, (const char *) c_program); return NULL; } - AWT_CHECK_HAVE_LOCK(); - c_res = XGetDefault((Display*)jlong_to_ptr(display), c_program, c_option); - if (!JNU_IsNull(env, program)) { - JNU_ReleaseStringPlatformChars(env, program, (const char *) c_program); - } - if (!JNU_IsNull(env, option)) { - JNU_ReleaseStringPlatformChars(env, option, (const char *) c_option); - } + AWT_CHECK_HAVE_LOCK_RETURN(NULL); + c_res = XGetDefault((Display*)jlong_to_ptr(display), c_program, c_option); + // The strings returned by XGetDefault() are owned by Xlib and + // should not be modified or freed by the client. + + JNU_ReleaseStringPlatformChars(env, program, (const char *) c_program); + JNU_ReleaseStringPlatformChars(env, option, (const char *) c_option); if (c_res != NULL) { - // Memory leak??? return JNU_NewStringPlatform(env, c_res); } else { return NULL; @@ -1103,7 +1180,7 @@ { XWindowAttributes attrs; memset(&attrs, 0, sizeof(attrs)); - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); XGetWindowAttributes((Display *) jlong_to_ptr(display), window, &attrs); return ptr_to_jlong(attrs.screen); } @@ -1116,7 +1193,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XScreenNumberOfScreen (JNIEnv *env, jclass clazz, jlong screen) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(-1); if(jlong_to_ptr(screen) == NULL) { return -1; } @@ -1131,7 +1208,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XIconifyWindow (JNIEnv *env, jclass clazz, jlong display, jlong window, jlong screenNumber) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XIconifyWindow((Display*) jlong_to_ptr(display), window, screenNumber); } @@ -1158,10 +1235,9 @@ unsigned char * str = (unsigned char*) jlong_to_ptr(str_ptr); long length = strlen((char*)str); jbyteArray res = (*env)->NewByteArray(env, length); - void * storage = malloc(length+1); - memcpy(storage, str, length+1); + CHECK_NULL_RETURN(res, NULL); (*env)->SetByteArrayRegion(env, res, 0, length, - (const signed char*) storage); + (const signed char*) str); return res; } @@ -1174,7 +1250,7 @@ JNIEXPORT jstring JNICALL Java_sun_awt_X11_XlibWrapper_ServerVendor (JNIEnv *env, jclass clazz, jlong display) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(NULL); return JNU_NewStringPlatform(env, ServerVendor((Display*)jlong_to_ptr(display))); } /* @@ -1185,7 +1261,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_VendorRelease (JNIEnv *env, jclass clazz, jlong display) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return VendorRelease((Display*)jlong_to_ptr(display)); } /* @@ -1203,7 +1279,7 @@ // second, in which place in the keysymarray is XK_KP_7 // using XKeycodeToKeysym. int kc7; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); kc7 = XKeysymToKeycode((Display*)jlong_to_ptr(display), XK_KP_7); if( !kc7 ) { // keycode is not defined. Why, it's a reduced keyboard perhaps: @@ -1226,7 +1302,7 @@ (JNIEnv *env, jclass clazz, jlong display) { int xx; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); xx = XKeysymToKeycode((Display*)jlong_to_ptr(display), SunXK_F37); return (!xx) ? JNI_FALSE : JNI_TRUE; } @@ -1242,7 +1318,7 @@ int32_t i; int32_t kanaCount = 0; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); // There's no direct way to determine whether the keyboard has // a kana lock key. From available keyboard mapping tables, it looks @@ -1289,8 +1365,10 @@ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_SetToolkitErrorHandler (JNIEnv *env, jclass clazz) { - (*env)->GetJavaVM(env, &jvm); - AWT_CHECK_HAVE_LOCK(); + if ((*env)->GetJavaVM(env, &jvm) < 0) { + return 0; + } + AWT_CHECK_HAVE_LOCK_RETURN(0); return ptr_to_jlong(XSetErrorHandler(ToolkitErrorHandler)); } @@ -1350,28 +1428,14 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XInternAtoms (JNIEnv *env, jclass clazz, jlong display, jobjectArray names_arr, jboolean only_if_exists, jlong atoms) { - int length = (*env)->GetArrayLength(env, names_arr); - char ** names = (char**)malloc(length*sizeof(char*)); - jboolean copy; - int index, name_index = 0; - int status; - - AWT_CHECK_HAVE_LOCK(); - - for (index = 0; index < length; index++) { - jstring str = (*env)->GetObjectArrayElement(env, names_arr, index); - if (!JNU_IsNull(env, str)) { - const char * str_char = JNU_GetStringPlatformChars(env, str, NULL); - names[name_index++] = strdup(str_char); - JNU_ReleaseStringPlatformChars(env, str, str_char); - (*env)->DeleteLocalRef(env, str); - } + int status = 0; + AWT_CHECK_HAVE_LOCK_RETURN(0); + jsize length; + char** names = stringArrayToNative(env, names_arr, &length); + if (names) { + status = XInternAtoms((Display*)jlong_to_ptr(display), names, length, only_if_exists, (Atom*) jlong_to_ptr(atoms)); + freeNativeStringArray(names, length); } - status = XInternAtoms((Display*)jlong_to_ptr(display), names, name_index, only_if_exists, (Atom*) jlong_to_ptr(atoms)); - for (index = 0; index < length; index++) { - free(names[index]); - } - free(names); return status; } @@ -1386,7 +1450,7 @@ (JNIEnv *env, jclass clazz, jlong display, jlong window, jlong attr_ptr) { jint status; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); memset((XWindowAttributes*) jlong_to_ptr(attr_ptr), 0, sizeof(XWindowAttributes)); status = XGetWindowAttributes((Display*)jlong_to_ptr(display), window, (XWindowAttributes*) jlong_to_ptr(attr_ptr)); return status; @@ -1404,7 +1468,7 @@ jlong border_width_return, jlong depth_return) { jint status; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); status = XGetGeometry((Display *)jlong_to_ptr(display), (Drawable)drawable, (Window *)jlong_to_ptr(root_return), (int *)jlong_to_ptr(x_return), (int *)jlong_to_ptr(y_return), @@ -1423,7 +1487,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XGetWMNormalHints (JNIEnv *env, jclass clazz, jlong display, jlong window, jlong hints, jlong supplied_return) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XGetWMNormalHints((Display*) jlong_to_ptr(display), window, (XSizeHints*) jlong_to_ptr(hints), @@ -1462,7 +1526,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XSendEvent (JNIEnv *env, jclass clazz, jlong display, jlong window, jboolean propagate, jlong event_mask, jlong event) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XSendEvent((Display*) jlong_to_ptr(display), window, propagate==JNI_TRUE?True:False, @@ -1479,7 +1543,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XQueryTree (JNIEnv *env, jclass clazz, jlong display, jlong window, jlong root_return, jlong parent_return, jlong children_return, jlong nchildren_return) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XQueryTree((Display*) jlong_to_ptr(display), window, (Window *) jlong_to_ptr(root_return), @@ -1524,7 +1588,7 @@ (JNIEnv *env, jclass clazz, jlong display, jlong vinfo_mask, jlong vinfo_template, jlong nitems_return) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return ptr_to_jlong(XGetVisualInfo((Display*) jlong_to_ptr(display), (long) vinfo_mask, (XVisualInfo*) jlong_to_ptr(vinfo_template), @@ -1534,7 +1598,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XAllocSizeHints (JNIEnv *env, jclass clazz) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return ptr_to_jlong(XAllocSizeHints()); } @@ -1560,7 +1624,7 @@ (JNIEnv *env, jclass clazz, jlong display , jlong colormap, jlong xcolor) { Status status; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); status = XAllocColor((Display *) jlong_to_ptr(display), (Colormap) colormap, (XColor *) jlong_to_ptr(xcolor)); if (status == 0) return JNI_FALSE; @@ -1575,7 +1639,7 @@ */ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XCreateBitmapFromData (JNIEnv *env, jclass clazz, jlong display, jlong drawable, jlong data, jint width, jint height) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return (jlong) XCreateBitmapFromData((Display *) jlong_to_ptr(display), (Drawable) drawable, (char *) jlong_to_ptr(data), width, height); @@ -1640,7 +1704,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XGetSelectionOwner(JNIEnv *env, jclass clazz, jlong display, jlong selection) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return (jlong)XGetSelectionOwner((Display*)jlong_to_ptr(display), selection); } @@ -1655,7 +1719,7 @@ { jstring string = NULL; char* name; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(NULL); name = (char*) XGetAtomName((Display*)jlong_to_ptr(display), atom); if (name == NULL) { @@ -1679,21 +1743,21 @@ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XMaxRequestSize(JNIEnv *env, jclass clazz, jlong display) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XMaxRequestSize((Display*) jlong_to_ptr(display)); } JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XAllocWMHints(JNIEnv *env, jclass clazz) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return ptr_to_jlong(XAllocWMHints()); } JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XCreatePixmap(JNIEnv *env, jclass clazz, jlong display, jlong drawable, jint width, jint height, jint depth) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XCreatePixmap((Display*)jlong_to_ptr(display), (Drawable)drawable, width, height, depth); } JNIEXPORT jlong JNICALL @@ -1702,7 +1766,7 @@ jint depth, jint format, jint offset, jlong data, jint width, jint height, jint bitmap_pad, jint bytes_per_line) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return ptr_to_jlong(XCreateImage((Display*) jlong_to_ptr(display), (Visual*) jlong_to_ptr(visual_ptr), depth, format, offset, (char*) jlong_to_ptr(data), width, height, bitmap_pad, bytes_per_line)); @@ -1712,7 +1776,7 @@ (JNIEnv *env, jclass clazz, jlong display, jlong drawable, jlong valuemask, jlong values) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return ptr_to_jlong(XCreateGC((Display*) jlong_to_ptr(display), (Drawable)drawable, valuemask, (XGCValues*) jlong_to_ptr(values))); } @@ -1762,7 +1826,7 @@ XIconSize** psize = (XIconSize**) jlong_to_ptr(ret_sizes); int * pcount = (int *) jlong_to_ptr(ret_count); Status res; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); res = XGetIconSizes((Display*) jlong_to_ptr(display), (Window)window, psize, pcount); return res; } @@ -1771,7 +1835,7 @@ (JNIEnv *env, jclass clazz, jlong display, jlong major_version_return, jlong minor_version_return) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XdbeQueryExtension((Display*) jlong_to_ptr(display), (int *) jlong_to_ptr(major_version_return), (int *) jlong_to_ptr(minor_version_return)); } @@ -1784,11 +1848,12 @@ Boolean bu; if (!JNU_IsNull(env, jstr)) { cname = (char *)JNU_GetStringPlatformChars(env, jstr, NULL); + CHECK_NULL_RETURN(cname, JNI_FALSE); } else { cname = ""; } - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); bu = XQueryExtension((Display*) jlong_to_ptr(display), cname, (int *) jlong_to_ptr(mop_return), (int *) jlong_to_ptr(feve_return), (int *) jlong_to_ptr(err_return)); if (!JNU_IsNull(env, jstr)) { @@ -1800,7 +1865,7 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_IsKeypadKey (JNIEnv *env, jclass clazz, jlong keysym) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); if(IsKeypadKey(keysym)) { return JNI_TRUE; } @@ -1810,7 +1875,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XdbeAllocateBackBufferName (JNIEnv *env, jclass clazz, jlong display, jlong window, jint swap_action) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XdbeAllocateBackBufferName((Display*) jlong_to_ptr(display), (Window) window, (XdbeSwapAction) swap_action); } @@ -1818,28 +1883,28 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XdbeDeallocateBackBufferName (JNIEnv *env, jclass clazz, jlong display, jlong buffer) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XdbeDeallocateBackBufferName((Display*) jlong_to_ptr(display), (XdbeBackBuffer) buffer); } JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XdbeBeginIdiom (JNIEnv *env, jclass clazz, jlong display) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XdbeBeginIdiom((Display*) jlong_to_ptr(display)); } JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XdbeEndIdiom (JNIEnv *env, jclass clazz, jlong display) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XdbeEndIdiom((Display*) jlong_to_ptr(display)); } JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XdbeSwapBuffers (JNIEnv *env, jclass clazz, jlong display, jlong swap_info, jint num_windows) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XdbeSwapBuffers((Display*) jlong_to_ptr(display), (XdbeSwapInfo *) jlong_to_ptr(swap_info), num_windows); } JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XQueryKeymap @@ -1854,7 +1919,7 @@ Java_sun_awt_X11_XlibWrapper_XKeycodeToKeysym(JNIEnv *env, jclass clazz, jlong display, jint keycode, jint index) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XKeycodeToKeysym((Display*) jlong_to_ptr(display), (unsigned int)keycode, (int)index); } @@ -1862,7 +1927,7 @@ Java_sun_awt_X11_XlibWrapper_XkbGetEffectiveGroup(JNIEnv *env, jclass clazz, jlong display) { XkbStateRec sr; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); memset(&sr, 0, sizeof(XkbStateRec)); XkbGetState((Display*) jlong_to_ptr(display), XkbUseCoreKbd, &sr); // printf("-------------------------------------VVVV\n"); @@ -1887,21 +1952,21 @@ Java_sun_awt_X11_XlibWrapper_XkbKeycodeToKeysym(JNIEnv *env, jclass clazz, jlong display, jint keycode, jint group, jint level) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XkbKeycodeToKeysym((Display*) jlong_to_ptr(display), (unsigned int)keycode, (unsigned int)group, (unsigned int)level); } JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XKeysymToKeycode(JNIEnv *env, jclass clazz, jlong display, jlong keysym) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return XKeysymToKeycode((Display*) jlong_to_ptr(display), (KeySym)keysym); } JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XGetModifierMapping(JNIEnv *env, jclass clazz, jlong display) { - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(0); return ptr_to_jlong(XGetModifierMapping((Display*) jlong_to_ptr(display))); } @@ -1958,7 +2023,7 @@ jlong display, jlong ptr) { uint32_t timeout = 1; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); exitSecondaryLoop = False; while (!exitSecondaryLoop) { if (XCheckIfEvent((Display*) jlong_to_ptr(display), (XEvent*) jlong_to_ptr(ptr), secondary_loop_event, NULL)) { @@ -1996,7 +2061,7 @@ static jclass stringClass = NULL; jclass stringClassLocal = NULL; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(NULL); if (JNU_IsNull(env, stringClass)) { stringClassLocal = (*env)->FindClass(env, "java/lang/String"); @@ -2148,7 +2213,7 @@ { jboolean status; - AWT_CHECK_HAVE_LOCK(); + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); status = XShapeQueryExtension((Display *)jlong_to_ptr(display), (int *)jlong_to_ptr(event_base_return), (int *)jlong_to_ptr(error_base_return)); diff -r a77941f17614 -r 0d1f816217dc jdk/src/solaris/native/sun/xawt/awt_Desktop.c --- a/jdk/src/solaris/native/sun/xawt/awt_Desktop.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/solaris/native/sun/xawt/awt_Desktop.c Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ * questions. */ +#include "jni_util.h" #include "gtk2_interface.h" #include "gnome_interface.h" @@ -65,6 +66,12 @@ const gchar* url_c; url_c = (char*)(*env)->GetByteArrayElements(env, url_j, NULL); + if (url_c == NULL) { + if (!(*env)->ExceptionCheck(env)) { + JNU_ThrowOutOfMemoryError(env, 0); + } + return JNI_FALSE; + } if (gtk_has_been_loaded) { fp_gdk_threads_enter(); diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java --- a/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java Wed Jul 05 19:39:35 2017 +0200 @@ -98,6 +98,7 @@ 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_ROOT = 144; public static final int ERROR_DIR_NOT_EMPTY = 145; public static final int ERROR_ALREADY_EXISTS = 183; public static final int ERROR_MORE_DATA = 234; diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java --- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java Wed Jul 05 19:39:35 2017 +0200 @@ -86,14 +86,28 @@ WindowsFileAttributes.get(file, true); target = file.getPathForWin32Calls(); } - String root = GetVolumePathName(target); - return new WindowsFileStore(root); + try { + return createFromPath(target); + } catch (WindowsException e) { + if (e.lastError() != ERROR_DIR_NOT_ROOT) + throw e; + target = WindowsLinkSupport.getFinalPath(file); + if (target == null) + throw new FileSystemException(file.getPathForExceptionMessage(), + null, "Couldn't resolve path"); + return createFromPath(target); + } } catch (WindowsException x) { x.rethrowAsIOException(file); return null; // keep compiler happy } } + private static WindowsFileStore createFromPath(String target) throws WindowsException { + String root = GetVolumePathName(target); + return new WindowsFileStore(root); + } + VolumeInformation volumeInformation() { return volInfo; } diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java --- a/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java Wed Jul 05 19:39:35 2017 +0200 @@ -66,7 +66,7 @@ * Returns the final path (all symbolic links resolved) or null if this * operation is not supported. */ - private static String getFinalPath(WindowsPath input) throws IOException { + static String getFinalPath(WindowsPath input) throws IOException { long h = 0; try { h = input.openForReadAttributeAccess(true); diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/java2d/d3d/D3DBadHardware.h --- a/jdk/src/windows/native/sun/java2d/d3d/D3DBadHardware.h Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/java2d/d3d/D3DBadHardware.h Wed Jul 05 19:39:35 2017 +0200 @@ -53,27 +53,18 @@ // Intel HD // Clarkdale (Desktop) GMA HD Lines - { 0x8086, 0x0042, D_VERSION(6,14,10,5394), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x0042, D_VERSION(8,15,10,2993), OS_VISTA | OS_WINDOWS7 }, + { 0x8086, 0x0042, NO_VERSION, OS_ALL }, // Arrandale (Mobile) GMA HD Lines - { 0x8086, 0x0046, D_VERSION(6,14,10,5394), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x0046, D_VERSION(8,15,10,2993), OS_VISTA | OS_WINDOWS7 }, + { 0x8086, 0x0046, NO_VERSION, OS_ALL }, // Sandy Bridge HD Graphics 3000/2000 - { 0x8086, 0x0102, D_VERSION(6,14,10,5437), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x0102, D_VERSION(9,17,10,3223), OS_VISTA | OS_WINDOWS7 }, - { 0x8086, 0x0106, D_VERSION(6,14,10,5437), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x0106, D_VERSION(9,17,10,3223), OS_VISTA | OS_WINDOWS7 }, - { 0x8086, 0x0112, D_VERSION(6,14,10,5437), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x0112, D_VERSION(9,17,10,3223), OS_VISTA | OS_WINDOWS7 }, - { 0x8086, 0x0116, D_VERSION(6,14,10,5437), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x0116, D_VERSION(9,17,10,3223), OS_VISTA | OS_WINDOWS7 }, - { 0x8086, 0x0122, D_VERSION(6,14,10,5437), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x0122, D_VERSION(9,17,10,3223), OS_VISTA | OS_WINDOWS7 }, - { 0x8086, 0x0126, D_VERSION(6,14,10,5437), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x0126, D_VERSION(9,17,10,3223), OS_VISTA | OS_WINDOWS7 }, - { 0x8086, 0x010A, D_VERSION(6,14,10,5437), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x010A, D_VERSION(9,17,10,3223), OS_VISTA | OS_WINDOWS7 }, + { 0x8086, 0x0102, NO_VERSION, OS_ALL }, + { 0x8086, 0x0106, NO_VERSION, OS_ALL }, + { 0x8086, 0x0112, NO_VERSION, OS_ALL }, + { 0x8086, 0x0116, NO_VERSION, OS_ALL }, + { 0x8086, 0x0122, NO_VERSION, OS_ALL }, + { 0x8086, 0x0126, NO_VERSION, OS_ALL }, + { 0x8086, 0x010A, NO_VERSION, OS_ALL }, // Ivy Bridge { 0x8086, 0x0162, D_VERSION(6,14,10,5437), OS_WINXP | OS_WINXP_64 }, @@ -170,33 +161,21 @@ { 0x8086, 0x2A13, NO_VERSION, OS_ALL }, // Eaglelake (Desktop) GMA 4500 Lines - { 0x8086, 0x2E42, D_VERSION(6,14,10,5420), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x2E42, D_VERSION(8,15,10,2869), OS_VISTA | OS_WINDOWS7 }, - { 0x8086, 0x2E43, D_VERSION(6,14,10,5420), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x2E43, D_VERSION(8,15,10,2869), OS_VISTA | OS_WINDOWS7 }, - { 0x8086, 0x2E92, D_VERSION(6,14,10,5420), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x2E92, D_VERSION(8,15,10,2869), OS_VISTA | OS_WINDOWS7 }, - { 0x8086, 0x2E93, D_VERSION(6,14,10,5420), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x2E93, D_VERSION(8,15,10,2869), OS_VISTA | OS_WINDOWS7 }, - { 0x8086, 0x2E12, D_VERSION(6,14,10,5420), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x2E12, D_VERSION(8,15,10,2869), OS_VISTA | OS_WINDOWS7 }, - { 0x8086, 0x2E13, D_VERSION(6,14,10,5420), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x2E13, D_VERSION(8,15,10,2869), OS_VISTA | OS_WINDOWS7 }, + { 0x8086, 0x2E42, NO_VERSION, OS_ALL }, + { 0x8086, 0x2E43, NO_VERSION, OS_ALL }, + { 0x8086, 0x2E92, NO_VERSION, OS_ALL }, + { 0x8086, 0x2E93, NO_VERSION, OS_ALL }, + { 0x8086, 0x2E12, NO_VERSION, OS_ALL }, + { 0x8086, 0x2E13, NO_VERSION, OS_ALL }, // Eaglelake (Desktop) GMA X4500 Lines - { 0x8086, 0x2E32, D_VERSION(6,14,10,5420), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x2E32, D_VERSION(8,15,10,2869), OS_VISTA | OS_WINDOWS7 }, - { 0x8086, 0x2E33, D_VERSION(6,14,10,5420), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x2E33, D_VERSION(8,15,10,2869), OS_VISTA | OS_WINDOWS7 }, - { 0x8086, 0x2E22, D_VERSION(6,14,10,5420), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x2E22, D_VERSION(8,15,10,2869), OS_VISTA | OS_WINDOWS7 }, + { 0x8086, 0x2E32, NO_VERSION, OS_ALL }, + { 0x8086, 0x2E33, NO_VERSION, OS_ALL }, + { 0x8086, 0x2E22, NO_VERSION, OS_ALL }, // Eaglelake (Desktop) GMA X4500HD Lines - { 0x8086, 0x2E23, D_VERSION(6,14,10,5420), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x2E23, D_VERSION(8,15,10,2869), OS_VISTA | OS_WINDOWS7 }, + { 0x8086, 0x2E23, NO_VERSION, OS_ALL }, // Cantiga (Mobile) GMA 4500MHD Lines - { 0x8086, 0x2A42, D_VERSION(6,14,10,5420), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x2A42, D_VERSION(8,15,10,2869), OS_VISTA | OS_WINDOWS7 }, - { 0x8086, 0x2A43, D_VERSION(6,14,10,5420), OS_WINXP | OS_WINXP_64 }, - { 0x8086, 0x2A43, D_VERSION(8,15,10,2869), OS_VISTA | OS_WINDOWS7 }, + { 0x8086, 0x2A42, NO_VERSION, OS_ALL }, + { 0x8086, 0x2A43, NO_VERSION, OS_ALL }, // ATI Mobility Radeon X1600, X1400, X1450, X1300, X1350 // Reason: workaround for 6613066, 6687166 diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/java2d/d3d/D3DSurfaceData.cpp --- a/jdk/src/windows/native/sun/java2d/d3d/D3DSurfaceData.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/java2d/d3d/D3DSurfaceData.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -33,9 +33,16 @@ #include "awt_BitmapUtil.h" #include "D3DRenderQueue.h" + // REMIND: move to awt_Component.h extern "C" HWND AwtComponent_GetHWnd(JNIEnv *env, jlong pData); +/* This looks weird. but since some AWT headers need to be included, + * we end up with AWT's alloc.h macro definition of ExceptionOccurred. + * The reasons for that re-defintion do not apply to this code, so undef it. + */ +#undef ExceptionOccurred + /** * Initializes nativeWidth/Height fields of the SurfaceData object with * dimensions on the native surface. @@ -55,7 +62,9 @@ } JNU_SetFieldByName(env, NULL, sdObject, "nativeWidth", "I", width); - JNU_SetFieldByName(env, NULL, sdObject, "nativeHeight", "I", height); + if (!(env->ExceptionOccurred())) { + JNU_SetFieldByName(env, NULL, sdObject, "nativeHeight", "I", height); + } env->DeleteLocalRef(sdObject); } diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.cpp --- a/jdk/src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -354,17 +354,26 @@ initThreadInfoIndex(); xorCompClass = (jclass)env->NewGlobalRef(XORComp); + if (env->ExceptionCheck()) { + return; + } tc = env->FindClass("java/lang/Thread"); DASSERT(tc != NULL); + CHECK_NULL(tc); + threadClass = (jclass)env->NewGlobalRef(tc); DASSERT(threadClass != NULL); + CHECK_NULL(threadClass); + currentThreadMethodID = env->GetStaticMethodID(threadClass, "currentThread", "()Ljava/lang/Thread;"); DASSERT(currentThreadMethodID != NULL); } +#undef ExceptionOccurred + /* * Class: sun_java2d_windows_GDIWindowSurfaceData * Method: initOps @@ -394,6 +403,9 @@ wsdo->invalid = JNI_FALSE; wsdo->lockType = WIN32SD_LOCK_UNLOCKED; wsdo->peer = env->NewWeakGlobalRef(peer); + if (env->ExceptionOccurred()) { + return; + } wsdo->depth = depth; wsdo->pixelMasks[0] = redMask; wsdo->pixelMasks[1] = greenMask; @@ -997,7 +1009,7 @@ ThreadGraphicsInfo *info = GetThreadGraphicsInfo(env, wsdo); GDIWinSD_InitDC(env, wsdo, info, type, patrop, clip, comp, color); - return info->hDC; + return env->ExceptionCheck() ? (HDC)NULL : info->hDC; } JNIEXPORT void JNICALL @@ -1056,8 +1068,14 @@ int topInset = wsdo->insets.top; Region_StartIteration(env, &clipInfo); jint numrects = Region_CountIterationRects(&clipInfo); - RGNDATA *lpRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(safe_Malloc, + RGNDATA *lpRgnData; + try { + lpRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(safe_Malloc, sizeof(RGNDATAHEADER), numrects, sizeof(RECT)); + } catch (std::bad_alloc&) { + JNU_ThrowOutOfMemoryError(env, "Initialization of surface region data failed."); + return; + } const DWORD nCount = sizeof(RGNDATAHEADER) + numrects * sizeof(RECT); lpRgnData->rdh.dwSize = sizeof(RGNDATAHEADER); lpRgnData->rdh.iType = RDH_RECTANGLES; @@ -1086,6 +1104,9 @@ env->DeleteWeakGlobalRef(info->clip); } info->clip = env->NewWeakGlobalRef(clip); + if (env->ExceptionCheck()) { + return; + } } // init composite diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c --- a/jdk/src/windows/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c Wed Jul 05 19:39:35 2017 +0200 @@ -235,7 +235,7 @@ (*env)->ReleaseStringChars(env, jlangtag, langtag); - return (*env)->NewString(env, pattern, wcslen(pattern)); + return (*env)->NewString(env, pattern, (jsize)wcslen(pattern)); } /* @@ -263,6 +263,7 @@ (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray ampms) { WCHAR buf[BUFLEN]; const jchar *langtag; + jstring tmp_string; // AM int got; @@ -270,13 +271,21 @@ CHECK_NULL_RETURN(langtag, NULL); got = getLocaleInfoWrapper(langtag, LOCALE_S1159, buf, BUFLEN); if (got) { - (*env)->SetObjectArrayElement(env, ampms, 0, (*env)->NewString(env, buf, wcslen(buf))); + tmp_string = (*env)->NewString(env, buf, (jsize)wcslen(buf)); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, ampms, 0, tmp_string); + } } - // PM - got = getLocaleInfoWrapper(langtag, LOCALE_S2359, buf, BUFLEN); - if (got) { - (*env)->SetObjectArrayElement(env, ampms, 1, (*env)->NewString(env, buf, wcslen(buf))); + if (!(*env)->ExceptionCheck(env)){ + // PM + got = getLocaleInfoWrapper(langtag, LOCALE_S2359, buf, BUFLEN); + if (got) { + tmp_string = (*env)->NewString(env, buf, (jsize)wcslen(buf)); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, ampms, 1, tmp_string); + } + } } (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -293,13 +302,17 @@ (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray eras) { WCHAR ad[BUFLEN]; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + jstring tmp_string; CHECK_NULL_RETURN(langtag, eras); getCalendarInfoWrapper(langtag, getCalendarID(langtag), NULL, CAL_SERASTRING, ad, BUFLEN, NULL); // Windows does not provide B.C. era. - (*env)->SetObjectArrayElement(env, eras, 1, (*env)->NewString(env, ad, wcslen(ad))); + tmp_string = (*env)->NewString(env, ad, (jsize)wcslen(ad)); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, eras, 1, tmp_string); + } (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -371,7 +384,7 @@ CHECK_NULL_RETURN(pattern, NULL); (*env)->ReleaseStringChars(env, jlangtag, langtag); - ret = (*env)->NewString(env, pattern, wcslen(pattern)); + ret = (*env)->NewString(env, pattern, (jsize)wcslen(pattern)); free(pattern); return ret; @@ -411,7 +424,7 @@ (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { - return (*env)->NewString(env, buf, wcslen(buf)); + return (*env)->NewString(env, buf, (jsize)wcslen(buf)); } else { return currencySymbol; } @@ -474,7 +487,7 @@ (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { - return (*env)->NewString(env, buf, wcslen(buf)); + return (*env)->NewString(env, buf, (jsize)wcslen(buf)); } else { return infinity; } @@ -495,7 +508,7 @@ (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { - return (*env)->NewString(env, buf, wcslen(buf)); + return (*env)->NewString(env, buf, (jsize)wcslen(buf)); } else { return internationalCurrencySymbol; } @@ -558,7 +571,7 @@ (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { - return (*env)->NewString(env, buf, wcslen(buf)); + return (*env)->NewString(env, buf, (jsize)wcslen(buf)); } else { return nan; } @@ -701,7 +714,7 @@ (*env)->ReleaseStringChars(env, jStr, pjChar); if (got) { - return (*env)->NewString(env, buf, wcslen(buf)); + return (*env)->NewString(env, buf, (jsize)wcslen(buf)); } else { return NULL; } @@ -754,9 +767,10 @@ void replaceCalendarArrayElems(JNIEnv *env, jstring jlangtag, jobjectArray jarray, CALTYPE* pCalTypes, int offset, int length) { WCHAR name[BUFLEN]; - const jchar *langtag; + const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); int calid; - langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + jstring tmp_string; + CHECK_NULL(langtag); calid = getCalendarID(langtag); @@ -765,8 +779,10 @@ for (i = 0; i < length; i++) { getCalendarInfoWrapper(langtag, calid, NULL, pCalTypes[i], name, BUFLEN, NULL); - (*env)->SetObjectArrayElement(env, jarray, i + offset, - (*env)->NewString(env, name, wcslen(name))); + tmp_string = (*env)->NewString(env, name, (jsize)wcslen(name)); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, jarray, i + offset, tmp_string); + } } } diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/windows/ThemeReader.cpp --- a/jdk/src/windows/native/sun/windows/ThemeReader.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/windows/ThemeReader.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -233,7 +233,7 @@ Themed = InitThemes(); TryLoadingThemeLib = TRUE; } - return Themed; + return JNI_IS_TRUE(Themed); } @@ -271,6 +271,10 @@ (JNIEnv *env, jclass klass, jstring widget) { LPCTSTR str = (LPCTSTR) JNU_GetStringPlatformChars(env, widget, NULL); + if (str == NULL) { + JNU_ThrowOutOfMemoryError(env, 0); + return 0; + } // We need to open the Theme on a Window that will stick around. // The best one for that purpose is the Toolkit window. HTHEME htheme = OpenThemeData(AwtToolkit::GetInstance().GetHWnd(), str); @@ -485,6 +489,7 @@ if (insetsClassID == NULL) { jclass insetsClassIDLocal = env->FindClass("java/awt/Insets"); + CHECK_NULL_RETURN(insetsClassIDLocal, NULL); insetsClassID = (jclass)env->NewGlobalRef(insetsClassIDLocal); env->DeleteLocalRef(insetsClassIDLocal); } @@ -533,7 +538,7 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_windows_ThemeReader_isThemePartDefined (JNIEnv *env, jclass klass, jlong theme, jint part, jint state) { HTHEME hTheme = (HTHEME) theme; - return IsThemePartDefined(hTheme, part, state); + return JNI_IS_TRUE(IsThemePartDefined(hTheme, part, state)); } /* @@ -562,12 +567,14 @@ if (colorClassID == NULL) { jclass colorClassIDLocal = env->FindClass("java/awt/Color"); + CHECK_NULL_RETURN(colorClassIDLocal, NULL); colorClassID = (jclass)env->NewGlobalRef(colorClassIDLocal); env->DeleteLocalRef(colorClassIDLocal); } if (colorMID == NULL) { colorMID = env->GetMethodID(colorClassID, "", "(III)V"); + CHECK_NULL_RETURN(colorMID, NULL); } jobject colorObj = env->NewObject(colorClassID, colorMID, GetRValue(color), GetGValue(color),GetBValue(color)); @@ -628,7 +635,7 @@ HRESULT hres = GetThemeBool(hTheme, part, state, prop, &retVal); assert_result(hres, env); } - return retVal; + return JNI_IS_TRUE(retVal); } /* @@ -640,15 +647,11 @@ (JNIEnv *env, jclass klass, jlong theme, jint prop) { HTHEME hTheme = (HTHEME)theme; if (hTheme != NULL) { - return GetThemeSysBool(hTheme, prop); + return JNI_IS_TRUE(GetThemeSysBool(hTheme, prop)); } - return FALSE; + return JNI_FALSE; } - - - - /* * Class: sun_awt_windows_ThemeReader * Method: getPoint @@ -673,12 +676,14 @@ if (pointClassID == NULL) { jclass pointClassIDLocal = env->FindClass("java/awt/Point"); + CHECK_NULL_RETURN(pointClassIDLocal, NULL); pointClassID = (jclass)env->NewGlobalRef(pointClassIDLocal); env->DeleteLocalRef(pointClassIDLocal); } if (pointMID == NULL) { pointMID = env->GetMethodID(pointClassID, "", "(II)V"); + CHECK_NULL_RETURN(pointMID, NULL); } jobject pointObj = env->NewObject(pointClassID, pointMID, point.x, point.y); @@ -720,11 +725,13 @@ static jclass dimClassID = NULL; if (dimClassID == NULL) { jclass dimClassIDLocal = env->FindClass("java/awt/Dimension"); + CHECK_NULL_RETURN(dimClassIDLocal, NULL); dimClassID = (jclass)env->NewGlobalRef(dimClassIDLocal); env->DeleteLocalRef(dimClassIDLocal); } if (dimMID == NULL) { dimMID = env->GetMethodID(dimClassID, "", "(II)V"); + CHECK_NULL_RETURN(dimMID, NULL); } jobject dimObj = env->NewObject(dimClassID, dimMID, point.x, point.y); @@ -755,11 +762,13 @@ static jclass dimClassID = NULL; if (dimClassID == NULL) { jclass dimClassIDLocal = env->FindClass("java/awt/Dimension"); + CHECK_NULL_RETURN(dimClassIDLocal, NULL); dimClassID = (jclass)env->NewGlobalRef(dimClassIDLocal); env->DeleteLocalRef(dimClassIDLocal); } if (dimMID == NULL) { dimMID = env->GetMethodID(dimClassID, "", "(II)V"); + CHECK_NULL_RETURN(dimMID, NULL); } jobject dimObj = env->NewObject(dimClassID, dimMID, size.cx, size.cy); if (safe_ExceptionOccurred(env)) { diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/windows/WPrinterJob.cpp --- a/jdk/src/windows/native/sun/windows/WPrinterJob.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/windows/WPrinterJob.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -130,6 +130,9 @@ jstring utf_str; jclass clazz = env->FindClass("java/lang/String"); + if (clazz == NULL) { + return NULL; + } jobjectArray nameArray; try { @@ -240,6 +243,9 @@ LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); + if (printerName == NULL) { + return NULL; + } jfloatArray printableArray = NULL; @@ -262,7 +268,7 @@ if (pDevMode != NULL) { ::GlobalFree(pDevMode); } - + DeleteDC(pdc); ::ClosePrinter(hPrinter); JNU_ReleaseStringPlatformChars(env, printer, printerName); return printableArray; @@ -283,25 +289,21 @@ int resy = GetDeviceCaps(pdc, LOGPIXELSY); printableArray=env->NewFloatArray(4); - if (printableArray == NULL) { - throw std::bad_alloc(); + if (printableArray != NULL) { + jfloat *iPrintables = + env->GetFloatArrayElements(printableArray, NULL); + if (iPrintables != NULL) { + iPrintables[0] = (float)left/resx; + iPrintables[1] = (float)top/resy; + iPrintables[2] = (float)width/resx; + iPrintables[3] = (float)height/resy; + env->ReleaseFloatArrayElements(printableArray, iPrintables, 0); + } } - jboolean isCopy; - jfloat *iPrintables = env->GetFloatArrayElements(printableArray, - &isCopy), - *savePrintables = iPrintables; - - iPrintables[0] = (float)left/resx; - iPrintables[1] = (float)top/resy; - iPrintables[2] = (float)width/resx; - iPrintables[3] = (float)height/resy; - - env->ReleaseFloatArrayElements(printableArray, savePrintables, 0); - GlobalFree(pDevMode); + DeleteDC(pdc); } - DeleteDC(pdc); JNU_ReleaseStringPlatformChars(env, printer, printerName); return printableArray; @@ -309,6 +311,60 @@ CATCH_BAD_ALLOC_RET(NULL); } +jintArray getIDs(JNIEnv *env, jstring printer, jstring port, int dm_id) +{ + + LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); + LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); + + if (printerName == NULL || printerPort == NULL) { + if (printerName != NULL) { + JNU_ReleaseStringPlatformChars(env, printer, printerName); + } + if (printerPort != NULL) { + JNU_ReleaseStringPlatformChars(env, port, printerPort); + } + return NULL; + } + + SAVE_CONTROLWORD + int numIDs = ::DeviceCapabilities(printerName, printerPort, dm_id, + NULL, NULL); + RESTORE_CONTROLWORD + + jintArray idArray = NULL; + if (numIDs > 0) { + idArray = env->NewIntArray(numIDs); + if (idArray != NULL) { + jint *jpcIndices = env->GetIntArrayElements(idArray, NULL); + if (jpcIndices != NULL) { + jint *saveFormats = jpcIndices; + LPTSTR buf = NULL; + try { + buf = (LPTSTR)new char[numIDs * sizeof(WORD)]; + } catch (std::bad_alloc&) { + buf = NULL; + } + if (buf != NULL) { + if (::DeviceCapabilities(printerName, printerPort, + dm_id, buf, NULL) != -1) { + WORD *id = (WORD *)buf; + for (int i = 0; i < numIDs; i++, id++) { + jpcIndices[i] = *id; + } + } + RESTORE_CONTROLWORD + delete[] buf; + } + env->ReleaseIntArrayElements(idArray, saveFormats, 0); + } + } + } + + JNU_ReleaseStringPlatformChars(env, printer, printerName); + JNU_ReleaseStringPlatformChars(env, port, printerPort); + return idArray; +} JNIEXPORT jintArray JNICALL Java_sun_print_Win32PrintService_getAllMediaIDs(JNIEnv *env, @@ -316,45 +372,7 @@ jstring printer, jstring port) { - TRY; - - LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); - LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); - jintArray mediasizeArray = NULL; - - SAVE_CONTROLWORD - int numSizes = ::DeviceCapabilities(printerName, printerPort, - DC_PAPERS, NULL, NULL); - RESTORE_CONTROLWORD - - if (numSizes > 0) { - - mediasizeArray = env->NewIntArray(numSizes); - if (mediasizeArray == NULL) { - throw std::bad_alloc(); - } - - jboolean isCopy; - jint *jpcIndices = env->GetIntArrayElements(mediasizeArray, - &isCopy), *saveFormats = jpcIndices; - LPTSTR papersBuf = (LPTSTR)new char[numSizes * sizeof(WORD)]; - if (::DeviceCapabilities(printerName, printerPort, - DC_PAPERS, papersBuf, NULL) != -1) { - RESTORE_CONTROLWORD - WORD *pDmPaperSize = (WORD *)papersBuf; - for (int i = 0; i < numSizes; i++, pDmPaperSize++) { - jpcIndices[i] = *pDmPaperSize; - } - } - delete[] papersBuf; - env->ReleaseIntArrayElements(mediasizeArray, saveFormats, 0); - } - - JNU_ReleaseStringPlatformChars(env, printer, printerName); - JNU_ReleaseStringPlatformChars(env, port, printerPort); - return mediasizeArray; - - CATCH_BAD_ALLOC_RET(NULL); + return getIDs(env, printer, port, DC_PAPERS); } @@ -364,47 +382,7 @@ jstring printer, jstring port) { - TRY; - - LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, - printer, NULL); - LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); - - jintArray mediaTrayArray = NULL; - - SAVE_CONTROLWORD - int nBins = ::DeviceCapabilities(printerName, printerPort, - DC_BINS, NULL, NULL) ; - RESTORE_CONTROLWORD - if (nBins > 0) { - mediaTrayArray = env->NewIntArray(nBins); - if (mediaTrayArray == NULL) { - throw std::bad_alloc(); - } - - jboolean isCopy; - jint *jpcIndices = env->GetIntArrayElements(mediaTrayArray, - &isCopy), *saveFormats = jpcIndices; - - LPTSTR buf = (LPTSTR)new char[nBins * sizeof(WORD)]; - - if (::DeviceCapabilities(printerName, printerPort, - DC_BINS, buf, NULL) != -1) { - RESTORE_CONTROLWORD - WORD *pBins = (WORD *)buf; - for (int i = 0; i < nBins; i++) { - jpcIndices[i] = *(pBins+i); - } - } - delete[] buf; - env->ReleaseIntArrayElements(mediaTrayArray, saveFormats, 0); - } - - JNU_ReleaseStringPlatformChars(env, printer, printerName); - JNU_ReleaseStringPlatformChars(env, port, printerPort); - return mediaTrayArray; - - CATCH_BAD_ALLOC_RET(NULL); + return getIDs(env, printer, port, DC_BINS); } @@ -414,100 +392,139 @@ jstring printer, jstring port) { - TRY; - - LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, - printer, NULL); + LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); - jintArray mediaArray = NULL; + if (printerName == NULL || printerPort == NULL) { + if (printerName != NULL) { + JNU_ReleaseStringPlatformChars(env, printer, printerName); + } + if (printerPort != NULL) { + JNU_ReleaseStringPlatformChars(env, port, printerPort); + } + return NULL; + } SAVE_CONTROLWORD - int nPapers = ::DeviceCapabilities(printerName, printerPort, - DC_PAPERSIZE, NULL, NULL) ; + int nPapers = ::DeviceCapabilities(printerName, printerPort, DC_PAPERSIZE, + NULL, NULL) ; RESTORE_CONTROLWORD - if (nPapers > 0) { - mediaArray = env->NewIntArray(nPapers*2); - if (mediaArray == NULL) { - throw std::bad_alloc(); - } - jboolean isCopy; - jint *jpcIndices = env->GetIntArrayElements(mediaArray, - &isCopy), *saveFormats = jpcIndices; + jintArray mediaArray = NULL; + jint *saveFormats = NULL; - LPTSTR buf = (LPTSTR)new char[nPapers * sizeof(POINT)]; // array of POINTs - - if (::DeviceCapabilities(printerName, printerPort, - DC_PAPERSIZE, buf, NULL) != -1) { - - POINT *pDim = (POINT *)buf; - for (int i = 0; i < nPapers; i++) { - jpcIndices[i*2] = (pDim+i)->x; - jpcIndices[i*2+1] = (pDim+i)->y; + if (nPapers > 0) { + mediaArray = env->NewIntArray(nPapers*2); + if (mediaArray != NULL) { + jint *jpcIndices = env->GetIntArrayElements(mediaArray, NULL); + if (jpcIndices != NULL) { + saveFormats = jpcIndices; + LPTSTR buf = NULL; + try { + buf = (LPTSTR)new char[nPapers * sizeof(POINT)]; + } catch (std::bad_alloc&) { + buf = NULL; + } + if (buf != NULL) { + if (::DeviceCapabilities(printerName, printerPort, + DC_PAPERSIZE, buf, NULL) != -1) { + POINT *pDim = (POINT *)buf; + for (int i = 0; i < nPapers; i++) { + jpcIndices[i*2] = (pDim+i)->x; + jpcIndices[i*2+1] = (pDim+i)->y; + } + } + RESTORE_CONTROLWORD + delete[] buf; + } + env->ReleaseIntArrayElements(mediaArray, saveFormats, 0); + saveFormats = NULL; + } } - } - RESTORE_CONTROLWORD - delete[] buf; - env->ReleaseIntArrayElements(mediaArray, saveFormats, 0); } JNU_ReleaseStringPlatformChars(env, printer, printerName); JNU_ReleaseStringPlatformChars(env, port, printerPort); + if (mediaArray != NULL && saveFormats != NULL) { + env->ReleaseIntArrayElements(mediaArray, saveFormats, 0); + } return mediaArray; - CATCH_BAD_ALLOC_RET(NULL); } jobjectArray getAllDCNames(JNIEnv *env, jobject peer, jstring printer, jstring port, unsigned int dc_id, unsigned int buf_len) { - TRY; - LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, - printer, NULL); + LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); + if (printerName == NULL || printerPort == NULL) { + if (printerName != NULL) { + JNU_ReleaseStringPlatformChars(env, printer, printerName); + } + if (printerPort != NULL) { + JNU_ReleaseStringPlatformChars(env, port, printerPort); + } + return NULL; + } + jstring utf_str; - jclass cls = env->FindClass("java/lang/String"); - jobjectArray names= NULL; + jobjectArray names = NULL; LPTSTR buf = NULL; SAVE_CONTROLWORD int cReturned = ::DeviceCapabilities(printerName, printerPort, dc_id, NULL, NULL); RESTORE_CONTROLWORD - if (cReturned > 0) { - - buf = (LPTSTR)new char[cReturned * buf_len * sizeof(TCHAR)]; - if (buf == NULL) { - throw std::bad_alloc(); - } + if (cReturned <= 0) { + JNU_ReleaseStringPlatformChars(env, printer, printerName); + JNU_ReleaseStringPlatformChars(env, port, printerPort); + return NULL; + } - cReturned = ::DeviceCapabilities(printerName, printerPort, - dc_id, buf, NULL); - RESTORE_CONTROLWORD + try { + buf = (LPTSTR)new char[cReturned * buf_len * sizeof(TCHAR)]; + } catch (std::bad_alloc&) { + buf = NULL; + } + if (buf == NULL) { + JNU_ReleaseStringPlatformChars(env, printer, printerName); + JNU_ReleaseStringPlatformChars(env, port, printerPort); + JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); + return NULL; + } - if (cReturned > 0) { - names = env->NewObjectArray(cReturned, cls, NULL); - if (names == NULL) { - throw std::bad_alloc(); + cReturned = ::DeviceCapabilities(printerName, printerPort, + dc_id, buf, NULL); + RESTORE_CONTROLWORD + + JNU_ReleaseStringPlatformChars(env, printer, printerName); + JNU_ReleaseStringPlatformChars(env, port, printerPort); + + if (cReturned > 0) { + jclass cls = env->FindClass("java/lang/String"); + if (cls != NULL) { + names = env->NewObjectArray(cReturned, cls, NULL); + } + if (names == NULL || cls == NULL) { + delete buf; + return names; } for (int i = 0; i < cReturned; i++) { - utf_str = JNU_NewStringPlatform(env, buf+(buf_len*i)); - if (utf_str == NULL) { - throw std::bad_alloc(); + utf_str = JNU_NewStringPlatform(env, buf+(buf_len*i)); + if (utf_str == NULL) { + delete buf; + return names; + } + env->SetObjectArrayElement(names, i, utf_str); + env->DeleteLocalRef(utf_str); } - env->SetObjectArrayElement(names, i, utf_str); - env->DeleteLocalRef(utf_str); - } } delete[] buf; - } - return names; + return names; - CATCH_BAD_ALLOC_RET(NULL); } @@ -540,6 +557,16 @@ LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); + if (printerName == NULL || printerPort == NULL) { + if (printerName != NULL) { + JNU_ReleaseStringPlatformChars(env, printer, printerName); + } + if (printerPort != NULL) { + JNU_ReleaseStringPlatformChars(env, port, printerPort); + } + return 1; + } + SAVE_CONTROLWORD int numCopies = ::DeviceCapabilities(printerName, printerPort, DC_COPIES, NULL, NULL); @@ -573,48 +600,58 @@ jstring printer, jstring port) { - TRY; - LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); - jintArray resolutionArray = NULL; + if (printerName == NULL || printerPort == NULL) { + if (printerName != NULL) { + JNU_ReleaseStringPlatformChars(env, printer, printerName); + } + if (printerPort != NULL) { + JNU_ReleaseStringPlatformChars(env, port, printerPort); + } + return NULL; + } SAVE_CONTROLWORD int nResolutions = ::DeviceCapabilities(printerName, printerPort, DC_ENUMRESOLUTIONS, NULL, NULL); RESTORE_CONTROLWORD + + jintArray resolutionArray = NULL; if (nResolutions > 0) { resolutionArray = env->NewIntArray(nResolutions*2); - if (resolutionArray == NULL) { - throw std::bad_alloc(); + if (resolutionArray != NULL) { + jint *jpcIndices = env->GetIntArrayElements(resolutionArray, NULL); + if (jpcIndices != NULL) { + jint *saveFormats = jpcIndices; + LPTSTR resBuf = NULL; + try { + resBuf = (LPTSTR)new char[nResolutions * sizeof(LONG) * 2]; + } catch (std::bad_alloc&) { + resBuf = NULL; + } + if (resBuf != NULL) { + if (::DeviceCapabilities(printerName, printerPort, + DC_ENUMRESOLUTIONS, resBuf, + NULL) != -1) { + LONG *pResolution = (LONG *)resBuf; + for (int i = 0; i < nResolutions; i++) { + jpcIndices[i*2] = *pResolution++; + jpcIndices[i*2+1] = *pResolution++; + } + } + RESTORE_CONTROLWORD + delete[] resBuf; + } + env->ReleaseIntArrayElements(resolutionArray, saveFormats, 0); + } } - - jboolean isCopy; - jint *jpcIndices = env->GetIntArrayElements(resolutionArray, - &isCopy), *saveFormats = jpcIndices; - - LPTSTR resBuf = (LPTSTR)new char[nResolutions * sizeof(LONG) * 2]; // pairs of long - - if (::DeviceCapabilities(printerName, printerPort, - DC_ENUMRESOLUTIONS, resBuf, NULL) != -1) { - - LONG *pResolution = (LONG *)resBuf; - for (int i = 0; i < nResolutions; i++) { - jpcIndices[i*2] = *pResolution++; - jpcIndices[i*2+1] = *pResolution++; - } - } - RESTORE_CONTROLWORD - delete[] resBuf; - env->ReleaseIntArrayElements(resolutionArray, saveFormats, 0); } JNU_ReleaseStringPlatformChars(env, printer, printerName); JNU_ReleaseStringPlatformChars(env, printer, printerPort); return resolutionArray; - - CATCH_BAD_ALLOC_RET(NULL); } @@ -672,6 +709,7 @@ } catch (std::bad_alloc&) { delete [] buffer; JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); + return NULL; } if (printerPort == NULL) { @@ -692,6 +730,17 @@ { LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); + + if (printerName == NULL || printerPort == NULL) { + if (printerName != NULL) { + JNU_ReleaseStringPlatformChars(env, printer, printerName); + } + if (printerPort != NULL) { + JNU_ReleaseStringPlatformChars(env, port, printerPort); + } + return NULL; + } + // 0x1000 is a flag to indicate that getCapabilities has already been called. // 0x0001 is a flag for color support and supported is the default. jint ret = 0x1001; @@ -761,28 +810,41 @@ HANDLE hPrinter; LPDEVMODE pDevMode = NULL; - TRY; - LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); - jintArray defaultArray = env->NewIntArray(NDEFAULT); - if (defaultArray == NULL) { - throw std::bad_alloc(); + if (printerName == NULL || printerPort == NULL) { + if (printerName != NULL) { + JNU_ReleaseStringPlatformChars(env, printer, printerName); + } + if (printerPort != NULL) { + JNU_ReleaseStringPlatformChars(env, port, printerPort); + } + return NULL; } - jboolean isCopy; - jint *defIndices = env->GetIntArrayElements(defaultArray, - &isCopy), *saveFormats = defIndices; + jint* defIndices = NULL; + jintArray defaultArray = env->NewIntArray(NDEFAULT); + if (defaultArray != NULL) { + defIndices = env->GetIntArrayElements(defaultArray, NULL); + } + if (defIndices == NULL) { + JNU_ReleaseStringPlatformChars(env, printer, printerName); + JNU_ReleaseStringPlatformChars(env, port, printerPort); + return NULL; + } - for (int i=0; iReleaseIntArrayElements(defaultArray, saveFormats, 0); JNU_ReleaseStringPlatformChars(env, printer, printerName); + JNU_ReleaseStringPlatformChars(env, port, printerPort); return defaultArray; } @@ -794,6 +856,7 @@ ::ClosePrinter(hPrinter); env->ReleaseIntArrayElements(defaultArray, saveFormats, 0); JNU_ReleaseStringPlatformChars(env, printer, printerName); + JNU_ReleaseStringPlatformChars(env, port, printerPort); return defaultArray; } @@ -863,7 +926,6 @@ defIndices[8] = pDevMode->dmColor; } - GlobalFree(pDevMode); ::ClosePrinter(hPrinter); @@ -873,8 +935,6 @@ JNU_ReleaseStringPlatformChars(env, port, printerPort); return defaultArray; - - CATCH_BAD_ALLOC_RET(NULL); } @@ -891,6 +951,9 @@ int ret=0; LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); + if (printerName == NULL) { + return -1; + } // Start by opening the printer if (!::OpenPrinter(printerName, &hPrinter, NULL)) { @@ -959,13 +1022,15 @@ jclass myClass = env->GetObjectClass(self); jfieldID fieldId = env->GetFieldID(myClass, fieldName, "J"); DASSERT(fieldId != 0); - return fieldId; } static inline HANDLE getHPrinter(JNIEnv *env, jobject self) { jfieldID fieldId = getIdOfLongField(env, self, HPRINTER_STR); + if (fieldId == (jfieldID)0) { + return (HANDLE)NULL; + } return (HANDLE)(env->GetLongField(self, fieldId)); } @@ -979,6 +1044,9 @@ HANDLE hPrinter; DOC_INFO_1 DocInfo; LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); + if (printerName == NULL) { + return false; + } DASSERT(jobname != NULL); LPTSTR lpJobName = (LPTSTR)JNU_GetStringPlatformChars(env, jobname, NULL); LPTSTR jname = _tcsdup(lpJobName); @@ -1016,8 +1084,12 @@ // store handle jfieldID fieldId = getIdOfLongField(env, peer, HPRINTER_STR); - env->SetLongField(peer, fieldId, reinterpret_cast(hPrinter)); - return true; + if (fieldId == (jfieldID)0) { + return false; + } else { + env->SetLongField(peer, fieldId, reinterpret_cast(hPrinter)); + return true; + } } @@ -1039,6 +1111,9 @@ try { data=(jbyte *)env->GetPrimitiveArrayCritical(dataArray, 0); + if (data == NULL) { + return false; + } // Send the data to the printer. if( ! ::WritePrinter(hPrinter, data, count,(LPDWORD)&dwBytesWritten)) { diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/windows/awt.h --- a/jdk/src/windows/native/sun/windows/awt.h Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/windows/awt.h Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,8 @@ class AwtObject; typedef AwtObject* PDATA; +#define JNI_IS_TRUE(obj) ((obj) ? JNI_TRUE : JNI_FALSE) + #define JNI_CHECK_NULL_GOTO(obj, msg, where) { \ if (obj == NULL) { \ env->ExceptionClear(); \ diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/windows/awt_Choice.cpp --- a/jdk/src/windows/native/sun/windows/awt_Choice.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/windows/awt_Choice.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -157,6 +157,7 @@ "preferredSize", "()Ljava/awt/Dimension;").l; DASSERT(!safe_ExceptionOccurred(env)); + if (env->ExceptionCheck()) goto done; if (dimension != NULL && width == 0) { width = env->GetIntField(dimension, AwtDimension::widthID); @@ -337,9 +338,8 @@ "preferredSize", "()Ljava/awt/Dimension;").l; DASSERT(!safe_ExceptionOccurred(env)); - if (dimension == NULL) { - return NULL; - } + CHECK_NULL_RETURN(dimension, NULL); + /* This size is window size of choice and it's too big for each * drop down item height. */ @@ -605,7 +605,8 @@ for (i = 0; i < itemCount; i++) { jstring item = (jstring)env->GetObjectArrayElement(items, i); - JNI_CHECK_NULL_GOTO(item, "null item", next_elem); + if (env->ExceptionCheck()) goto done; + if (item == NULL) goto next_elem; c->SendMessage(CB_INSERTSTRING, index + i, JavaStringBuffer(env, item)); env->DeleteLocalRef(item); next_elem: diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/windows/awt_Component.cpp --- a/jdk/src/windows/native/sun/windows/awt_Component.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -1729,9 +1729,11 @@ case WM_IME_SETCONTEXT: // lParam is passed as pointer and it can be modified. mr = WmImeSetContext(static_cast(wParam), &lParam); + CallProxyDefWindowProc(message, wParam, lParam, retValue, mr); break; case WM_IME_NOTIFY: mr = WmImeNotify(wParam, lParam); + CallProxyDefWindowProc(message, wParam, lParam, retValue, mr); break; case WM_IME_STARTCOMPOSITION: mr = WmImeStartComposition(); @@ -4085,7 +4087,7 @@ { if (mr != mrConsume) { HWND proxy = GetProxyFocusOwner(); - if (proxy != NULL) { + if (proxy != NULL && ::IsWindowEnabled(proxy)) { retVal = ComCtl32Util::GetInstance().DefWindowProc(NULL, proxy, message, wParam, lParam); mr = mrConsume; } @@ -6112,7 +6114,7 @@ c = (AwtComponent *)pData; if (::IsWindow(c->GetHWnd())) { - result = (jboolean)c->InheritsNativeMouseWheelBehavior(); + result = JNI_IS_TRUE(c->InheritsNativeMouseWheelBehavior()); } ret: env->DeleteGlobalRef(self); @@ -6928,9 +6930,9 @@ { TRY; - return (jboolean)AwtToolkit::GetInstance().SyncCall( + return JNI_IS_TRUE(AwtToolkit::GetInstance().SyncCall( (void *(*)(void *))AwtComponent::_NativeHandlesWheelScrolling, - env->NewGlobalRef(self)); + env->NewGlobalRef(self))); // global ref is deleted in _NativeHandlesWheelScrolling CATCH_BAD_ALLOC_RET(NULL); @@ -6949,9 +6951,9 @@ jobject selfGlobalRef = env->NewGlobalRef(self); - return (jboolean)AwtToolkit::GetInstance().SyncCall( + return JNI_IS_TRUE(AwtToolkit::GetInstance().SyncCall( (void*(*)(void*))AwtComponent::_IsObscured, - (void *)selfGlobalRef); + (void *)selfGlobalRef)); // selfGlobalRef is deleted in _IsObscured CATCH_BAD_ALLOC_RET(NULL); diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/windows/awt_Font.cpp --- a/jdk/src/windows/native/sun/windows/awt_Font.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/windows/awt_Font.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -49,9 +49,12 @@ if (obj == NULL) { return JNI_FALSE; } - if (env->EnsureLocalCapacity(2)) + if (env->EnsureLocalCapacity(2)) { + env->ExceptionClear(); return JNI_FALSE; + } jobject peer = env->CallObjectMethod(obj, AwtFont::peerMID); + env->ExceptionClear(); if (peer == NULL) { return JNI_FALSE; } @@ -66,10 +69,12 @@ { DASSERT(font != NULL); if (env->EnsureLocalCapacity(2)) { + env->ExceptionClear(); return NULL; } jobject peer = env->CallObjectMethod(font, AwtFont::peerMID); DASSERT(peer != NULL); + if (peer == NULL) return NULL; jstring textComponentFontName = (jstring) env->GetObjectField(peer, AwtFont::textComponentFontNameID); env->DeleteLocalRef(peer); @@ -191,6 +196,9 @@ } awtFont = Create(env, font, angle, awScale); + if (awtFont == NULL) { + return NULL; + } env->SetLongField(font, AwtFont::pDataID, reinterpret_cast(awtFont)); @@ -272,6 +280,9 @@ if (cfnum > 0) { // Ask peer class for the text component font name jstring jTextComponentFontName = GetTextComponentFontName(env, font); + if (jTextComponentFontName == NULL) { + return NULL; + } LPCWSTR textComponentFontName = JNU_GetStringPlatformChars(env, jTextComponentFontName, NULL); awtFont->m_textInput = -1; @@ -285,6 +296,9 @@ AwtFont::nativeNameID); wName = JNU_GetStringPlatformChars(env, nativeName, NULL); DASSERT(wName); + if (wName == NULL) { + wName = L"Arial"; + } //On NT platforms, if the font is not Symbol or Dingbats //use "W" version of Win32 APIs directly, info the FontDescription @@ -321,7 +335,12 @@ // Instantiation for English version. jstring fontName = (jstring)env->GetObjectField(font, AwtFont::nameID); - wName = JNU_GetStringPlatformChars(env, fontName, NULL); + if (fontName != NULL) { + wName = JNU_GetStringPlatformChars(env, fontName, NULL); + } + if (wName == NULL) { + wName = L"Arial"; + } WCHAR* wEName; if (!wcscmp(wName, L"Helvetica") || !wcscmp(wName, L"SansSerif")) { @@ -647,6 +666,9 @@ //"useUnicode" field might not be initialized correctly (font in Menu Component, //for example"). AwtFont* awtFont = AwtFont::GetFont(env, font); + if (awtFont == NULL) { + return size; + } if (IsMultiFont(env, font)) { jobject peer = env->CallObjectMethod(font, AwtFont::peerMID); @@ -668,6 +690,9 @@ if (arrayLength == 0) { int length = env->GetStringLength(str); LPCWSTR strW = JNU_GetStringPlatformChars(env, str, NULL); + if (strW == NULL) { + return size; + } VERIFY(::SelectObject(hDC, awtFont->GetHFont())); if (AwtComponent::GetRTLReadingOrder()){ VERIFY(!draw || ::ExtTextOut(hDC, x, y, ETO_RTLREADING, NULL, @@ -692,6 +717,9 @@ } int fdIndex = getFontDescriptorNumber(env, font, fontDescriptor); + if (env->ExceptionCheck()) { + return size; //fdIndex==0 return could be exception or not. + } VERIFY(::SelectObject(hDC, awtFont->GetHFont(fdIndex))); /* @@ -705,10 +733,14 @@ * 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); + if (buffer == NULL) { + return size; + } int buflen = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; @@ -816,8 +848,11 @@ jchar *strp = new jchar[len]; env->GetCharArrayRegion(str, off, len, strp); jstring jstr = env->NewString(strp, len); - jint result = Java_sun_awt_windows_WFontMetrics_stringWidth(env, self, - jstr); + jint result = 0; + if (jstr != NULL) { + result = Java_sun_awt_windows_WFontMetrics_stringWidth(env, self, + jstr); + } delete [] strp; return result; @@ -850,13 +885,25 @@ try { jintArray array = (jintArray)env->GetObjectField(self, AwtFont::widthsID); + if (array == NULL) { + JNU_ThrowNullPointerException(env, "Can't access widths array."); + return NULL; + } pStrBody = (char *)env->GetPrimitiveArrayCritical(str, 0); + if (pStrBody == NULL) { + JNU_ThrowNullPointerException(env, "Can't access str bytes."); + return NULL; + } char *pStr = pStrBody + off; jint *widths = NULL; try { widths = (jint *)env->GetPrimitiveArrayCritical(array, 0); - + if (widths == NULL) { + env->ReleasePrimitiveArrayCritical(str, pStrBody, 0); + JNU_ThrowNullPointerException(env, "Can't access widths."); + return NULL; + } for (; len; len--) { result += widths[*pStr++]; } @@ -915,29 +962,15 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WFontMetrics_initIDs(JNIEnv *env, jclass cls) { - TRY; - - AwtFont::widthsID = env->GetFieldID(cls, "widths", "[I"); - AwtFont::ascentID = env->GetFieldID(cls, "ascent", "I"); - AwtFont::descentID = env->GetFieldID(cls, "descent", "I"); - AwtFont::leadingID = env->GetFieldID(cls, "leading", "I"); - AwtFont::heightID = env->GetFieldID(cls, "height", "I"); - AwtFont::maxAscentID = env->GetFieldID(cls, "maxAscent", "I"); - AwtFont::maxDescentID = env->GetFieldID(cls, "maxDescent", "I"); - AwtFont::maxHeightID = env->GetFieldID(cls, "maxHeight", "I"); - AwtFont::maxAdvanceID = env->GetFieldID(cls, "maxAdvance", "I"); - - DASSERT(AwtFont::widthsID != NULL); - DASSERT(AwtFont::ascentID != NULL); - DASSERT(AwtFont::descentID != NULL); - DASSERT(AwtFont::leadingID != NULL); - DASSERT(AwtFont::heightID != NULL); - DASSERT(AwtFont::maxAscentID != NULL); - DASSERT(AwtFont::maxDescentID != NULL); - DASSERT(AwtFont::maxHeightID != NULL); - DASSERT(AwtFont::maxAdvanceID != NULL); - - CATCH_BAD_ALLOC; + CHECK_NULL(AwtFont::widthsID = env->GetFieldID(cls, "widths", "[I")); + CHECK_NULL(AwtFont::ascentID = env->GetFieldID(cls, "ascent", "I")); + CHECK_NULL(AwtFont::descentID = env->GetFieldID(cls, "descent", "I")); + CHECK_NULL(AwtFont::leadingID = env->GetFieldID(cls, "leading", "I")); + CHECK_NULL(AwtFont::heightID = env->GetFieldID(cls, "height", "I")); + CHECK_NULL(AwtFont::maxAscentID = env->GetFieldID(cls, "maxAscent", "I")); + CHECK_NULL(AwtFont::maxDescentID = env->GetFieldID(cls, "maxDescent", "I")); + CHECK_NULL(AwtFont::maxHeightID = env->GetFieldID(cls, "maxHeight", "I")); + AwtFont::maxAdvanceID = env->GetFieldID(cls, "maxAdvance", "I"); } } /* extern "C" */ @@ -952,28 +985,16 @@ JNIEXPORT void JNICALL Java_java_awt_Font_initIDs(JNIEnv *env, jclass cls) { - TRY; - - AwtFont::peerMID = env->GetMethodID(cls, "getPeer", - "()Ljava/awt/peer/FontPeer;"); - AwtFont::pDataID = env->GetFieldID(cls, "pData", "J"); - AwtFont::nameID = env->GetFieldID(cls, "name", "Ljava/lang/String;"); - AwtFont::sizeID = env->GetFieldID(cls, "size", "I"); - AwtFont::styleID = env->GetFieldID(cls, "style", "I"); - + CHECK_NULL(AwtFont::peerMID = env->GetMethodID(cls, "getPeer", + "()Ljava/awt/peer/FontPeer;")); + CHECK_NULL(AwtFont::pDataID = env->GetFieldID(cls, "pData", "J")); + CHECK_NULL(AwtFont::nameID = + env->GetFieldID(cls, "name", "Ljava/lang/String;")); + CHECK_NULL(AwtFont::sizeID = env->GetFieldID(cls, "size", "I")); + CHECK_NULL(AwtFont::styleID = env->GetFieldID(cls, "style", "I")); AwtFont::getFontMID = env->GetStaticMethodID(cls, "getFont", "(Ljava/lang/String;)Ljava/awt/Font;"); - - DASSERT(AwtFont::peerMID != NULL); - DASSERT(AwtFont::pDataID != NULL); - DASSERT(AwtFont::nameID != NULL); - DASSERT(AwtFont::sizeID != NULL); - DASSERT(AwtFont::styleID != NULL); - - DASSERT(AwtFont::getFontMID != NULL); - - CATCH_BAD_ALLOC; } } /* extern "C" */ @@ -988,15 +1009,9 @@ JNIEXPORT void JNICALL Java_java_awt_FontMetrics_initIDs(JNIEnv *env, jclass cls) { - TRY; - - AwtFont::fontID = env->GetFieldID(cls, "font", "Ljava/awt/Font;"); + CHECK_NULL(AwtFont::fontID = + env->GetFieldID(cls, "font", "Ljava/awt/Font;")); AwtFont::getHeightMID = env->GetMethodID(cls, "getHeight", "()I"); - - DASSERT(AwtFont::fontID); - DASSERT(AwtFont::getHeightMID); - - CATCH_BAD_ALLOC; } } /* extern "C" */ @@ -1010,16 +1025,10 @@ JNIEXPORT void JNICALL Java_sun_awt_FontDescriptor_initIDs(JNIEnv *env, jclass cls) { - TRY; - - AwtFont::nativeNameID = env->GetFieldID(cls, "nativeName", - "Ljava/lang/String;"); + CHECK_NULL(AwtFont::nativeNameID = + env->GetFieldID(cls, "nativeName", "Ljava/lang/String;")); AwtFont::useUnicodeID = env->GetFieldID(cls, "useUnicode", "Z"); - DASSERT(AwtFont::nativeNameID != NULL); - DASSERT(AwtFont::useUnicodeID != NULL); - - CATCH_BAD_ALLOC; } } /* extern "C" */ @@ -1034,20 +1043,13 @@ JNIEXPORT void JNICALL Java_sun_awt_PlatformFont_initIDs(JNIEnv *env, jclass cls) { - TRY; - - AwtFont::fontConfigID = env->GetFieldID(cls, "fontConfig", "Lsun/awt/FontConfiguration;"); - AwtFont::componentFontsID = - env->GetFieldID(cls, "componentFonts", "[Lsun/awt/FontDescriptor;"); + CHECK_NULL(AwtFont::fontConfigID = + env->GetFieldID(cls, "fontConfig", "Lsun/awt/FontConfiguration;")); + CHECK_NULL(AwtFont::componentFontsID = + env->GetFieldID(cls, "componentFonts", "[Lsun/awt/FontDescriptor;")); AwtFont::makeConvertedMultiFontStringMID = env->GetMethodID(cls, "makeConvertedMultiFontString", "(Ljava/lang/String;)[Ljava/lang/Object;"); - - DASSERT(AwtFont::makeConvertedMultiFontStringMID != NULL); - DASSERT(AwtFont::componentFontsID != NULL); - DASSERT(AwtFont::fontConfigID != NULL); - - CATCH_BAD_ALLOC; } } /* extern "C" */ @@ -1862,8 +1864,10 @@ static CCombinedSegTableManager tableManager; jstring fontName = (jstring)env->GetObjectField(self, AwtFont::fontNameID); - DASSERT(fontName != NULL); + DASSERT(fontName != NULL); // leave in for debug mode. + CHECK_NULL_RETURN(fontName, FALSE); // in production, just return LPCWSTR fontNameW = JNU_GetStringPlatformChars(env, fontName, NULL); + CHECK_NULL_RETURN(fontNameW, FALSE); CCombinedSegTable* pTable = tableManager.GetTable(fontNameW); JNU_ReleaseStringPlatformChars(env, fontName, fontNameW); return (pTable->In((USHORT) ch) ? JNI_TRUE : JNI_FALSE); diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/windows/awt_Frame.cpp --- a/jdk/src/windows/native/sun/windows/awt_Frame.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/windows/awt_Frame.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -351,6 +351,8 @@ case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION: case WM_IME_COMPOSITION: + case WM_IME_SETCONTEXT: + case WM_IME_NOTIFY: case WM_IME_CONTROL: case WM_IME_COMPOSITIONFULL: case WM_IME_SELECT: diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/windows/awt_InputMethod.cpp --- a/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -320,13 +320,18 @@ // current language ID (returned from 'getJavaIDFromLangID') is in // ASCII encoding, so we use 'GetStringUTFChars' to retrieve requested // language ID from the 'localeString' object. - const char * current = getJavaIDFromLangID(AwtComponent::GetInputLanguage()); jboolean isCopy; const char * requested = env->GetStringUTFChars(localeString, &isCopy); - if ((current != NULL) && (strcmp(current, requested) == 0)) { - env->ReleaseStringUTFChars(localeString, requested); + CHECK_NULL_RETURN(requested, JNI_FALSE); + + const char * current = getJavaIDFromLangID(AwtComponent::GetInputLanguage()); + if (current != NULL) { + if (strcmp(current, requested) == 0) { + env->ReleaseStringUTFChars(localeString, requested); + free((void *)current); + return JNI_TRUE; + } free((void *)current); - return JNI_TRUE; } // get list of available HKLs. Adding the user's preferred layout on top of the layout @@ -334,7 +339,10 @@ // looking up suitable layout. int layoutCount = ::GetKeyboardLayoutList(0, NULL) + 1; // +1 for user's preferred HKL HKL FAR * hKLList = (HKL FAR *)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, sizeof(HKL), layoutCount); - DASSERT(!safe_ExceptionOccurred(env)); + if (hKLList == NULL) { + env->ReleaseStringUTFChars(localeString, requested); + return JNI_FALSE; + } ::GetKeyboardLayoutList(layoutCount - 1, &(hKLList[1])); hKLList[0] = getDefaultKeyboardLayout(); // put user's preferred layout on top of the list @@ -342,20 +350,23 @@ jboolean retValue = JNI_FALSE; for (int i = 0; i < layoutCount; i++) { const char * supported = getJavaIDFromLangID(LOWORD(hKLList[i])); - if ((supported != NULL) && (strcmp(supported, requested) == 0)) { - // use special message to call ActivateKeyboardLayout() in main thread. - if (AwtToolkit::GetInstance().SendMessage(WM_AWT_ACTIVATEKEYBOARDLAYOUT, (WPARAM)onActivate, (LPARAM)hKLList[i])) { - //also need to change the same keyboard layout for the Java AWT-EventQueue thread - AwtToolkit::activateKeyboardLayout(hKLList[i]); - retValue = JNI_TRUE; + if (supported != NULL) { + if (strcmp(supported, requested) == 0) { + // use special message to call ActivateKeyboardLayout() in main thread. + if (AwtToolkit::GetInstance().SendMessage(WM_AWT_ACTIVATEKEYBOARDLAYOUT, (WPARAM)onActivate, (LPARAM)hKLList[i])) { + //also need to change the same keyboard layout for the Java AWT-EventQueue thread + AwtToolkit::activateKeyboardLayout(hKLList[i]); + retValue = JNI_TRUE; + } + free((void *)supported); + break; } - break; + free((void *)supported); } } env->ReleaseStringUTFChars(localeString, requested); free(hKLList); - free((void *)current); return retValue; CATCH_BAD_ALLOC_RET(JNI_FALSE); @@ -445,7 +456,7 @@ // get list of available HKLs int layoutCount = ::GetKeyboardLayoutList(0, NULL); HKL FAR * hKLList = (HKL FAR *)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, sizeof(HKL), layoutCount); - DASSERT(!safe_ExceptionOccurred(env)); + CHECK_NULL_RETURN(hKLList, NULL); ::GetKeyboardLayoutList(layoutCount, hKLList); // get list of Java locale names while getting rid of duplicates @@ -453,8 +464,13 @@ int destIndex = 0; int javaLocaleNameCount = 0; int current = 0; + const char ** javaLocaleNames = (const char **)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, sizeof(char *), layoutCount); - DASSERT(!safe_ExceptionOccurred(env)); + if (javaLocaleNames == NULL) { + free(hKLList); + return NULL; + } + for (; srcIndex < layoutCount; srcIndex++) { const char * srcLocaleName = getJavaIDFromLangID(LOWORD(hKLList[srcIndex])); @@ -477,18 +493,33 @@ } } + jobjectArray locales = NULL; // convert it to an array of Java locale objects jclass localeClass = env->FindClass("java/util/Locale"); - jobjectArray locales = env->NewObjectArray(javaLocaleNameCount, localeClass, NULL); + if (localeClass != NULL) { + locales = env->NewObjectArray(javaLocaleNameCount, localeClass, NULL); + if (locales != NULL) { + + for (current = 0; current < javaLocaleNameCount; current++) { + jobject obj = CreateLocaleObject(env, javaLocaleNames[current]); + if (env->ExceptionCheck()) { + env->DeleteLocalRef(locales); + locales = NULL; + break; + } + env->SetObjectArrayElement(locales, + current, + obj); + } + + } + env->DeleteLocalRef(localeClass); + } + for (current = 0; current < javaLocaleNameCount; current++) { - env->SetObjectArrayElement(locales, - current, - CreateLocaleObject(env, javaLocaleNames[current])); free((void *)javaLocaleNames[current]); } - DASSERT(!safe_ExceptionOccurred(env)); - env->DeleteLocalRef(localeClass); free(hKLList); free(javaLocaleNames); return locales; @@ -542,6 +573,7 @@ // create Locale object jobject langtagObj = env->NewStringUTF(name); + CHECK_NULL_RETURN(langtagObj, NULL); jobject localeObj = JNU_CallStaticMethodByName(env, NULL, "java/util/Locale", diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/windows/awt_List.cpp --- a/jdk/src/windows/native/sun/windows/awt_List.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/windows/awt_List.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -614,7 +614,8 @@ { LPTSTR itemPtr = NULL; jstring item = (jstring)env->GetObjectArrayElement(items, i); - JNI_CHECK_NULL_GOTO(item, "null item", next_item); + if (env->ExceptionCheck()) goto ret; + if (item == NULL) goto next_item; itemPtr = (LPTSTR)JNU_GetStringPlatformChars(env, item, 0); if (itemPtr == NULL) { @@ -1017,8 +1018,8 @@ ses->list = env->NewGlobalRef(self); ses->index = index; - return (jboolean)AwtToolkit::GetInstance().SyncCall( - (void *(*)(void *))AwtList::_IsSelected, ses); + return JNI_IS_TRUE(AwtToolkit::GetInstance().SyncCall( + (void *(*)(void *))AwtList::_IsSelected, ses)); // global ref and ses are deleted in _IsSelected CATCH_BAD_ALLOC_RET(FALSE); diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/windows/awt_MenuItem.cpp --- a/jdk/src/windows/native/sun/windows/awt_MenuItem.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/windows/awt_MenuItem.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -152,6 +152,9 @@ if (dw == ERROR_OUTOFMEMORY) { jstring errorMsg = JNU_NewStringPlatform(env, L"too many menu handles"); + if (errorMsg == NULL) { + throw std::bad_alloc(); + } createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError", "(Ljava/lang/String;)V", errorMsg); @@ -164,16 +167,19 @@ NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, 0, NULL); jstring s = JNU_NewStringPlatform(env, buf); + if (s == NULL) { + throw std::bad_alloc(); + } createError = JNU_NewObjectByName(env, "java/lang/InternalError", "(Ljava/lang/String;)V", s); LocalFree(buf); env->DeleteLocalRef(s); } + if (createError == NULL) { + throw std::bad_alloc(); + } env->SetObjectField(self, AwtObject::createErrorID, createError); - if (createError != NULL) - { - env->DeleteLocalRef(createError); - } + env->DeleteLocalRef(createError); return FALSE; } return TRUE; @@ -238,12 +244,18 @@ jobject self = GetPeer(env); jobject target = env->GetObjectField(self, AwtObject::targetID); jobject font = JNU_CallMethodByName(env, 0, target, "getFont_NoClientCode", "()Ljava/awt/Font;").l; + env->DeleteLocalRef(target); + if (env->ExceptionCheck()) { + throw std::bad_alloc(); + } if (font == NULL) { font = env->NewLocalRef(GetDefaultFont(env)); + if (env->ExceptionCheck()) { + throw std::bad_alloc(); + } } - env->DeleteLocalRef(target); return font; } @@ -251,13 +263,22 @@ AwtMenuItem::GetDefaultFont(JNIEnv *env) { if (AwtMenuItem::systemFont == NULL) { jclass cls = env->FindClass("sun/awt/windows/WMenuItemPeer"); - DASSERT(cls != NULL); + if (cls == NULL) { + throw std::bad_alloc(); + } AwtMenuItem::systemFont = env->CallStaticObjectMethod(cls, AwtMenuItem::getDefaultFontMID); - DASSERT(AwtMenuItem::systemFont); + if (env->ExceptionCheck()) { + env->DeleteLocalRef(cls); + throw std::bad_alloc(); + } AwtMenuItem::systemFont = env->NewGlobalRef(AwtMenuItem::systemFont); + if (systemFont == NULL) { + env->DeleteLocalRef(cls); + throw std::bad_alloc(); + } } return AwtMenuItem::systemFont; } @@ -284,8 +305,19 @@ DWORD crBack,crText; HBRUSH hbrBack; - jobject font = GetFont(env); + jobject font; + try { + font = GetFont(env); + } catch (std::bad_alloc&) { + env->DeleteLocalRef(target); + throw; + } + jstring text = GetJavaString(env); + if (env->ExceptionCheck()) { + env->DeleteLocalRef(target); + throw std::bad_alloc(); + } size = AwtFont::getMFStringSize(hDC, font, text); /* 4700350: If the font size is taller than the menubar, change to the @@ -294,7 +326,13 @@ */ if (IsTopMenu() && size.cy > ::GetSystemMetrics(SM_CYMENU)) { env->DeleteLocalRef(font); - font = env->NewLocalRef(GetDefaultFont(env)); + try { + font = env->NewLocalRef(GetDefaultFont(env)); + } catch (std::bad_alloc&) { + env->DeleteLocalRef(target); + env->DeleteLocalRef(text); + throw; + } size = AwtFont::getMFStringSize(hDC, font, text); } @@ -452,6 +490,10 @@ /* font is a java.awt.Font */ jobject font = GetFont(env); jstring text = GetJavaString(env); + if (env->ExceptionCheck()) { + env->DeleteLocalRef(font); + throw std::bad_alloc(); + } SIZE size = AwtFont::getMFStringSize(hDC, font, text); /* 4700350: If the font size is taller than the menubar, change to the @@ -459,7 +501,14 @@ * client area. -bchristi */ if (IsTopMenu() && size.cy > ::GetSystemMetrics(SM_CYMENU)) { - jobject defFont = GetDefaultFont(env); + jobject defFont; + try { + defFont = GetDefaultFont(env); + } catch (std::bad_alloc&) { + env->DeleteLocalRef(text); + env->DeleteLocalRef(font); + throw; + } env->DeleteLocalRef(font); font = env->NewLocalRef(defFont); size = AwtFont::getMFStringSize(hDC, font, text); @@ -468,13 +517,31 @@ jstring fontName = (jstring)JNU_CallMethodByName(env, 0,font, "getName", "()Ljava/lang/String;").l; + if (env->ExceptionCheck()) { + env->DeleteLocalRef(text); + env->DeleteLocalRef(font); + throw std::bad_alloc(); + } + /* fontMetrics is a Hsun_awt_windows_WFontMetrics */ jobject fontMetrics = GetFontMetrics(env, font); - + if (env->ExceptionCheck()) { + env->DeleteLocalRef(text); + env->DeleteLocalRef(font); + env->DeleteLocalRef(fontName); + throw std::bad_alloc(); + } // int height = env->GetIntField(fontMetrics, AwtFont::heightID); int height = (jint)JNU_CallMethodByName(env, 0, fontMetrics, "getHeight", "()I").i; + if (env->ExceptionCheck()) { + env->DeleteLocalRef(text); + env->DeleteLocalRef(font); + env->DeleteLocalRef(fontName); + env->DeleteLocalRef(fontMetrics); + throw std::bad_alloc(); + } measureInfo.itemHeight = height; measureInfo.itemHeight += measureInfo.itemHeight/3; @@ -520,10 +587,14 @@ if (env->PushLocalFrame(2) < 0) return NULL; jclass cls = env->FindClass("java/awt/Toolkit"); + CHECK_NULL_RETURN(cls, NULL); jobject toolkitLocal = env->CallStaticObjectMethod(cls, AwtToolkit::getDefaultToolkitMID); + env->DeleteLocalRef(cls); + CHECK_NULL_RETURN(toolkitLocal, NULL); toolkit = env->NewGlobalRef(toolkitLocal); - DASSERT(!safe_ExceptionOccurred(env)); + env->DeleteLocalRef(toolkitLocal); + CHECK_NULL_RETURN(toolkit, NULL); env->PopLocalFrame(0); } /* @@ -739,6 +810,10 @@ { empty = JNU_NewStringPlatform(env, TEXT("")); } + if (env->ExceptionCheck()) { + badAlloc = 1; + goto ret; + } LPCTSTR labelPtr; if (empty != NULL) { @@ -846,10 +921,9 @@ TRY; AwtMenuItem::fontID = env->GetFieldID(cls, "font", "Ljava/awt/Font;"); + CHECK_NULL(AwtMenuItem::fontID); AwtMenuItem::appContextID = env->GetFieldID(cls, "appContext", "Lsun/awt/AppContext;"); - DASSERT(AwtMenuItem::fontID != NULL); - CATCH_BAD_ALLOC; } @@ -868,11 +942,9 @@ TRY; AwtMenuItem::labelID = env->GetFieldID(cls, "label", "Ljava/lang/String;"); + CHECK_NULL(AwtMenuItem::labelID); AwtMenuItem::enabledID = env->GetFieldID(cls, "enabled", "Z"); - DASSERT(AwtMenuItem::labelID != NULL); - DASSERT(AwtMenuItem::enabledID != NULL); - CATCH_BAD_ALLOC; } @@ -892,8 +964,6 @@ AwtMenuItem::stateID = env->GetFieldID(cls, "state", "Z"); - DASSERT(AwtMenuItem::stateID != NULL); - CATCH_BAD_ALLOC; } @@ -917,15 +987,13 @@ TRY; AwtMenuItem::isCheckboxID = env->GetFieldID(cls, "isCheckbox", "Z"); + CHECK_NULL(AwtMenuItem::isCheckboxID); AwtMenuItem::shortcutLabelID = env->GetFieldID(cls, "shortcutLabel", "Ljava/lang/String;"); + CHECK_NULL(AwtMenuItem::shortcutLabelID); AwtMenuItem::getDefaultFontMID = env->GetStaticMethodID(cls, "getDefaultFont", "()Ljava/awt/Font;"); - DASSERT(AwtMenuItem::isCheckboxID != NULL); - DASSERT(AwtMenuItem::shortcutLabelID != NULL); - DASSERT(AwtMenuItem::getDefaultFontMID != NULL); - CATCH_BAD_ALLOC; } diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/windows/awt_PrintControl.cpp --- a/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -233,107 +233,166 @@ TRY; jclass cls = env->FindClass("sun/awt/windows/WPrinterJob"); + CHECK_NULL(cls); AwtPrintControl::dialogOwnerPeerID = env->GetFieldID(cls, "dialogOwnerPeer", "Ljava/awt/peer/ComponentPeer;"); + DASSERT(AwtPrintControl::dialogOwnerPeerID != NULL); + CHECK_NULL(AwtPrintControl::dialogOwnerPeerID); + AwtPrintControl::getPrintDCID = env->GetMethodID(cls, "getPrintDC", "()J"); + DASSERT(AwtPrintControl::getPrintDCID != NULL); + CHECK_NULL(AwtPrintControl::getPrintDCID); + AwtPrintControl::setPrintDCID = env->GetMethodID(cls, "setPrintDC", "(J)V"); + DASSERT(AwtPrintControl::setPrintDCID != NULL); + CHECK_NULL(AwtPrintControl::setPrintDCID); + AwtPrintControl::getDevmodeID = env->GetMethodID(cls, "getDevMode", "()J"); + DASSERT(AwtPrintControl::getDevmodeID != NULL); + CHECK_NULL(AwtPrintControl::getDevmodeID); + AwtPrintControl::setDevmodeID = env->GetMethodID(cls, "setDevMode", "(J)V"); + DASSERT(AwtPrintControl::setDevmodeID != NULL); + CHECK_NULL(AwtPrintControl::setDevmodeID); + AwtPrintControl::getDevnamesID = env->GetMethodID(cls, "getDevNames", "()J"); + DASSERT(AwtPrintControl::getDevnamesID != NULL); + CHECK_NULL(AwtPrintControl::getDevnamesID); + AwtPrintControl::setDevnamesID = env->GetMethodID(cls, "setDevNames", "(J)V"); + DASSERT(AwtPrintControl::setDevnamesID != NULL); + CHECK_NULL(AwtPrintControl::setDevnamesID); + AwtPrintControl::driverDoesMultipleCopiesID = env->GetFieldID(cls, "driverDoesMultipleCopies", "Z"); + DASSERT(AwtPrintControl::driverDoesMultipleCopiesID != NULL); + CHECK_NULL(AwtPrintControl::driverDoesMultipleCopiesID); + AwtPrintControl::driverDoesCollationID = env->GetFieldID(cls, "driverDoesCollation", "Z"); + DASSERT(AwtPrintControl::driverDoesCollationID != NULL); + CHECK_NULL(AwtPrintControl::driverDoesCollationID); + AwtPrintControl::getCopiesID = env->GetMethodID(cls, "getCopiesAttrib", "()I"); + DASSERT(AwtPrintControl::getCopiesID != NULL); + CHECK_NULL(AwtPrintControl::getCopiesID); + AwtPrintControl::getCollateID = env->GetMethodID(cls, "getCollateAttrib","()I"); + DASSERT(AwtPrintControl::getCollateID != NULL); + CHECK_NULL(AwtPrintControl::getCollateID); + AwtPrintControl::getOrientID = env->GetMethodID(cls, "getOrientAttrib", "()I"); + DASSERT(AwtPrintControl::getOrientID != NULL); + CHECK_NULL(AwtPrintControl::getOrientID); + AwtPrintControl::getFromPageID = env->GetMethodID(cls, "getFromPageAttrib", "()I"); + DASSERT(AwtPrintControl::getFromPageID != NULL); + CHECK_NULL(AwtPrintControl::getFromPageID); + AwtPrintControl::getToPageID = env->GetMethodID(cls, "getToPageAttrib", "()I"); + DASSERT(AwtPrintControl::getToPageID != NULL); + CHECK_NULL(AwtPrintControl::getToPageID); + AwtPrintControl::getMinPageID = env->GetMethodID(cls, "getMinPageAttrib", "()I"); + DASSERT(AwtPrintControl::getMinPageID != NULL); + CHECK_NULL(AwtPrintControl::getMinPageID); + AwtPrintControl::getMaxPageID = env->GetMethodID(cls, "getMaxPageAttrib", "()I"); + DASSERT(AwtPrintControl::getMaxPageID != NULL); + CHECK_NULL(AwtPrintControl::getMaxPageID); + AwtPrintControl::getDestID = env->GetMethodID(cls, "getDestAttrib", "()Z"); + DASSERT(AwtPrintControl::getDestID != NULL); + CHECK_NULL(AwtPrintControl::getDestID); + AwtPrintControl::getQualityID = env->GetMethodID(cls, "getQualityAttrib", "()I"); + DASSERT(AwtPrintControl::getQualityID != NULL); + CHECK_NULL(AwtPrintControl::getQualityID); + AwtPrintControl::getColorID = env->GetMethodID(cls, "getColorAttrib", "()I"); + DASSERT(AwtPrintControl::getColorID != NULL); + CHECK_NULL(AwtPrintControl::getColorID); + AwtPrintControl::getSidesID = env->GetMethodID(cls, "getSidesAttrib", "()I"); + DASSERT(AwtPrintControl::getSidesID != NULL); + CHECK_NULL(AwtPrintControl::getSidesID); + AwtPrintControl::getPrinterID = env->GetMethodID(cls, "getPrinterAttrib", "()Ljava/lang/String;"); + DASSERT(AwtPrintControl::getPrinterID != NULL); + CHECK_NULL(AwtPrintControl::getPrinterID); + AwtPrintControl::getWin32MediaID = env->GetMethodID(cls, "getWin32MediaAttrib", "()[I"); + DASSERT(AwtPrintControl::getWin32MediaID != NULL); + CHECK_NULL(AwtPrintControl::getWin32MediaID); + AwtPrintControl::setWin32MediaID = env->GetMethodID(cls, "setWin32MediaAttrib", "(III)V"); + DASSERT(AwtPrintControl::setWin32MediaID != NULL); + CHECK_NULL(AwtPrintControl::setWin32MediaID); + AwtPrintControl::getWin32MediaTrayID = env->GetMethodID(cls, "getMediaTrayAttrib", "()I"); + DASSERT(AwtPrintControl::getWin32MediaTrayID != NULL); + CHECK_NULL(AwtPrintControl::getWin32MediaTrayID); + AwtPrintControl::setWin32MediaTrayID = env->GetMethodID(cls, "setMediaTrayAttrib", "(I)V"); + DASSERT(AwtPrintControl::setWin32MediaTrayID != NULL); + CHECK_NULL(AwtPrintControl::setWin32MediaTrayID); + AwtPrintControl::getSelectID = env->GetMethodID(cls, "getSelectAttrib", "()I"); + DASSERT(AwtPrintControl::getSelectID != NULL); + CHECK_NULL(AwtPrintControl::getSelectID); + AwtPrintControl::getPrintToFileEnabledID = env->GetMethodID(cls, "getPrintToFileEnabled", "()Z"); + DASSERT(AwtPrintControl::getPrintToFileEnabledID != NULL); + CHECK_NULL(AwtPrintControl::getPrintToFileEnabledID); AwtPrintControl::setNativeAttID = env->GetMethodID(cls, "setNativeAttributes", "(III)V"); + DASSERT(AwtPrintControl::setNativeAttID != NULL); + CHECK_NULL(AwtPrintControl::setNativeAttID); AwtPrintControl::setRangeCopiesID = env->GetMethodID(cls, "setRangeCopiesAttribute", "(IIZI)V"); + DASSERT(AwtPrintControl::setRangeCopiesID != NULL); + CHECK_NULL(AwtPrintControl::setRangeCopiesID); + AwtPrintControl::setResID = env->GetMethodID(cls, "setResolutionDPI", "(II)V"); + DASSERT(AwtPrintControl::setResID != NULL); + CHECK_NULL(AwtPrintControl::setResID); AwtPrintControl::setPrinterID = env->GetMethodID(cls, "setPrinterNameAttrib", "(Ljava/lang/String;)V"); + DASSERT(AwtPrintControl::setPrinterID != NULL); + CHECK_NULL(AwtPrintControl::setPrinterID); AwtPrintControl::setJobAttributesID = env->GetMethodID(cls, "setJobAttributes", "(Ljavax/print/attribute/PrintRequestAttributeSet;IISSSSSSS)V"); - - DASSERT(AwtPrintControl::driverDoesMultipleCopiesID != NULL); - DASSERT(AwtPrintControl::getPrintDCID != NULL); - DASSERT(AwtPrintControl::setPrintDCID != NULL); - DASSERT(AwtPrintControl::getDevmodeID != NULL); - DASSERT(AwtPrintControl::setDevmodeID != NULL); - DASSERT(AwtPrintControl::getDevnamesID != NULL); - DASSERT(AwtPrintControl::setDevnamesID != NULL); - DASSERT(AwtPrintControl::driverDoesCollationID != NULL); - DASSERT(AwtPrintControl::getWin32MediaID != NULL); - DASSERT(AwtPrintControl::setWin32MediaID != NULL); - DASSERT(AwtPrintControl::getWin32MediaTrayID != NULL); - DASSERT(AwtPrintControl::setWin32MediaTrayID != NULL); - DASSERT(AwtPrintControl::setRangeCopiesID != NULL); - DASSERT(AwtPrintControl::setResID != NULL); - DASSERT(AwtPrintControl::setNativeAttID != NULL); - DASSERT(AwtPrintControl::dialogOwnerPeerID != NULL); - DASSERT(AwtPrintControl::getCopiesID != NULL); - DASSERT(AwtPrintControl::getOrientID != NULL); - DASSERT(AwtPrintControl::getPrinterID != NULL); - DASSERT(AwtPrintControl::getCollateID != NULL); - DASSERT(AwtPrintControl::getFromPageID != NULL); - DASSERT(AwtPrintControl::getToPageID != NULL); - DASSERT(AwtPrintControl::getMinPageID != NULL); - DASSERT(AwtPrintControl::getMaxPageID != NULL); - DASSERT(AwtPrintControl::getDestID != NULL); - DASSERT(AwtPrintControl::getQualityID != NULL); - DASSERT(AwtPrintControl::getColorID != NULL); - DASSERT(AwtPrintControl::getSidesID != NULL); - DASSERT(AwtPrintControl::getSelectID != NULL); - DASSERT(AwtPrintControl::getPrintToFileEnabledID != NULL); DASSERT(AwtPrintControl::setJobAttributesID != NULL); - + CHECK_NULL(AwtPrintControl::setJobAttributesID); CATCH_BAD_ALLOC; } @@ -606,6 +665,10 @@ LPTSTR getName = (LPTSTR)JNU_GetStringPlatformChars(env, printerName, NULL); + if (getName == NULL) { + env->DeleteLocalRef(printerName); + throw std::bad_alloc(); + } BOOL samePrinter = FALSE; @@ -652,6 +715,7 @@ if (portName != NULL) { free(portName); } + env->DeleteLocalRef(printerName); return FALSE; } @@ -664,11 +728,13 @@ if (portName != NULL) { free(portName); } + env->DeleteLocalRef(printerName); return FALSE; } delete [] buffer; } + env->DeleteLocalRef(printerName); // PrintDlg may change the values of hDevMode and hDevNames so we // re-initialize our saved handles. AwtPrintControl::setPrintHDMode(env, printCtrl, NULL); diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/windows/awt_PrintDialog.cpp --- a/jdk/src/windows/native/sun/windows/awt_PrintDialog.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/windows/awt_PrintDialog.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -193,11 +193,24 @@ // as peer object is used later on another thread, create a global ref jobject peerGlobalRef = env->NewGlobalRef(peer); DASSERT(peerGlobalRef != NULL); + CHECK_NULL_RETURN(peerGlobalRef, 0); jobject target = env->GetObjectField(peerGlobalRef, AwtObject::targetID); DASSERT(target != NULL); + if (target == NULL) { + env->DeleteGlobalRef(peerGlobalRef); + return 0; + } jobject parent = env->GetObjectField(peerGlobalRef, AwtPrintDialog::parentID); jobject control = env->GetObjectField(target, AwtPrintDialog::controlID); DASSERT(control != NULL); + if (control == NULL) { + env->DeleteGlobalRef(peerGlobalRef); + env->DeleteLocalRef(target); + if (parent != NULL) { + env->DeleteLocalRef(parent); + } + return 0; + } AwtComponent *awtParent = (parent != NULL) ? (AwtComponent *)JNI_GET_PDATA(parent) : NULL; HWND hwndOwner = awtParent ? awtParent->GetHWnd() : NULL; @@ -206,7 +219,18 @@ memset(&pd, 0, sizeof(PRINTDLG)); pd.lStructSize = sizeof(PRINTDLG); pd.lCustData = (LPARAM)peerGlobalRef; - BOOL ret = AwtPrintControl::InitPrintDialog(env, control, pd); + BOOL ret; + try { + ret = AwtPrintControl::InitPrintDialog(env, control, pd); + } catch (std::bad_alloc&) { + env->DeleteGlobalRef(peerGlobalRef); + env->DeleteLocalRef(target); + if (parent != NULL) { + env->DeleteLocalRef(parent); + } + env->DeleteLocalRef(control); + throw; + } if (!ret) { /* Couldn't use the printer, or spooler isn't running * Call Page dialog with ' PD_RETURNDEFAULT' so it doesn't try diff -r a77941f17614 -r 0d1f816217dc jdk/src/windows/native/sun/windows/awt_new.cpp --- a/jdk/src/windows/native/sun/windows/awt_new.cpp Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/src/windows/native/sun/windows/awt_new.cpp Wed Jul 05 19:39:35 2017 +0200 @@ -149,7 +149,7 @@ handle_bad_alloc(void) { if (jvm != NULL) { JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - if (env != NULL) { + if (env != NULL && !env->ExceptionCheck()) { JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); } } diff -r a77941f17614 -r 0d1f816217dc jdk/test/com/sun/jdi/EvalInterfaceStatic.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/jdi/EvalInterfaceStatic.sh Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,126 @@ +#!/bin/sh + +# +# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @bug 8031195 +# @summary JDB allows evaluation of calls to static interface methods +# @author Jaroslav Bachorik +# +# @run shell/timeout=300 EvalInterfaceStatic.sh + +# The test exercises the ability to invoke static methods on interfaces. +# Static interface methods are a new feature added in JDK8. +# +# The test makes sure that it is, at all, possible to invoke an interface +# static method and that the static methods are not inherited by extending +# interfaces. + +classname=EvalStaticInterfaces + +createJavaFile() +{ + cat < $classname.java.1 +public interface $classname { + static String staticMethod1() { + return "base:staticMethod1"; + } + + static String staticMethod2() { + return "base:staticMethod2"; + } + + public static void main(String[] args) { + // prove that these work + System.out.println("base staticMethod1(): " + $classname.staticMethod1()); + System.out.println("base staticMethod2(): " + $classname.staticMethod2()); + System.out.println("overridden staticMethod2(): " + Extended$classname.staticMethod2()); + System.out.println("base staticMethod3(): " + Extended$classname.staticMethod3()); + + gus(); + } + + static void gus() { + int x = 0; // @1 breakpoint + } +} + +interface Extended$classname extends $classname { + static String staticMethod2() { + return "extended:staticMethod2"; + } + + static String staticMethod3() { + return "extended:staticMethod3"; + } +} + + + +EOF +} + +# drive jdb by sending cmds to it and examining its output +dojdbCmds() +{ + setBkpts @1 + runToBkpt @1 + + cmd eval "$classname.staticMethod1()" + jdbFailIfNotPresent "base:staticMethod1" 2 + + cmd eval "$classname.staticMethod2()" + jdbFailIfNotPresent "base:staticMethod2" 2 + + cmd eval "Extended$classname.staticMethod1()" + jdbFailIfPresent "base:staticMethod1" 2 + + cmd eval "Extended$classname.staticMethod2()" + jdbFailIfNotPresent "extended:staticMethod2" 2 + + cmd eval "Extended$classname.staticMethod3()" + jdbFailIfNotPresent "extended:staticMethod3" 2 +} + + +mysetup() +{ + if [ -z "$TESTSRC" ] ; then + TESTSRC=. + fi + + for ii in . $TESTSRC $TESTSRC/.. ; do + if [ -r "$ii/ShellScaffold.sh" ] ; then + . $ii/ShellScaffold.sh + break + fi + done +} + +# You could replace this next line with the contents +# of ShellScaffold.sh and this script will run just the same. +mysetup + +runit +pass diff -r a77941f17614 -r 0d1f816217dc jdk/test/com/sun/jdi/InterfaceMethodsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/jdi/InterfaceMethodsTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8031195 + * @summary JDI: Add support for static and default methods in interfaces + * + * @run build TestScaffold VMConnection TargetListener TargetAdapter + * @run build InterfaceMethodsTest + * @run main InterfaceMethodsTest + */ +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import java.util.Collections; + +public class InterfaceMethodsTest extends TestScaffold { + private static final int RESULT_A = 1; + private static final int RESULT_B = 1; + private static final int RESULT_TARGET = 1; + static interface InterfaceA { + static int staticMethodA() { + System.out.println("-InterfaceA: static interface method A-"); + return RESULT_A; + } + static int staticMethodB() { + System.out.println("-InterfaceA: static interface method B-"); + return RESULT_A; + } + default int defaultMethodA() { + System.out.println("-InterfaceA: default interface method A-"); + return RESULT_A; + } + default int defaultMethodB() { + System.out.println("-InterfaceA: default interface method B-"); + return RESULT_A; + } + default int defaultMethodC() { + System.out.println("-InterfaceA: default interface method C-"); + return RESULT_A; + } + + int implementedMethod(); + } + + static interface InterfaceB extends InterfaceA { + @Override + default int defaultMethodC() { + System.out.println("-InterfaceB: overridden default interface method C-"); + return RESULT_B; + } + default int defaultMethodD() { + System.out.println("-InterfaceB: default interface method D-"); + return RESULT_B; + } + + static int staticMethodB() { + System.out.println("-InterfaceB: overridden static interface method B-"); + return RESULT_B; + } + + static int staticMethodC() { + System.out.println("-InterfaceB: static interface method C-"); + return RESULT_B; + } + } + + final static class TargetClass implements InterfaceB { + public int classMethod() { + System.out.println("-TargetClass: class only method-"); + return RESULT_TARGET; + } + + @Override + public int implementedMethod() { + System.out.println("-TargetClass: implemented non-default interface method-"); + return RESULT_TARGET; + } + + @Override + public int defaultMethodB() { + System.out.println("-TargetClass: overridden default interface method D"); + + return RESULT_TARGET; + } + + public static void main(String[] args) { + TargetClass tc = new TargetClass(); + tc.doTests(tc); + } + + private void doTests(TargetClass ref) { + // break + } + } + + public InterfaceMethodsTest(String[] args) { + super(args); + } + + public static void main(String[] args) throws Exception { + new InterfaceMethodsTest(args).startTests(); + } + + private static final String TEST_CLASS_NAME = InterfaceMethodsTest.class.getName().replace('.', '/'); + private static final String TARGET_CLASS_NAME = TargetClass.class.getName().replace('.', '/'); + private static final String INTERFACEA_NAME = InterfaceA.class.getName().replace('.', '/'); + private static final String INTERFACEB_NAME = InterfaceB.class.getName().replace('.', '/'); + + protected void runTests() throws Exception { + /* + * Get to the top of main() + * to determine targetClass and mainThread + */ + BreakpointEvent bpe = startToMain(TARGET_CLASS_NAME); + + bpe = resumeTo(TARGET_CLASS_NAME, "doTests", "(L" + TARGET_CLASS_NAME +";)V"); + + mainThread = bpe.thread(); + + StackFrame frame = mainThread.frame(0); + ObjectReference thisObject = frame.thisObject(); + ObjectReference ref = (ObjectReference)frame.getArgumentValues().get(0); + + ReferenceType targetClass = bpe.location().declaringType(); + testImplementationClass(targetClass, thisObject); + + testInterfaceA(ref); + + testInterfaceB(ref); + + /* + * resume the target listening for events + */ + listenUntilVMDisconnect(); + + /* + * deal with results of test + * if anything has called failure("foo") testFailed will be true + */ + if (!testFailed) { + println("InterfaceMethodsTest: passed"); + } else { + throw new Exception("InterfaceMethodsTest: failed"); + } + } + + private void testInterfaceA(ObjectReference ref) { + // Test non-virtual calls on InterfaceA + + ReferenceType ifaceClass = (ReferenceType)vm().classesByName(INTERFACEA_NAME).get(0); + /* Default method calls */ + + // invoke the InterfaceA's "defaultMethodA" + testInvokePos(ifaceClass, ref, "defaultMethodA", "()I", vm().mirrorOf(RESULT_A)); + + // invoke the InterfaceA's "defaultMethodB" + testInvokePos(ifaceClass, ref, "defaultMethodB", "()I", vm().mirrorOf(RESULT_A)); + + // invoke the InterfaceA's "defaultMethodC" + testInvokePos(ifaceClass, ref, "defaultMethodC", "()I", vm().mirrorOf(RESULT_A)); + + // "defaultMethodD" from InterfaceB is not accessible from here + testInvokeNeg(ifaceClass, ref, "defaultMethodD", "()I", vm().mirrorOf(RESULT_B), + "Attempted to invoke non-existing method"); + + // trying to invoke the asbtract method "implementedMethod" + testInvokeNeg(ifaceClass, ref, "implementedMethod", "()I", vm().mirrorOf(TARGET_CLASS_NAME), + "Invocation of non-default methods is not supported"); + + + /* Static method calls */ + + // invoke interface static method A + testInvokePos(ifaceClass, null, "staticMethodA", "()I", vm().mirrorOf(RESULT_A)); + + // try to invoke static method A on the instance + testInvokePos(ifaceClass, ref, "staticMethodA", "()I", vm().mirrorOf(RESULT_A)); + + // invoke interface static method B + testInvokePos(ifaceClass, null, "staticMethodB", "()I", vm().mirrorOf(RESULT_A)); + + // try to invoke static method B on the instance + testInvokePos(ifaceClass, ref, "staticMethodB", "()I", vm().mirrorOf(RESULT_A)); + } + + private void testInterfaceB(ObjectReference ref) { + // Test non-virtual calls on InterfaceB + ReferenceType ifaceClass = (ReferenceType)vm().classesByName(INTERFACEB_NAME).get(0); + + /* Default method calls */ + + // invoke the inherited "defaultMethodA" + testInvokePos(ifaceClass, ref, "defaultMethodA", "()I", vm().mirrorOf(RESULT_A)); + + // invoke the inherited "defaultMethodB" + testInvokePos(ifaceClass, ref, "defaultMethodB", "()I", vm().mirrorOf(RESULT_A)); + + // invoke the inherited and overridden "defaultMethodC" + testInvokePos(ifaceClass, ref, "defaultMethodC", "()I", vm().mirrorOf(RESULT_B)); + + // invoke InterfaceB only "defaultMethodD" + testInvokePos(ifaceClass, ref, "defaultMethodD", "()I", vm().mirrorOf(RESULT_B)); + + // "implementedMethod" is not present in InterfaceB + testInvokeNeg(ifaceClass, ref, "implementedMethod", "()I", vm().mirrorOf(RESULT_TARGET), + "Invocation of non-default methods is not supported"); + + + /* Static method calls*/ + + // "staticMethodA" must not be inherited by InterfaceB + testInvokeNeg(ifaceClass, null, "staticMethodA", "()I", vm().mirrorOf(RESULT_A), + "Static interface methods are not inheritable"); + + // however it is possible to call "staticMethodA" on the actual instance + testInvokeNeg(ifaceClass, ref, "staticMethodA", "()I", vm().mirrorOf(RESULT_A), + "Static interface methods are not inheritable"); + + // "staticMethodB" is overridden in InterfaceB + testInvokePos(ifaceClass, null, "staticMethodB", "()I", vm().mirrorOf(RESULT_B)); + + // the instance invokes the overriden form of "staticMethodB" from InterfaceB + testInvokePos(ifaceClass, ref, "staticMethodB", "()I", vm().mirrorOf(RESULT_B)); + + // "staticMethodC" is present only in InterfaceB + testInvokePos(ifaceClass, null, "staticMethodC", "()I", vm().mirrorOf(RESULT_B)); + + // "staticMethodC" should be reachable from the instance too + testInvokePos(ifaceClass, ref, "staticMethodC", "()I", vm().mirrorOf(RESULT_B)); + } + + private void testImplementationClass(ReferenceType targetClass, ObjectReference thisObject) { + // Test invocations on the implementation object + + /* Default method calls */ + + // "defaultMethodA" is accessible and not overridden + testInvokePos(targetClass, thisObject, "defaultMethodA", "()I", vm().mirrorOf(RESULT_TARGET)); + + // "defaultMethodB" is accessible and overridden in TargetClass + testInvokePos(targetClass, thisObject, "defaultMethodB", "()I", vm().mirrorOf(RESULT_TARGET)); + + // "defaultMethodC" is accessible and overridden in InterfaceB + testInvokePos(targetClass, thisObject, "defaultMethodC", "()I", vm().mirrorOf(RESULT_TARGET)); + + // "defaultMethodD" is accessible + testInvokePos(targetClass, thisObject, "defaultMethodD", "()I", vm().mirrorOf(RESULT_TARGET)); + + + /* Non-default instance method calls */ + + // "classMethod" declared in TargetClass is accessible + testInvokePos(targetClass, thisObject, "classMethod", "()I", vm().mirrorOf(RESULT_TARGET)); + + // the abstract "implementedMethod" has been implemented in TargetClass + testInvokePos(targetClass, thisObject, "implementedMethod", "()I", vm().mirrorOf(RESULT_TARGET)); + + + /* Static method calls */ + + // All the static methods declared by the interfaces are not reachable from the instance of the implementor class + testInvokeNeg(targetClass, thisObject, "staticMethodA", "()I", vm().mirrorOf(RESULT_A), + "Static interface methods are not inheritable"); + + testInvokeNeg(targetClass, thisObject, "staticMethodB", "()I", vm().mirrorOf(RESULT_B), + "Static interface methods are not inheritable"); + + testInvokeNeg(targetClass, thisObject, "staticMethodC", "()I", vm().mirrorOf(RESULT_B), + "Static interface methods are not inheritable"); + + // All the static methods declared by the interfaces are not reachable through the implementor class + testInvokeNeg(targetClass, null, "staticMethodA", "()I", vm().mirrorOf(RESULT_A), + "Static interface methods are not inheritable"); + + testInvokeNeg(targetClass, null, "staticMethodB", "()I", vm().mirrorOf(RESULT_B), + "Static interface methods are not inheritable"); + + testInvokeNeg(targetClass, null, "staticMethodC", "()I", vm().mirrorOf(RESULT_B), + "Static interface methods are not inheritable"); + } + + private void testInvokePos(ReferenceType targetClass, ObjectReference ref, String methodName, + String methodSig, Value value) { + logInvocation(ref, methodName, methodSig, targetClass); + try { + invoke(targetClass, ref, methodName, methodSig, value); + System.err.println("--- PASSED"); + } catch (Exception e) { + System.err.println("--- FAILED"); + failure("FAILED: Invocation failed with error message " + e.getLocalizedMessage()); + } + } + + private void testInvokeNeg(ReferenceType targetClass, ObjectReference ref, String methodName, + String methodSig, Value value, String msg) { + logInvocation(ref, methodName, methodSig, targetClass); + try { + invoke(targetClass, ref, methodName, methodSig, value); + System.err.println("--- FAILED"); + failure("FAILED: " + msg); + } catch (Exception e) { + System.err.println("--- PASSED"); + + } + } + + private void invoke(ReferenceType targetClass, ObjectReference ref, String methodName, + String methodSig, Value value) + throws Exception { + Method method = getMethod(targetClass, methodName, methodSig); + if (method == null) { + throw new Exception("Can't find method: " + methodName + " for class = " + targetClass); + } + + println("Invoking " + (method.isAbstract() ? "abstract " : " ") + "method: " + method); + + Value returnValue = null; + if (ref != null) { + returnValue = invokeInstance(ref, method); + } else { + returnValue = invokeStatic(targetClass, method); + } + + println(" return val = " + returnValue); + // It has to be the same value as what we passed in! + if (returnValue.equals(value)) { + println(" " + method.name() + " return value matches: " + + value); + } else { + if (value != null) { + throw new Exception(method.name() + " returned: " + returnValue + + " expected: " + value ); + } else { + println(" " + method.name() + " return value : " + returnValue); + } + + } + } + + private Value invokeInstance(ObjectReference ref, Method method) throws Exception { + return ref.invokeMethod(mainThread, method, Collections.emptyList(), ObjectReference.INVOKE_NONVIRTUAL); + } + + private Value invokeStatic(ReferenceType refType, Method method) throws Exception { + if (refType instanceof ClassType) { + return ((ClassType)refType).invokeMethod(mainThread, method, Collections.emptyList(), ObjectReference.INVOKE_NONVIRTUAL); + } else { + return ((InterfaceType)refType).invokeMethod(mainThread, method, Collections.emptyList(), ObjectReference.INVOKE_NONVIRTUAL); + } + } + + private Method getMethod(ReferenceType rt, String name, String signature) { + if (rt == null) return null; + Method m = findMethod(rt, name, signature); + if (m == null) { + if (rt instanceof ClassType) { + for (Object ifc : ((ClassType)rt).interfaces()) { + m = getMethod((ReferenceType)ifc, name, signature); + if (m != null) { + break; + } + } + if (m == null) { + m = getMethod(((ClassType)rt).superclass(), name, signature); + } else { + if (m.isStatic()) { + // interface static methods are not inherited + m = null; + } + } + } else if (rt instanceof InterfaceType) { + for(Object ifc : ((InterfaceType)rt).superinterfaces()) { + m = getMethod((ReferenceType)ifc, name, signature); + if (m != null) { + if (m.isStatic()) { + // interface static methods are not inherited + m = null; + } + break; + } + } + } + } + + return m; + } + + private void logInvocation(ObjectReference ref, String methodName, String methodSig, ReferenceType targetClass) { + if (ref != null) { + System.err.println("Invoking: " + ref.referenceType().name() + "." + + methodName + methodSig + " with target of type " + + targetClass.name()); + } else { + System.err.println("Invoking static : " + targetClass.name() + "." + + methodName + methodSig); + } + } +} + + + diff -r a77941f17614 -r 0d1f816217dc jdk/test/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java --- a/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java Wed Jul 05 19:39:35 2017 +0200 @@ -58,6 +58,7 @@ ProcessBuilder pb = ProcessTools. createJavaProcessBuilder( + "-XX:+UseConcMarkSweepGC", // this will cause UseParNewGC to be FLAG_SET_ERGO "-XX:+PrintGCDetails", "-XX:Flags=" + flagsFile.getAbsolutePath(), "-cp", System.getProperty("test.class.path") + File.pathSeparator + getToolsJarPath(), @@ -84,12 +85,20 @@ setOptionUsingAttach("HeapDumpPath", "/a/sample/path"); // check the origin field for all the options we set + + // Not set, so should be default checkOrigin("ManagementServer", Origin.DEFAULT); + // Set on the command line checkOrigin("PrintGCDetails", Origin.VM_CREATION); + // Set in _JAVA_OPTIONS checkOrigin("PrintOopAddress", Origin.ENVIRON_VAR); + // Set in -XX:Flags file checkOrigin("PrintSafepointStatistics", Origin.CONFIG_FILE); + // Set through j.l.m checkOrigin("HeapDumpOnOutOfMemoryError", Origin.MANAGEMENT); - checkOrigin("NewSize", Origin.ERGONOMIC); + // Should be set by the VM, when we set UseConcMarkSweepGC + checkOrigin("UseParNewGC", Origin.ERGONOMIC); + // Set using attach checkOrigin("HeapDumpPath", Origin.ATTACH_ON_DEMAND); } } diff -r a77941f17614 -r 0d1f816217dc jdk/test/com/sun/tools/attach/BasicTests.java diff -r a77941f17614 -r 0d1f816217dc jdk/test/com/sun/tools/attach/RunnerUtil.java diff -r a77941f17614 -r 0d1f816217dc jdk/test/com/sun/tools/attach/java.policy.allow diff -r a77941f17614 -r 0d1f816217dc jdk/test/com/sun/tools/attach/java.policy.deny diff -r a77941f17614 -r 0d1f816217dc jdk/test/demo/jvmti/mtrace/TraceJFrame.java --- a/jdk/test/demo/jvmti/mtrace/TraceJFrame.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/demo/jvmti/mtrace/TraceJFrame.java Wed Jul 05 19:39:35 2017 +0200 @@ -36,7 +36,7 @@ public class TraceJFrame { public static void main(String args[]) throws Exception { - if (GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance()) { + if (GraphicsEnvironment.isHeadless()) { System.out.println("JFrame test was skipped due to headless mode"); } else { DemoRun demo; diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/Frame/7024749/bug7024749.java --- a/jdk/test/java/awt/Frame/7024749/bug7024749.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/java/awt/Frame/7024749/bug7024749.java Wed Jul 05 19:39:35 2017 +0200 @@ -23,7 +23,7 @@ /* * @test - * @bug 7024749 + * @bug 7024749 8019990 * @summary JDK7 b131---a crash in: Java_sun_awt_windows_ThemeReader_isGetThemeTransitionDurationDefined+0x75 * @library ../../regtesthelpers * @build Util diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/Frame/SlideNotResizableTest/SlideNotResizableTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Frame/SlideNotResizableTest/SlideNotResizableTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import sun.awt.SunToolkit; + +import java.awt.*; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.event.InputEvent; + +/** + * @test + * @bug 8032595 + * @summary setResizable(false) makes a frame slide down + * @author Petr Pchelko + */ + +public class SlideNotResizableTest { + + private static volatile boolean passed = false; + private static final Dimension FRAME_SIZE = new Dimension(100, 100); + private static final Point FRAME_LOCATION = new Point(200, 200); + + public static void main(String[] args) throws Throwable { + Frame aFrame = null; + try { + aFrame = new Frame(); + aFrame.setSize(FRAME_SIZE); + aFrame.setLocation(FRAME_LOCATION); + aFrame.setResizable(false); + aFrame.setVisible(true); + + sync(); + + if (!aFrame.getLocation().equals(FRAME_LOCATION)) { + throw new RuntimeException("FAILED: Wrong frame position"); + } + } finally { + if (aFrame != null) { + aFrame.dispose(); + } + } + } + + private static void sync() throws InterruptedException { + ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); + Thread.sleep(1000); + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/Paint/bug8024864.java --- a/jdk/test/java/awt/Paint/bug8024864.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/java/awt/Paint/bug8024864.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - * @bug 8024864 + * @bug 8024864 8031422 * @summary [macosx] Problems with rendering of controls * @author Petr Pchelko * @library ../regtesthelpers @@ -65,7 +65,7 @@ Util.waitForIdle(r); Dimension frameSize = frame.getSize(); - Point loc = new Point(frameSize.width - 5, frameSize.height - 5); + Point loc = new Point(frameSize.width - 15, frameSize.height - 15); SwingUtilities.convertPointToScreen(loc, frame); Color c = r.getPixelColor(loc.x, loc.y); diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/datatransfer/DataFlavor/EqualsHashCodeSymmetryTest/EqualsHashCodeSymmetryTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/datatransfer/DataFlavor/EqualsHashCodeSymmetryTest/EqualsHashCodeSymmetryTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.datatransfer.DataFlavor; + +/** + * @test + * @bug 8038999 + * @summary DataFlavor.equals is not symmetric + * @author Petr Pchelko + */ +public class EqualsHashCodeSymmetryTest { + + private static final DataFlavor[] dataFlavors = { + DataFlavor.stringFlavor, + DataFlavor.imageFlavor, + DataFlavor.javaFileListFlavor, + DataFlavor.allHtmlFlavor, + DataFlavor.selectionHtmlFlavor, + DataFlavor.fragmentHtmlFlavor, + createFlavor("text/html; class=java.lang.String"), + new DataFlavor(String.class, "My test flavor number 1"), + new DataFlavor(String.class, "My test flavor number 2"), + new DataFlavor(StringBuilder.class, "My test flavor number 1") + }; + + public static void main(String[] args) { + testEqualsSymmetry(); + testEqualsHashCodeConsistency(); + testSimpleCollision(); + } + + private static void testEqualsSymmetry() { + for (DataFlavor flavor1 : dataFlavors) { + for (DataFlavor flavor2 : dataFlavors) { + if (flavor1.equals(flavor2) != flavor2.equals(flavor1)) { + throw new RuntimeException( + String.format("Equals is not symmetric for %s and %s", flavor1, flavor2)); + } + } + } + } + + private static void testEqualsHashCodeConsistency() { + for (DataFlavor flavor1 : dataFlavors) { + for (DataFlavor flavor2 : dataFlavors) { + if ((flavor1.equals(flavor2) && flavor1.hashCode() != flavor2.hashCode())) { + throw new RuntimeException( + String.format("Equals and hash code not consistent for %s and %s", flavor1, flavor2)); + } + } + } + } + + private static void testSimpleCollision() { + if (createFlavor("text/html; class=java.lang.String").hashCode() == DataFlavor.allHtmlFlavor.hashCode()) { + throw new RuntimeException("HashCode collision because the document parameter is not used"); + } + } + + private static DataFlavor createFlavor(String mime) { + try { + return new DataFlavor(mime); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/dnd/DragSourceListenerSerializationTest/DragSourceListenerSerializationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/dnd/DragSourceListenerSerializationTest/DragSourceListenerSerializationTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4422345 8039083 + @summary tests serialization of DragSourceListeners + @author das@sparc.spb.su area=dnd + @library ../../../../lib/testlibrary + @build jdk.testlibrary.Asserts + @run main/othervm DragSourceListenerSerializationTest +*/ + +import java.awt.Button; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureRecognizer; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceContext; +import java.awt.dnd.DragSourceListener; +import java.awt.dnd.DragSourceMotionListener; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Arrays; +import java.util.TooManyListenersException; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static jdk.testlibrary.Asserts.assertEquals; + +public class DragSourceListenerSerializationTest { + public static void main(String[] args) throws Exception { + DragSource ds = new DragSource(); + TestDragSourceAdapter dsa1 = new TestDragSourceAdapter(1); + TestDragSourceAdapter dsa2 = new TestDragSourceAdapter(2); + Component c = new Button(); + DragGestureRecognizer dgr = ds.createDefaultDragGestureRecognizer(c, + DnDConstants.ACTION_COPY, + e -> e.startDrag(null, null)); + MouseEvent me = new MouseEvent(c, MouseEvent.MOUSE_PRESSED, 0, + InputEvent.CTRL_MASK, 100, 100, 0, false); + DragGestureEvent dge = new DragGestureEvent(dgr, DnDConstants.ACTION_COPY, + new Point(100, 100), + Arrays.asList(me)); + DragSourceContext dsc = new DragSourceContext( + Toolkit.getDefaultToolkit().createDragSourceContextPeer(dge), + dge, + new Cursor(Cursor.HAND_CURSOR), + null, null, new StringSelection("TEXT"), null); + + ds.addDragSourceListener(dsa1); + ds.addDragSourceListener(dsa2); + ds.addDragSourceListener(dsa2); + ds.addDragSourceMotionListener(dsa1); + ds.addDragSourceMotionListener(dsa1); + ds.addDragSourceMotionListener(dsa2); + dsc.addDragSourceListener(dsa2); + + byte[] serialized; + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos)) { + oos.writeObject(dsc); + serialized = bos.toByteArray(); + } + + DragSourceContext dsc_copy; + try (ByteArrayInputStream bis = new ByteArrayInputStream(serialized); + ObjectInputStream ois = new ObjectInputStream(bis)) { + dsc_copy = (DragSourceContext) ois.readObject(); + } + + try { + dsc_copy.addDragSourceListener(dsa1); + throw new RuntimeException("Test failed. Listener addition succeeded"); + } catch (TooManyListenersException ignored) { + } + + try { + dsc_copy.addDragSourceListener(dsa2); + throw new RuntimeException("Test failed. Listener addition succeeded"); + } catch (TooManyListenersException ignored) { + } + + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos)) { + oos.writeObject(ds); + serialized = bos.toByteArray(); + } + + DragSource ds_copy; + try (ByteArrayInputStream bis = new ByteArrayInputStream(serialized); + ObjectInputStream ois = new ObjectInputStream(bis)) { + ds_copy = (DragSource) ois.readObject(); + } + + DragSourceListener[] dsls = ds_copy.getDragSourceListeners(); + assertEquals(3, dsls.length, "DragSourceListeners number"); + assertEquals(1, Stream.of(dsls).filter(dsa1::equals).collect(Collectors.counting()).intValue()); + assertEquals(2, Stream.of(dsls).filter(dsa2::equals).collect(Collectors.counting()).intValue()); + + DragSourceMotionListener[] dsmls = ds_copy.getDragSourceMotionListeners(); + assertEquals(3, dsmls.length, "DragSourceMotionListeners number"); + assertEquals(2, Stream.of(dsmls).filter(dsa1::equals).collect(Collectors.counting()).intValue()); + assertEquals(1, Stream.of(dsmls).filter(dsa2::equals).collect(Collectors.counting()).intValue()); + } +} + +class TestDragSourceAdapter extends DragSourceAdapter implements Serializable { + final int id; + + TestDragSourceAdapter(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + public boolean equals(Object obj) { + if (obj instanceof TestDragSourceAdapter) { + TestDragSourceAdapter tdsa = (TestDragSourceAdapter) obj; + return tdsa.getId() == getId(); + } + return false; + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/Dialog/DestinationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/Dialog/DestinationTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4846344 4851365 4851321 4851316 4863656 5046198 6293139 + * @summary Confirm that cancelling the dialog will not prompt for file. + * @run main/manual DestinationTest + */ +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.io.*; + +public class DestinationTest extends Frame implements ActionListener { + //Declare things used in the test, like buttons and labels here + + DisplayImages images; + Button nativeDlg, nativeDlg2, commonSelectionDlg, commonRangeDlg, fileDlg; + + public DestinationTest() { + + images = new DisplayImages(); + images.setSize(530, 480); + add(images, "Center"); + + Panel printpanel = new Panel(); + + nativeDlg = new Button("Native"); + nativeDlg.addActionListener(this); + printpanel.add(nativeDlg); + + nativeDlg2 = new Button("Native 2"); + nativeDlg2.addActionListener(this); + printpanel.add(nativeDlg2); + + commonSelectionDlg = new Button("Common Selection"); + commonSelectionDlg.addActionListener(this); + printpanel.add(commonSelectionDlg); + + commonRangeDlg = new Button("Common Range"); + commonRangeDlg.addActionListener(this); + printpanel.add(commonRangeDlg); + + fileDlg = new Button("Print To File - Common Dialog"); + fileDlg.addActionListener(this); + printpanel.add(fileDlg); + + add(printpanel, "South"); + setSize(900, 300); + setVisible(true); + } + + public static void main (String args[]) { + DestinationTest test = new DestinationTest(); + } + + + public void actionPerformed(ActionEvent e) { + + JobAttributes ja = new JobAttributes(); + PageAttributes pa = new PageAttributes(); + ja.setDestination(JobAttributes.DestinationType.FILE); + ja.setFileName("test_file_name.prn"); + + if(e.getSource()== nativeDlg) { + ja.setDefaultSelection(JobAttributes.DefaultSelectionType.SELECTION); + ja.setPageRanges(new int[][] {new int[] {2,3}, new int[] {5,6}}); + ja.setDialog(JobAttributes.DialogType.NATIVE); + } + + if(e.getSource()== nativeDlg2) { + ja.setFileName(""); + ja.setDialog(JobAttributes.DialogType.NATIVE); + } + + if(e.getSource()== commonRangeDlg) { + ja = new JobAttributes(); + ja.setDefaultSelection(JobAttributes.DefaultSelectionType.RANGE); + ja.setPageRanges(new int[][] {new int[] {1,3}, new int[] {5,6}}); + ja.setDialog(JobAttributes.DialogType.COMMON); + } + + if (e.getSource() == fileDlg) { + ja = new JobAttributes(); + ja.setDestination(JobAttributes.DestinationType.FILE); + ja.setDialog(JobAttributes.DialogType.COMMON); + } + + if(e.getSource()== commonSelectionDlg) { + ja.setDefaultSelection(JobAttributes.DefaultSelectionType.SELECTION); + ja.setDialog(JobAttributes.DialogType.COMMON); + } + + PrintJob pjob = getToolkit().getPrintJob(this,"Printing Test",ja,pa); + System.out.println("6293139: Chosen printer is: "+ja.getPrinter()); + if(pjob != null) { + + Graphics pg = pjob.getGraphics(); + + if(pg != null) { + //images.printAll(pg); + this.printAll(pg); + pg.dispose(); + } + pjob.end(); + } + } +} + +class DisplayImages extends Canvas { + + public void paint(Graphics g) { + + g.setFont(new Font("Helvetica", Font.BOLD, 12)); + g.drawString("PRINTING TEST", 1, 10); + g.drawString(" 4846344: Confirm that cancelling the native dialog will not prompt for file.", 1, 25); + g.drawString(" 4851365: Confirm that printing in native dialog shows test_file_name.prn as default.", 1, 40); + g.drawString(" 4851321: Confirm that in the Common Range dialog, page ranges is set to 1-6.", 1, 55); + g.drawString(" 4851316: Confirm that NPE is not thrown upon selecting Common Selection dialog.", 1, 70); + g.drawString(" 4863656: Confirm that no IAE is thrown when printing in native dialog.", 1, 85); + g.drawString(" 4864444: Confirm that the default directory in Native 2 is same as current one with no filename set.", 1, 100); + g.drawString(" 5046198: Confirm that the default filename in Common Range dialog when printing to a file is same as that of PrintToFile dialog.", 1, 115); + g.drawString(" 6293139: In Common Range dialog, change printer before printing then confirm the chosen printer.", 1, 130); + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/Dialog/MediaInPrintable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/Dialog/MediaInPrintable.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4869575 6361766 + * @summary Setting orientation in the page format does not have any effect on the printout. To test 6361766, the application must exit. + * @run main/manual MediaInPrintable + */ +import java.awt.*; +import java.awt.print.*; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; + +public class MediaInPrintable implements Printable { + private static Font fnt = new Font("Helvetica",Font.PLAIN,24); + public static void main(String[] args) { + + System.out.println("arguments : native1 | native2\nExpected output :\n\tnative1 - Landscape orientation.\n\tnative2 - Legal paper is selected."); + if (args.length == 0) { + return; + } + + + // Get a PrinterJob + PrinterJob job = PrinterJob.getPrinterJob(); + PageFormat pf = new PageFormat(); + + if (args[0].equals("native1")) { + pf.setOrientation(PageFormat.LANDSCAPE); + job.setPrintable(new MediaInPrintable(), pf); + if (job.printDialog()) { + // Print the job if the user didn't cancel printing + try { + job.print(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if (args[0].equals("native2")) { + Paper p = new Paper(); + p.setSize(612.0, 1008.0); + p.setImageableArea(72.0, 72.0, 468.0, 864.0); + pf.setPaper(p); + + job.setPrintable(new MediaInPrintable(), pf); + if (job.printDialog()) { + // Print the job if the user didn't cancel printing + try { + job.print(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + } + + //System.exit(0); + } + + public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException { + if (pageIndex > 0) { + return Printable.NO_SUCH_PAGE; + } + g.setFont(fnt); + g.setColor(Color.green); + g.drawString("Page " + (pageIndex+1), 100, 100); + return Printable.PAGE_EXISTS; + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/Dialog/PrintApplet.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/Dialog/PrintApplet.html Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,29 @@ +!-- + Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> + +PrintApplet +

    PrintApplet

    + + + +

    diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/Dialog/PrintApplet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/Dialog/PrintApplet.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 5024549 + @summary Pass if dialogs are modal. + @run applet/manual PrintApplet.html +*/ +import java.awt.*; +import java.awt.event.*; +import java.applet.*; +import java.awt.print.*; +import javax.swing.*; + +public class PrintApplet extends JApplet implements Printable { + private JButton jButton1 = new JButton(); + + + public PrintApplet() { + } + + public void init() { + try { + jbInit(); + } + catch(Exception e) { + e.printStackTrace(); + } + } + + private void jbInit() throws Exception { + jButton1.setText("PRINT"); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + jButton1_actionPerformed(e); + } + }); + jButton1.setBounds(new Rectangle(165, 248, 80, 30)); + this.setSize(new Dimension(400,300)); + this.getContentPane().setLayout(null); + this.getContentPane().setBackground(Color.pink); + this.getContentPane().add(jButton1, BorderLayout.SOUTH); + } + + public void start() { + } + + public void stop() { + } + + public void destroy() { + } + + public String getAppletInfo() { + return "Applet inf"; + } + + public String[][] getParameterInfo() { + return null; + } + + + public int print(Graphics g, PageFormat pf, int page) throws PrinterException { + System.out.println("Calling print"); + if (page == 0) { + Graphics2D g2 = (Graphics2D)g; + g2.translate(pf.getImageableX(), pf.getImageableY()); + g2.setColor(Color.black); + g2.drawString("Hello World", 20, 100); + + return Printable.PAGE_EXISTS; + } + return Printable.NO_SUCH_PAGE; + } + + + + void jButton1_actionPerformed(ActionEvent e) { + PrinterJob printJob = null; + PageFormat pageFormat = null; + Paper prtPaper = null; + boolean bPrintFlg = true; + + + try{ + printJob = PrinterJob.getPrinterJob(); + + } + catch(SecurityException se){ + + bPrintFlg = false; + } + + if (bPrintFlg) { + + pageFormat = printJob.pageDialog(printJob.defaultPage()); + System.out.println("PrintApplet: pageFormat = "+pageFormat.getWidth()/72.0+" x "+pageFormat.getHeight()/72.0); + if (pageFormat != null) { + + prtPaper = pageFormat.getPaper(); + pageFormat.setPaper(prtPaper); + + + printJob.setPrintable(this, pageFormat); + } + + if (printJob.printDialog()) { + + try { + printJob.print(); + } + catch (java.awt.print.PrinterException ex) { + ex.printStackTrace(); + } + + } + + } + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/Dialog/PrintDialog.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/Dialog/PrintDialog.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 6342748 + @summary Pass if dialogs display correctly + @run main/manual PrintDialog +*/ +import java.awt.print.*; +import javax.print.attribute.*; + +public class PrintDialog { + + public static void main(java.lang.String[] args) { + PrinterJob pj = PrinterJob.getPrinterJob(); + PrintRequestAttributeSet pSet = new HashPrintRequestAttributeSet(); + System.out.println("Verify page setup dialog appears correctly then cancel or OK"); + pj.pageDialog(pSet); + System.out.println("Verify all tabs of print dialog appear correctly then cancel or OK"); + pj.printDialog(pSet); + return; + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/Dialog/PrintDlgApp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/Dialog/PrintDlgApp.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4865976 7158366 + @summary Pass if it program exits. + @run main/manual PrintDlgApp +*/ +import java.awt.*; +import java.awt.print.*; +import javax.print.attribute.*; +import javax.print.attribute.standard.Copies; +import javax.print.attribute.standard.Destination; +import java.util.Locale; + +import javax.print.*; + +class PrintDlgApp implements Printable { + /** + * Constructor + */ + public PrintDlgApp() { + super(); + } + /** + * Starts the application. + */ + public static void main(java.lang.String[] args) { + PrintDlgApp pd = new PrintDlgApp(); + PrinterJob pj = PrinterJob.getPrinterJob(); + System.out.println(pj); + PrintRequestAttributeSet pSet = new HashPrintRequestAttributeSet(); + pSet.add(new Copies(1)); + //PageFormat pf = pj.pageDialog(pSet); + PageFormat pf = new PageFormat(); + System.out.println("Setting Printable...pf = "+pf); + if (pf == null) { + return; + } + pj.setPrintable(pd,pf); + + //try { pj.setPrintService(services[0]); } catch(Exception e) { e.printStackTrace(); } + pSet.add(new Destination(new java.io.File("./out.prn").toURI())); + System.out.println("open PrintDialog.."); + for (int i=0; i<2; i++) { + if (pj.printDialog(pSet)) { + try { + System.out.println("About to print the data ..."); + pj.print(pSet); + System.out.println("Printed"); + } + catch (PrinterException pe) { + pe.printStackTrace(); + } + } + } + + } + + //printable interface + public int print(Graphics g, PageFormat pf, int pi) throws +PrinterException { + + if (pi > 0) { + System.out.println("pi is greater than 0"); + return Printable.NO_SUCH_PAGE; + } + // Simply draw two rectangles + Graphics2D g2 = (Graphics2D)g; + g2.setColor(Color.black); + g2.translate(pf.getImageableX(), pf.getImageableY()); + g2.drawRect(1,1,200,300); + g2.drawRect(1,1,25,25); + System.out.println("print method called "+pi); + return Printable.PAGE_EXISTS; + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/Dialog/PrintDlgPageable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/Dialog/PrintDlgPageable.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4869502 4869539 + * @summary Confirm that ToPage is populated for argument =2. Range is disabled for argument = 0. + * @run main/manual PrintDlgPageable + */ +import java.awt.*; +import java.awt.print.*; +import java.util.Locale; + +import javax.print.*; + +class PrintDlgPageable implements Printable { + public static int arg; + /** + * Constructor + */ + public PrintDlgPageable() { + super(); + } + /** + * Starts the application. + */ + public static void main(java.lang.String[] args) { + if (args.length < 1) { + System.out.println("usage: java PrintDlgPageable { 0 | 2}"); + return; + } + arg = Integer.parseInt(args[0]); + PrintDlgPageable pd = new PrintDlgPageable(); + PrinterJob pj = PrinterJob.getPrinterJob(); + PageableHandler handler = new PageableHandler(); + pj.setPageable(handler); + + System.out.println("open PrintDialog.."); + if (pj.printDialog()) { + try { + System.out.println("About to print the data ..."); + pj.print(); + System.out.println("Printed"); + } + catch (PrinterException pe) { + pe.printStackTrace(); + } + } + + } + + //printable interface + public int print(Graphics g, PageFormat pf, int pi) throws +PrinterException { + + /*if (pi > 0) { + System.out.println("pi is greater than 0"); + return Printable.NO_SUCH_PAGE; + }*/ + // Simply draw two rectangles + Graphics2D g2 = (Graphics2D)g; + g2.setColor(Color.black); + g2.translate(pf.getImageableX(), pf.getImageableY()); + g2.drawRect(1,1,200,300); + g2.drawRect(1,1,25,25); + System.out.println("print method called "+pi + " Orientation "+pf.getOrientation()); + return Printable.PAGE_EXISTS; + } +} + +class PageableHandler implements Pageable { + + PageFormat pf = new PageFormat(); + + public int getNumberOfPages() { + return PrintDlgPageable.arg; + //return 0; + } + + public Printable getPrintable(int pageIndex) { + return new PrintDlgPageable(); + } + + public PageFormat getPageFormat(int pageIndex) { + System.out.println("getPageFormat called "+pageIndex); + if (pageIndex == 0) { + pf.setOrientation(PageFormat.PORTRAIT); + System.out.println("Orientation returned from Pageable "+findOrientation(pf.getOrientation())); + return pf; + } else { + pf.setOrientation(PageFormat.LANDSCAPE); + System.out.println("Orientation returned from Pageable "+findOrientation(pf.getOrientation())); + return pf; + } + } + + public String findOrientation(int orient) { + if (orient == PageFormat.LANDSCAPE) { + return "LANDSCAPE"; + }else if (orient == PageFormat.PORTRAIT) { + return "PORTRAIT"; + } else if (orient == PageFormat.REVERSE_LANDSCAPE) { + return "REVERSE LANDSCAPE"; + } else { + return null; + } + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/Dialog/RestoreActiveWindowTest/RestoreActiveWindowTest.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/Dialog/RestoreActiveWindowTest/RestoreActiveWindowTest.html Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,43 @@ + + + + + +RestoreActiveWindowTest + + + +

    RestoreActiveWindowTest
    Bug ID: 6365992

    + +

    See the dialog box (usually in upper left corner) for instructions

    + + + + diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/Dialog/RestoreActiveWindowTest/RestoreActiveWindowTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/Dialog/RestoreActiveWindowTest/RestoreActiveWindowTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + test + @bug 6365992 6379599 + @summary REG: Showing and disposing a native print dialog makes the main frame inactive, Win32 + @author Dmitry.Cherepanov@SUN.COM area=awt.printdialog + @run applet/manual=yesno RestoreActiveWindowTest.html +*/ + +import java.applet.Applet; +import java.awt.*; +import java.awt.event.*; +import java.awt.print.*; +import javax.print.attribute.*; + +public class RestoreActiveWindowTest extends Applet +{ + Button showBtn1 = new Button("show a native print dialog"); + Button showBtn2 = new Button("show a native page dialog"); + + public void init() + { + showBtn1.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent ae) { + PrinterJob.getPrinterJob().printDialog(); + } + }); + showBtn2.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent ae){ + PrinterJob.getPrinterJob().pageDialog(new PageFormat()); + } + }); + + add(showBtn1); + add(showBtn2); + + String[] instructions = { + "1.1) Click on 'show a native print dialog'. A native print dialog will come up.", + "1.2) Click on the 'close'(X) button. The dialog will be closed.", + "1.3) After the dialog closing another window should become the active window.", + "1.4) If there no any active window then the test failed.", + "2.1) Click on 'show a native page dialog'. A native page dialog will come up.", + "2.2) Click on the 'close'(X) button. The dialog will be closed.", + "2.3) After the dialog closing another window should become the active window.", + "2.4) If there no any active window then the test failed.", + "3) Test Passed." + }; + + Sysout.createDialogWithInstructions( instructions ); + + }//End init() + + public void start () + { + //Get things going. Request focus, set size, et cetera + setSize (200,200); + show(); + + }// start() + + //The rest of this class is the actions which perform the test... + + //Use Sysout.println to communicate with the user NOT System.out!! + //Sysout.println ("Something Happened!"); + +}// class ManualYesNoTest + +/* 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 = 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 -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PageFormat/CustomPaper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PageFormat/CustomPaper.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4355514 + * @bug 4385157 + * @author Jennifer Godinez + * @summary Prints a rectangle to show the imageable area of a + * 12in x 14in custom paper size. + * @run main/manual CustomPaper + */ + +import java.awt.*; +import java.awt.print.*; +import java.awt.geom.*; + +public class CustomPaper implements Pageable, Printable{ + + private static double PIXELS_PER_INCH = 72.0; + + private PrinterJob printerJob; + private PageFormat pageFormat; + + CustomPaper(){ + printerJob = PrinterJob.getPrinterJob(); + createPageFormat(); + } + + private void createPageFormat(){ + pageFormat = new PageFormat(); + Paper p = new Paper(); + double width = 12.0*PIXELS_PER_INCH; + double height = 14.0*PIXELS_PER_INCH; + double ix = PIXELS_PER_INCH; + double iy = PIXELS_PER_INCH; + double iwidth = width - 2.0*PIXELS_PER_INCH; + double iheight = height - 2.0*PIXELS_PER_INCH; + p.setSize(width, height); + p.setImageableArea(ix, iy, iwidth, iheight); + pageFormat.setPaper(p); + } + + public Printable getPrintable(int index){ + return this; + } + + public PageFormat getPageFormat(int index){ + return pageFormat; + } + + public int getNumberOfPages(){ + return 1; + } + + public void print(){ + if(printerJob.printDialog()) + { + try{ + printerJob.setPageable(this); + printerJob.print(); + }catch(Exception e){e.printStackTrace();} + } + + } + + public int print(Graphics g, PageFormat pf, int pageIndex){ + if(pageIndex == 0){ + Graphics2D g2 = (Graphics2D)g; + Rectangle2D r = new Rectangle2D.Double(pf.getImageableX(), + pf.getImageableY(), + pf.getImageableWidth(), + pf.getImageableHeight()); + g2.setStroke(new BasicStroke(3.0f)); + g2.draw(r); + return PAGE_EXISTS; + }else{ + return NO_SUCH_PAGE; + } + } + + public static void main(String[] args){ + + String[] instructions = + { + "You must have a printer that supports custom paper size of ", + "at least 12 x 14 inches to perform this test. It requires", + "user interaction and you must have a 12 x 14 inch paper available.", + " ", + "To test bug ID 4385157, click OK on print dialog box to print.", + " ", + "To test bug ID 4355514, select the printer in the Print Setup dialog and add a ", + "custom paper size under Printer properties' Paper selection menu. ", + "Set the dimension to width=12 inches and height=14 inches.", + "Select this custom paper size before proceeding to print.", + " ", + "Visual inspection of the one-page printout is needed. A passing", + "test will print a rectangle of the imageable area which is approximately", + "10 x 12 inches.", + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + CustomPaper pt = new CustomPaper(); + pt.print(); + //System.exit (0); + } + +} + + +class Sysout { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PageFormat/NullPaper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PageFormat/NullPaper.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,423 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4199506 + @summary java.awt.print.PageFormat.setpaper(Paper paper) + assertion test fails by not throwing + NullPointerException when a null paper instance is + passed as argument and this is specified in the doc. + @author rbi: area=PageFormat + @run main NullPaper +*/ + + +//*** global search and replace NullPaper with name of the test *** + +/** + * NullPaper.java + * + * summary: java.awt.print.PageFormat.setpaper(Paper paper) + assertion test fails by not throwing + NullPointerException when a null paper instance is + passed as argument and this is specified in the doc. + + */ + +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.*; +import java.awt.print.*; + +// This test is a "main" test as applets would need Runtime permission +// "queuePrintJob". + +public class NullPaper { + + private static void init() + { + //*** Create instructions for the user here *** + + String[] instructions = + { + "This test should throw a NullPointerException. ", + "If the NullPointerException is correctly thrown ", + "by the call to setPaper() then the test succeeds. ", + "If no exception is thrown by setPaper() or if an ", + "exception other than NullPointerException is thrown ", + "then the test fails." + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + boolean settingNullWorked = false; + + try { + /* Setting the paper to null should throw an exception. + * The bug was the exception was not being thrown. + */ + new PageFormat().setPaper(null); + settingNullWorked = true; + + /* If the test succeeds we'll end up here, so write + * to standard out. + */ + } catch (NullPointerException e) { + pass(); + + /* The test failed if we end up here because an exception + * other than the one we were expecting was thrown. + */ + } catch (Exception e) { + fail("Instead of the expected NullPointerException, '" + e + "' was thrown."); + } + + if (settingNullWorked) { + fail("The expected NullPointerException was not thrown"); + } + + }//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-defined + 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; + + 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 passed nor test failed 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) + { + 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(); + } + //pass was called from a different thread, so set the flag and interrupt + // the main thead. + 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 NullPaper + +//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 **************** + +// make listeners in a class defined here, and 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 + + NullPaper.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + NullPaper.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.show(); + 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.show(); + 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 implements ActionListener + { + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + Panel buttonP = new Panel(); + Button passB = new Button( "pass" ); + Button failB = new Button( "fail" ); + + //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); + + passB = new Button( "pass" ); + passB.setActionCommand( "pass" ); + passB.addActionListener( this ); + buttonP.add( "East", passB ); + + failB = new Button( "fail" ); + failB.setActionCommand( "fail" ); + failB.addActionListener( this ); + buttonP.add( "West", failB ); + + add( "South", buttonP ); + pack(); + + show(); + }// 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" ); + } + + //catch presses of the passed and failed buttons. + //simply call the standard pass() or fail() static methods of + //NullPaper + public void actionPerformed( ActionEvent e ) + { + if( e.getActionCommand() == "pass" ) + { + NullPaper.pass(); + } + else + { + NullPaper.fail(); + } + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PageFormat/Orient.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PageFormat/Orient.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,460 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4236095 + @summary Confirm that the you get three pages of output, one + each in portrait, landscape, and reverse landscape + orientations. + @author rbi: area=PageFormat + @run main/manual Orient +*/ + + +//*** global search and replace Orient with name of the test *** + +/** + * Orient.java + * + * summary: + */ + +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.*; +import java.awt.print.*; + +// This test is a "main" test as applets would need Runtime permission +// "queuePrintJob". + +public class Orient implements Printable { + + private static void init() + { + //*** Create instructions for the user here *** + + String[] instructions = + { + "On-screen inspection is not possible for this printing-specific", + "test therefore its only output is three printed pages.", + "To be able to run this test it is required to have a default", + "printer configured in your user environment.", + "", + "Visual inspection of the printed page is needed. A passing", + "test will print three pages each containing a large oval ", + "with the text describing the orientation: PORTRAIT, LANDSCAPE", + "or REVERSE_LANDSCAPE, inside of it. The first page will ", + "be emitted in portait orientation, the second page in landscape ", + "orientation and the third page in reverse-landscape orientation. ", + "On each page the oval will be wholly within the imageable area ", + "of the page. In a failing test the oval on the third page ", + "will be clipped against the imageable area.", + "Axes will indicate the direction of increasing X and Y" + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PrinterJob pjob = PrinterJob.getPrinterJob(); + + Book book = new Book(); + + // Page 1 + PageFormat portrait = pjob.defaultPage(); + portrait.setOrientation(PageFormat.PORTRAIT); + book.append(new Orient(), portrait); + + // Page 2 + PageFormat landscape = pjob.defaultPage(); + landscape.setOrientation(PageFormat.LANDSCAPE); + book.append(new Orient(), landscape); + + // Page 3 + PageFormat reverseLandscape = pjob.defaultPage(); + reverseLandscape.setOrientation(PageFormat.REVERSE_LANDSCAPE); + book.append(new Orient(), reverseLandscape); + + pjob.setPageable(book); + try { + pjob.print(); + } catch (PrinterException e) { + e.printStackTrace(); + } + + }//End init() + + public int print(Graphics g, PageFormat pf, int pageIndex) { + + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pf.getImageableX(), pf.getImageableY()); + drawGraphics(g2d, pf); + return Printable.PAGE_EXISTS; + } + + void drawGraphics(Graphics2D g, PageFormat pf) { + double iw = pf.getImageableWidth(); + double ih = pf.getImageableHeight(); + + g.setColor(Color.black); + String orientation; + switch (pf.getOrientation()) { + case PageFormat.PORTRAIT : orientation = "PORTRAIT"; + break; + case PageFormat.LANDSCAPE : orientation = "LANDSCAPE"; + break; + case PageFormat.REVERSE_LANDSCAPE : + orientation = "REVERSE_LANDSCAPE"; + break; + default : orientation = "INVALID"; + } + g.drawString(orientation, 100, 300); + g.draw(new Ellipse2D.Double(0, 0, iw, ih)); + g.drawString("(0,0)", 5,15); + g.drawLine(0,0,300,0); + g.drawString("X", 300,15); + g.drawLine(0,0,0,300); + g.drawString("Y",5,300); + } + + + /***************************************************** + 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-defined + 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; + + 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 passed nor test failed 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) + { + 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(); + } + //pass was called from a different thread, so set the flag and interrupt + // the main thead. + 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 Orient + +//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 **************** + +// make listeners in a class defined here, and 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 + + Orient.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + Orient.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.show(); + 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.show(); + 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 implements ActionListener + { + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + Panel buttonP = new Panel(); + Button passB = new Button( "pass" ); + Button failB = new Button( "fail" ); + + //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); + + passB = new Button( "pass" ); + passB.setActionCommand( "pass" ); + passB.addActionListener( this ); + buttonP.add( "East", passB ); + + failB = new Button( "fail" ); + failB.setActionCommand( "fail" ); + failB.addActionListener( this ); + buttonP.add( "West", failB ); + + add( "South", buttonP ); + pack(); + + show(); + }// 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" ); + } + + //catch presses of the passed and failed buttons. + //simply call the standard pass() or fail() static methods of + //Orient + public void actionPerformed( ActionEvent e ) + { + if( e.getActionCommand() == "pass" ) + { + Orient.pass(); + } + else + { + Orient.fail(); + } + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PageFormat/PDialogTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PageFormat/PDialogTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4855801 + * @summary Changing margins in the page format does not have any effect + * @run main/manual PDialogTest + */ +import java.awt.print.*; +import javax.print.attribute.*; +import javax.print.attribute.standard.*; + +public class PDialogTest +{ + + public static void main(String[] args) { + PageFormat page=new PageFormat(); + while(true){ + page=java.awt.print.PrinterJob.getPrinterJob().pageDialog(page); + } + + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PageFormat/PageSetupDialog.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PageFormat/PageSetupDialog.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4197377 + * @bug 4299145 + * @bug 6358747 + * @bug 6574633 + * @summary Page setup dialog settings + * @author prr + * @run main/manual PageSetupDialog + */ + +import java.awt.*; +import java.awt.event.*; +import java.awt.print.*; + +public class PageSetupDialog extends Frame implements Printable { + + PrinterJob myPrinterJob; + PageFormat myPageFormat; + Label pw, ph, pglm, pgiw, pgrm, pgtm, pgih, pgbm; + Label myWidthLabel; + Label myHeightLabel; + Label myImageableXLabel; + Label myImageableYLabel; + Label myImageableRightLabel; + Label myImageableBottomLabel; + Label myImageableWidthLabel; + Label myImageableHeightLabel; + Label myOrientationLabel; + Checkbox reverseCB; + boolean alpha = false; + boolean reverse = false; + + protected void displayPageFormatAttributes() { + + myWidthLabel.setText("Format Width = " + (float)myPageFormat.getWidth()); + myHeightLabel.setText("Format Height = " + (float)myPageFormat.getHeight()); + myImageableXLabel.setText + ("Format Left Margin = " + (float)myPageFormat.getImageableX()); + myImageableRightLabel.setText + ("Format Right Margin = " + (float)(myPageFormat.getWidth() - + (myPageFormat.getImageableX() + myPageFormat.getImageableWidth()))); + myImageableWidthLabel.setText + ("Format ImageableWidth = " + (float)myPageFormat.getImageableWidth()); + myImageableYLabel.setText + ("Format Top Margin = " + (float)myPageFormat.getImageableY()); + myImageableBottomLabel.setText + ("Format Bottom Margin = " + (float)(myPageFormat.getHeight() - + (myPageFormat.getImageableY() + myPageFormat.getImageableHeight()))); + myImageableHeightLabel.setText + ("Format ImageableHeight = " + (float)myPageFormat.getImageableHeight()); + int o = myPageFormat.getOrientation(); + if (o == PageFormat.LANDSCAPE && reverse) { + o = PageFormat.REVERSE_LANDSCAPE; + myPageFormat.setOrientation(PageFormat.REVERSE_LANDSCAPE); + } else if (o == PageFormat.REVERSE_LANDSCAPE && !reverse) { + o = PageFormat.LANDSCAPE; + myPageFormat.setOrientation(PageFormat.LANDSCAPE); + } + myOrientationLabel.setText + ("Format Orientation = " + + (o == PageFormat.PORTRAIT ? "PORTRAIT" : + o == PageFormat.LANDSCAPE ? "LANDSCAPE" : + o == PageFormat.REVERSE_LANDSCAPE ? "REVERSE_LANDSCAPE" : + "")); + Paper p = myPageFormat.getPaper(); + pw.setText("Paper Width = " + (float)p.getWidth()); + ph.setText("Paper Height = " + (float)p.getHeight()); + pglm.setText("Paper Left Margin = " + (float)p.getImageableX()); + pgiw.setText("Paper Imageable Width = " + (float)p.getImageableWidth()); + pgrm.setText("Paper Right Margin = " + + (float)(p.getWidth() - (p.getImageableX()+p.getImageableWidth()))); + pgtm.setText("Paper Top Margin = " + (float)p.getImageableY()); + pgih.setText("Paper Imageable Height = " + (float)p.getImageableHeight()); + pgbm.setText("Paper Bottom Margin = " + + (float)(p.getHeight() - (p.getImageableY()+p.getImageableHeight()))); + } + + public PageSetupDialog() { + super ("Page Dialog Test"); + myPrinterJob = PrinterJob.getPrinterJob(); + myPageFormat = new PageFormat(); + Paper p = new Paper(); + double margin = 1.5*72; + p.setImageableArea(margin, margin, + p.getWidth()-2*margin, p.getHeight()-2*margin); + myPageFormat.setPaper(p); + Panel c = new Panel(); + c.setLayout (new GridLayout (9, 2, 0, 0)); + c.add (reverseCB = new Checkbox("reverse if landscape")); + c.add (myOrientationLabel = new Label()); + c.add (myWidthLabel = new Label()); + c.add (pw = new Label()); + c.add (myImageableXLabel = new Label()); + c.add (pglm = new Label()); + c.add (myImageableRightLabel = new Label()); + c.add (pgrm = new Label()); + c.add (myImageableWidthLabel = new Label()); + c.add (pgiw = new Label()); + c.add (myHeightLabel = new Label()); + c.add (ph = new Label()); + c.add (myImageableYLabel = new Label()); + c.add (pgtm = new Label()); + c.add (myImageableHeightLabel = new Label()); + c.add (pgih = new Label()); + c.add (myImageableBottomLabel = new Label()); + c.add (pgbm = new Label()); + + reverseCB.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + reverse = e.getStateChange() == ItemEvent.SELECTED; + int o = myPageFormat.getOrientation(); + if (o == PageFormat.LANDSCAPE || + o == PageFormat.REVERSE_LANDSCAPE) { + displayPageFormatAttributes(); + } + } + }); + + add("Center", c); + displayPageFormatAttributes(); + Panel panel = new Panel(); + Button pageButton = new Button ("Page Setup..."); + pageButton.addActionListener(new ActionListener() { + public void actionPerformed (ActionEvent e) { + myPageFormat = myPrinterJob.pageDialog (myPageFormat); + displayPageFormatAttributes(); + } + }); + Button printButton = new Button ("Print ..."); + printButton.addActionListener(new ActionListener() { + public void actionPerformed (ActionEvent e) { + try { + if (myPrinterJob.printDialog()) { + myPrinterJob.setPrintable(PageSetupDialog.this, + myPageFormat); + alpha = false; + myPrinterJob.print(); + } + } catch (PrinterException pe ) { + } + } + }); + Button printAlphaButton = new Button ("Print w/Alpha..."); + printAlphaButton.addActionListener(new ActionListener() { + public void actionPerformed (ActionEvent e) { + try { + if (myPrinterJob.printDialog()) { + myPrinterJob.setPrintable(PageSetupDialog.this, + myPageFormat); + alpha = true; + myPrinterJob.print(); + } + } catch (PrinterException pe ) { + } + } + }); + panel.add (pageButton); + panel.add (printButton); + panel.add (printAlphaButton); + add("South", panel); + addWindowListener (new WindowAdapter() { + public void windowClosing (WindowEvent e) { + dispose(); + System.exit (0); + } + + }); + //setSize (280, 550); + pack(); + setVisible (true); + } + + public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) { + + if (pageIndex > 0) { + return Printable.NO_SUCH_PAGE; + } + + Graphics2D g2d = (Graphics2D)graphics; + g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY()); + g2d.drawString("ORIGIN("+pageFormat.getImageableX()+","+ + pageFormat.getImageableY()+")", 20, 20); + g2d.drawString("X THIS WAY", 200, 50); + g2d.drawString("Y THIS WAY", 60 , 200); + g2d.drawString("Graphics is " + g2d.getClass().getName(), 100, 100); + g2d.drawRect(0,0,(int)pageFormat.getImageableWidth(), + (int)pageFormat.getImageableHeight()); + if (alpha) { + g2d.setColor(new Color(0,0,255,192)); + } else { + g2d.setColor(Color.blue); + } + g2d.drawRect(1,1,(int)pageFormat.getImageableWidth()-2, + (int)pageFormat.getImageableHeight()-2); + + return Printable.PAGE_EXISTS; + } + + public static void main( String[] args) { + + String[] instructions = + { + "You must have a printer available to perform this test", + "This test is very flexible and requires much interaction.", + "If the platform print dialog supports it, adjust orientation", + "and margins and print pages and compare the results with the", + "request." + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + new PageSetupDialog(); + } + +} + +class Sysout { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PageFormat/ReverseLandscapeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PageFormat/ReverseLandscapeTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4254954 + * @summary PageFormat would fail on solaris when setting orientation + */ + +import java.awt.*; +import java.awt.event.*; +import java.awt.print.*; + +public class ReverseLandscapeTest extends Frame { + + private TextCanvas c; + + public static void main(String args[]) { + ReverseLandscapeTest f = new ReverseLandscapeTest(); + f.show(); + } + + public ReverseLandscapeTest() { + super("JDK 1.2 Text Printing"); + + c = new TextCanvas(); + add("Center", c); + + PrinterJob pj = PrinterJob.getPrinterJob(); + + PageFormat pf = pj.defaultPage(); + pf.setOrientation(PageFormat.REVERSE_LANDSCAPE); + + // This code can be added if one wishes to test printing +// pf = pj.pageDialog(pf); + +// if (pj != null && pj.printDialog()) { + +// pj.setPrintable(c, pf); +// try { +// pj.print(); +// } catch (PrinterException pe) { +// } finally { +// System.err.println("PRINT RETURNED"); +// } +// } + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + pack(); + } + + class TextCanvas extends Panel implements Printable { + + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { + int iw = getWidth(); + int ih = getHeight(); + Graphics2D g2d = (Graphics2D)g; + + if (pgIndex > 0) + return Printable.NO_SUCH_PAGE; + + g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); + g2d.translate(iw/2, ih/2); + g2d.setFont(new Font("Times",Font.PLAIN, 12)); + g2d.setPaint(new Color(0,0,0)); + g2d.setStroke(new BasicStroke(1f)); + g2d.drawString("Print REVERSE_LANDSCAPE", 30, 40); + + return Printable.PAGE_EXISTS; + } + + public void paint(Graphics g) { + g.drawString("Print REVERSE_LANDSCAPE", 30, 40); + } + + public Dimension getPreferredSize() { + return new Dimension(250, 100); + } + } + +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PageFormat/SetOrient.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PageFormat/SetOrient.html Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,48 @@ + + + + + + + SetOrient + + + +This test prints two pages and sends them to the printer. +One page is in PORTRAIT orientation and the other is in LANDSCAPE +orientation. On each page it draws an ellipse inscribed in the clip +boundary established by the PrinterJob. The ellipse should fill the +page within the bounds established by the default margins and not +extend off any end or side of the page. Also, the string "Portrait" +or "Landscape" should be oriented correctly. + + + + diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PageFormat/SetOrient.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PageFormat/SetOrient.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @bug 4186119: setting orientation does not affect printer + * @summary Confirm that the clip and transform of the Graphics2D is + * affected by the landscape orientation of the PageFormat. + * @run applet/manual=yesno SetOrient.html + */ + +import java.awt.*; +import java.awt.geom.*; +import java.awt.print.*; +import java.applet.Applet; + +public class SetOrient extends Applet implements Printable { + PrinterJob pjob; + + public void init() { + pjob = PrinterJob.getPrinterJob(); + + Book book = new Book(); + PageFormat pf = pjob.defaultPage(); + pf.setOrientation(PageFormat.PORTRAIT); + book.append(this, pf); + pf = pjob.defaultPage(); + pf.setOrientation(PageFormat.LANDSCAPE); + book.append(this, pf); + pjob.setPageable(book); + + try { + pjob.print(); + } catch (PrinterException e) { + throw new RuntimeException(e.getMessage()); + } + } + + public int print(Graphics g, PageFormat pf, int pageIndex) { + Graphics2D g2d = (Graphics2D)g; + drawGraphics(g2d, pf); + return Printable.PAGE_EXISTS; + } + + void drawGraphics(Graphics2D g, PageFormat pf) { + double ix = pf.getImageableX(); + double iy = pf.getImageableY(); + double iw = pf.getImageableWidth(); + double ih = pf.getImageableHeight(); + + g.setColor(Color.black); + g.drawString(((pf.getOrientation() == PageFormat.PORTRAIT) + ? "Portrait" : "Landscape"), + (int) (ix+iw/2), (int) (iy+ih/2)); + g.draw(new Ellipse2D.Double(ix, iy, iw, ih)); + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PageFormat/SmallPaperPrinting.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PageFormat/SmallPaperPrinting.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + import java.awt.*; + import java.awt.print.*; + + public class SmallPaperPrinting + { + public static void main(String args[]) + { + System.out.println("----------------- Instructions --------------------"); + System.out.println("Arguments: (none) - paper width=1, height=.0001"); + System.out.println(" 1 - paper width=.0001, height=1"); + System.out.println(" 2 - paper width=-1, height=1"); + System.out.println("A passing test should catch a PrinterException"); + System.out.println("and should display \"Print error: (exception msg)\"."); + System.out.println("---------------------------------------------------\n"); + PrinterJob job = PrinterJob.getPrinterJob(); + PageFormat format = job.defaultPage(); + Paper paper = format.getPaper(); + + double w = 1, h = .0001; // Generates ArithmeticException: / by zero. + if(args.length > 0 && args[0].equals("1")) { + w = .0001; h = 1; } // Generates IllegalArgumentException. + else if(args.length > 0 && args[0].equals("2")) { + w = -1; h = 1; } // Generates NegativeArraySizeException. + paper.setSize(w, h); + paper.setImageableArea(0, 0, w, h); + format.setPaper(paper); + job.setPrintable( + new Printable() { + public int print(Graphics g, PageFormat page_format, int page) { + return NO_SUCH_PAGE; + } + }, format); + + try { + job.print(); } + catch(PrinterException e) { + System.err.println("Print error:\n" + e.getMessage()); // Passing test! + } + } + } diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PageFormat/ValidateCustom.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PageFormat/ValidateCustom.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4414987 + * @author Jennifer Godinez + * @summary Displays width & height of validated custom paper size + * @run main/manual ValidateCustom + */ +import java.awt.*; +import java.awt.print.*; +import java.awt.geom.*; +import javax.swing.*; + +public class ValidateCustom implements Pageable, Printable{ + + private static double PIXELS_PER_INCH = 72.0; + private static double WIDTH = 17.0; //width of paper in inches + private static double LENGTH = 24.0; //length of paper in inches + private static boolean VALIDATE = true; + + private PrinterJob printerJob; + private PageFormat pageFormat; + + ValidateCustom(){ + printerJob = PrinterJob.getPrinterJob(); + createPageFormat(); + } + + private void createPageFormat(){ + pageFormat = new PageFormat(); + Paper p = new Paper(); + double width = WIDTH*PIXELS_PER_INCH; + double height = LENGTH*PIXELS_PER_INCH; + double ix = PIXELS_PER_INCH; + double iy = PIXELS_PER_INCH; + double iwidth = width - 2.0*PIXELS_PER_INCH; + double iheight = height - 2.0*PIXELS_PER_INCH; + p.setSize(width, height); + p.setImageableArea(ix, iy, iwidth, iheight); + pageFormat.setPaper(p); + } + + public Printable getPrintable(int index){ + return this; + } + + public PageFormat getPageFormat(int index){ + return pageFormat; + } + + public int getNumberOfPages(){ + return 1; + } + + private void printPaperSize(PageFormat pf){ + Paper p = pf.getPaper(); + System.out.println("paper size = ("+p.getWidth()+", "+p.getHeight()+")"); + } + + public void print(){ + //if(printerJob.printDialog()) + { + try{ + //printPaperSize(pageFormat); + if(VALIDATE){ + this.pageFormat = printerJob.validatePage(this.pageFormat); + } + printPaperSize(pageFormat); + //printerJob.setPageable(this); + //printerJob.print(); + }catch(Exception e){e.printStackTrace();} + } + } + + public int print(Graphics g, PageFormat pf, int pageIndex){ + if(pageIndex == 0){ + Graphics2D g2 = (Graphics2D)g; + Rectangle2D r = new Rectangle2D.Double(PIXELS_PER_INCH, PIXELS_PER_INCH, PIXELS_PER_INCH, PIXELS_PER_INCH); + g2.setStroke(new BasicStroke(1.0f)); + g2.draw(r); + return PAGE_EXISTS; + }else{ + return NO_SUCH_PAGE; + } + } + + public static void main(String[] args){ + System.out.println("-----------------instructions--------------------"); + System.out.println("You must have a printer installed in your system \nthat supports custom paper sizes in order to run this test."); + System.out.println("Passing test will display the correct width & height\nof custom paper in 1/72nds of an inch.\n"); + System.out.println("-------------------------------------------------"); + ValidateCustom pt = new ValidateCustom(); + pt.print(); + try{ + System.in.read(); + }catch(Exception e){} + } + +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/Cancel/PrinterJobCancel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/Cancel/PrinterJobCancel.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4245280 + * @summary PrinterJob not cancelled when PrinterJob.cancel() is used + * @author prr + * @run main/manual PrinterJobCancel + */ + +import java.awt.* ; +import java.awt.print.* ; + +public class PrinterJobCancel extends Thread implements Printable { + + PrinterJob pj ; + boolean okayed; + + public static void main ( String args[] ) { + + String[] instructions = + { + "Test that print job cancellation works.", + "You must have a printer available to perform this test.", + "This test silently starts a print job and while the job is", + "still being printed, cancels the print job", + "You should see a message on System.out that the job", + "was properly cancelled.", + "You will need to kill the application manually since regression", + "tests apparently aren't supposed to call System.exit()" + }; + + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PrinterJobCancel pjc = new PrinterJobCancel() ; + + if (pjc.okayed) { + pjc.start(); + try { + Thread.sleep(5000); + pjc.pj.cancel(); + } catch ( InterruptedException e ) { + } + } + } + + public PrinterJobCancel() { + + pj = PrinterJob.getPrinterJob() ; + pj.setPrintable(this); + okayed = pj.printDialog(); + } + + public void run() { + boolean cancelWorked = false; + try { + pj.print() ; + } + catch ( PrinterAbortException paex ) { + cancelWorked = true; + System.out.println("Job was properly cancelled and we"); + System.out.println("got the expected PrintAbortException"); + } + catch ( PrinterException prex ) { + System.out.println("This is wrong .. we shouldn't be here"); + System.out.println("Looks like a test failure"); + prex.printStackTrace() ; + //throw prex; + } + finally { + System.out.println("DONE PRINTING"); + if (!cancelWorked) { + System.out.println("Looks like the test failed - we didn't get"); + System.out.println("the expected PrintAbortException "); + } + } + //System.exit(0); + } + + public int print(Graphics g, PageFormat pagef, int pidx) { + + if (pidx > 5) { + return( Printable.NO_SUCH_PAGE ) ; + } + + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pagef.getImageableX(), pagef.getImageableY()); + g2d.setColor(Color.black); + + g2d.drawString(("This is page"+(pidx+1)), 60 , 80); + // Need to slow things down a bit .. important not to try this + // on the event dispathching thread of course. + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + } + + return ( Printable.PAGE_EXISTS ); + } + +} + + +class Sysout { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/CheckAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/CheckAccess.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4151121 + * @summary Confirm that PrinterJob.getPrinterJob is access checked. + * @author Graham Hamilton + */ + +import java.awt.print.*; +import java.security.*; + +public class CheckAccess { + + static boolean verbose; + + private static void println(String mess) { + if (verbose) { + System.err.println(mess); + } + } + + /** + * SecurityManager that rejects all print requests, + * but allows everything else. + */ + static class PrintHater extends SecurityManager { + + public void checkPermission(Permission p) { + // We're easy. + } + + public void checkPrintJobAccess() { + throw new SecurityException("No way!"); + } + } + + public static void main(String argv[]) { + + if (argv.length > 0 && argv[0].equals("-v")) { + verbose = true; + } + + // Try to install our own security manager. + try { + SecurityManager sm = new PrintHater(); + println("Installing PrintHater security manager"); + System.setSecurityManager(sm); + println("Installed security manager OK"); + + } catch (Throwable th) { + System.err.println("Failed to install SecurityManager"); + th.printStackTrace(); + throw new RuntimeException("Failed to install SecurityManager"); + } + + try { + + println("Calling PrinterJob.getPrinterJob()"); + PrinterJob.getPrinterJob(); + + // Woops. We did not get the SecurityException we expected. + println("Failed to get SecurityException"); + throw new RuntimeException("Failed to get expected SecurityException"); + + } catch (SecurityException ex) { + // Happy, happy. This is what we want. + println("Got expected SecurityException OK."); + return; + } + + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/CheckPrivilege.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/CheckPrivilege.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4151151 + * @summary Confirm that low-level print code does doPrivilege. + * @author Graham Hamilton + */ + +import java.awt.print.*; + +public class CheckPrivilege implements Printable { + + static boolean verbose; + + private static void println(String mess) { + if (verbose) { + System.err.println(mess); + } + } + + /** + * SecurityManager that allows print requests, but + * causes things like "exec" to get checked. + */ + static class PrintLover extends SecurityManager { + public void checkPrintJobAccess() { + } + public void checkPackageAccess(String pkg) { + } + public void checkPropertyAccess(String key) { + } + } + + /** + * Internal exception to boucne us out of the print code + */ + class Printing extends RuntimeException { + } + + public static void main(String argv[]) { + + System.out.println( "-----------------------------------------------------------------------"); + System.out.println( "INSTRUCTIONS: You should have a printer configured in your system to do this test. Test fails if you get this error message:"); + System.out.println(" \"Regression: printing causes a NullPointerException\""); + System.out.println( "-----------------------------------------------------------------------"); + + if (argv.length > 0 && argv[0].equals("-v")) { + verbose = true; + } + + // We need to make sure AWT is initialized. This is bug #4162674 + java.awt.Toolkit.getDefaultToolkit(); + + // Try to install our own security manager. + try { + SecurityManager sm = new PrintLover(); + println("Installing PrintLover security manager"); + System.setSecurityManager(sm); + println("Installed security manager OK"); + + } catch (Throwable th) { + System.err.println("Failed to install SecurityManager"); + th.printStackTrace(); + throw new RuntimeException("Failed to install SecurityManager"); + } + + try { + println("calling getPrinterJob"); + PrinterJob pj = PrinterJob.getPrinterJob(); + if ((pj == null) || (pj.getPrintService() == null)){ + return; + } + + println("PrinterJob class is " + pj.getClass()); + println("calling pj.setPrintable"); + pj.setPrintable(new CheckPrivilege()); + println("calling pj.print"); + pj.print(); + println("done pj.print"); + + } catch (Printing ex) { + // We get here if the print request started OK. + println("Caught \"Printing\" exception OK"); + + } catch (PrinterException ex) { + System.err.println("Caught " + ex); + throw new RuntimeException("" + ex); + + } catch (NullPointerException ex) { + // This is the bug: + System.err.println("Caught " + ex); + System.err.println("Regression: printing causes a NullPointerException"); + throw ex; + } + + //System.exit(0); + + } + + // Back-call from the new print APIs. + // We always say we have bothing to print. + public int print(java.awt.Graphics g, PageFormat pf, int index) { + println("Started printing " + index); + return Printable.NO_SUCH_PAGE; + } + + +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/CompareImageable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/CompareImageable.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4748055 + @summary PASS if the values are same in both cases (2 and 3) below. + @run main/manual CompareImageable +*/ + +/******************************************************************** +Testcase for comparing the imageable width and height of the paper +with and without using print dialog. + +How to run: + +1. Launch the app. You'll find a checkbox and a print button. +2. Click on the print button with the checkbox unselected. Note the +imageable width and height displayed on the console +3. Click on the print button with the checkbox selected. This popus up +the print dialog. Click ok on the dialog. Note the imageable width and +height displayed on the console. + +Result: It's a PASS if the values are same in both cases (2 and 3), + otherwise not. + +*********************************************************************/ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.awt.print.*; + + +public class CompareImageable implements Printable { + + + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { + + //get the printable width and height of the paper. + int pageHeight = (int)pgFmt.getImageableHeight(); + int pageWidth = (int)pgFmt.getImageableWidth(); + + System.out.println("imageable width = " + pageWidth + " height = " + pageHeight); + return Printable.NO_SUCH_PAGE; + } + + + public static void main(String [] args) { + + final JFrame frame = new JFrame("Print Test"); + final JButton printBtn = new JButton("Print"); + final JCheckBox dialogBtn = new JCheckBox("Native dialog"); + + JPanel panel = new JPanel(new FlowLayout()); + panel.add(dialogBtn); + panel.add(printBtn); + frame.getContentPane().add(panel); + + printBtn.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + + CompareImageable test = new CompareImageable(); + PrinterJob pj = PrinterJob.getPrinterJob(); + + if (dialogBtn.isSelected() && !pj.printDialog()) { + //user clicked 'Cancel' button in the print dialog. No printing. + return; + } + + if (dialogBtn.isSelected()) { + System.out.println("With print dialog..."); + } else { + System.out.println("Without print dialog..."); + } + + if (pj == null) { + System.out.println("No printer job found..."); + return; + } + pj.setPrintable(test); + + try { + pj.print(); + + } catch (Exception ex) { + ex.printStackTrace(); + } + } + }); + + + frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE); + frame.setSize(400, 400); + frame.setVisible(true); + + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/CustomFont/A.ttf Binary file jdk/test/java/awt/print/PrinterJob/CustomFont/A.ttf has changed diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/CustomFont/CustomFont.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/CustomFont/CustomFont.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4386025 + @summary fonts not in win32 font directory print incorrectly. + @author prr: area=PrinterJob + @run main/manual CustomFont +*/ +import java.io.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.print.*; + + +public class CustomFont implements Printable { + + private Image opaqueimg,transimg; + + private static void init() { + + //*** Create instructions for the user here *** + + String[] instructions = { + "On-screen inspection is not possible for this printing-specific", + "test therefore its only output is a printed page.", + "To be able to run this test it is required to have a default", + "printer configured in your user environment.", + "", + "Visual inspection of the printed page is needed. A passing", + "test will print a page on which one line of text will be", + "printed: a long string of 'A' characters.", + "The A should have of a curly style", + "If instead its in the default sansserif font, the test fails", + }; + + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PrinterJob pjob = PrinterJob.getPrinterJob(); + + Book book = new Book(); + + PageFormat portrait = pjob.defaultPage(); + book.append(new CustomFont(),portrait); + + pjob.setPageable(book); + + if (pjob.printDialog()) { + try { + pjob.print(); + } catch (PrinterException e) { + System.err.println(e); + e.printStackTrace(); + } + } + System.out.println("Done Printing"); + + }//End init() + + + Font customFont; + public CustomFont() { + try { + FileInputStream fin = new FileInputStream("A.ttf"); + Font cf = Font.createFont(Font.TRUETYPE_FONT, fin); + customFont = cf.deriveFont(Font.PLAIN, 14); + } catch (Exception ioe) { + System.err.println(ioe.getMessage()); + customFont = new Font("serif", Font.PLAIN, 14); + } + } + + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { + + Graphics2D g2D = (Graphics2D) g; + g2D.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); + + g2D.setColor(Color.black); + g2D.setFont(customFont); + String str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + g.drawString(str, 100, 100); + + return Printable.PAGE_EXISTS; + } + + /** + * The graphics is scaled and the font and the positions + * are reduced in respect to the scaling, so that all + * printing should be the same. + * + * @param g2D graphics2D to paint on + * @param font font to paint + * @param scale scale for the painting + * @param x x position + * @param y y position + */ + private void printScale(Graphics2D g2D, Font font, + float scale, float x, float y) { + + int RES = 72; + + g2D.scale(scale, scale); + + g2D.setFont (font.deriveFont(10.0f / scale)); + g2D.drawString("This text is scaled by a factor of " + scale, + x * RES / scale, y * RES / scale); + + g2D.scale(1/scale, 1/scale); + +} + + /***************************************************** + 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-defined + 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; + + 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 passed nor test failed 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) + { + 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(); + } + //pass was called from a different thread, so set the flag and interrupt + // the main thead. + theTestPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + }//pass() + + public static synchronized void fail() + { + //test writer didn't specify why test failed, s 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 CustomFont + +//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 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.show(); + 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.show(); + 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 implements ActionListener { + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + Panel buttonP = new Panel(); + Button passB = new Button( "pass" ); + Button failB = new Button( "fail" ); + + //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); + + passB = new Button( "pass" ); + passB.setActionCommand( "pass" ); + passB.addActionListener( this ); + buttonP.add( "East", passB ); + + failB = new Button( "fail" ); + failB.setActionCommand( "fail" ); + failB.addActionListener( this ); + buttonP.add( "West", failB ); + + add( "South", buttonP ); + pack(); + + show(); + }// 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" ); + } + + //catch presses of the passed and failed buttons. + //simply call the standard pass() or fail() static methods of + //CustomFont + public void actionPerformed( ActionEvent e ) + { + if( e.getActionCommand() == "pass" ) + { + CustomFont.pass(); + } + else + { + CustomFont.fail(); + } + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/DeviceScale.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/DeviceScale.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test 1.2 02/05/15 + @bug 4810363 4924441 + @run main DeviceScale + @summary check the peek scale is the same as the device scale, and that the + clips are also the same +*/ +import java.io.*; +import java.net.*; +import java.awt.*; +import java.awt.geom.*; +import java.awt.print.*; +import javax.print.attribute.*; +import javax.print.attribute.standard.*; + +public class DeviceScale implements Printable { + + boolean firstTime = true; + double sx, sy; + Shape clip, firstClip; + + public int print(Graphics g, PageFormat pf, int pageIndex) { + Graphics2D g2 = (Graphics2D)g; + if (pageIndex>=1) { + return Printable.NO_SUCH_PAGE; + } + AffineTransform at = g2.getTransform(); + System.out.println(at); + clip = g2.getClip(); + System.out.println(clip); + if (firstTime) { + firstTime = false; + sx = Math.abs(at.getScaleX()); + sy = Math.abs(at.getScaleY()); + firstClip = clip; + } else { + double newSx = Math.abs(at.getScaleX()); + double newSy = Math.abs(at.getScaleY()); + if (Math.abs(sx - newSx) > 0.1 || + Math.abs(sy - newSy) > 0.1) { + throw new RuntimeException("different scale, was "+ + sx+","+sy+" now " + + newSx+","+ newSy); + } + if (!clip.equals(firstClip)) { + throw new RuntimeException("different clip, was "+ firstClip + + " now "+ clip); + } + } + return Printable.PAGE_EXISTS; + } + + public static void doit(OrientationRequested o) throws Exception { + PrinterJob pj = PrinterJob.getPrinterJob(); + if (pj.getPrintService() == null) { + System.out.println("No print service found."); + return; + } + pj.setPrintable(new DeviceScale()); + PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); + aset.add(o); + String fileName = "out.prn"; + File f = new File(fileName); + f.deleteOnExit(); + URI dest = f.toURI(); + aset.add(new Destination(dest)); + pj.print(aset); + } + + + public static void main(String arg[]) throws Exception { + + doit(OrientationRequested.PORTRAIT); + doit(OrientationRequested.LANDSCAPE); + doit(OrientationRequested.REVERSE_LANDSCAPE); + + } + +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/DrawImage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/DrawImage.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4329866 + * @summary Confirm that no printing exception is generated. + * @author jgodinez + * @run main/manual DrawImage + */ + +import java.util.*; +import java.text.*; +import java.io.*; +import java.net.*; +import java.awt.*; +import java.awt.font.*; +import java.awt.geom.*; +import java.awt.print.*; +import java.awt.event.*; +import java.awt.image.*; +import java.awt.image.renderable.*; +import javax.swing.*; +import javax.swing.text.*; +import javax.swing.border.*; +import javax.swing.event.*; + +public class DrawImage +{ + protected static final double _hwBorder = 72 / 4; // 1/4 inch + protected static final double _border = 72 / 4; // 1/4 inch + protected static final int _objectBorder = 15; + protected static final int _verticalGap = 20; + protected static final int _textIndent = 150; + + protected BufferedImage _image; + + protected PageFormat _pageFormat; + + public DrawImage(BufferedImage image) { + _image = image; + PrinterJob pj = PrinterJob.getPrinterJob(); + _pageFormat = pj.defaultPage(); + + } + + + protected int printImage(Graphics g, PageFormat pf, BufferedImage image) { + Graphics2D g2D = (Graphics2D)g; + g2D.transform(new AffineTransform(_pageFormat.getMatrix())); + + int paperW = (int)pf.getImageableWidth(), paperH = + (int)pf.getImageableHeight(); + + int x = (int)pf.getImageableX(), y = (int)pf.getImageableY(); + g2D.setClip(x, y, paperW, paperH); + + // print images + if (image != null ) { + int imageH = image.getHeight(), imageW = image.getWidth(); + // make slightly smaller (25) than max possible width + float scaleFactor = ((float)((paperW - 25) - _objectBorder - + _objectBorder) / (float)(imageW)); + int scaledW = (int)(imageW * scaleFactor), + scaledH = (int)(imageH *scaleFactor); + BufferedImageOp scaleOp = new RescaleOp(scaleFactor, 0, null); + g2D.drawImage(image, scaleOp, x + _objectBorder, y + _objectBorder); + y += _objectBorder + scaledH + _objectBorder; + return Printable.PAGE_EXISTS; + } + else { + return Printable.NO_SUCH_PAGE; + } + } + + public void print() { + try { + final PrinterJob pj = PrinterJob.getPrinterJob(); + pj.setJobName("Print Image"); + pj.setPrintable(new Printable() { + public int print(Graphics g, PageFormat pf, int pageIndex) { + int result = NO_SUCH_PAGE; + if (pageIndex == 0) { + result = printImage(g, _pageFormat, _image); + } + return result; + } + }); + if (pj.printDialog()) { + try { pj.print(); } + catch (PrinterException e) { + System.out.println(e); + } + } + + } + catch (Exception e) { + e.printStackTrace(System.out); + } + } + + public static void main(String[] args) { + String[] instructions = + { + "You must have a printer available to perform this test.", + "The test passes if you get a printout of a gray rectangle", + "with white text without any exception." + }; + + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + BufferedImage image = prepareFrontImage(); + DrawImage pt = new DrawImage(image); + pt.print(); + // System.exit(0); + } + + + + public static BufferedImage prepareFrontImage() { + // build my own test images + BufferedImage result = new BufferedImage(400, 200, + BufferedImage.TYPE_BYTE_GRAY); + + Graphics2D g2D = (Graphics2D)result.getGraphics(); + g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_OFF); + int w = result.getWidth(), h = result.getHeight(); + + g2D.setColor(Color.gray); + g2D.fill(new Rectangle(0, 0, w, h)); + + g2D.setColor(Color.white); + + AffineTransform original = g2D.getTransform(); + AffineTransform originXform = AffineTransform.getTranslateInstance(w / +5, h / 5); + g2D.transform(originXform); + + + g2D.drawString("Front Side", 20, h / 2); + + return result; + } + + +} + +class Sysout { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/DrawStringMethods.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/DrawStringMethods.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4185019 + * @summary Confirm that all of the drawString methods on Graphics2D + * work for printer graphics objects. + * @run main/manual DrawStringMethods + */ + +import java.awt.*; +import java.text.*; +import java.awt.font.*; +import java.awt.print.*; + +public class DrawStringMethods implements Printable { + + public static void main(String args[]) { + String[] instructions = + { + "Confirm that the methods are printed.", + " For Graphics: drawString, drawString, drawChars, drawBytes", + " For Graphics2D: drawString, drawString, drawGlyphVector" + }; + Sysout.createDialogWithInstructions( instructions ); + + + PrinterJob pjob = PrinterJob.getPrinterJob(); + PageFormat pf = pjob.defaultPage(); + Book book = new Book(); + + book.append(new DrawStringMethods(), pf); + pjob.setPageable(book); + + try { + pjob.print(); + } catch (PrinterException e) { + throw new RuntimeException(e.getMessage()); + } + } + + public static AttributedCharacterIterator getIterator(String s) { + return new AttributedString(s).getIterator(); + } + + public int print(Graphics g, PageFormat pf, int pageIndex) { + int ix = (int) pf.getImageableX(); + int iy = (int) pf.getImageableY(); + String s; + + g.setColor(Color.black); + + iy += 50; + s = "--- Graphics methods: ---"; + g.drawString(s, ix, iy); + + iy += 30; + s = "drawString(String str, int x, int y)"; + g.drawLine(ix, iy, ix+10, iy); + g.drawString(s, ix+20, iy); + + iy += 30; + s = "drawString(AttributedCharacterIterator iterator, int x, int y)"; + g.drawLine(ix, iy, ix+10, iy); + g.drawString(getIterator(s), ix+20, iy); + + iy += 30; + s = "drawChars(char data[], int offset, int length, int x, int y)"; + g.drawLine(ix, iy, ix+10, iy); + g.drawChars(s.toCharArray(), 0, s.length(), ix+20, iy); + + iy += 30; + s = "drawBytes(byte data[], int offset, int length, int x, int y)"; + byte data[] = new byte[s.length()]; + for (int i = 0; i < data.length; i++) { + data[i] = (byte) s.charAt(i); + } + g.drawLine(ix, iy, ix+10, iy); + g.drawBytes(data, 0, data.length, ix+20, iy); + + iy += 50; + s = "--- Graphics2D methods: ---"; + g.drawString(s, ix, iy); + + if (g instanceof Graphics2D) { + Graphics2D g2d = (Graphics2D) g; + Font f = g2d.getFont(); + FontRenderContext frc = g2d.getFontRenderContext(); + + iy += 30; + s = "drawString(String s, float x, float y)"; + g.drawLine(ix, iy, ix+10, iy); + g2d.drawString(s, (float) ix+20, (float) iy); + + iy += 30; + s = "drawString(AttributedCharacterIterator iterator, "+ + "float x, float y)"; + g.drawLine(ix, iy, ix+10, iy); + g2d.drawString(getIterator(s), (float) ix+20, (float) iy); + + iy += 30; + s = "drawGlyphVector(GlyphVector g, float x, float y)"; + g.drawLine(ix, iy, ix+10, iy); + g2d.drawGlyphVector(f.createGlyphVector(frc, s), ix+20, iy); + } else { + iy += 30; + s = "Graphics object does not support Graphics2D methods"; + g.drawString(s, ix+20, iy); + } + + return PAGE_EXISTS; + } +} + +class Sysout + { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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("South", messageText); + + pack(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/EmptyFill.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/EmptyFill.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4509958 + * @summary Tests that the empty areas aren't drawn. + * @run main EmptyFill + */ + +import java.io.*; +import java.awt.*; +import java.awt.geom.*; +import java.awt.print.*; +import javax.print.*; +import javax.print.attribute.*; + +public class EmptyFill implements Printable { + + public int print(Graphics g, PageFormat pf, int pageIndex) { + + if (pageIndex > 0) { + return Printable.NO_SUCH_PAGE; + } + + g.setColor(Color.black); + + int[] xq = { 75, 125, 75 }; + int[] yq = { 140, 140, 140}; + + g.fillPolygon( xq, yq, 3 ); + + return Printable.PAGE_EXISTS; + } + + public static void main(String arg[]) throws Exception { + + DocFlavor psFlavor = new DocFlavor("application/postscript", + "java.io.OutputStream"); + + StreamPrintServiceFactory[] spfs = + PrinterJob.lookupStreamPrintServices("application/postscript"); + + if (spfs.length == 0) { + return; + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); + StreamPrintService svc = spfs[0].getPrintService(baos); + + PrinterJob pj = PrinterJob.getPrinterJob(); + if (svc == null) { + return; + } + pj.setPrintService(svc); + pj.setPrintable(new EmptyFill()); + pj.print(); + + String outStr = baos.toString("ISO-8859-1"); + if (outStr.indexOf("\nfill\n") > 0) { + throw new Exception("Expected no fills"); + } + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/GlyphPositions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/GlyphPositions.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6186840 6324057 + * @summary Tests that explicitly positioned glyphs print correctly. + * @run main GlyphPositions + */ + +import java.io.*; +import java.awt.*; +import java.awt.font.*; +import java.awt.geom.*; +import java.awt.print.*; +import javax.print.*; +import javax.print.attribute.*; + +public class GlyphPositions implements Printable { + + static String testString = "0123456789"; + public int print(Graphics g, PageFormat pf, int pageIndex) { + + if (pageIndex > 0) { + return Printable.NO_SUCH_PAGE; + } + + g.setColor(Color.black); + float x = (float)pf.getImageableX() + 20f, + y = (float)pf.getImageableY() + 30f; + + Graphics2D g2 = (Graphics2D)g; + Font font = new Font("SansSerif", Font.PLAIN, 20); + FontRenderContext frc = g2.getFontRenderContext(); + GlyphVector v = font.createGlyphVector(frc, testString); + + for(int i = 0; i <= v.getNumGlyphs(); i++) + { + Point2D.Float p = new Point2D.Float(); + p.x = i * 40f; + p.y = 0; + v.setGlyphPosition(i, p); + } + + g2.drawGlyphVector(v, x, y); + + return Printable.PAGE_EXISTS; + } + + public static void main(String arg[]) throws Exception { + + DocFlavor psFlavor = new DocFlavor("application/postscript", + "java.io.OutputStream"); + + StreamPrintServiceFactory[] spfs = + PrinterJob.lookupStreamPrintServices("application/postscript"); + + if (spfs.length == 0) { + return; + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); + StreamPrintService svc = spfs[0].getPrintService(baos); + + PrinterJob pj = PrinterJob.getPrinterJob(); + if (svc == null) { + return; + } + pj.setPrintService(svc); + pj.setPrintable(new GlyphPositions()); + pj.print(); + + /* Expect to see that the 10 glyphs are drawn individually which + * because of their positions. + * This test will need to be updated if the postscript generation + * changes. + */ + String outStr = baos.toString("ISO-8859-1"); + String ls = System.getProperty("line.separator"); + int indexCount = 0; + int index = 0; + while (index >= 0) { + index = outStr.indexOf("20.0 12 F"+ls, index+1); + if (index > 0) indexCount++; + } + if (indexCount < testString.length()) { + throw new Exception("Positions not used"); + } + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/HeadlessPrintingTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/HeadlessPrintingTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4936867 + * @summary Printing crashes in headless mode. + * @run main/othervm HeadlessPrintingTest + */ + + +import java.awt.*; +import javax.print.*; +import javax.print.attribute.*; +import javax.print.attribute.standard.*; +import java.awt.print.*; +import java.io.*; + +public class HeadlessPrintingTest { + + public static void main(String[] args) { + System.setProperty("java.awt.headless", "true"); + PrinterJob pj = PrinterJob.getPrinterJob(); + pj.setPrintable(new Printable() { + public int print(Graphics g, PageFormat pg, int pageIndex) { + Graphics2D g2d = (Graphics2D)g; + if (pageIndex > 2) { + return Printable.NO_SUCH_PAGE; + } else { + g2d.translate(pg.getImageableX(), pg.getImageableY()); + g2d.setColor(Color.RED); + g2d.drawString("page " + pageIndex, 100, 100); + return Printable.PAGE_EXISTS; + } + } + }); + + try { + HashPrintRequestAttributeSet attr = new HashPrintRequestAttributeSet(); + File f = File.createTempFile("out", "ps"); + f.deleteOnExit(); + Destination dest = new Destination(f.toURI()); + attr.add(dest); + pj.print(attr); + } catch (Exception e) { + } + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/InitToBlack.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/InitToBlack.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @bug 4184565 + * @summary Confirm that the default foreground color on a printer + * graphics object is black so that rendering will appear + * without having to execute setColor first. + * @run applet/manual=yesno InitToBlack.html + */ + +import java.awt.*; +import java.awt.print.*; +import java.applet.Applet; + +public class InitToBlack extends Applet implements Printable { + + public void init() { + PrinterJob pjob = PrinterJob.getPrinterJob(); + + Book book = new Book(); + book.append(this, pjob.defaultPage()); + pjob.setPageable(book); + + try { + pjob.print(); + } catch (PrinterException e) { + throw new RuntimeException(e.getMessage()); + } + } + + public int print(Graphics g, PageFormat pf, int pageIndex) { + Graphics2D g2d = (Graphics2D) g; + g2d.translate(pf.getImageableX(), pf.getImageableY()); + + g.drawString("Test Passes", 200, 200); + + return PAGE_EXISTS; + } + + public static void main(String[] args) { + new InitToBlack().init(); + System.exit(0); + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/InvalidPage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/InvalidPage.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test InvalidPage.java + * @bug 4671634 6506286 + * @summary Invalid page format can crash win32 JRE + * @author prr + * @run main/manual InvalidPage + */ + +import java.awt.*; +import java.awt.event.*; +import java.awt.print.*; + +public class InvalidPage extends Frame implements Printable { + + PrinterJob pJob; + PageFormat pf; + + public InvalidPage() { + super ("Validate Page Test"); + pJob = PrinterJob.getPrinterJob(); + pf = pJob.defaultPage(); + Paper p = pf.getPaper(); + p.setImageableArea(0,0,p.getWidth(), p.getHeight()); + pf.setPaper(p); + setLayout(new FlowLayout()); + Panel panel = new Panel(); + Button printButton = new Button ("Print"); + printButton.addActionListener(new ActionListener() { + public void actionPerformed (ActionEvent e) { + try { + if (pJob.printDialog()) { + pJob.setPrintable(InvalidPage.this, pf); + pJob.print(); + } + } catch (PrinterException pe ) { + } + } + }); + panel.add (printButton); + add(panel); + + addWindowListener (new WindowAdapter() { + public void windowClosing (WindowEvent e) { + dispose(); + System.exit (0); + } + + }); + setSize (200, 200); + setVisible (true); + } + + public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) { + + if (pageIndex > 1) { + return Printable.NO_SUCH_PAGE; + } + + Graphics2D g2d = (Graphics2D)graphics; + + g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY()); + g2d.drawString("ORIGIN", 30, 30); + g2d.drawString("X THIS WAY", 200, 50); + g2d.drawString("Y THIS WAY", 60 , 200); + g2d.drawRect(0,0,(int)pageFormat.getImageableWidth(), + (int)pageFormat.getImageableHeight()); + if (pageIndex == 0) { + g2d.setColor(Color.black); + } else { + g2d.setColor(new Color(0,0,0,128)); + } + g2d.drawRect(1,1,(int)pageFormat.getImageableWidth()-2, + (int)pageFormat.getImageableHeight()-2); + + g2d.drawLine(0,0, + (int)pageFormat.getImageableWidth(), + (int)pageFormat.getImageableHeight()); + g2d.drawLine((int)pageFormat.getImageableWidth(),0, + 0,(int)pageFormat.getImageableHeight()); + return Printable.PAGE_EXISTS; + } + + public static void main( String[] args) { + String[] instructions = + { + "You must have a printer available to perform this test", + "Press the print button, which brings up a print dialog and", + "in the dialog select a printer and press the print button", + "in the dialog. Repeat for as many printers as you have installed", + "On solaris and linux just one printer is sufficient", + "Collect the output and examine it, each print job has two pages", + "of very similar output, except that the 2nd page of the job may", + "appear in a different colour, and the output near the edge of", + "the page may be clipped. This is OK. Hold up both pieces of paper", + "to the light and confirm that the lines and text (where present)", + "are positioned identically on both pages", + "The test fails if the JRE crashes, or if the output from the two", + "pages of a job is aligned differently" + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + new InvalidPage(); + } + +} + +class Sysout { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/JobName/PrinterJobName.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/JobName/PrinterJobName.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4205601 + * @summary setJobName should be used by PrinterJob + * @author prr + * @run main/manual PrinterJobName + */ + +import java.awt.*; +import java.awt.print.*; + +public class PrinterJobName implements Printable { + + + static String theName = "Testing the Jobname setting"; + + public static void main(String[] args) { + + String[] instructions = + { + "You must have a printer available to perform this test", + "This test prints a page with a banner/job name of", + theName + }; + + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PrinterJob job = PrinterJob.getPrinterJob(); + job.setJobName(theName); + job.setPrintable(new PrinterJobName()); + try { + job.print(); + System.out.println("PRINTING DONE."); + } + catch (Exception exc) { + System.out.println("Printer Exception"); + } + } + + + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { + if (pgIndex > 0 ) { + return Printable.NO_SUCH_PAGE; + } + + double iw = pgFmt.getImageableWidth(); + double ih = pgFmt.getImageableHeight(); + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); + g2d.drawString("Name is: "+theName,20,20 ); + return Printable.PAGE_EXISTS; + } + +} + + +class Sysout { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/Legal/PrintTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/Legal/PrintTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4886069 8023045 + * @summary Confirm that printer recognizes the Legal selection either by + * prompting the user to put Legal paper or automatically selecting + * the tray containing Legal Paper. The printout image should not + * be shifted up by about 3". + * @run main/manual PrintTest + * + */ +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.border.*; + +import java.awt.print.*; +import javax.print.*; +import javax.print.attribute.*; +import javax.print.attribute.standard.*; +import java.io.*; + + +public class PrintTest extends JFrame { + private JPanel contentPane; + private JMenuBar jMenuBar1 = new JMenuBar(); + private JMenu jMenuFile = new JMenu(); + private JMenuItem jMenuItem1 = new JMenuItem(); + private BorderLayout borderLayout1 = new BorderLayout(); + private JPanel jPanel1 = new JPanel(); + private BorderLayout borderLayout2 = new BorderLayout(); + private JScrollPane jScrollPane1 = new JScrollPane(); + private JTextArea jTextArea1 = new JTextArea(); + private Border border1; + + //Construct the frame + public PrintTest() { + enableEvents(AWTEvent.WINDOW_EVENT_MASK); + try { + jbInit(); + + } + catch(Exception e) { + e.printStackTrace(); + } + } + private void jbInit() throws Exception { + contentPane = (JPanel) this.getContentPane(); + border1 = BorderFactory.createLineBorder(Color.black,1); + contentPane.setLayout(borderLayout1); + this.setTitle("Print Test"); + jMenuFile.setText("File"); + jMenuItem1.setText("Print"); + jMenuItem1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(80, java.awt.event.KeyEvent.CTRL_MASK, false)); + jMenuItem1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + jMenuItem1_actionPerformed(e); + } + }); + jPanel1.setLayout(borderLayout2); + jTextArea1.setBorder(border1); + jTextArea1.setText("1. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "2. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "3. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "4. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "5. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "6. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "7. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "8. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "9. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "10. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "11. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "12. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "13. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "14. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "15. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "16. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "17. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "18. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "19. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "20. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "21. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "22. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "23. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "24. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "25. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "26. This is a printer test designed to illustrate a bug in the java printing API.\n\n"+ + "27. This is a printer test designed to illustrate a bug in the java printing API."); + jMenuFile.add(jMenuItem1); + contentPane.add(jPanel1, BorderLayout.CENTER); + jPanel1.add(jScrollPane1, BorderLayout.CENTER); + jScrollPane1.getViewport().add(jTextArea1, null); + jScrollPane1.setPreferredSize(new Dimension(468,648)); + jTextArea1.setPreferredSize(new Dimension(468,864)); + jMenuBar1.add(jMenuFile); + this.setJMenuBar(jMenuBar1); + } + + protected void processWindowEvent(WindowEvent e) { + super.processWindowEvent(e); + if (e.getID() == WindowEvent.WINDOW_CLOSING) { + System.exit(0); + } + } + + void jMenuItem1_actionPerformed(ActionEvent e) { + PrintUtils.printComponent(jTextArea1); + } + + + + + public static class PrintUtils implements Printable { + private JComponent componentToBePrinted; + protected double scale =1.0; + PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet(); + + + public static void printComponent(JComponent c) { + new PrintUtils(c).print(); + } + + public PrintUtils(JComponent componentToBePrinted) { + this.componentToBePrinted = componentToBePrinted; + + } + + void print() { + DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE; + pras.add(MediaSizeName.NA_LEGAL); + + PrintService printService[] = PrintServiceLookup.lookupPrintServices(flavor,pras); + PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService(); + if ((defaultService == null) || (printService.length == 0)) { + System.out.println("No default print service found. Test aborted."); + return; + } + + PrintService service = ServiceUI.printDialog(null,100,100,printService,defaultService,flavor,pras); + + if(service != null) { + DocPrintJob job = service.createPrintJob(); + DocAttributeSet das = new HashDocAttributeSet(); + + Doc doc = new SimpleDoc(this,flavor,das); + + try { + job.print(doc,pras); + + } catch(PrintException pe) { + pe.printStackTrace(); + } + } + + } + + + public int print(Graphics g, PageFormat pageFormat, int pageIndex) + { + + double h=componentToBePrinted.getHeight(); + double pageHeight=pageFormat.getImageableHeight(); + + if (pageIndex * pageHeight > h * scale) { + return(NO_SUCH_PAGE); + } else { + + Graphics2D g2d = (Graphics2D)g; + + //move past unprintable area + double xOffset=pageFormat.getImageableX(); + double yOffset=pageFormat.getImageableY(); + g2d.translate(xOffset,yOffset); + + + //move to correct page taking into account the scaling + double newx=0; + double newy=pageHeight*(-pageIndex); + g2d.translate(newx / 1.0,newy / 1.0 ); + + //print + + componentToBePrinted.print(g2d); + return(PAGE_EXISTS); + } + } + + public static void disableDoubleBuffering(Component c) { + RepaintManager currentManager = RepaintManager.currentManager(c); + currentManager.setDoubleBufferingEnabled(false); + } + + /** Re-enables double buffering globally. */ + + public static void enableDoubleBuffering(Component c) { + RepaintManager currentManager = RepaintManager.currentManager(c); + currentManager.setDoubleBufferingEnabled(true); + } +} + + public static void main(String[] args) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } + catch(Exception e) { + e.printStackTrace(); + } + PrintTest frame = new PrintTest(); + frame.pack(); + + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Dimension frameSize = frame.getSize(); + if (frameSize.height > screenSize.height) { + frameSize.height = screenSize.height; + } + if (frameSize.width > screenSize.width) { + frameSize.width = screenSize.width; + } + frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2); + frame.setVisible(true); + } + +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/MultiThread/MultiThreadTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/MultiThread/MultiThreadTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4922036 + * @summary Confirm that no Exception is thrown and 2 identical output is produced. + * @run main/manual MultiThreadTest + */ +import java.io.*; +import javax.print.*; + + +public class MultiThreadTest extends Thread { + + private PrintService service = PrintServiceLookup.lookupDefaultPrintService(); + private Doc doc = null; + + public MultiThreadTest(Doc docObject) { + this.doc = docObject; + } + + public void print() { + try { + DocPrintJob job = null; + + job = this.service.createPrintJob(); + if (job == null) { + System.out.println("Fail: DocPrintJob is null..."); + return; + } + System.out.println("About to print image..."); + + job.print(this.doc, null); + System.out.println("Image printed."); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void run() { + this.print(); + } + + public static void main(String args[]) { + if (args.length <= 0) { + System.out.println("Usage: java MultiThreadTest "); + return; + } + Object printData = null; + + try { + File file = new File(args[0]); + + printData = new byte[(int) file.length()]; + FileInputStream in = new FileInputStream(file); + + in.read((byte[]) printData); + in.close(); + } catch (FileNotFoundException fe) { + System.out.println("ByteDoc: FileNotFoundException: " + + fe.toString()); + + } catch (IOException ie) { + System.out.println("ByteDoc: IOException: " + ie.toString()); + } + Doc doc1 = new ByteDoc(printData, DocFlavor.BYTE_ARRAY.GIF); + Doc doc2 = new ByteDoc(printData, DocFlavor.BYTE_ARRAY.GIF); + + Thread thread1 = new MultiThreadTest(doc1); + Thread thread2 = new MultiThreadTest(doc2); + + thread1.start(); + thread2.start(); + } +} + + +class ByteDoc implements Doc { + + protected DocFlavor flavor = null; + protected Object printData = null; + protected InputStream instream = null; + protected FileReader reader = null; + + // constructor takes the resource file and the document flavor. + public ByteDoc(Object printdata, DocFlavor docFlavor) { + this.printData = printdata; + this.flavor = docFlavor; + } + + public javax.print.attribute.DocAttributeSet getAttributes() { + return null; + } + + public DocFlavor getDocFlavor() { + return this.flavor; + } + + public Object getPrintData() { + return this.printData; + } + + public Reader getReaderForText() { + // Document says that if MIME type is non-text and representation class is input stream + // then return null; + return null; + } + + public InputStream getStreamForBytes() { + synchronized (this) { + if ((this.instream == null) && (this.printData instanceof byte[])) { + // its a byte array so create a ByteArrayInputStream. + System.out.println("creating ByteArrayInputStream..."); + this.instream = new ByteArrayInputStream((byte[]) printData); + } + } + return this.instream; + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/NullGetName.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/NullGetName.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 6397684 + @summary PASS if no VM crash. + @run main NullGetName +*/ + + +import javax.print.*; +import javax.print.attribute.*; +import javax.print.event.*; +import java.awt.print.*; + + +public class NullGetName { + + public static void main(String[] args) { + PrinterJob printerJob = PrinterJob.getPrinterJob(); + try { + printerJob.setPrintService(new ImagePrintService()); + } catch (PrinterException e) { + } + } +} + + +class ImagePrintService implements PrintService { + + + public Class[] getSupportedAttributeCategories() { + // TODO Auto-generated method stub + return null; + } + + public boolean isAttributeCategorySupported(Class category) { + // TODO Auto-generated method stub + return false; + } + + public String getName() { + // TODO Auto-generated method stub + return null; + } + + public DocFlavor[] getSupportedDocFlavors() { + // TODO Auto-generated method stub + return null; + } + + + public boolean isDocFlavorSupported(DocFlavor flavor) { + if(DocFlavor.SERVICE_FORMATTED.PAGEABLE.equals(flavor)) + return true; + if(DocFlavor.SERVICE_FORMATTED.PRINTABLE.equals(flavor)) + return true; + return false; + } + + public DocPrintJob createPrintJob() { + // TODO Auto-generated method stub + return null; + } + + public ServiceUIFactory getServiceUIFactory() { + // TODO Auto-generated method stub + return null; + } + + + public PrintServiceAttributeSet getAttributes() { + // TODO Auto-generated method stub + return null; + } + + public void addPrintServiceAttributeListener( + PrintServiceAttributeListener listener) { + // TODO Auto-generated method stub + + } + + public void removePrintServiceAttributeListener( + PrintServiceAttributeListener listener) { + // TODO Auto-generated method stub + + } + + public Object getDefaultAttributeValue(Class category) { + // TODO Auto-generated method stub + return null; + } + + public T + getAttribute(Class category) { + // TODO Auto-generated method stub + return null; + } + + public boolean isAttributeValueSupported(Attribute attrval, + DocFlavor flavor, AttributeSet attributes) { + // TODO Auto-generated method stub + return false; + } + + public AttributeSet getUnsupportedAttributes(DocFlavor flavor, + AttributeSet attributes) { + // TODO Auto-generated method stub + return null; + } + + public Object getSupportedAttributeValues(Class category, DocFlavor flavor, + AttributeSet attributes) { + // TODO Auto-generated method stub + return null; + } + +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/NumCopies.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/NumCopies.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4258003 + * @summary Checks the right number of copies are printed + * @author prr + * @run main/manual NumCopies + */ + +import java.awt.*; +import java.awt.print.*; + +public class NumCopies implements Printable { + + + public static void main(String[] args) { + + String[] instructions = + { + "You must have a printer available to perform this test", + "This test should print a total of four pages which are two", + " copies of each of two pages which consist of the text :-", + "'This is page number N', where N is 0 and 1.", + "The pages should be uncollated." + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PrinterJob job = PrinterJob.getPrinterJob(); + job.setCopies(2); + job.setPrintable(new NumCopies()); + try { + job.print(); + } + catch (Exception exc) { + System.out.println("Printer Exception"); + } + } + + public int print(Graphics g, PageFormat pf, int pageIndex) + throws PrinterException { + + if (pageIndex > 1) { + return NO_SUCH_PAGE; + } + g.translate((int)pf.getImageableX(), (int)pf.getImageableY()); + g.setColor(Color.black); + g.drawString("This is page number " + Integer.toString(pageIndex), 50, 50); + return PAGE_EXISTS ; + } + +} + +class Sysout + { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PSQuestionMark.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PSQuestionMark.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6217355 6324057 + * @summary Tests that '?' prints with postscript fonts + * @run main PSQuestionMark + */ + +import java.io.*; +import java.awt.*; +import java.awt.print.*; +import javax.print.*; +import javax.print.attribute.*; + +public class PSQuestionMark implements Printable { + + public int print(Graphics g, PageFormat pf, int pageIndex) { + + if (pageIndex > 0) { + return Printable.NO_SUCH_PAGE; + } + + g.setColor(Color.black); + g.setFont(new Font("Serif", Font.PLAIN, 12)); + g.drawString("?", 100, 150); + + return Printable.PAGE_EXISTS; + } + + public static void main(String arg[]) throws Exception { + + DocFlavor psFlavor = new DocFlavor("application/postscript", + "java.io.OutputStream"); + + StreamPrintServiceFactory[] spfs = + PrinterJob.lookupStreamPrintServices("application/postscript"); + + if (spfs.length == 0) { + return; + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); + //FileOutputStream baos = new FileOutputStream("q.ps"); + StreamPrintService svc = spfs[0].getPrintService(baos); + + PrinterJob pj = PrinterJob.getPrinterJob(); + if (svc == null) { + return; + } + pj.setPrintService(svc); + pj.setPrintable(new PSQuestionMark()); + pj.print(); + //baos.close(); + + /* Expect to see the PS we generate for setting 12 pt Times Roman + * and the hex value of '?' + * "12.0 12 F" + * "<3f> 6.72 100.0 150.0 S" + * This test will need to be updated if the postscript generation + * changes. + */ + String outStr = baos.toString("ISO-8859-1"); + String ls = System.getProperty("line.separator"); + if (outStr.indexOf("12.0 32 F"+ls+"<3f>") < 0) { + throw new Exception("PS font not used"); + } + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PSWindingRule.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PSWindingRule.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4423489 + * @summary Tests that the postscript renders using the appropriate + * winding rule. Runs as "main" as can't run in sandbox. + * @run main PSWindingRule + */ + +import java.io.*; +import java.awt.*; +import java.awt.geom.*; +import java.awt.print.*; +import javax.print.*; +import javax.print.attribute.*; + +public class PSWindingRule implements Printable { + + public int print(Graphics g, PageFormat pf, int pageIndex) { + + if (pageIndex > 0) { + return Printable.NO_SUCH_PAGE; + } + + Graphics2D g2 = (Graphics2D)g; + + GeneralPath path1 = new GeneralPath(PathIterator.WIND_EVEN_ODD); + GeneralPath path2 = new GeneralPath(PathIterator.WIND_EVEN_ODD); + GeneralPath path3 = new GeneralPath(PathIterator.WIND_EVEN_ODD); + path1.append(new Ellipse2D.Double(100, 100, 100, 100), false); + path1.append(new Ellipse2D.Double(120, 120, 60, 60), false); + path1.append(new Ellipse2D.Double(140, 140, 20, 20), false); + + path2.append(new Ellipse2D.Double(150, 100, 100, 100), false); + path2.append(new Ellipse2D.Double(170, 120, 60, 60), false); + path2.append(new Ellipse2D.Double(190, 140, 20, 20), false); + + path3.append(new Ellipse2D.Double(-50, -50, 100, 100), false); + path3.append(new Ellipse2D.Double(-30, -30, 60, 60), false); + path3.append(new Ellipse2D.Double(-10, -10, 20, 20), false); + + Rectangle clip = new Rectangle(); + g2.getClipBounds(clip); + + g2.setColor(Color.white); + g2.fillRect(clip.x, clip.y, clip.width, clip.height); + + g2.setColor(Color.red); + g2.fill(path1); + + g2.setColor(Color.black); + g2.fill(path2); + + g2.translate(150, 400); + g2.setColor(Color.red); + g2.fill(path3); + + g2.translate(50, 0); + g2.setColor(Color.black); + g2.fill(path3); + + return Printable.PAGE_EXISTS; + } + + public static void main(String arg[]) throws Exception { + + DocFlavor psFlavor = new DocFlavor("application/postscript", + "java.io.OutputStream"); + + StreamPrintServiceFactory[] spfs = + PrinterJob.lookupStreamPrintServices("application/postscript"); + + if (spfs.length == 0) { + return; + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); + StreamPrintService svc = spfs[0].getPrintService(baos); + + PrinterJob pj = PrinterJob.getPrinterJob(); + if (svc == null) { + return; + } + pj.setPrintService(svc); + pj.setPrintable(new PSWindingRule()); + pj.print(); + + String outStr = baos.toString("ISO-8859-1"); + int eofillCnt = 0; + int index = 0; + String ls = System.getProperty ("line.separator"); + + while (index >= 0) { + index = outStr.indexOf(ls+"EF"+ls, index+1); + if (index >=0 ) { + eofillCnt++; + } + } + if (eofillCnt != 4) { + throw new Exception("Expected 4 eofill's, got: " + eofillCnt); + } + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PageDialogTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PageDialogTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 6302514 + @run main/manual=yesno PageDialogTest + @summary A toolkit modal dialog should not be blocked by Page/Print dialog. +*/ +import java.awt.*; +import java.awt.event.*; +import java.awt.print.*; + +import javax.swing.*; + +public class PageDialogTest { + + public static void main(String[] args) { + String[] instructions = + { + "The test shows a Toolkit modal dialog. ", + "Click the 'Open' button. It opens a page dialog.", + "The test fails if the page dialog blocks the toolkit", + "modal dialog, otherwise it passes." + }; + + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + Dialog td = new Dialog((Frame) null, "Toolkit modal dialog", + Dialog.ModalityType.TOOLKIT_MODAL); + td.setLayout(new FlowLayout()); + td.add(new Button("Dummy")); + Button tdb = new Button("Open"); + tdb.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + PrinterJob.getPrinterJob().pageDialog(new PageFormat()); + } + }); + td.add(tdb); + td.setSize(250, 150); + td.setVisible(true); + } +} + +class Sysout { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PageDlgPrnButton.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PageDlgPrnButton.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4956397 + * @run main/manual PageDlgPrnButton + */ + +import java.awt.print.PrinterJob; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.* ; + +public class PageDlgPrnButton implements Printable +{ + public static void main ( String args[] ) { + + String[] instructions = + {"For non-windows OS, this test PASSes.", + "You must have at least 2 printers available to perform this test.", + "This test brings up a native Windows page dialog.", + "Click on the Printer... button and change the selected printer. ", + "Test passes if the printout comes from the new selected printer.", + }; + + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PageDlgPrnButton pdpb = new PageDlgPrnButton() ; + } + + public PageDlgPrnButton() + { + try + { + pageDialogExample(); + } + catch(Exception e) + {e.printStackTrace(System.err);} + } + + + // This example just displays the page dialog - you cannot change + // the printer (press the "Printer..." button and choose one if you like). + public void pageDialogExample() throws PrinterException + { + PrinterJob job = PrinterJob.getPrinterJob(); + PageFormat originalPageFormat = job.defaultPage(); + PageFormat pageFormat = job.pageDialog(originalPageFormat); + + if(originalPageFormat == pageFormat) return; + + job.setPrintable(this,pageFormat); + job.print(); + } + + + + public int print(Graphics g, PageFormat pageFormat, int pageIndex) + { + final int boxWidth = 100; + final int boxHeight = 100; + final Rectangle rect = new Rectangle(0,0,boxWidth,boxHeight); + final double pageH = pageFormat.getImageableHeight(); + final double pageW = pageFormat.getImageableWidth(); + + if (pageIndex > 0) return (NO_SUCH_PAGE); + + final Graphics2D g2d = (Graphics2D)g; + + // Move the (x,y) origin to account for the left-hand and top margins + g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY()); + + // Draw the page bounding box + g2d.drawRect(0,0,(int)pageW,(int)pageH); + + // Select the smaller scaling factor so that the figure + // fits on the page in both dimensions + final double scale = Math.min( (pageW/boxWidth), (pageH/boxHeight) ); + + if(scale < 1.0) g2d.scale(scale, scale); + + // Paint the scaled component on the printer + g2d.fillRect(rect.x, rect.y, rect.width, rect.height); + + return(PAGE_EXISTS); + } +} + +class Sysout { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PaintText.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PaintText.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6498340 + * @summary No exception when printing text with a paint. + * @run main PaintText + */ + +import java.awt.*; +import java.awt.event.*; +import java.text.*; +import java.util.*; +import java.awt.font.*; +import java.awt.geom.*; +import java.awt.print.*; +import javax.swing.*; + +public class PaintText extends Component implements Printable { + + static int preferredSize; + static int NUMTABS = 6; + int tabNumber; + + public static void main(String args[]) { + + PrinterJob pjob = PrinterJob.getPrinterJob(); + if (pjob.getPrintService() == null) { + System.out.println("No printers: cannot continue"); + return; + } + + PageFormat pf = pjob.defaultPage(); + preferredSize = (int)pf.getImageableWidth(); + + Book book = new Book(); + + JTabbedPane p = new JTabbedPane(); + + for (int id=1; id <= NUMTABS; id++) { + String name = "Tab " + new Integer(id); + PaintText ptt = new PaintText(id); + p.add(name, ptt); + book.append(ptt, pf); + } + pjob.setPageable(book); + + JFrame f = new JFrame(); + f.add(BorderLayout.CENTER, p); + f.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) {System.exit(0);} + }); + f.pack(); + f.show(); + + /* Non-jtreg execution will display the dialog */ + if (System.getProperty("test.java") == null) { + if (!pjob.printDialog()) { + return; + } + } + try { + pjob.print(); + } catch (PrinterException e) { + throw new RuntimeException(e.getMessage()); + } + } + + public PaintText(int id) { + tabNumber = id; + } + + public int print(Graphics g, PageFormat pf, int pageIndex) { + System.out.println(""+pageIndex); + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pf.getImageableX(), pf.getImageableY()); + g.drawString("ID="+tabNumber,100,20); + g.translate(0, 25); + paint(g); + return PAGE_EXISTS; + } + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + public Dimension getPreferredSize() { + return new Dimension(preferredSize, preferredSize); + } + + public void paint(Graphics g) { + + /* fill with white before any transformation is applied */ + g.setColor(Color.white); + g.fillRect(0, 0, getSize().width, getSize().height); + + Graphics2D g2d = (Graphics2D)g; + + Font f = new Font("Lucida Sans", Font.PLAIN, 40); + Color c = new Color(0,0,255,96); + Paint p = new GradientPaint(0f, 0f, Color.green, + 10f, 10f, Color.red, + true); + String s = "Sample Text To Paint"; + float x = 20, y= 50; + + switch (tabNumber) { + case 1: + g2d.setFont(f); + g2d.setColor(c); + g2d.drawString(s, x, y); + break; + + case 2: + g2d.setFont(f); + g2d.setPaint(p); + g2d.drawString(s, x, y); + break; + + case 3: + AttributedString as = new AttributedString(s); + as.addAttribute(TextAttribute.FONT, f); + as.addAttribute(TextAttribute.FOREGROUND, c); + g2d.drawString(as.getIterator(), x, y); + break; + + case 4: + as = new AttributedString(s); + as.addAttribute(TextAttribute.FONT, f); + as.addAttribute(TextAttribute.FOREGROUND, p); + g2d.drawString(as.getIterator(), x, y); + break; + + case 5: + as = new AttributedString(s); + as.addAttribute(TextAttribute.FONT, f); + as.addAttribute(TextAttribute.FOREGROUND, c); + FontRenderContext frc = g2d.getFontRenderContext(); + TextLayout tl = new TextLayout(as.getIterator(), frc); + tl.draw(g2d, x, y); + break; + + case 6: + as = new AttributedString(s); + as.addAttribute(TextAttribute.FONT, f); + as.addAttribute(TextAttribute.FOREGROUND, p); + frc = g2d.getFontRenderContext(); + tl = new TextLayout(as.getIterator(), frc); + tl.draw(g2d, x, y); + break; + + default: + } + } + +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintAllFonts.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintAllFonts.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * + * @bug 4884389 7183516 + * @summary Font specified with face name loses style on printing + * @run main/manual PrintRotatedText + */ + +import java.awt.*; +import java.awt.print.*; +import java.awt.GraphicsEnvironment; + +public class PrintAllFonts implements Printable { + + static Font[] allFonts; + int fontNum = 0; + int startNum = 0; + int lineHeight = 18; + boolean done = false; + int thisPage = 0; + + + public static void main(String[] args) throws Exception { + + String[] instructions = + { + "You must have a printer available to perform this test and should use Win 98.", + "This bug is system dependent and is not always reproducible.", + " ", + "A passing test will have all text printed with correct font style.", + }; + + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + GraphicsEnvironment ge = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + allFonts = ge.getAllFonts(); + + PrinterJob pj = PrinterJob.getPrinterJob(); + pj.setPrintable(new PrintAllFonts()); + if (pj.printDialog()) { + pj.print(); + } + } + + public int print(Graphics g, PageFormat pf, int pageIndex) { + + if (fontNum >= allFonts.length && pageIndex > thisPage) { + return NO_SUCH_PAGE; + } + if (pageIndex > thisPage) { + startNum = fontNum; + thisPage = pageIndex; + } else { + fontNum = startNum; + } + g.setColor(Color.black); + + int hgt = (int)pf.getImageableHeight(); + int fontsPerPage = hgt/lineHeight; + int x = (int)pf.getImageableX()+10; + int y = (int)pf.getImageableY()+lineHeight; + + for (int n = 0; n < fontsPerPage; n++) { + Font f = allFonts[fontNum].deriveFont(Font.PLAIN, 16); + g.setFont(f); + g.drawString(f.getFontName(), x, y); + y+= lineHeight; + fontNum++; + if (fontNum >= allFonts.length) { + break; + } + } + return PAGE_EXISTS; + } +} + +class Sysout { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintBadImage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintBadImage.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4398853 + * @summary Printing shouldn't hang on bad images + * @author prr + * @run main/manual PrintBadImage + */ + +import java.awt.*; +import java.awt.print.*; + + +public class PrintBadImage implements Printable { + + public static void main(String args[]) { + + PrintBadImage pbi = new PrintBadImage(); + PrinterJob pj = PrinterJob.getPrinterJob(); + if (pj != null) { + pj.setPrintable(pbi); + try { + pj.print(); + } catch (PrinterException pe) { + } finally { + System.err.println("PRINT RETURNED"); + } + } + } + + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { + if (pgIndex > 0) + return Printable.NO_SUCH_PAGE; + + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); + Image imgJava = Toolkit.getDefaultToolkit().getImage("img.bad"); + g2d.drawImage(imgJava, 0, 0, null); + + return Printable.PAGE_EXISTS; + } + +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintCompoundString.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintCompoundString.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4396835 + * @summary Compound font string not printing. + * @author prr + * @run main/manual PrintCompoundString + */ + + +import java.awt.*; +import java.awt.event.*; +import java.awt.print.*; +import java.text.*; + +public class PrintCompoundString extends Frame implements ActionListener { + + private TextCanvas c; + + public static void main(String args[]) { + + String[] instructions = + { + "You must have a printer available to perform this test", + "This test should print a page which contains the same", + "text message as in the test window on the screen", + "You should also monitor the command line to see if any exceptions", + "were thrown", + "If an exception is thrown, or the page doesn't print properly", + "then the test fails", + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PrintCompoundString f = new PrintCompoundString(); + f.show(); + } + + public PrintCompoundString() { + super("JDK 1.2 drawString Printing"); + + c = new TextCanvas(); + add("Center", c); + + Button printButton = new Button("Print"); + printButton.addActionListener(this); + add("South", printButton); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + pack(); + } + + public void actionPerformed(ActionEvent e) { + + PrinterJob pj = PrinterJob.getPrinterJob(); + + if (pj != null && pj.printDialog()) { + + pj.setPrintable(c); + try { + pj.print(); + } catch (PrinterException pe) { + } finally { + System.err.println("PRINT RETURNED"); + } + } + } + + class TextCanvas extends Panel implements Printable { + + String nullStr = null; + String emptyStr = new String(); + AttributedString nullAttStr = null; + AttributedString emptyAttStr = new AttributedString(emptyStr); + AttributedCharacterIterator nullIterator = null; + AttributedCharacterIterator emptyIterator = emptyAttStr.getIterator(); + + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { + + if (pgIndex > 0) + return Printable.NO_SUCH_PAGE; + + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); + + paint(g); + + return Printable.PAGE_EXISTS; + } + + public void paint(Graphics g1) { + Graphics2D g = (Graphics2D)g1; + + String str = "Test string compound printing \u2203\u2200\u2211"; + g.drawString(str, 20, 40); + + } + + public Dimension getPreferredSize() { + return new Dimension(450, 250); + } + } + +} + +class Sysout + { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintDialog.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintDialog.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test PrintDialog.java + @bug 4257903 + @summary Confirm that the you see the print dialog. + @author prr: area=PrinterJob + @run main/manual PrintDialog +*/ + + +//*** global search and replace PrintDialog with name of the test *** + +/** + * PrintDialog.java + * + * summary: + */ + +import java.awt.*; +import java.awt.event.*; +import java.awt.print.*; + +// This test is a "main" test as applets would need Runtime permission +// "queuePrintJob". + +public class PrintDialog { + + + private static void init() + { + //*** Create instructions for the user here *** + + String[] instructions = + { + "Visual inspection of the dialog is needed. It should be", + "a Printer Job Setup Dialog", + "You may cancel or OK the dialog." + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PrinterJob pjob = PrinterJob.getPrinterJob(); + pjob.printDialog(); + + }//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-defined + 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; + + 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 passed nor test failed 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) + { + 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(); + } + //pass was called from a different thread, so set the flag and interrupt + // the main thead. + 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 PrintDialog + +//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 **************** + +// make listeners in a class defined here, and 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 + + PrintDialog.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + PrintDialog.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.show(); + 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.show(); + 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 implements ActionListener + { + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + Panel buttonP = new Panel(); + Button passB = new Button( "pass" ); + Button failB = new Button( "fail" ); + + //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); + + passB = new Button( "pass" ); + passB.setActionCommand( "pass" ); + passB.addActionListener( this ); + buttonP.add( "East", passB ); + + failB = new Button( "fail" ); + failB.setActionCommand( "fail" ); + failB.addActionListener( this ); + buttonP.add( "West", failB ); + + add( "South", buttonP ); + pack(); + + show(); + }// 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" ); + } + + //catch presses of the passed and failed buttons. + //simply call the standard pass() or fail() static methods of + //PrintDialog + public void actionPerformed( ActionEvent e ) + { + if( e.getActionCommand() == "pass" ) + { + PrintDialog.pass(); + } + else + { + PrintDialog.fail(); + } + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintDialogCancel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintDialogCancel.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4398231 + @summary Confirm that the print dialog returns false when cancelled. + @author prr: area=PrinterJob + @run main/manual PrintDialogCancel +*/ + + +//*** global search and replace PrintDialogCancel with name of the test *** + +/** + * PrintDialogCancel.java + * + * summary: + */ + +import javax.print.attribute.HashPrintRequestAttributeSet; +import java.awt.*; +import java.awt.event.*; +import java.awt.print.*; + +// This test is a "main" test as applets would need Runtime permission +// "queuePrintJob". + +public class PrintDialogCancel { + + + private static void init() + { + //*** Create instructions for the user here *** + + String[] instructions = + { + "Visual inspection of the dialog is needed. It should be", + "a Printer Job Setup Dialog", + "Do nothing except Cancel", + "You must NOT press OK", + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PrinterJob pjob = PrinterJob.getPrinterJob(); + boolean rv = pjob.printDialog(new HashPrintRequestAttributeSet()); + if (rv) { + throw new RuntimeException("User pressed cancel, but true returned"); + } + }//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-defined + 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; + + 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 passed nor test failed 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) + { + 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(); + } + //pass was called from a different thread, so set the flag and interrupt + // the main thead. + 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 PrintDialogCancel + +//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 **************** + +// make listeners in a class defined here, and 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 + + PrintDialogCancel.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + PrintDialogCancel.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.show(); + 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.show(); + 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 implements ActionListener + { + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + Panel buttonP = new Panel(); + Button passB = new Button( "pass" ); + Button failB = new Button( "fail" ); + + //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); + + passB = new Button( "pass" ); + passB.setActionCommand( "pass" ); + passB.addActionListener( this ); + buttonP.add( "East", passB ); + + failB = new Button( "fail" ); + failB.setActionCommand( "fail" ); + failB.addActionListener( this ); + buttonP.add( "West", failB ); + + add( "South", buttonP ); + pack(); + + show(); + }// 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" ); + } + + //catch presses of the passed and failed buttons. + //simply call the standard pass() or fail() static methods of + //PrintDialogCancel + public void actionPerformed( ActionEvent e ) + { + if( e.getActionCommand() == "pass" ) + { + PrintDialogCancel.pass(); + } + else + { + PrintDialogCancel.fail(); + } + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintFontStyle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintFontStyle.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.*; +import java.awt.print.*; +import java.awt.GraphicsEnvironment; + +public class PrintFontStyle { + public static void main(String[] args) { + + String[] instructions = + { + "You must have a printer available to perform this test and should use Win 98.", + "This bug is system dependent and is not always reproducible.", + " ", + "A passing test will have all text printed with correct font style.", + }; + + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PrinterJob pj=PrinterJob.getPrinterJob(); + pj.setPrintable(new FontPrintable()); + if (pj.printDialog()) + { + try { pj.print(); } + catch (PrinterException e) { + System.out.println(e); + } + } + } +} + +class FontPrintable + implements Printable { + + public int print(Graphics g, PageFormat pf, int pageIndex) { + if (pageIndex != 0) return NO_SUCH_PAGE; + Graphics2D g2= (Graphics2D)g; + + g2.setPaint(Color.black); + + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + String[] fontList = ge.getAvailableFontFamilyNames(); + g2.setFont (new Font ("Arial", Font.PLAIN, 20)); + g2.drawString("Arial - Plain", 144, 120); + g2.setFont (new Font ("Arial", Font.BOLD, 20)); + g2.drawString("Arial - Bold", 144, 145); + g2.setFont (new Font ("Arial", Font.ITALIC, 20)); + g2.drawString("Arial - Italic", 144, 170); + g2.setFont (new Font ("Times New Roman", Font.PLAIN, 20)); + g2.drawString("Times New Roman - Plain", 144, 195); + g2.setFont (new Font ("Times New Roman", Font.BOLD, 20)); + g2.drawString("Times New Roman - Bold", 144, 220); + g2.setFont (new Font ("Times New Roman", Font.ITALIC, 20)); + g2.drawString("Times New Roman - Italic", 144, 245); + + return PAGE_EXISTS; + } +} + +class Sysout { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintImage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintImage.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test %I %W + * @bug 4298489 + * @summary Confirm that output is same as screen. + * @author jgodinez + * @run main/manual PrintImage + */ +import java.awt.*; +import java.awt.print.*; +import java.awt.event.*; + +public class PrintImage extends Frame implements ActionListener { + + private PrintImageCanvas printImageCanvas; + + private MenuItem print1Menu = new MenuItem("PrintTest1"); + private MenuItem print2Menu = new MenuItem("PrintTest2"); + private MenuItem exitMenu = new MenuItem("Exit"); + + public static void main(String[] argv) { + String[] instructions = + { "You must have a printer available to perform this test,", + "prefererably Canon LaserShot A309GII.", + "Printing must be done in Win 98 Japanese 2nd Edition.", + "", + "Passing test : Output of text image for PrintTest1 and PrintTest2 should be same as that on the screen.", + }; + + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + new PrintImage(); + } + + public PrintImage() { + super("PrintImage"); + initPrintImage(); + } + + public void initPrintImage() { + + printImageCanvas = new PrintImageCanvas(this); + + initMenu(); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent ev) { + dispose(); + } + public void windowClosed(WindowEvent ev) { + System.exit(0); + } + }); + + setLayout(new BorderLayout()); + add(printImageCanvas, BorderLayout.CENTER); + pack(); + + setSize(500,500); + setVisible(true); + } + + private void initMenu() { + MenuBar mb = new MenuBar(); + Menu me = new Menu("File"); + me.add(print1Menu); + me.add(print2Menu); + me.add("-"); + me.add(exitMenu); + mb.add(me); + this.setMenuBar(mb); + + print1Menu.addActionListener(this); + print2Menu.addActionListener(this); + exitMenu.addActionListener(this); + } + + public void actionPerformed(ActionEvent e) { + Object target = e.getSource(); + if( target.equals(print1Menu) ) { + printMain1(); + } + else if( target.equals(print2Menu) ) { + printMain2(); + } + else if( target.equals(exitMenu) ) { + dispose(); + } + } + + private void printMain1(){ + + PrinterJob printerJob = PrinterJob.getPrinterJob(); + PageFormat pageFormat = printerJob.defaultPage(); + + printerJob.setPrintable((Printable)printImageCanvas, pageFormat); + + if(printerJob.printDialog()){ + try { + printerJob.print(); + } + catch(PrinterException p){ + } + } + else + printerJob.cancel(); + } + + private void printMain2(){ + + PrinterJob printerJob = PrinterJob.getPrinterJob(); + PageFormat pageFormat = printerJob.pageDialog(printerJob.defaultPage()); + + printerJob.setPrintable((Printable)printImageCanvas, pageFormat); + + if(printerJob.printDialog()){ + try { + printerJob.print(); + } + catch(PrinterException p){ + } + } + else + printerJob.cancel(); + } + +} + +class PrintImageCanvas extends Canvas implements Printable { + + private PrintImage pdsFrame; + + public PrintImageCanvas(PrintImage pds) { + pdsFrame = pds; + } + + public void paint(Graphics g) { + Font drawFont = new Font("MS Mincho",Font.ITALIC,50); + g.setFont(drawFont); + g.drawString("PrintSample!",100,150); + } + + public int print(Graphics g, PageFormat pf, int pi) + throws PrinterException { + + if(pi>=1) + return NO_SUCH_PAGE; + else{ + Graphics2D g2 = (Graphics2D)g; + g.setColor(new Color(0,0,0,200)); + + Font drawFont = new Font("MS Mincho",Font.ITALIC,50); + g.setFont(drawFont); + g.drawString("PrintSample!",100,150); + return PAGE_EXISTS; + } + } +} + + +class Sysout { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintNullString.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintNullString.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4223328 + * @summary Printer graphics must behave the same as screen graphics + * @author prr + * @run main/manual PrintNullString + */ + + +import java.awt.*; +import java.awt.event.*; +import java.awt.print.*; +import java.text.*; + +public class PrintNullString extends Frame implements ActionListener { + + private TextCanvas c; + + public static void main(String args[]) { + + String[] instructions = + { + "You must have a printer available to perform this test", + "This test should print a page which contains the same", + "text messages as in the test window on the screen", + "The messages should contain only 'OK' and 'expected' messages", + "There should be no FAILURE messages.", + "You should also monitor the command line to see if any exceptions", + "were thrown", + "If the page fails to print, but there were no exceptions", + "then the problem is likely elsewhere (ie your printer)" + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PrintNullString f = new PrintNullString(); + f.show(); + } + + public PrintNullString() { + super("JDK 1.2 drawString Printing"); + + c = new TextCanvas(); + add("Center", c); + + Button printButton = new Button("Print"); + printButton.addActionListener(this); + add("South", printButton); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + pack(); + } + + public void actionPerformed(ActionEvent e) { + + PrinterJob pj = PrinterJob.getPrinterJob(); + + if (pj != null && pj.printDialog()) { + + pj.setPrintable(c); + try { + pj.print(); + } catch (PrinterException pe) { + } finally { + System.err.println("PRINT RETURNED"); + } + } + } + + class TextCanvas extends Panel implements Printable { + + String nullStr = null; + String emptyStr = new String(); + AttributedString nullAttStr = null; + AttributedString emptyAttStr = new AttributedString(emptyStr); + AttributedCharacterIterator nullIterator = null; + AttributedCharacterIterator emptyIterator = emptyAttStr.getIterator(); + + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { + + if (pgIndex > 0) + return Printable.NO_SUCH_PAGE; + + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); + + paint(g); + + return Printable.PAGE_EXISTS; + } + + public void paint(Graphics g1) { + Graphics2D g = (Graphics2D)g1; + + // API 1: null & empty drawString(String, int, int); + try { + g.drawString(nullStr, 20, 40); + g.drawString("FAILURE: No NPE for null String, int", 20, 40); + } catch (NullPointerException e) { + g.drawString("caught expected NPE for null String, int", 20, 40); + }/* catch (Exception e) { + g.drawString("FAILURE: unexpected exception for null String, int", + 20, 40); + }*/ + + //try { + g.drawString(emptyStr, 20, 60); + g.drawString("OK for empty String, int", 20, 60); + /*} catch (Exception e) { + g.drawString("FAILURE: unexpected exception for empty String, int", + 20, 60); + }*/ + + + // API 2: null & empty drawString(String, float, float); + try { + g.drawString(nullStr, 20.0f, 80.0f); + g.drawString("FAILURE: No NPE for null String, float", 20, 80); + } catch (NullPointerException e) { + g.drawString("caught expected NPE for null String, float", 20, 80); + } /*catch (Exception e) { + g.drawString("FAILURE: unexpected exception for null String, float", + 20, 80); + }*/ + //try { + g.drawString(emptyStr, 20.0f, 100.0f); + g.drawString("OK for empty String, float", 20.0f, 100.f); + /* } catch (Exception e) { + g.drawString("FAILURE: unexpected exception for empty String, float", + 20, 100); + }*/ + + // API 3: null & empty drawString(Iterator, int, int); + try { + g.drawString(nullIterator, 20, 120); + g.drawString("FAILURE: No NPE for null iterator, float", 20, 120); + } catch (NullPointerException e) { + g.drawString("caught expected NPE for null iterator, int", 20, 120); + } /*catch (Exception e) { + g.drawString("FAILURE: unexpected exception for null iterator, int", + 20, 120); + } */ + try { + g.drawString(emptyIterator, 20, 140); + g.drawString("FAILURE: No IAE for empty iterator, int", + 20, 140); + } catch (IllegalArgumentException e) { + g.drawString("caught expected IAE for empty iterator, int", + 20, 140); + } /*catch (Exception e) { + g.drawString("FAILURE: unexpected exception for empty iterator, int", + 20, 140); + } */ + + + // API 4: null & empty drawString(Iterator, float, int); + try { + g.drawString(nullIterator, 20.0f, 160.0f); + g.drawString("FAILURE: No NPE for null iterator, float", 20, 160); + } catch (NullPointerException e) { + g.drawString("caught expected NPE for null iterator, float", 20, 160); + } /*catch (Exception e) { + g.drawString("FAILURE: unexpected exception for null iterator, float", + 20, 160); + } */ + + try { + g.drawString(emptyIterator, 20, 180); + g.drawString("FAILURE: No IAE for empty iterator, float", + 20, 180); + } catch (IllegalArgumentException e) { + g.drawString("caught expected IAE for empty iterator, float", + 20, 180); + } /*catch (Exception e) { + g.drawString("FAILURE: unexpected exception for empty iterator, float", + 20, 180); + } */ + } + + public Dimension getPreferredSize() { + return new Dimension(450, 250); + } + } + +} + +class Sysout + { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintParenString.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintParenString.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4399442 + * @summary Brackets should be quoted in Postscript output + * @author prr + * @run main/manual PrintParenString + */ + + +import java.awt.*; +import java.awt.event.*; +import java.awt.print.*; +import java.text.*; + +public class PrintParenString extends Frame implements ActionListener { + + private TextCanvas c; + + public static void main(String args[]) { + + String[] instructions = + { + "You must have a printer available to perform this test", + "This test should print a page which contains the same", + "text message as in the test window on the screen", + "You should also monitor the command line to see if any exceptions", + "were thrown", + "If an exception is thrown, or the page doesn't print properly", + "then the test fails", + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PrintParenString f = new PrintParenString(); + f.show(); + } + + public PrintParenString() { + super("JDK 1.2 drawString Printing"); + + c = new TextCanvas(); + add("Center", c); + + Button printButton = new Button("Print"); + printButton.addActionListener(this); + add("South", printButton); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + pack(); + } + + public void actionPerformed(ActionEvent e) { + + PrinterJob pj = PrinterJob.getPrinterJob(); + + if (pj != null && pj.printDialog()) { + + pj.setPrintable(c); + try { + pj.print(); + } catch (PrinterException pe) { + } finally { + System.err.println("PRINT RETURNED"); + } + } + } + + class TextCanvas extends Panel implements Printable { + + String nullStr = null; + String emptyStr = new String(); + AttributedString nullAttStr = null; + AttributedString emptyAttStr = new AttributedString(emptyStr); + AttributedCharacterIterator nullIterator = null; + AttributedCharacterIterator emptyIterator = emptyAttStr.getIterator(); + + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { + + if (pgIndex > 0) + return Printable.NO_SUCH_PAGE; + + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); + + paint(g); + + return Printable.PAGE_EXISTS; + } + + public void paint(Graphics g1) { + Graphics2D g = (Graphics2D)g1; + + String str = "String containing unclosed parenthesis (."; + g.drawString(str, 20, 40); + + } + + public Dimension getPreferredSize() { + return new Dimension(450, 250); + } + } + +} + +class Sysout + { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintRotatedText.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintRotatedText.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4271596 + * @bug 4460699 + * @summary Rotated text printing + * @author prr + * @run main/manual PrintRotatedText + */ + +/* Text is drawn as spokes of a wheel with both a uniform scale and + * a non-uniform scale. + * The test is checking whether the implementation properly handles this + * and in particular that asking win32 GDI to draw text rotated works + * properly. + * + */ +import java.awt.*; +import java.awt.event.*; +import java.awt.font.*; +import java.awt.geom.*; +import java.awt.print.*; + +public class PrintRotatedText extends Frame implements ActionListener { + static String fontname="Lucida Sans Regular"; // our font + private TextCanvas c; + + public static void main(String args[]) { + + PrintRotatedText f = new PrintRotatedText(); + f.show(); + } + + public PrintRotatedText() { + super("JDK 1.2 Text Printing"); + + String []fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + for (int i=0;i MAXPAGE) throw new IndexOutOfBoundsException(); + PageFormat pf = new PageFormat(); + Paper p = pf.getPaper(); + p.setImageableArea(36, 36, p.getWidth()-72, p.getHeight()-72); + pf.setPaper(p); + +/* + if (pageIndex==1) + pf.setOrientation(PageFormat.LANDSCAPE); + else if (pageIndex==2) + pf.setOrientation(PageFormat.REVERSE_LANDSCAPE); +*/ + + return pf; + } + + public Printable getPrintable(int pageIndex) { + if (pageIndex > MAXPAGE) throw new IndexOutOfBoundsException(); + return this; + } + + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { +System.out.println("****"+pgIndex); + double iw = pgFmt.getImageableWidth(); + double ih = pgFmt.getImageableHeight(); + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); + //g2d.drawString("top left of page format",20,20 ); + int modulo = pgIndex % 4; + int divvy = pgIndex / 4; + if (divvy != 0 ) { + g2d.setFont(new Font(fontname,Font.PLAIN, 18)); + estr = ""; + } else { + estr = extra; + } + + int xs = 1; + int ys = 1; + + if (modulo == 1) { + xs = -1; + } + if (modulo == 2) { + ys = -1; + } + if (modulo == 3) { + xs = -1; + ys = -1; + } + + g2d.translate(iw*0.25, ih*0.2); + drawTheText((Graphics2D)g2d.create(), xs*1.0,ys* 1.0); + g2d.translate(iw*0.25, ih*0.2); + drawTheText((Graphics2D)g2d.create(), xs*1.0,ys* 1.5); + g2d.translate(-iw*0.2, ih*0.3); + drawTheText((Graphics2D)g2d.create(), xs*1.5, ys*1.0); + + return Printable.PAGE_EXISTS; + } + + private void drawTheText(Graphics2D g2d, double sx, double sy) { + double mat[]= new double[6]; + + g2d.drawOval(-75,-75,150,150); + int degrees = 30; + for (int i=0;i<360;i=i+degrees) { + AffineTransform saveXfm = g2d.getTransform(); + g2d.scale(sx, sy); + int ttype = g2d.getTransform().getType(); + String s = "ANGLE="+i; + s +=estr; + g2d.drawString(s, 20, 0); + FontRenderContext frc = g2d.getFontRenderContext(); + Font f = g2d.getFont(); + Rectangle2D r2d = f.getStringBounds(s, frc); + g2d.drawLine(20, 1, 20+(int)r2d.getWidth(), 1); + g2d.scale(1.0/sx, 1.0/sy); + g2d.setTransform(saveXfm); + + g2d.rotate(Math.toRadians(degrees)); + } + } + + public void paint(Graphics g) { + g.translate(200,200); + g.setFont(new Font("serif", Font.PLAIN, 12)); + drawTheText((Graphics2D)g, 1.0, 1.5); + } + + public Dimension getPreferredSize() { + return new Dimension(400, 400); + } + } + +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintTextLayout.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintTextLayout.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4480930 + * @summary TextLayout prints as filled shapes + * @author prr + * @run main/manual PrintTextLayout + */ + +/* This is a MANUAL test and must be run on a system with a printer + * configured. + */ + +import java.io.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.font.*; +import java.awt.geom.*; +import java.awt.print.*; +import javax.print.attribute.*; +import javax.print.attribute.standard.*; + +public class PrintTextLayout implements Printable { + static String[] fontnames = { + "Lucida Sans", + "Lucida Bright", + "Lucida Sans Typewriter", + "SansSerif", + "Serif", + "Monospaced", + }; + + static String text = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890"; + + public static void main(String args[]) { + PrinterJob pj = PrinterJob.getPrinterJob(); + + if (pj != null) { + PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); + aset.add(new Destination((new File("./out.ps")).toURI())); + PageFormat pf = pj.defaultPage(); + Paper p = pf.getPaper(); + // Extend imageable width to reduce likelihood end of text + // is clipped as we'd like to see the end of the line. + p.setImageableArea(p.getImageableX(), p.getImageableY(), + p.getWidth()-p.getImageableX(), + p.getImageableHeight()); + pf.setPaper(p); + pj.setPrintable( new PrintTextLayout(), pf); + try { + pj.print(aset); + } catch (PrinterException pe) { + pe.printStackTrace(); + } finally { + } + } + } + + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { + if (pgIndex > 0) return Printable.NO_SUCH_PAGE; + + double iw = pgFmt.getImageableWidth(); + double ih = pgFmt.getImageableHeight(); + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY()+50); + + float ypos = 20f; + for (int f=0; f< fontnames.length; f++) { + for (int s=0;s<4;s++) { + Font font = new Font(fontnames[f], s, 12); + ypos = drawText(g2d, font, ypos); + } + } + return Printable.PAGE_EXISTS; + } + + float drawText(Graphics2D g2d, Font font, float ypos) { + int x = 10; + /* Set the graphics font to something odd before using TL so + * can be sure it picks up the font from the TL, not the graphics */ + Font f1 = new Font("serif", Font.ITALIC, 1); + g2d.setFont(f1); + FontRenderContext frc = new FontRenderContext(null, false, false); + TextLayout tl = new TextLayout(text ,font, frc); + float ascent = tl.getAscent(); + int dpos = (int)(ypos+ascent); + tl.draw(g2d, x, dpos); + int dpos2 = (int)(ypos+ascent+tl.getDescent()); + g2d.drawLine(x, dpos2, x+(int)tl.getAdvance(), dpos2); + float tlHeight = tl.getAscent()+tl.getDescent()+tl.getLeading(); + return ypos+tlHeight; + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintTextPane.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintTextPane.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test PrintTextPane.java + @bug 6452415 6570471 + @summary Test that swing text prints using GDI printer fonts. + @author prr: area=PrinterJob + @run main PrintTextPane + + */ +import java.io.*; +import java.net.*; +import java.awt.*; +import java.awt.event.*; +import javax.print.attribute.*; +import javax.print.attribute.standard.*; +import javax.swing.*; +import javax.swing.text.*; +import java.awt.print.*; + +public class PrintTextPane extends JTextPane implements Printable { + + static String text = "Twinkle twinkle little star, \n" + + "How I wonder what you are. \n" + + "Up above the world so high, \n" + + "Like a diamond in the sky. \n" + + "Twinkle, twinkle, little star, \n" + + "How I wonder what you are!\n"; + + public int print(Graphics g, PageFormat pf, int page) + throws PrinterException { + if (page > 0) { + return NO_SUCH_PAGE; + } + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pf.getImageableX(), pf.getImageableY()); + printAll(g); + return PAGE_EXISTS; + } + + public void printPane(PrintRequestAttributeSet aset) { + try { + print(null, null, false, null, aset, false); + } catch (PrinterException ex) { + throw new RuntimeException(ex); + } + } + + public void printPaneJob(PrintRequestAttributeSet aset) { + PrinterJob job = PrinterJob.getPrinterJob(); + job.setPrintable(this); + try { + job.print(aset); + } catch (PrinterException ex) { + throw new RuntimeException(ex); + } + } + + public PrintTextPane(String fontFamily) { + super(); + SimpleAttributeSet aset = new SimpleAttributeSet(); + StyleConstants.setFontFamily(aset, fontFamily); + setCharacterAttributes(aset, false); + setText(text+text+text+text+text+text+text+text); + } + + public static void main(String args[]) throws Exception { + + String os = System.getProperty("os.name"); + + if (!os.startsWith("Windows")) { + return; + } + + PrinterJob job = PrinterJob.getPrinterJob(); + if (job.getPrintService() == null) { + System.err.println("Warning: no printers, skipping test"); + return; + } + JFrame f = new JFrame("Print Text Pane1"); + f.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) {System.exit(0);} + }); + PrintTextPane monoPane = new PrintTextPane("Monospaced"); + f.add("East", monoPane); + PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); + PrintTextPane courPane = new PrintTextPane("Courier New"); + f.add("West", courPane); + f.pack(); + f.setVisible(true); + + File spoolFile = File.createTempFile("CourText", ".prn"); + System.out.println(spoolFile); + Destination dest = new Destination(spoolFile.toURI()); + aset.add(dest); + courPane.printPane(aset); + long courLen = spoolFile.length(); + System.out.println("CourText="+spoolFile.length()); + spoolFile.delete(); + + spoolFile = File.createTempFile("MonoText", ".prn"); + System.out.println(spoolFile); + dest = new Destination(spoolFile.toURI()); + aset.add(dest); + monoPane.printPane(aset); + long monoLen = spoolFile.length(); + System.out.println("MonoText="+spoolFile.length()); + spoolFile.delete(); + + if (courLen > 2 * monoLen) { + throw new RuntimeException("Shapes being printed?"); + } + + spoolFile = File.createTempFile("CourJob", ".prn"); + System.out.println(spoolFile); + dest = new Destination(spoolFile.toURI()); + aset.add(dest); + courPane.printPaneJob(aset); + courLen = spoolFile.length(); + System.out.println("CourJob="+spoolFile.length()); + spoolFile.delete(); + + spoolFile = File.createTempFile("MonoJob", ".prn"); + System.out.println(spoolFile); + dest = new Destination(spoolFile.toURI()); + aset.add(dest); + monoPane.printPaneJob(aset); + monoLen = spoolFile.length(); + System.out.println("MonoJob="+spoolFile.length()); + spoolFile.delete(); + + if (courLen > 2 * monoLen) { + throw new RuntimeException("Shapes being printed?"); + } + + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintTextTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintTextTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6425068 7157659 + * @summary Confirm that text prints where we expect to the length we expect. + * @run main/manual=yesno PrintTextTest + */ + +import java.awt.*; +import java.awt.event.*; +import java.text.*; +import java.util.*; +import java.awt.font.*; +import java.awt.geom.*; +import java.awt.print.*; +import javax.swing.*; + +public class PrintTextTest extends Component implements Printable { + + static int preferredSize; + Font textFont; + AffineTransform gxTx; + String page; + boolean useFM; + + public static void main(String args[]) { + String[] instructions = + { + "This tests that printed text renders similarly to on-screen", + "under a variety of APIs and graphics and font transforms", + "Print to your preferred printer. Collect the output.", + "Refer to the onscreen buttons to cycle through the on-screen", + "content", + "For each page, confirm that the printed content corresponds to", + "the on-screen rendering for that *same* page.", + "Some cases may look odd but its intentional. Verify", + "it looks the same on screen and on the printer.", + "Note that text does not scale linearly from screen to printer", + "so some differences are normal and not a bug.", + "The easiest way to spot real problems is to check that", + "any underlines are the same length as the underlined text", + "and that any rotations are the same in each case.", + "Note that each on-screen page is printed in both portrait", + "and landscape mode", + "So for example, Page 1/Portrait, and Page 1/Landscape when", + "rotated to view properly, should both match Page 1 on screen.", + }; + Sysout.createDialogWithInstructions(instructions); + + + PrinterJob pjob = PrinterJob.getPrinterJob(); + PageFormat portrait = pjob.defaultPage(); + portrait.setOrientation(PageFormat.PORTRAIT); + preferredSize = (int)portrait.getImageableWidth(); + + PageFormat landscape = pjob.defaultPage(); + landscape.setOrientation(PageFormat.LANDSCAPE); + + Book book = new Book(); + + JTabbedPane p = new JTabbedPane(); + + int page = 1; + Font font = new Font("Dialog", Font.PLAIN, 18); + String name = "Page " + new Integer(page++); + PrintTextTest ptt = new PrintTextTest(name, font, null, false); + p.add(name, ptt); + book.append(ptt, portrait); + book.append(ptt, landscape); + + font = new Font("Dialog", Font.PLAIN, 18); + name = "Page " + new Integer(page++); + ptt = new PrintTextTest(name, font, null, true); + p.add(name, ptt); + book.append(ptt, portrait); + book.append(ptt, landscape); + + font = new Font("Lucida Sans", Font.PLAIN, 18); + name = "Page " + new Integer(page++); + ptt = new PrintTextTest(name, font, null, false); + p.add(name, ptt); + book.append(ptt, portrait); + book.append(ptt, landscape); + + font = new Font("Lucida Sans", Font.PLAIN, 18); + AffineTransform rotTx = AffineTransform.getRotateInstance(0.15); + rotTx.translate(60,0); + name = "Page " + new Integer(page++); + ptt = new PrintTextTest(name, font, rotTx, false); + p.add(name, ptt); + book.append(ptt, portrait); + book.append(ptt, landscape); + + font = font.deriveFont(rotTx); + name = "Page " + new Integer(page++); + ptt = new PrintTextTest(name, font, null, false); + p.add(ptt, BorderLayout.CENTER); + p.add(name, ptt); + book.append(ptt, portrait); + book.append(ptt, landscape); + + if (System.getProperty("os.name").startsWith("Windows")) { + font = new Font("MS Gothic", Font.PLAIN, 12); + name = "Page " + new Integer(page++); + ptt = new PrintJAText(name, font, null, true); + p.add(ptt, BorderLayout.CENTER); + p.add(name, ptt); + book.append(ptt, portrait); + book.append(ptt, landscape); + + font = new Font("MS Gothic", Font.PLAIN, 12); + name = "Page " + new Integer(page++); + rotTx = AffineTransform.getRotateInstance(0.15); + ptt = new PrintJAText(name, font, rotTx, true); + p.add(ptt, BorderLayout.CENTER); + p.add(name, ptt); + book.append(ptt, portrait); + book.append(ptt, landscape); + } + + pjob.setPageable(book); + + JFrame f = new JFrame(); + f.add(BorderLayout.CENTER, p); + f.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) {System.exit(0);} + }); + f.pack(); + f.show(); + + try { + if (pjob.printDialog()) { + pjob.print(); + } + } catch (PrinterException e) { + throw new RuntimeException(e.getMessage()); + } + } + + public PrintTextTest(String page, Font font, AffineTransform gxTx, + boolean fm) { + this.page = page; + textFont = font; + this.gxTx = gxTx; + this.useFM = fm; + setBackground(Color.white); + } + + public static AttributedCharacterIterator getIterator(String s) { + return new AttributedString(s).getIterator(); + } + + static String orient(PageFormat pf) { + if (pf.getOrientation() == PageFormat.PORTRAIT) { + return "Portrait"; + } else { + return "Landscape"; + } + } + + public int print(Graphics g, PageFormat pf, int pageIndex) { + + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pf.getImageableX(), pf.getImageableY()); + g.drawString(page+" "+orient(pf),50,20); + g.translate(0, 25); + paint(g); + return PAGE_EXISTS; + } + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + public Dimension getPreferredSize() { + return new Dimension(preferredSize, preferredSize); + } + + public void paint(Graphics g) { + + /* fill with white before any transformation is applied */ + g.setColor(Color.white); + g.fillRect(0, 0, getSize().width, getSize().height); + + + Graphics2D g2d = (Graphics2D) g; + if (gxTx != null) { + g2d.transform(gxTx); + } + if (useFM) { + g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, + RenderingHints.VALUE_FRACTIONALMETRICS_ON); + } + + g.setFont(textFont); + FontMetrics fm = g.getFontMetrics(); + + String s; + int LS = 30; + int ix=10, iy=LS+10; + g.setColor(Color.black); + + s = "drawString(String str, int x, int y)"; + g.drawString(s, ix, iy); + if (!textFont.isTransformed()) { + g.drawLine(ix, iy+1, ix+fm.stringWidth(s), iy+1); + } + + iy += LS; + s = "drawString(AttributedCharacterIterator iterator, int x, int y)"; + g.drawString(getIterator(s), ix, iy); + + iy += LS; + s = "\tdrawChars(\t\r\nchar[], int off, int len, int x, int y\t)"; + g.drawChars(s.toCharArray(), 0, s.length(), ix, iy); + if (!textFont.isTransformed()) { + g.drawLine(ix, iy+1, ix+fm.stringWidth(s), iy+1); + } + + iy += LS; + s = "drawBytes(byte[], int off, int len, int x, int y)"; + byte data[] = new byte[s.length()]; + for (int i = 0; i < data.length; i++) { + data[i] = (byte) s.charAt(i); + } + g.drawBytes(data, 0, data.length, ix, iy); + + Font f = g2d.getFont(); + FontRenderContext frc = g2d.getFontRenderContext(); + + iy += LS; + s = "drawString(String s, float x, float y)"; + g2d.drawString(s, (float) ix, (float) iy); + if (!textFont.isTransformed()) { + g.drawLine(ix, iy+1, ix+fm.stringWidth(s), iy+1); + } + + iy += LS; + s = "drawString(AttributedCharacterIterator iterator, "+ + "float x, float y)"; + g2d.drawString(getIterator(s), (float) ix, (float) iy); + + iy += LS; + s = "drawGlyphVector(GlyphVector g, float x, float y)"; + GlyphVector gv = f.createGlyphVector(frc, s); + g2d.drawGlyphVector(gv, ix, iy); + Point2D adv = gv.getGlyphPosition(gv.getNumGlyphs()); + if (!textFont.isTransformed()) { + g.drawLine(ix, iy+1, ix+(int)adv.getX(), iy+1); + } + + iy += LS; + s = "GlyphVector with position adjustments"; + + gv = f.createGlyphVector(frc, s); + int ng = gv.getNumGlyphs(); + adv = gv.getGlyphPosition(ng); + for (int i=0; i 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" ); + } + +}// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintTranslatedFont.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintTranslatedFont.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6359734 + * @summary Test that fonts with a translation print where they should. + * @author prr + * @run main/manual PrintTranslatedFont + */ + + +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.*; +import java.awt.print.*; +import java.text.*; + +public class PrintTranslatedFont extends Frame implements ActionListener { + + private TextCanvas c; + + public static void main(String args[]) { + + String[] instructions = + { + "You must have a printer available to perform this test", + "This test should print a page which contains the same", + "content as the test window on the screen, in particular the lines", + "should be immediately under the text", + "You should also monitor the command line to see if any exceptions", + "were thrown", + "If an exception is thrown, or the page doesn't print properly", + "then the test fails", + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PrintTranslatedFont f = new PrintTranslatedFont(); + f.show(); + } + + public PrintTranslatedFont() { + super("JDK 1.2 drawString Printing"); + + c = new TextCanvas(); + add("Center", c); + + Button printButton = new Button("Print"); + printButton.addActionListener(this); + add("South", printButton); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + pack(); + } + + public void actionPerformed(ActionEvent e) { + + PrinterJob pj = PrinterJob.getPrinterJob(); + + if (pj != null && pj.printDialog()) { + + pj.setPrintable(c); + try { + pj.print(); + } catch (PrinterException pe) { + } finally { + System.err.println("PRINT RETURNED"); + } + } + } + + class TextCanvas extends Panel implements Printable { + + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { + + if (pgIndex > 0) + return Printable.NO_SUCH_PAGE; + + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); + + paint(g); + + return Printable.PAGE_EXISTS; + } + + public void paint(Graphics g1) { + Graphics2D g = (Graphics2D)g1; + + Font f = new Font("Dialog", Font.PLAIN, 20); + int tx = 20; + int ty = 20; + AffineTransform at = AffineTransform.getTranslateInstance(tx, ty); + f = f.deriveFont(at); + g.setFont(f); + + FontMetrics fm = g.getFontMetrics(); + String str = "Basic ascii string"; + int sw = fm.stringWidth(str); + int posx = 20, posy = 40; + g.drawString(str, posx, posy); + g.drawLine(posx+tx, posy+ty+2, posx+tx+sw, posy+ty+2); + + posx = 20; posy = 70; + str = "Test string compound printing \u2203\u2200"; + sw = fm.stringWidth(str); + g.drawString(str, posx, posy); + g.drawLine(posx+tx, posy+ty+2, posx+tx+sw, posy+ty+2); + } + + public Dimension getPreferredSize() { + return new Dimension(450, 250); + } + } + +} + +class Sysout + { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrintVolatileImage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrintVolatileImage.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4511023 + * @summary Image should be sent to printer, no exceptions thrown + * @author prr + * @run main/manual PrintVolatileImage + */ + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; +import java.awt.print.*; + +public class PrintVolatileImage extends Component + implements ActionListener, Printable { + + VolatileImage vimg = null; + + public static void main(String args[]) { + Frame f = new Frame(); + PrintVolatileImage pvi = new PrintVolatileImage(); + f.add("Center", pvi); + Button b = new Button("Print"); + b.addActionListener(pvi); + f.add("South", b); + f.pack(); + f.show(); + } + + public PrintVolatileImage() { + } + + public Dimension getPreferredSize() { + return new Dimension(100,100); + } + + public void paint(Graphics g) { + if (vimg == null) { + vimg = createVolatileImage(100,100); + Graphics ig = vimg.getGraphics(); + ig.setColor(Color.white); + ig.fillRect(0,0,100,100); + ig.setColor(Color.black); + ig.drawLine(0,0,100,100); + ig.drawLine(100,0,0,100); + } + g.drawImage(vimg, 0,0, null); + } + + public void actionPerformed(ActionEvent e) { + + PrinterJob pj = PrinterJob.getPrinterJob(); + + if (pj != null && pj.printDialog()) { + pj.setPrintable(this); + try { + pj.print(); + } catch (PrinterException pe) { + } finally { + System.err.println("PRINT RETURNED"); + } + } + } + + + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { + if (pgIndex > 0) + return Printable.NO_SUCH_PAGE; + + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); + paint(g); + return Printable.PAGE_EXISTS; + } + +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrinterDevice.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrinterDevice.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * + * @bug 4276227 + * @summary Checks that the PrinterGraphics is for a Printer GraphicsDevice. + * Test doesn't run unless there's a printer on the system. + * @author prr + * @run main/othervm PrinterDevice + */ + +import java.awt.*; +import java.awt.geom.*; +import java.awt.print.*; +import java.io.*; +import javax.print.attribute.*; +import javax.print.attribute.standard.*; + +public class PrinterDevice implements Printable { + + public static void main(String args[]) throws PrinterException { + System.setProperty("java.awt.headless", "true"); + + PrinterJob pj = PrinterJob.getPrinterJob(); + if (pj.getPrintService() == null) { + return; /* Need a printer to run this test */ + } + + PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); + File f = new File("./out.prn"); + f.deleteOnExit(); + aset.add(new Destination(f.toURI())); + aset.add(OrientationRequested.LANDSCAPE); + pj.setPrintable(new PrinterDevice()); + pj.print(aset); + } + + public int print(Graphics g, PageFormat pf, int pageIndex) { + if (pageIndex > 0 ) { + return Printable.NO_SUCH_PAGE; + } + + /* Make sure calls to get DeviceConfig, its transforms, + * etc all work without exceptions and as expected */ + Graphics2D g2 = (Graphics2D)g; + GraphicsConfiguration gConfig = g2.getDeviceConfiguration(); + AffineTransform dt = gConfig.getDefaultTransform(); + AffineTransform nt = gConfig.getNormalizingTransform(); + AffineTransform gt = g2.getTransform(); + + System.out.println("Graphics2D transform = " + gt); + System.out.println("Default transform = " + dt); + System.out.println("Normalizing transform = " + nt); + + Rectangle bounds = gConfig.getBounds(); + System.out.println("Bounds = " + bounds); + if (!nt.isIdentity()) { + throw new RuntimeException("Expected Identity transdform"); + } + + /* Make sure that device really is TYPE_PRINTER */ + GraphicsDevice gd = gConfig.getDevice(); + System.out.println("Printer Device ID = " + gd.getIDstring()); + if (!(gd.getType() == GraphicsDevice.TYPE_PRINTER)) { + throw new RuntimeException("Expected printer device"); + } + System.out.println(" *** "); + System.out.println(""); + return Printable.PAGE_EXISTS; + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrinterDialogsModalityTest/PrinterDialogsModalityTest.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrinterDialogsModalityTest/PrinterDialogsModalityTest.html Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,43 @@ + + + + + + PrinterDialogsModalityTest + + + +

    PrinterDialogsModalityTest
    Bug ID: 4784285 4785920

    + +

    See the dialog box (usually in upper left corner) for instructions

    + + + + diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrinterDialogsModalityTest/PrinterDialogsModalityTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrinterDialogsModalityTest/PrinterDialogsModalityTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + test + @bug 4784285 4785920 + @summary check whether Print- and Page- dialogs are modal and correct window activated after their closing + @author son@sparc.spb.su: area=PrinterJob.modality + @run applet/manual=yesno PrinterDialogsModalityTest.html +*/ + +/** + * PrinterDialogsModalityTest.java + * + * summary: check whether Print- and Page- dialogs are modal and correct window activated after their closing + */ + +import java.applet.Applet; + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Dialog; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.TextArea; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import java.awt.print.PageFormat; +import java.awt.print.PrinterJob; + +public class PrinterDialogsModalityTest extends Applet +{ + //Declare things used in the test, like buttons and labels here + + public void init() + { + //Create instructions for the user here, as well as set up + // the environment -- set the layout manager, add buttons, + // etc. + this.setLayout (new BorderLayout ()); + + String[] instructions = + { + "This is a Windows only test, for other platforms consider it passed", + "After test start you will see frame titled \"test Frame\"", + "with two buttons - \"Page Dialog\" and \"Print Dialog\"", + "1. make the frame active by clicking on title", + "2. press \"Page Dialog\" button, page dailog should popup", + "3. make sure page dialog is modal (if not test is failed)", + "4. close the dialog (either cancel it or press ok)", + "5. make sure the frame is still active (if not test is failed)", + "6. press \"Print Dialog\" button, print dialog should popup", + "7. repeat steps 3.-5.", + "", + "If you are able to execute all steps successfully then test is passed, else failed." + }; + Sysout.createDialogWithInstructions( instructions ); + + }//End init() + + public void start () + { + //Get things going. Request focus, set size, et cetera + setSize (200,200); + setVisible(true); + validate(); + + Button page = new Button("Page Dialog"); + page.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PrinterJob prnJob = PrinterJob.getPrinterJob(); + prnJob.pageDialog(new PageFormat()); + } + }); + Button print = new Button("Print Dialog"); + print.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PrinterJob prnJob = PrinterJob.getPrinterJob(); + prnJob.printDialog(); + } + }); + Frame frame = new Frame("Test Frame"); + frame.setLayout(new FlowLayout()); + frame.add(page); + frame.add(print); + frame.setLocation(200, 200); + frame.pack(); + frame.setVisible(true); + + }// start() + + //The rest of this class is the actions which perform the test... + + //Use Sysout.println to communicate with the user NOT System.out!! + //Sysout.println ("Something Happened!"); + +}// class PrinterDialogsModalityTest + +/* 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 = 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 -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/PrinterJobDialogBugDemo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/PrinterJobDialogBugDemo.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4775862 + * @run main/manual PrinterJobDialogBugDemo + */ +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.SwingConstants; + +public class PrinterJobDialogBugDemo extends JFrame implements Printable { + + public static void main(String[] args) { + new PrinterJobDialogBugDemo(); + } + + private PrinterJobDialogBugDemo() { + super("Printer Job Dialog Bug Demo"); + + setDefaultCloseOperation(EXIT_ON_CLOSE); + setSize(700,700); + + JButton btnPrint = new JButton("Print..."); + btnPrint.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent ae) { + showPrintDialog(); + } + }); + + Container contentPane = getContentPane(); + contentPane.add( + new JLabel("This is the main Application Window. " + + "To demonstrate the problem:" + + "
      " + + "
    1. Click the Print button at the bottom of this window. " + + "The Print dialog will appear." + + "
    2. Select another application window." + + "
    3. On the Windows taskbar, click the coffee-cup icon for " + + "this demo application. This brings this window to the " + + "front but the Print dialog remains hidden. " + + "Since this window " + + "is no longer selectable, it can't be moved aside to expose " ++ + "the Print dialog that is now behind it." + + "
    ", + SwingConstants.CENTER), + BorderLayout.NORTH); + contentPane.add(btnPrint, BorderLayout.SOUTH); + setVisible(true); + } + + private void showPrintDialog() { + PrinterJob printJob = PrinterJob.getPrinterJob(); + printJob.setPrintable(this); + PrintRequestAttributeSet printRequestAttrSet = + new HashPrintRequestAttributeSet(); + printJob.printDialog(printRequestAttrSet); + } + + public int print(java.awt.Graphics g, java.awt.print.PageFormat pageFormat, +int pageIndex) { + if (pageIndex == 0) { + return(PAGE_EXISTS); + } else { + return(NO_SUCH_PAGE); + } + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/RemoveListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/RemoveListener.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test 1.1 01/05/17 + * @bug 4459889 + * @summary No NullPointerException should occur. + * @run main RemoveListener +*/ +import javax.print.*; +import javax.print.attribute.*; +import javax.print.event.*; +import javax.print.attribute.standard.*; + +public class RemoveListener { + public static void main(String[] args){ + PrintService[] pservices = PrintServiceLookup.lookupPrintServices(null, null); + if (pservices.length == 0){ + return; + } + DocPrintJob pj = pservices[0].createPrintJob(); + PrintJobAttributeSet aset = new HashPrintJobAttributeSet(); + aset.add(JobState.PROCESSING); + PrintJobAttributeListener listener = new PJAListener(); + pj.addPrintJobAttributeListener(listener, aset); + pj.removePrintJobAttributeListener(listener); + return; + } +} + +class PJAListener implements PrintJobAttributeListener { + public void attributeUpdate(PrintJobAttributeEvent pjae){ + return; + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/ScaledText/ScaledText.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/ScaledText/ScaledText.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,438 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4291373 + @summary Printing of scaled text is wrong / disappearing + @author prr: area=PrinterJob + @run main/manual ScaledText +*/ +import java.awt.*; +import java.awt.event.*; +import java.awt.print.*; + + +public class ScaledText implements Printable { + + private Image opaqueimg,transimg; + + private static void init() { + + //*** Create instructions for the user here *** + + String[] instructions = { + "On-screen inspection is not possible for this printing-specific", + "test therefore its only output is two printed pages.", + "To be able to run this test it is required to have a default", + "printer configured in your user environment.", + "", + "Visual inspection of the printed pages is needed. A passing", + "test will print a page on which 6 lines of text will be", + "printed, all of the same size. The test fails only if the sizes", + "are different, or not all of the sizes labelled 1.0, 2.0, 4.0", + "8.0, 16.0, 32.0 appear." + }; + + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PrinterJob pjob = PrinterJob.getPrinterJob(); + + Book book = new Book(); + + PageFormat portrait = pjob.defaultPage(); + book.append(new ScaledText(),portrait); + + pjob.setPageable(book); + + if (pjob.printDialog()) { + try { + pjob.print(); + } catch (PrinterException e) { + System.err.println(e); + e.printStackTrace(); + } + } + System.out.println("Done Printing"); + + }//End init() + + + public ScaledText() { + } + + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { + + Graphics2D g2D = (Graphics2D) g; + g2D.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); + + g2D.setColor(Color.black); + Font font = new Font("serif", Font.PLAIN, 1); + + float scale; + float x; + float y; + + scale = 1.0f; + x = 3.0f; + y = 3.0f; + printScale(g2D, font, scale, x, y); + + scale = 2.0f; + x = 3.0f; + y = 3.5f; + printScale(g2D, font, scale, x, y); + + scale = 4.0f; + x = 3.0f; + y = 4.0f; + printScale(g2D, font, scale, x, y); + + scale = 8.0f; + x = 3.0f; + y = 4.5f; + printScale(g2D, font, scale, x, y); + + scale = 16.0f; + x = 3.0f; + y = 5.0f; + printScale(g2D, font, scale, x, y); + + scale = 32.0f; + x = 3.0f; + y = 5.5f; + printScale(g2D, font, scale, x, y); + + return Printable.PAGE_EXISTS; + } + + /** + * The graphics is scaled and the font and the positions + * are reduced in respect to the scaling, so that all + * printing should be the same. + * + * @param g2D graphics2D to paint on + * @param font font to paint + * @param scale scale for the painting + * @param x x position + * @param y y position + */ + private void printScale(Graphics2D g2D, Font font, + float scale, float x, float y) { + + int RES = 72; + + g2D.scale(scale, scale); + + g2D.setFont (font.deriveFont(10.0f / scale)); + g2D.drawString("This text is scaled by a factor of " + scale, + x * RES / scale, y * RES / scale); + + g2D.scale(1/scale, 1/scale); + +} + + /***************************************************** + 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-defined + 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; + + 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 passed nor test failed 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) + { + 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(); + } + //pass was called from a different thread, so set the flag and interrupt + // the main thead. + theTestPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + }//pass() + + public static synchronized void fail() + { + //test writer didn't specify why test failed, s 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 ScaledText + +//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 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.show(); + 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.show(); + 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 implements ActionListener { + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + Panel buttonP = new Panel(); + Button passB = new Button( "pass" ); + Button failB = new Button( "fail" ); + + //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); + + passB = new Button( "pass" ); + passB.setActionCommand( "pass" ); + passB.addActionListener( this ); + buttonP.add( "East", passB ); + + failB = new Button( "fail" ); + failB.setActionCommand( "fail" ); + failB.addActionListener( this ); + buttonP.add( "West", failB ); + + add( "South", buttonP ); + pack(); + + show(); + }// 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" ); + } + + //catch presses of the passed and failed buttons. + //simply call the standard pass() or fail() static methods of + //ScaledText + public void actionPerformed( ActionEvent e ) + { + if( e.getActionCommand() == "pass" ) + { + ScaledText.pass(); + } + else + { + ScaledText.fail(); + } + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/SecurityDialogTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/SecurityDialogTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4937672 5100706 6252456 + * @run main/manual SecurityDialogTest + */ + +import java.awt.* ; +import java.awt.print.* ; +import java.io.*; +import java.security.*; +import javax.print.*; +import javax.print.attribute.*; + +public class SecurityDialogTest { + + + public static void main ( String args[] ) { + + String[] instructions = + { + "You must have a printer available to perform this test.", + "This test brings up a native and cross-platform page and", + "print dialogs.", + "The dialogs should be displayed even when ", + "there is no queuePrintJob permission.", + "If the dialog has an option to save to file, the option ought", + "to be disabled if there is no read/write file permission.", + "You should test this by trying different policy files." + }; + + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + SecurityDialogTest pjc = new SecurityDialogTest() ; + } + + + public SecurityDialogTest() { + + PrinterJob pj = PrinterJob.getPrinterJob() ; + + // Install a security manager which does not allow reading and + // writing of files. + //PrintTestSecurityManager ptsm = new PrintTestSecurityManager(); + SecurityManager ptsm = new SecurityManager(); + + try { + System.setSecurityManager(ptsm); + } catch (SecurityException e) { + System.out.println("Could not run test - security exception"); + } + + try { + PrintJob pjob = Toolkit.getDefaultToolkit().getPrintJob(new Frame(), "Printing", null, null); + Sysout.println("If the value of pjob is null, the test fails.\n"); + Sysout.println(" pjob = "+pjob); + } catch (SecurityException e) { + } + + PrintService[] services = PrinterJob.lookupPrintServices(); + for (int i=0; i 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/SetCopies/Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/SetCopies/Test.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4694495 + * @summary Check that the dialog shows copies = 3. + * @run main/manual Test + */ +import java.awt.print.*; +import javax.print.*; +import javax.print.attribute.*; +import javax.print.attribute.standard.*; + +public class Test { + static public void main(String args[]) { + DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PAGEABLE; + PrintRequestAttributeSet aSet + = new HashPrintRequestAttributeSet(); + PrintService[] services + = PrintServiceLookup.lookupPrintServices(flavor, aSet); + + PrinterJob pj = PrinterJob.getPrinterJob(); + + for (int i=0; iText"; + String TABLE_BEGIN = ""; + String TABLE_END = "
    "; + StringBuffer buffer = new StringBuffer(); + buffer.append("").append(TABLE_BEGIN); + for (int j = 0; j < 15; j++) { + buffer.append(CELL); + } + buffer.append(""); + buffer.append(TABLE_END).append(""); + editor.setText(buffer.toString()); + + panel.add(editor); + + frame = new JFrame("Swing UI Text Printing Test"); + frame.getContentPane().add(panel); + frame.pack(); + frame.setVisible(true); + + PrinterJob job = PrinterJob.getPrinterJob(); + PageFormat pf = job.defaultPage(); + job.setPrintable(new SwingUIText(), pf); + if (job.printDialog()) { + try { job.print(); } + catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + } + + + static void displayText(JPanel p, String text) { + JPanel panel = new JPanel(); + panel.setLayout(new GridLayout(2,1)); + JPanel row = new JPanel(); + Font font = new Font("Dialog", Font.PLAIN, 12); + + JLabel label = new JLabel(text); + label.setFont(font); + row.add(label); + + JButton button = new JButton("Print "+text); + button.setMnemonic('P'); + button.setFont(font); + row.add(button); + + panel.add(row); + + row = new JPanel(); + JTextField textField = new JTextField(text); + row.add(textField); + + JTextArea textArea = new JTextArea(); + textArea.setText(text); + row.add(textArea); + + panel.add(row); + p.add(panel); + } + + public int print(Graphics g, PageFormat pf, int pageIndex) + throws PrinterException { + + if (pageIndex >= 1) { + return Printable.NO_SUCH_PAGE; + } + g.translate((int)pf.getImageableX(), (int)pf.getImageableY()); + frame.printAll(g); + + return Printable.PAGE_EXISTS; + } + +} + +class Sysout + { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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( "", 10, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("South", messageText); + + pack(); + + show(); + }// 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" ); + } + +}// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/ThinLines.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/ThinLines.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4190081 + @summary Confirm that the you see "Z" shapes on the printed page. + @author prr/rbi: area=PrinterJob + @run main/manual ThinLines +*/ + + +//*** global search and replace ThinLines with name of the test *** + +/** + * ThinLines.java + * + * summary: + */ + +import java.awt.*; +import java.awt.event.*; +import java.awt.print.*; + +// This test is a "main" test as applets would need Runtime permission +// "queuePrintJob". + +public class ThinLines implements Printable { + + private static final int INCH = 72; + + private static void init() + { + //*** Create instructions for the user here *** + + String[] instructions = + { + "On-screen inspection is not possible for this printing-specific", + "test therefore its only output is a printed page.", + "To be able to run this test it is required to have a default", + "printer configured in your user environment.", + "", + "Visual inspection of the printed page is needed. A passing", + "test will print a large \"Z\" shape which is repeated 6 times.", + "The top-most and diagonal lines of each \"Z\" are thin lines.", + "The bottom line of each \"Z\" is a thicker line.", + "In a failing test, the thin lines do not appear." + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + PrinterJob pjob = PrinterJob.getPrinterJob(); + PageFormat pf = pjob.defaultPage(); + Book book = new Book(); + + book.append(new ThinLines(), pf); + pjob.setPageable(book); + + try { + pjob.print(); + } catch (PrinterException e) { + e.printStackTrace(); + } + + }//End init() + + public int print(Graphics g, PageFormat pf, int pageIndex) { + Graphics2D g2d = (Graphics2D) g; + g2d.translate(pf.getImageableX(), pf.getImageableY()); + + g2d.setColor(Color.black); + Stroke thinLine = new BasicStroke(0.01f); + Stroke thickLine = new BasicStroke(1.0f); + + + for (int y = 100; y < 900; y += 100) { + g2d.setStroke(thinLine); + g2d.drawLine(INCH, y, INCH * 3, y); + g2d.drawLine(INCH * 3, y, INCH, y + INCH/2); + g2d.setStroke(thickLine); + g2d.drawLine(INCH, y + INCH/2, INCH * 3, y + INCH/2); + } + + return PAGE_EXISTS; + } + + + + /***************************************************** + 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-defined + 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; + + 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 passed nor test failed 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) + { + 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(); + } + //pass was called from a different thread, so set the flag and interrupt + // the main thead. + 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 ThinLines + +//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 **************** + +// make listeners in a class defined here, and 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 + + ThinLines.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + ThinLines.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.show(); + 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.show(); + 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 implements ActionListener + { + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + Panel buttonP = new Panel(); + Button passB = new Button( "pass" ); + Button failB = new Button( "fail" ); + + //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); + + passB = new Button( "pass" ); + passB.setActionCommand( "pass" ); + passB.addActionListener( this ); + buttonP.add( "East", passB ); + + failB = new Button( "fail" ); + failB.setActionCommand( "fail" ); + failB.addActionListener( this ); + buttonP.add( "West", failB ); + + add( "South", buttonP ); + pack(); + + show(); + }// 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" ); + } + + //catch presses of the passed and failed buttons. + //simply call the standard pass() or fail() static methods of + //ThinLines + public void actionPerformed( ActionEvent e ) + { + if( e.getActionCommand() == "pass" ) + { + ThinLines.pass(); + } + else + { + ThinLines.fail(); + } + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/XparColor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/XparColor.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @bug 4179262 + * @summary Confirm that transparent colors are printed correctly. The + * printout should show transparent rings with increasing darkness toward + * the center. + *@run applet/manual=yesno XparColor.html + */ + +import java.applet.Applet; +import java.awt.*; +import java.awt.print.*; +import java.awt.event.*; +import java.awt.geom.Ellipse2D; + + +/** + * Creating colors with an alpha value. + */ +public class XparColor extends Applet implements Printable { + + public void init() { + String[] instructions = + { + "This test verify that the BullsEye rings are printed correctly. The printout should show transparent rings with increasing darkness toward the center" + }; + Sysout.createDialogWithInstructions( instructions ); + } + + public XparColor() { + PrinterJob printJob = PrinterJob.getPrinterJob(); + printJob.setPrintable(this); + if (printJob.printDialog()) { + try { + printJob.print(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + + public static void main(String s[]) { + XparColor xc = new XparColor(); + PrinterJob printJob = PrinterJob.getPrinterJob(); + printJob.setPrintable(xc); + if (printJob.printDialog()) { + try { + printJob.print(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + public int print(Graphics g, PageFormat pf, int pi) + throws PrinterException { + if (pi >= 1) { + return Printable.NO_SUCH_PAGE; + } + + Graphics2D g2d = (Graphics2D) g; + g2d.translate(pf.getImageableX(), pf.getImageableY()); + g2d.translate(pf.getImageableWidth() / 2, + pf.getImageableHeight() / 2); + + Dimension d = new Dimension(400, 400); + + double scale = Math.min(pf.getImageableWidth() / d.width, + pf.getImageableHeight() / d.height); + if (scale < 1.0) { + g2d.scale(scale, scale); + } + + g2d.translate(-d.width / 2.0, -d.height / 2.0); + + Graphics2D g2 = (Graphics2D)g; + drawDemo(d.width, d.height, g2); + g2.dispose(); + + return Printable.PAGE_EXISTS; + } + + public void drawDemo(int w, int h, Graphics2D g2) { + + Color reds[] = { Color.red.darker(), Color.red }; + for (int N = 0; N < 18; N++) { + float i = (N + 2) / 2.0f; + float x = (float) (5+i*(w/2/10)); + float y = (float) (5+i*(h/2/10)); + float ew = (w-10)-(i*w/10); + float eh = (h-10)-(i*h/10); + float alpha = (N == 0) ? 0.1f : 1.0f / (19.0f - N); + if ( N >= 16 ) + g2.setColor(reds[N-16]); + else + g2.setColor(new Color(0f, 0f, 0f, alpha)); + g2.fill(new Ellipse2D.Float(x,y,ew,eh)); + } + } +} +/**************************************************** + 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.show(); + 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.show(); + 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 = 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("South", messageText); + + pack(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/awt/print/PrinterJob/raster/RasterTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/raster/RasterTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4242639 + * @summary Printing quality problem on Canon and NEC + * @author prr + * @run main/manual RasterTest + */ +import java.awt.*; +import java.awt.geom.*; +import java.awt.event.*; +import java.awt.print.*; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; + + +public class RasterTest extends Frame implements ActionListener { + + private RasterCanvas c; + + public static void main(String args[]) { + String[] instructions = + { + "You must have a printer available to perform this test", + "This test uses rendering operations which force the implementation", + "to print the page as a raster", + "You should see two square images, the 1st containing overlapping", + "composited squares, the lower image shows a gradient paint.", + "The printed output should match the on-screen display, although", + "only colour printers will be able to accurately reproduce the", + "subtle color changes." + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + RasterTest f = new RasterTest(); + f.show(); + } + + public RasterTest() { + super("Java 2D Raster Printing"); + + c = new RasterCanvas(); + add("Center", c); + + Button printButton = new Button("Print"); + printButton.addActionListener(this); + add("South", printButton); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + pack(); + + setBackground(Color.white); + + } + + public void actionPerformed(ActionEvent e) { + + PrinterJob pj = PrinterJob.getPrinterJob(); + + if (pj != null && pj.printDialog()) { + pj.setPrintable(c); + try { + pj.print(); + } catch (PrinterException pe) { + } finally { + System.err.println("PRINT RETURNED"); + } + } +} + + + class RasterCanvas extends Canvas implements Printable { + + + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { + if (pgIndex > 0) + return Printable.NO_SUCH_PAGE; + + Graphics2D g2d= (Graphics2D)g; + g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); + doPaint(g2d); + return Printable.PAGE_EXISTS; + } + + public void paint(Graphics g) { + doPaint(g); + } + + public void paintComponent(Graphics g) { + doPaint(g); + } + + public void doPaint(Graphics g) { + Graphics2D g2 = (Graphics2D)g; + + g2.setColor(Color.black); + + BufferedImage bimg = new BufferedImage(200, 200, + BufferedImage.TYPE_INT_ARGB); + Graphics ig = bimg.getGraphics(); + Color alphared = new Color(255, 0, 0, 128); + Color alphagreen = new Color(0, 255, 0, 128); + Color alphablue = new Color(0, 0, 255, 128); + ig.setColor(alphared); + ig.fillRect(0,0,200,200); + ig.setColor(alphagreen); + ig.fillRect(25,25,150,150); + ig.setColor(alphablue); + ig.fillRect(75,75,125,125); + g.drawImage(bimg, 10, 25, this); + + GradientPaint gp = + new GradientPaint(10.0f, 10.0f, alphablue, 210.0f, 210.0f, alphared, true); + g2.setPaint(gp); + g2.fillRect(10, 240, 200, 200); + + } + + public Dimension getPreferredSize() { + return new Dimension(500, 500); + } + + } + +} + + +class Sysout { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + 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.show(); + 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 = 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(); + + show(); + }// 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" ); + } + + }// TestDialog class diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/beans/Introspector/Test8039776.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/beans/Introspector/Test8039776.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Set; +import java.util.SortedSet; + +import static java.beans.Introspector.getBeanInfo; + +/* + * @test + * @bug 8039776 + * @summary Tests that Introspector does not throw NPE + * @author Sergey Malenkov + */ + +public class Test8039776 { + public static void main(String[] args) throws Exception { + getBeanInfo(Base.class, Object.class); + getBeanInfo(Child.class, Base.class); + getBeanInfo(Child.class, Object.class); + } + + public static class Base { + private SortedSet value; + + public Set getValue() { + return this.value; + } + + public void setValue(SortedSet value) { + this.value = value; + } + } + + public static class Child extends Base { + public Set getValue() { + return super.getValue(); + } + + public void setValue(SortedSet items) { + super.setValue(items); + } + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/beans/Introspector/TestCacheRecursion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/beans/Introspector/TestCacheRecursion.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.beans.util.Cache; + +/* + * @test + * @bug 8039137 + * @summary Tests Cache recursion + * @author Sergey Malenkov + * @compile -XDignore.symbol.file TestCacheRecursion.java + * @run main TestCacheRecursion + */ + +public class TestCacheRecursion { + private static boolean ERROR; + private static final Cache,Boolean> CACHE + = new Cache,Boolean>(Cache.Kind.WEAK, Cache.Kind.STRONG) { + @Override + public Boolean create(Class type) { + if (ERROR) { + throw new Error("not initialized"); + } + type = type.getSuperclass(); + return (type != null) && get(type); + } + }; + + public static void main(String[] args) { + CACHE.get(Z.class); + ERROR = true; + for (Class type = Z.class; type != null; type = type.getSuperclass()) { + CACHE.get(type); + } + } + + private class A {} + private class B extends A {} + private class C extends B {} + private class D extends C {} + private class E extends D {} + private class F extends E {} + private class G extends F {} + private class H extends G {} + private class I extends H {} + private class J extends I {} + private class K extends J {} + private class L extends K {} + private class M extends L {} + private class N extends M {} + private class O extends N {} + private class P extends O {} + private class Q extends P {} + private class R extends Q {} + private class S extends R {} + private class T extends S {} + private class U extends T {} + private class V extends U {} + private class W extends V {} + private class X extends W {} + private class Y extends X {} + private class Z extends Y {} +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/math/BigInteger/BitLengthOverflow.java --- a/jdk/test/java/math/BigInteger/BitLengthOverflow.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/java/math/BigInteger/BitLengthOverflow.java Wed Jul 05 19:39:35 2017 +0200 @@ -41,6 +41,10 @@ } catch (ArithmeticException e) { // expected System.out.println("Overflow is reported by ArithmeticException, as expected"); + } catch (OutOfMemoryError e) { + // possible + System.err.println("BitLengthOverflow skipped: OutOfMemoryError"); + System.err.println("Run jtreg with -javaoption:-Xmx8g"); } } } diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/math/BigInteger/DoubleValueOverflow.java --- a/jdk/test/java/math/BigInteger/DoubleValueOverflow.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/java/math/BigInteger/DoubleValueOverflow.java Wed Jul 05 19:39:35 2017 +0200 @@ -41,6 +41,10 @@ } catch (ArithmeticException e) { // expected System.out.println("Overflow is reported by ArithmeticException, as expected"); + } catch (OutOfMemoryError e) { + // possible + System.err.println("DoubleValueOverflow skipped: OutOfMemoryError"); + System.err.println("Run jtreg with -javaoption:-Xmx8g"); } } } diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/net/Inet4Address/DummyNameService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/net/Inet4Address/DummyNameService.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * A simple name service which throws an exception when invoked + */ + +import java.net.UnknownHostException; +import java.net.InetAddress; +import sun.net.spi.nameservice.*; +import java.util.*; + +public final class DummyNameService implements NameService { + + public DummyNameService() throws Exception { + } + + public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException { + throw new UnknownHostException("Dummy name service"); + } + + public String getHostByAddr(byte[] addr) throws UnknownHostException { + throw new UnknownHostException("Dummy name service"); + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/net/Inet4Address/DummyNameServiceDescriptor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/net/Inet4Address/DummyNameServiceDescriptor.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Descriptor for the dummy name service + */ + +import sun.net.spi.nameservice.*; + +public final class DummyNameServiceDescriptor implements NameServiceDescriptor { + + /** + * Create a new instance of the corresponding name service. + */ + public NameService createNameService() throws Exception { + return new DummyNameService(); + } + + /** + * Returns this service provider's name + * + */ + public String getProviderName() { + return "oracle"; + } + + /** + * Returns this name service type + * "dns" "nis" etc + */ + public String getType() { + return "dummy"; + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/net/Inet4Address/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/net/Inet4Address/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,22 @@ +# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +DummyNameServiceDescriptor # name service provider descriptor diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/net/Inet4Address/textToNumericFormat.java --- a/jdk/test/java/net/Inet4Address/textToNumericFormat.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/java/net/Inet4Address/textToNumericFormat.java Wed Jul 05 19:39:35 2017 +0200 @@ -25,8 +25,18 @@ * @test * @bug 4749938 * @summary Bug in the parsing IPv4 literal addresses + * @compile -XDignore.symbol.file=true DummyNameService.java DummyNameServiceDescriptor.java + * @run main/othervm -Dsun.net.spi.nameservice.provider.1=dummy,oracle textToNumericFormat */ +/** + * We use a dummy name service which throws UHE any time it is called. + * We do this because the "good" tests here should parse correctly + * without needing to call the name service, and the bad tests will + * not parse and then invoke the name service, where we expect + * the exception. + */ + import java.net.InetAddress; import java.net.UnknownHostException; import java.util.*; diff -r a77941f17614 -r 0d1f816217dc jdk/test/java/util/Arrays/Correct.java --- a/jdk/test/java/util/Arrays/Correct.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/java/util/Arrays/Correct.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,44 +23,49 @@ /* * @test - * @bug 4726380 + * @bug 4726380 8037097 * @summary Check that different sorts give equivalent results. + * @run testng Correct */ import java.util.*; +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; +import static org.testng.Assert.fail; +import static org.testng.Assert.assertEquals; + public class Correct { - static Random rnd = new Random(); + static final Random rnd = new Random(); static final int ITERATIONS = 1000; static final int TEST_SIZE = 1000; - public static void main(String[] args) throws Exception { - Object[] array1 = null; - Object[] array2 = null; - + @Test + public void testDefaultSort() { for (int i=0; i comparator) { + for (int i=0; i comparators() { + Object[][] comparators = new Object[][] { + new Object[] { Comparator.naturalOrder() }, + new Object[] { Comparator.naturalOrder().reversed() }, + new Object[] { STANDARD_ORDER }, + new Object[] { STANDARD_ORDER.reversed() }, + new Object[] { REVERSE_ORDER }, + new Object[] { REVERSE_ORDER.reversed() }, + new Object[] { Comparator.comparingInt(Integer::intValue) } + }; - private static class IntegerComparator implements Comparator { - public int compare(Object o1, Object o2) { - Comparable c1 = (Comparable)o1; - Comparable c2 = (Comparable)o2; - return c1.compareTo(c2); + return Arrays.asList(comparators).iterator(); + } + + private static final Comparator STANDARD_ORDER = new Comparator() { + public int compare(Integer o1, Integer o2) { + return o1.compareTo(o2); } - } + }; + + private static final Comparator REVERSE_ORDER = new Comparator() { + public int compare(Integer o1, Integer o2) { + return - o1.compareTo(o2); + } + }; } diff -r a77941f17614 -r 0d1f816217dc jdk/test/javax/swing/JCheckBox/8032667/bug8032667.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JCheckBox/8032667/bug8032667.html Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,36 @@ + + + + + +Verify that scaled components are rendered smoothly to image. + +1. Run the test. +2. Check that Selected and Deselected JCheckBox icons are drawn smoothly. +If so, press PASS, else press FAIL. + + + + + diff -r a77941f17614 -r 0d1f816217dc jdk/test/javax/swing/JCheckBox/8032667/bug8032667.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JCheckBox/8032667/bug8032667.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.image.BufferedImage; +import javax.swing.JApplet; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; + +/* @test + * @bug 8032667 + * @summary [macosx] Components cannot be rendered in HiDPI to BufferedImage + * @run applet/manual=yesno bug8032667.html + */ +public class bug8032667 extends JApplet { + + static final int scale = 2; + static final int width = 130; + static final int height = 50; + static final int scaledWidth = scale * width; + static final int scaledHeight = scale * height; + + @Override + public void init() { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + final Image image1 = getImage(getCheckBox("Deselected", false)); + final Image image2 = getImage(getCheckBox("Selected", true)); + + Canvas canvas = new Canvas() { + + @Override + public void paint(Graphics g) { + super.paint(g); + g.drawImage(image1, 0, 0, scaledWidth, scaledHeight, this); + g.drawImage(image2, 0, scaledHeight + 5, + scaledWidth, scaledHeight, this); + } + }; + + getContentPane().add(canvas, BorderLayout.CENTER); + } + }); + } + + static JCheckBox getCheckBox(String text, boolean selected) { + JCheckBox checkBox = new JCheckBox(text); + checkBox.setSelected(selected); + checkBox.setSize(new Dimension(width, height)); + return checkBox; + } + + static Image getImage(JComponent component) { + final BufferedImage image = new BufferedImage( + scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB); + final Graphics g = image.getGraphics(); + ((Graphics2D) g).scale(scale, scale); + component.paint(g); + g.dispose(); + + return image; + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/javax/swing/JCheckBox/8032667/bug8032667_image_diff.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JCheckBox/8032667/bug8032667_image_diff.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.image.BufferedImage; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import sun.awt.OSInfo; + +/* @test + * @bug 8032667 + * @summary [macosx] Components cannot be rendered in HiDPI to BufferedImage + * @run main bug8032667_image_diff + */ +public class bug8032667_image_diff { + + static final int IMAGE_WIDTH = 130; + static final int IMAGE_HEIGHT = 50; + + public static void main(String[] args) throws Exception { + + if(!OSInfo.OSType.MACOSX.equals(OSInfo.getOSType())){ + return; + } + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + + JCheckBox checkBox = new JCheckBox(); + checkBox.setSelected(true); + checkBox.setSize(new Dimension(IMAGE_WIDTH, IMAGE_HEIGHT)); + + final BufferedImage image1 = getHiDPIImage(checkBox); + final BufferedImage image2 = getScaledImage(checkBox); + + if(equal(image1, image2)){ + throw new RuntimeException("2x image equals to non smooth image"); + } + } + }); + } + + static boolean equal(BufferedImage image1, BufferedImage image2) { + + int w = image1.getWidth(); + int h = image1.getHeight(); + + if (w != image2.getWidth() || h != image2.getHeight()) { + return false; + } + + for (int i = 0; i < w; i++) { + for (int j = 0; j < h; j++) { + int color1 = image1.getRGB(i, j); + int color2 = image2.getRGB(i, j); + + if (color1 != color2) { + return false; + } + } + } + return true; + } + + static BufferedImage getHiDPIImage(JComponent component) { + return getImage(component, 2, IMAGE_WIDTH, IMAGE_HEIGHT); + } + + static BufferedImage getScaledImage(JComponent component) { + Image image1x = getImage(component, 1, IMAGE_WIDTH, IMAGE_HEIGHT); + final BufferedImage image2x = new BufferedImage( + 2 * IMAGE_WIDTH, 2 * IMAGE_HEIGHT, BufferedImage.TYPE_INT_ARGB); + final Graphics g = image2x.getGraphics(); + ((Graphics2D) g).scale(2, 2); + g.drawImage(image1x, 0, 0, null); + g.dispose(); + return image2x; + } + + static BufferedImage getImage(JComponent component, int scale, int width, int height) { + final BufferedImage image = new BufferedImage( + scale * width, scale * height, BufferedImage.TYPE_INT_ARGB); + final Graphics g = image.getGraphics(); + ((Graphics2D) g).scale(scale, scale); + component.paint(g); + g.dispose(); + return image; + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/javax/swing/JTable/8031971/bug8031971.java --- a/jdk/test/javax/swing/JTable/8031971/bug8031971.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/javax/swing/JTable/8031971/bug8031971.java Wed Jul 05 19:39:35 2017 +0200 @@ -29,7 +29,7 @@ /** * @test - * @bug 8031971 + * @bug 8031971 8039750 * @author Alexander Scherbatiy * @summary Use only public methods in the SwingLazyValue * @run main bug8031971 diff -r a77941f17614 -r 0d1f816217dc jdk/test/javax/swing/JTable/8032874/bug8032874.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTable/8032874/bug8032874.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8032874 + * @summary Test whether ArrayIndexOutOfBoundsException is thrown or not, + * once selected row is removed from JTable with Sorter and Filter + * @author Dmitry Markov + * @run main bug8032874 + */ + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.*; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableRowSorter; + +import sun.awt.SunToolkit; + +public class bug8032874 { + private static final int ROW_COUNT = 5; + private static JTable table; + private static TestTableModel tableModel; + + public static void main(String args[]) throws Exception { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + createAndShowUI(); + } + }); + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + table.getRowSorter().toggleSortOrder(0); + table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + table.setRowSelectionInterval(1, 2); + } + }); + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + for (int i = 0; i < ROW_COUNT; i++) { + tableModel.remove(0); + table.getRowSorter().toggleSortOrder(0); + } + } + }); + } + + public static void createAndShowUI() { + try { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException(e); + } + + JFrame frame = new JFrame("bug8032874"); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + + tableModel = new TestTableModel(); + table = new JTable(tableModel); + table.setSurrendersFocusOnKeystroke(true); + + final TableRowSorter rowSorter = new TableRowSorter(tableModel); + rowSorter.setRowFilter(new RowFilter() { + @Override + public boolean include(Entry entry) { + return entry.getIdentifier() % 2 == 0; + } + }); + table.setRowSorter(rowSorter); + + JScrollPane jScrollPane = new JScrollPane(table); + panel.add(jScrollPane); + + frame.setContentPane(panel); + frame.setSize(new Dimension(800, 600)); + frame.setVisible(true); + } + + private static class TestTableModel extends AbstractTableModel { + private final List data; + + public TestTableModel() { + data = new ArrayList(); + + for (int i = 0; i < ROW_COUNT; i++) { + data.add(i); + } + } + + @Override + public int getRowCount() { + return data.size(); + } + + @Override + public int getColumnCount() { + return 1; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + return data.get(rowIndex); + } + + public void remove(int row) { + data.remove(row); + fireTableRowsDeleted(row, row); + } + } +} + diff -r a77941f17614 -r 0d1f816217dc jdk/test/javax/swing/JTree/8038113/bug8038113.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTree/8038113/bug8038113.html Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,36 @@ + + + + + +Verify that scaled icons are rendered smoothly. + +1. Run the test. +2. Check that Collapsed and Expanded JTree icons are drawn smoothly. +If so, press PASS, else press FAIL. + + + + + diff -r a77941f17614 -r 0d1f816217dc jdk/test/javax/swing/JTree/8038113/bug8038113.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTree/8038113/bug8038113.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Graphics; +import java.awt.Graphics2D; +import javax.swing.Icon; +import javax.swing.JApplet; +import javax.swing.JPanel; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.plaf.basic.BasicTreeUI; + +/* @test + * @bug 8038113 + * @summary [macosx] JTree icon is not rendered in high resolution on Retina + * @run applet/manual=yesno bug8038113.html + */ +public class bug8038113 extends JApplet { + + @Override + public void init() { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + final JTree tree = new JTree(); + final BasicTreeUI treeUI = (BasicTreeUI) tree.getUI(); + + final JPanel panel = new JPanel() { + + @Override + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2 = (Graphics2D) g; + g2.setStroke(new BasicStroke(0.5f)); + g2.scale(2, 2); + + int x = 10; + int y = 10; + Icon collapsedIcon = treeUI.getCollapsedIcon(); + Icon expandeIcon = treeUI.getExpandedIcon(); + int w = collapsedIcon.getIconWidth(); + int h = collapsedIcon.getIconHeight(); + collapsedIcon.paintIcon(this, g, x, y); + g.drawRect(x, y, w, h); + + y += 10 + h; + w = expandeIcon.getIconWidth(); + h = expandeIcon.getIconHeight(); + expandeIcon.paintIcon(this, g, x, y); + g.drawRect(x, y, w, h); + + } + }; + getContentPane().setLayout(new BorderLayout()); + getContentPane().add(panel, BorderLayout.CENTER); + } + }); + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/javax/swing/SwingUtilities/8032219/DrawRect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/SwingUtilities/8032219/DrawRect.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import sun.swing.SwingUtilities2; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +/** + * @test + * @bug 8032219 + * @author Sergey Bylokhov + */ +public final class DrawRect { + + private static final int size = 50; + + private static final Rectangle[] rects = { + new Rectangle(0, 0, 1, 1), + new Rectangle(0, 0, 1, 2), + new Rectangle(0, 0, 2, 1), + new Rectangle(10, 10, 10, 10), + new Rectangle(10, 10, -1, -1), + new Rectangle(-1, -1, 10, 10), + new Rectangle(-1, -1, -10, -10), + new Rectangle(0, 0, size, size), + }; + + private static final Rectangle[] vlines = {new Rectangle(0, 0, 0, 0), + new Rectangle(0, 0, 0, 1), + new Rectangle(0, 0, 0, -1), + new Rectangle(1, 1, 0, 1), + new Rectangle(1, 1, 0, -1), + new Rectangle(15, 15, 0, 10), + new Rectangle(15, 15, 0, -10), + }; + private static final Rectangle[] hlines = {new Rectangle(0, 0, 0, 0), + new Rectangle(0, 0, 1, 0), + new Rectangle(0, 0, -1, 0), + new Rectangle(1, 1, 1, 0), + new Rectangle(1, 1, -1, 0), + new Rectangle(15, 15, 10, 0), + new Rectangle(15, 15, -10, 0), + }; + + public static void main(final String[] args) throws IOException { + BufferedImage gold = new BufferedImage(size, size, + BufferedImage.TYPE_INT_ARGB); + Graphics2D g = gold.createGraphics(); + BufferedImage bi = new BufferedImage(size, size, + BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = bi.createGraphics(); + g2d.setColor(new Color(0, 250, 0, 100)); + g2d.setBackground(Color.BLACK); + g.setColor(new Color(0, 250, 0, 100)); + g.setBackground(Color.BLACK); + // Rectangle + for (final Rectangle r : rects) { + g.clearRect(0, 0, size, size); + g2d.clearRect(0, 0, size, size); + g.drawRect(r.x, r.y, r.width, r.height); + SwingUtilities2.drawRect(g2d, r.x, r.y, r.width, r.height); + test(gold, bi); + } + // Vertical Line + for (final Rectangle l : vlines) { + g.clearRect(0, 0, size, size); + g2d.clearRect(0, 0, size, size); + g.drawLine(l.x, l.y, l.x + l.width, l.y + l.height); + SwingUtilities2.drawVLine(g2d, l.x, l.y, l.y + l.height); + test(gold, bi); + } + // Horizontal Line + for (final Rectangle l : hlines) { + g.clearRect(0, 0, size, size); + g2d.clearRect(0, 0, size, size); + g.drawLine(l.x, l.y, l.x + l.width, l.y + l.height); + SwingUtilities2.drawHLine(g2d, l.x, l.x+l.width, l.y); + test(gold, bi); + } + + g.dispose(); + g2d.dispose(); + } + + private static void test(final BufferedImage gold, final BufferedImage bi) + throws IOException { + for (int x = 0; x < size; x++) { + for (int y = 0; y < size; y++) { + if (gold.getRGB(x, y) != bi.getRGB(x, y)) { + ImageIO.write(gold, "png", new File("gold.png")); + ImageIO.write(bi, "png", new File("image.png")); + throw new RuntimeException("wrong color"); + } + } + } + } +} \ No newline at end of file diff -r a77941f17614 -r 0d1f816217dc jdk/test/javax/swing/plaf/metal/MetalLookAndFeel/Test8039750.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/plaf/metal/MetalLookAndFeel/Test8039750.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.UIDefaults; +import javax.swing.border.CompoundBorder; +import javax.swing.plaf.metal.MetalLookAndFeel; + +/* + * @test + * @bug 8039750 + * @summary Tests MetalLazyValue removing + * @author Sergey Malenkov + */ +public class Test8039750 { + public static void main(String[] args) { + UIDefaults table= new MetalLookAndFeel().getDefaults(); + test(table.get("ToolBar.rolloverBorder"), + "javax.swing.plaf.metal.MetalBorders$ButtonBorder", + "javax.swing.plaf.metal.MetalBorders$RolloverMarginBorder"); + test(table.get("ToolBar.nonrolloverBorder"), + "javax.swing.plaf.metal.MetalBorders$ButtonBorder", + "javax.swing.plaf.metal.MetalBorders$RolloverMarginBorder"); + test(table.get("RootPane.frameBorder"), + "javax.swing.plaf.metal.MetalBorders$FrameBorder"); + test(table.get("RootPane.plainDialogBorder"), + "javax.swing.plaf.metal.MetalBorders$DialogBorder"); + test(table.get("RootPane.informationDialogBorder"), + "javax.swing.plaf.metal.MetalBorders$DialogBorder"); + test(table.get("RootPane.errorDialogBorder"), + "javax.swing.plaf.metal.MetalBorders$ErrorDialogBorder"); + test(table.get("RootPane.colorChooserDialogBorder"), + "javax.swing.plaf.metal.MetalBorders$QuestionDialogBorder"); + test(table.get("RootPane.fileChooserDialogBorder"), + "javax.swing.plaf.metal.MetalBorders$QuestionDialogBorder"); + test(table.get("RootPane.questionDialogBorder"), + "javax.swing.plaf.metal.MetalBorders$QuestionDialogBorder"); + test(table.get("RootPane.warningDialogBorder"), + "javax.swing.plaf.metal.MetalBorders$WarningDialogBorder"); + } + + private static void test(Object value, String name) { + if (!value.getClass().getName().equals(name)) { + throw new Error(name); + } + } + + private static void test(Object value, String one, String two) { + if (value instanceof CompoundBorder) { + CompoundBorder border = (CompoundBorder) value; + test(border.getOutsideBorder(), one); + test(border.getInsideBorder(), two); + } else { + throw new Error("CompoundBorder"); + } + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/javax/swing/text/GlyphView/4984669/bug4984669.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/text/GlyphView/4984669/bug4984669.html Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,30 @@ + + + + +The four lines printed above in a bold typeface should all be underlined. +It is a bug if any of these lines is underlined only partially. +The very first line should not be underlined at all. + + diff -r a77941f17614 -r 0d1f816217dc jdk/test/javax/swing/text/GlyphView/4984669/bug4984669.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/text/GlyphView/4984669/bug4984669.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 4984669 8002148 + @summary Tests HTML underlining + @author Peter Zhelezniakov + @run applet/manual=yesno bug4984669.html +*/ +import javax.swing.*; +import javax.swing.text.*; + +public class bug4984669 extends JApplet +{ + public void init() { + JEditorPane pane = new JEditorPane(); + this.getContentPane().add(new JScrollPane(pane)); + pane.setEditorKit(new StyledEditorKit()); + + try { + pane.getDocument().insertString(0,"12 \n",null); + MutableAttributeSet attrs = new SimpleAttributeSet(); + + StyleConstants.setFontSize(attrs, 36); + StyleConstants.setBold(attrs, true); + StyleConstants.setUnderline(attrs, true); + pane.getDocument().insertString(6, "aa\n", attrs); + pane.getDocument().insertString(9, "bbb\n", attrs); + pane.getDocument().insertString(13, "cccc\n", attrs); + pane.getDocument().insertString(18, "ddddd\n", attrs); + } catch (Exception e) { + throw new Error("Failed: Unexpected Exception", e); + } + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/lib/testlibrary/ExtendedRobot.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/lib/testlibrary/ExtendedRobot.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import sun.awt.ExtendedKeyCodes; +import sun.awt.SunToolkit; +import sun.security.action.GetIntegerAction; + +import java.awt.AWTException; +import java.awt.Robot; +import java.awt.GraphicsDevice; +import java.awt.Toolkit; +import java.awt.Point; +import java.awt.MouseInfo; +import java.awt.event.InputEvent; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * ExtendedRobot is a subclass of {@link java.awt.Robot}. It provides some convenience methods that are + * ought to be moved to {@link java.awt.Robot} class. + *

    + * ExtendedRobot uses delay {@link #getSyncDelay()} to make syncing threads with {@link #waitForIdle()} + * more stable. This delay can be set once on creating object and could not be changed throughout object + * lifecycle. Constructor reads vm integer property {@code java.awt.robotdelay} and sets the delay value + * equal to the property value. If the property was not set 500 milliseconds default value is used. + *

    + * When using jtreg you would include this class via something like: + *

    + * {@literal @}library ../../../../lib/testlibrary
    + * {@literal @}build ExtendedRobot
    + * 
    + * + * @author Dmitriy Ermashov + * @since 1.9 + */ + +public class ExtendedRobot extends Robot { + + private static int DEFAULT_SPEED = 20; // Speed for mouse glide and click + private static int DEFAULT_SYNC_DELAY = 500; // Default Additional delay for waitForIdle() + private static int DEFAULT_STEP_LENGTH = 2; // Step length (in pixels) for mouse glide + + private final int syncDelay = DEFAULT_SYNC_DELAY; + + //TODO: uncomment three lines below after moving functionality to java.awt.Robot + //{ + // syncDelay = AccessController.doPrivileged(new GetIntegerAction("java.awt.robotdelay", DEFAULT_SYNC_DELAY)); + //} + + /** + * Constructs an ExtendedRobot object in the coordinate system of the primary screen. + * + * @throws AWTException if the platform configuration does not allow low-level input + * control. This exception is always thrown when + * GraphicsEnvironment.isHeadless() returns true + * @throws SecurityException if {@code createRobot} permission is not granted + * + * @see java.awt.GraphicsEnvironment#isHeadless + * @see SecurityManager#checkPermission + * @see java.awt.AWTPermission + */ + public ExtendedRobot() throws AWTException { + super(); + } + + /** + * Creates an ExtendedRobot for the given screen device. Coordinates passed + * to ExtendedRobot method calls like mouseMove and createScreenCapture will + * be interpreted as being in the same coordinate system as the specified screen. + * Note that depending on the platform configuration, multiple screens may either: + *
      + *
    • share the same coordinate system to form a combined virtual screen
    • + *
    • use different coordinate systems to act as independent screens
    • + *
    + * This constructor is meant for the latter case. + *

    + * If screen devices are reconfigured such that the coordinate system is + * affected, the behavior of existing ExtendedRobot objects is undefined. + * + * @param screen A screen GraphicsDevice indicating the coordinate + * system the Robot will operate in. + * @throws AWTException if the platform configuration does not allow low-level input + * control. This exception is always thrown when + * GraphicsEnvironment.isHeadless() returns true. + * @throws IllegalArgumentException if {@code screen} is not a screen + * GraphicsDevice. + * @throws SecurityException if {@code createRobot} permission is not granted + * + * @see java.awt.GraphicsEnvironment#isHeadless + * @see GraphicsDevice + * @see SecurityManager#checkPermission + * @see java.awt.AWTPermission + */ + public ExtendedRobot(GraphicsDevice screen) throws AWTException { + super(screen); + } + + /** + * Returns delay length for {@link #waitForIdle()} method + * + * @return Current delay value + * + * @see #waitForIdle() + */ + public int getSyncDelay(){ return this.syncDelay; } + + /** + * Clicks mouse button(s) by calling {@link java.awt.Robot#mousePress(int)} and + * {@link java.awt.Robot#mouseRelease(int)} methods + * + * + * @param buttons The button mask; a combination of one or more mouse button masks. + * @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) + * @see #mouseRelease(int) + * @see InputEvent#getMaskForButton(int) + * @see Toolkit#areExtraMouseButtonsEnabled() + * @see java.awt.event.MouseEvent + */ + public void click(int buttons) { + mousePress(buttons); + waitForIdle(DEFAULT_SPEED); + mouseRelease(buttons); + waitForIdle(); + } + + /** + * Clicks mouse button 1 + * + * @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 #click(int) + */ + public void click() { + click(InputEvent.BUTTON1_DOWN_MASK); + } + + /** + * Waits until all events currently on the event queue have been processed with given + * delay after syncing threads. It uses more advanced method of synchronizing threads + * unlike {@link java.awt.Robot#waitForIdle()} + * + * @param delayValue Additional delay length in milliseconds to wait until thread + * sync been completed + * @throws sun.awt.SunToolkit.IllegalThreadException if called on the AWT event + * dispatching thread + */ + public synchronized void waitForIdle(int delayValue) { + SunToolkit.flushPendingEvents(); + ((SunToolkit) Toolkit.getDefaultToolkit()).realSync(); + delay(delayValue); + } + + /** + * Waits until all events currently on the event queue have been processed with delay + * {@link #getSyncDelay()} after syncing threads. It uses more advanced method of + * synchronizing threads unlike {@link java.awt.Robot#waitForIdle()} + * + * @throws sun.awt.SunToolkit.IllegalThreadException if called on the AWT event + * dispatching thread + * + * @see #waitForIdle(int) + */ + @Override + public synchronized void waitForIdle() { + waitForIdle(syncDelay); + } + + /** + * Move the mouse in multiple steps from where it is + * now to the destination coordinates. + * + * @param x Destination point x coordinate + * @param y Destination point y coordinate + * + * @see #glide(int, int, int, int) + */ + public void glide(int x, int y) { + Point p = MouseInfo.getPointerInfo().getLocation(); + glide(p.x, p.y, x, y); + } + + /** + * Move the mouse in multiple steps from where it is + * now to the destination point. + * + * @param dest Destination point + * + * @see #glide(int, int) + */ + public void glide(Point dest) { + glide(dest.x, dest.y); + } + + /** + * Move the mouse in multiple steps from source coordinates + * to the destination coordinates. + * + * @param fromX Source point x coordinate + * @param fromY Source point y coordinate + * @param toX Destination point x coordinate + * @param toY Destination point y coordinate + * + * @see #glide(int, int, int, int, int, int) + */ + public void glide(int fromX, int fromY, int toX, int toY) { + glide(fromX, fromY, toX, toY, DEFAULT_STEP_LENGTH, DEFAULT_SPEED); + } + + /** + * Move the mouse in multiple steps from source point to the + * destination point with default speed and step length. + * + * @param src Source point + * @param dest Destination point + * + * @see #glide(int, int, int, int, int, int) + */ + public void glide(Point src, Point dest) { + glide(src.x, src.y, dest.x, dest.y, DEFAULT_STEP_LENGTH, DEFAULT_SPEED); + } + + /** + * Move the mouse in multiple steps from source point to the + * destination point with given speed and step length. + * + * @param srcX Source point x cordinate + * @param srcY Source point y cordinate + * @param destX Destination point x cordinate + * @param destY Destination point y cordinate + * @param stepLength Approximate length of one step + * @param speed Delay between steps. + * + * @see #mouseMove(int, int) + * @see #delay(int) + */ + public void glide(int srcX, int srcY, int destX, int destY, int stepLength, int speed) { + int stepNum; + double tDx, tDy; + double dx, dy, ds; + double x, y; + + dx = (destX - srcX); + dy = (destY - srcY); + ds = Math.sqrt(dx*dx + dy*dy); + + tDx = dx / ds * stepLength; + tDy = dy / ds * stepLength; + + int stepsCount = (int) ds / stepLength; + + // Walk the mouse to the destination one step at a time + mouseMove(srcX, srcY); + + for (x = srcX, y = srcY, stepNum = 0; + stepNum < stepsCount; + stepNum++) { + x += tDx; + y += tDy; + mouseMove((int)x, (int)y); + delay(speed); + } + + // Ensure the mouse moves to the right destination. + // The steps may have led the mouse to a slightly wrong place. + mouseMove(destX, destY); + } + + /** + * Moves mouse pointer to given screen coordinates. + * + * @param position Target position + * + * @see java.awt.Robot#mouseMove(int, int) + */ + public synchronized void mouseMove(Point position) { + mouseMove(position.x, position.y); + } + + /** + * Successively presses and releases a given key. + *

    + * Key codes that have more than one physical key associated with them + * (e.g. {@code KeyEvent.VK_SHIFT} could mean either the + * left or right shift key) will map to the left key. + * + * @param keycode Key to press (e.g. {@code KeyEvent.VK_A}) + * @throws IllegalArgumentException if {@code keycode} is not + * a valid key + * + * @see java.awt.Robot#keyPress(int) + * @see java.awt.Robot#keyRelease(int) + * @see java.awt.event.KeyEvent + */ + public void type(int keycode) { + keyPress(keycode); + waitForIdle(DEFAULT_SPEED); + keyRelease(keycode); + waitForIdle(DEFAULT_SPEED); + } + + /** + * Types given character + * + * @param c Character to be typed (e.g. {@code 'a'}) + * + * @see #type(int) + * @see java.awt.event.KeyEvent + */ + public void type(char c) { + type(ExtendedKeyCodes.getExtendedKeyCodeForChar(c)); + } + + /** + * Types given array of characters one by one + * + * @param symbols Array of characters to be typed + * + * @see #type(char) + */ + public void type(char[] symbols) { + for (int i = 0; i < symbols.length; i++) { + type(symbols[i]); + } + } + + /** + * Types given string + * + * @param s String to be typed + * + * @see #type(char[]) + */ + public void type(String s) { + type(s.toCharArray()); + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/java2d/DrawCachedImageAndTransform.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/java2d/DrawCachedImageAndTransform.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.image.BufferedImage; +import java.awt.image.VolatileImage; + +/** + * @test + * @bug 8039774 + * @summary Verifies that we get no exception, when we draw with scale + * BufferedImage to VolatileImage via intermediate texture. + * @author Sergey Bylokhov + * @run main/othervm -Dsun.java2d.accthreshold=0 DrawCachedImageAndTransform + */ +public final class DrawCachedImageAndTransform { + + public static void main(String[] args) { + GraphicsEnvironment ge = GraphicsEnvironment + .getLocalGraphicsEnvironment(); + GraphicsConfiguration gc = ge.getDefaultScreenDevice() + .getDefaultConfiguration(); + VolatileImage vi = gc.createCompatibleVolatileImage(100, 100); + + Graphics2D g2d = vi.createGraphics(); + g2d.scale(2, 2); + BufferedImage img = new BufferedImage(50, 50, + BufferedImage.TYPE_INT_ARGB); + + g2d.drawImage(img, 10, 25, Color.blue, null); + g2d.dispose(); + } +} diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/mscapi/KeytoolChangeAlias.sh --- a/jdk/test/sun/security/mscapi/KeytoolChangeAlias.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/mscapi/KeytoolChangeAlias.sh Wed Jul 05 19:39:35 2017 +0200 @@ -56,7 +56,7 @@ # execute test program - rely on it to exit if platform unsupported echo "Creating the alias '246810' in the Windows-My store..." - ${TESTJAVA}/bin/keytool \ + ${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} \ -import \ -storetype Windows-My \ -file ${TESTSRC}/246810.cer \ @@ -68,13 +68,13 @@ fi echo "Removing the alias '13579', if it is already present..." - ${TESTJAVA}/bin/keytool \ + ${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} \ -list \ -storetype Windows-My \ -alias 13579 > /dev/null 2>&1 if [ $? ] ; then - ${TESTJAVA}/bin/keytool \ + ${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} \ -delete \ -storetype Windows-My \ -alias 13579 \ @@ -82,12 +82,12 @@ fi echo "Counting the entries in the store..." - count=`${TESTJAVA}/bin/keytool -list -storetype Windows-My | wc -l` + count=`${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} -list -storetype Windows-My | wc -l` before=$count echo "Changing the alias name from '246810' to '13579'..." - ${TESTJAVA}/bin/keytool \ + ${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} \ -changealias \ -storetype Windows-My \ -alias 246810 \ @@ -98,7 +98,7 @@ fi echo "Re-counting the entries in the store..." - count=`${TESTJAVA}/bin/keytool -list -storetype Windows-My | wc -l` + count=`${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} -list -storetype Windows-My | wc -l` after=$count if [ ! $before = $after ]; then @@ -107,7 +107,7 @@ fi echo "Confirming that the new alias is present..." - ${TESTJAVA}/bin/keytool \ + ${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} \ -list \ -storetype Windows-My \ -alias 13579 > /dev/null 2>&1 @@ -118,7 +118,7 @@ fi echo "Removing the new alias '13579'..." - ${TESTJAVA}/bin/keytool \ + ${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} \ -delete \ -storetype Windows-My \ -alias 13579 > /dev/null 2>&1 diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/mscapi/PublicKeyInterop.sh --- a/jdk/test/sun/security/mscapi/PublicKeyInterop.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/mscapi/PublicKeyInterop.sh Wed Jul 05 19:39:35 2017 +0200 @@ -51,7 +51,7 @@ Windows* | CYGWIN* ) echo "Creating a temporary RSA keypair in the Windows-My store..." - ${TESTJAVA}/bin/keytool \ + ${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} \ -genkeypair \ -storetype Windows-My \ -keyalg RSA \ @@ -61,14 +61,14 @@ echo echo "Running the test..." - ${TESTJAVA}/bin/javac -d . ${TESTSRC}\\PublicKeyInterop.java + ${TESTJAVA}/bin/javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS} -d . ${TESTSRC}\\PublicKeyInterop.java ${TESTJAVA}/bin/java ${TESTVMOPTS} PublicKeyInterop rc=$? echo echo "Removing the temporary RSA keypair from the Windows-My store..." - ${TESTJAVA}/bin/keytool \ + ${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} \ -delete \ -storetype Windows-My \ -alias 6888925 diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/mscapi/ShortRSAKey1024.sh --- a/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh Wed Jul 05 19:39:35 2017 +0200 @@ -63,14 +63,14 @@ Windows* | CYGWIN* ) echo "Removing the keypair if it already exists (for unknown reason)..." - ${TESTJAVA}${FS}bin${FS}keytool \ + ${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} \ -delete \ -storetype Windows-My \ -debug \ -alias 7106773.$BITS echo "Creating a temporary RSA keypair in the Windows-My store..." - ${TESTJAVA}${FS}bin${FS}keytool \ + ${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} \ -genkeypair \ -storetype Windows-My \ -keyalg RSA \ @@ -87,7 +87,7 @@ echo echo "Running the test..." - ${TESTJAVA}${FS}bin${FS}javac -d . \ + ${TESTJAVA}${FS}bin${FS}javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS} -d . \ ${TESTSRC}${FS}ShortRSAKeyWithinTLS.java ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ShortRSAKeyWithinTLS 7106773.$BITS $BITS \ TLSv1.2 TLS_DHE_RSA_WITH_AES_128_CBC_SHA @@ -96,7 +96,7 @@ echo echo "Removing the temporary RSA keypair from the Windows-My store..." - ${TESTJAVA}${FS}bin${FS}keytool \ + ${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} \ -delete \ -storetype Windows-My \ -debug \ diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh --- a/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh Wed Jul 05 19:39:35 2017 +0200 @@ -50,7 +50,7 @@ Windows* | CYGWIN* ) echo "Creating a temporary RSA keypair in the Windows-My store..." - ${TESTJAVA}/bin/keytool \ + ${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} \ -genkeypair \ -storetype Windows-My \ -keyalg RSA \ @@ -60,14 +60,14 @@ echo echo "Running the test..." - ${TESTJAVA}/bin/javac -d . ${TESTSRC}\\SignUsingNONEwithRSA.java + ${TESTJAVA}/bin/javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS} -d . ${TESTSRC}\\SignUsingNONEwithRSA.java ${TESTJAVA}/bin/java ${TESTVMOPTS} SignUsingNONEwithRSA rc=$? echo echo "Removing the temporary RSA keypair from the Windows-My store..." - ${TESTJAVA}/bin/keytool \ + ${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} \ -delete \ -storetype Windows-My \ -alias 6578658 diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/AlgOptions.sh --- a/jdk/test/sun/security/tools/jarsigner/AlgOptions.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/AlgOptions.sh Wed Jul 05 19:39:35 2017 +0200 @@ -75,7 +75,7 @@ failed=0 # test missing signature algorithm arg -${TESTJAVA}${FS}bin${FS}jarsigner \ +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} \ -keystore ${TESTSRC}${FS}JarSigning.keystore \ -storepass bbbbbb \ -sigalg \ @@ -89,7 +89,7 @@ fi # test missing digest algorithm arg -${TESTJAVA}${FS}bin${FS}jarsigner \ +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} \ -keystore ${TESTSRC}${FS}JarSigning.keystore \ -storepass bbbbbb \ -digestalg \ @@ -103,7 +103,7 @@ fi # test BOGUS signature algorithm -${TESTJAVA}${FS}bin${FS}jarsigner \ +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} \ -keystore ${TESTSRC}${FS}JarSigning.keystore \ -storepass bbbbbb \ -sigalg BOGUS \ @@ -117,7 +117,7 @@ fi # test BOGUS digest algorithm -${TESTJAVA}${FS}bin${FS}jarsigner \ +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} \ -keystore ${TESTSRC}${FS}JarSigning.keystore \ -storepass bbbbbb \ -digestalg BOGUS \ @@ -131,7 +131,7 @@ fi # test incompatible signature algorithm -${TESTJAVA}${FS}bin${FS}jarsigner \ +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} \ -keystore ${TESTSRC}${FS}JarSigning.keystore \ -storepass bbbbbb \ -sigalg SHA1withDSA \ @@ -145,7 +145,7 @@ fi # test compatible signature algorithm -${TESTJAVA}${FS}bin${FS}jarsigner \ +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} \ -keystore ${TESTSRC}${FS}JarSigning.keystore \ -storepass bbbbbb \ -sigalg SHA512withRSA \ @@ -159,7 +159,7 @@ fi # verify it -${TESTJAVA}${FS}bin${FS}jarsigner -verify ${TESTCLASSES}${FS}AlgOptionsTmp.jar +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -verify ${TESTCLASSES}${FS}AlgOptionsTmp.jar RESULT=$? if [ $RESULT -eq 0 ]; then echo "test 7 passed" @@ -169,7 +169,7 @@ fi # test non-default digest algorithm -${TESTJAVA}${FS}bin${FS}jarsigner \ +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} \ -keystore ${TESTSRC}${FS}JarSigning.keystore \ -storepass bbbbbb \ -digestalg SHA-256 \ @@ -183,7 +183,7 @@ fi # verify it -${TESTJAVA}${FS}bin${FS}jarsigner -verify ${TESTCLASSES}${FS}AlgOptionsTmp.jar +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -verify ${TESTCLASSES}${FS}AlgOptionsTmp.jar RESULT=$? if [ $RESULT -eq 0 ]; then echo "test 9 passed" @@ -193,7 +193,7 @@ fi # test SHA-512 digest algorithm (creates long lines) -${TESTJAVA}${FS}bin${FS}jarsigner \ +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} \ -keystore ${TESTSRC}${FS}JarSigning.keystore \ -storepass bbbbbb \ -digestalg SHA-512 \ @@ -208,7 +208,7 @@ fi # verify it -${TESTJAVA}${FS}bin${FS}jarsigner -verify ${TESTCLASSES}${FS}AlgOptionsTmp.jar +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -verify ${TESTCLASSES}${FS}AlgOptionsTmp.jar RESULT=$? if [ $RESULT -eq 0 ]; then echo "test 11 passed" diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/PercentSign.sh --- a/jdk/test/sun/security/tools/jarsigner/PercentSign.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/PercentSign.sh Wed Jul 05 19:39:35 2017 +0200 @@ -73,7 +73,7 @@ # copy jar file into writeable location ${CP} ${TESTSRC}${FS}AlgOptions.jar ${TESTCLASSES}${FS}AlgOptionsTmp.jar -${TESTJAVA}${FS}bin${FS}jarsigner \ +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} \ -keystore ${TESTSRC}${FS}a%b${FS}percent.keystore \ -storepass changeit \ ${TESTCLASSES}${FS}AlgOptionsTmp.jar ok diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/TimestampCheck.java --- a/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java Wed Jul 05 19:39:35 2017 +0200 @@ -255,18 +255,16 @@ // nonce generation in timestamping request. Not avaibale on // Windows and defaults to thread seed generator, not too bad. if (System.getProperty("java.home").endsWith("jre")) { - cmd = System.getProperty("java.home") + "/../bin/jarsigner" + + cmd = System.getProperty("java.home") + "/../bin/jarsigner"; + } else { + cmd = System.getProperty("java.home") + "/bin/jarsigner"; + } + + cmd += " " + System.getProperty("test.tool.vm.opts") + " -J-Djava.security.egd=file:/dev/./urandom" + " -debug -keystore " + TSKS + " -storepass changeit" + " -tsa http://localhost:" + port + "/%d" + " -signedjar new_%d.jar " + JAR + " old"; - } else { - cmd = System.getProperty("java.home") + "/bin/jarsigner" + - " -J-Djava.security.egd=file:/dev/./urandom" + - " -debug -keystore " + TSKS + " -storepass changeit" + - " -tsa http://localhost:" + port + "/%d" + - " -signedjar new_%d.jar " + JAR + " old"; - } try { if (args.length == 0) { // Run this test diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/checkusage.sh --- a/jdk/test/sun/security/tools/jarsigner/checkusage.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/checkusage.sh Wed Jul 05 19:39:35 2017 +0200 @@ -45,9 +45,9 @@ ;; esac -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keyalg rsa" -JAR=$TESTJAVA${FS}bin${FS}jar -JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner" +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keyalg rsa" +JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS}" rm js.jks trust.jks unrelated.jks 2> /dev/null diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/collator.sh --- a/jdk/test/sun/security/tools/jarsigner/collator.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/collator.sh Wed Jul 05 19:39:35 2017 +0200 @@ -46,10 +46,10 @@ KS=collator.jks JFILE=collator.jar -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit \ +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit \ -keyalg rsa -keystore $KS" -JAR=$TESTJAVA${FS}bin${FS}jar -JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner -keystore $KS -storepass changeit" +JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -keystore $KS -storepass changeit" rm $F $KS $JFILE 2> /dev/null diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/concise_jarsigner.sh --- a/jdk/test/sun/security/tools/jarsigner/concise_jarsigner.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/concise_jarsigner.sh Wed Jul 05 19:39:35 2017 +0200 @@ -47,10 +47,10 @@ # Choose 1024-bit RSA to make sure it runs fine and fast on all platforms. In # fact, every keyalg/keysize combination is OK for this test. -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore js.jks -keyalg rsa -keysize 1024" -JAR=$TESTJAVA${FS}bin${FS}jar -JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner -JAVAC=$TESTJAVA${FS}bin${FS}javac +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore js.jks -keyalg rsa -keysize 1024" +JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS}" +JAVAC="$TESTJAVA${FS}bin${FS}javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS}" rm js.jks diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/crl.sh --- a/jdk/test/sun/security/tools/jarsigner/crl.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/crl.sh Wed Jul 05 19:39:35 2017 +0200 @@ -45,7 +45,7 @@ KS=crl.jks -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS -keyalg rsa" +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore $KS -keyalg rsa" rm $KS 2> /dev/null diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/diffend.sh --- a/jdk/test/sun/security/tools/jarsigner/diffend.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/diffend.sh Wed Jul 05 19:39:35 2017 +0200 @@ -85,7 +85,7 @@ rm diffend.jar zip diffend.jar META-INF/MANIFEST.MF META-INF/x.RSA 1 -${TESTJAVA}${FS}bin${FS}jarsigner \ +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} \ -keystore ${TESTSRC}${FS}JarSigning.keystore \ -storepass bbbbbb \ -digestalg SHA1 \ @@ -99,7 +99,7 @@ rm diffend.jar zip diffend.jar META-INF/MANIFEST.MF 1 -${TESTJAVA}${FS}bin${FS}jarsigner \ +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} \ -keystore ${TESTSRC}${FS}JarSigning.keystore \ -storepass bbbbbb \ -digestalg SHA1 \ diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/ec.sh --- a/jdk/test/sun/security/tools/jarsigner/ec.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/ec.sh Wed Jul 05 19:39:35 2017 +0200 @@ -45,9 +45,9 @@ KS=ec.jks JFILE=ec.jar -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS" -JAR=$TESTJAVA${FS}bin${FS}jar -JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore $KS" +JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS}" rm $KS $JFILE echo A > A diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/emptymanifest.sh --- a/jdk/test/sun/security/tools/jarsigner/emptymanifest.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/emptymanifest.sh Wed Jul 05 19:39:35 2017 +0200 @@ -47,11 +47,11 @@ KS=emptymanifest.jks JFILE=em.jar -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS" -JAR=$TESTJAVA${FS}bin${FS}jar -JAVA=$TESTJAVA${FS}bin${FS}java -JAVAC=$TESTJAVA${FS}bin${FS}javac -JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore $KS" +JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JAVA="$TESTJAVA${FS}bin${FS}java ${TESTVMOPTS}" +JAVAC="$TESTJAVA${FS}bin${FS}javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS}" +JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS}" rm $KS $JFILE echo A > A @@ -65,7 +65,7 @@ } EOF $JAVAC CrLf.java -$JAVA ${TESTVMOPTS} CrLf > META-INF${FS}MANIFEST.MF +$JAVA CrLf > META-INF${FS}MANIFEST.MF zip $JFILE META-INF${FS}MANIFEST.MF A B $KT -alias a -dname CN=a -keyalg rsa -genkey -validity 300 diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/jvindex.sh --- a/jdk/test/sun/security/tools/jarsigner/jvindex.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/jvindex.sh Wed Jul 05 19:39:35 2017 +0200 @@ -46,10 +46,10 @@ KS=jvindex.jks JFILE=jvindex.jar -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit \ +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit \ -keystore $KS -keyalg rsa" -JAR=$TESTJAVA${FS}bin${FS}jar -JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner -keystore $KS -storepass changeit" +JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -keystore $KS -storepass changeit" rm $F $KS $JFILE 2> /dev/null diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/nameclash.sh --- a/jdk/test/sun/security/tools/jarsigner/nameclash.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/nameclash.sh Wed Jul 05 19:39:35 2017 +0200 @@ -45,9 +45,9 @@ KS=nc.jks JFILE=nc.jar -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS" -JAR=$TESTJAVA${FS}bin${FS}jar -JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore $KS" +JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS}" rm $KS $JFILE diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/newsize7.sh --- a/jdk/test/sun/security/tools/jarsigner/newsize7.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/newsize7.sh Wed Jul 05 19:39:35 2017 +0200 @@ -51,9 +51,9 @@ KSFILE=ns7.jks -KT="${TESTJAVA}${FS}bin${FS}keytool -keystore ns7.jks -storepass changeit -keypass changeit -keyalg rsa" -JAR="${TESTJAVA}${FS}bin${FS}jar" -JS="${TESTJAVA}${FS}bin${FS}jarsigner -keystore ns7.jks -storepass changeit" +KT="${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -keystore ns7.jks -storepass changeit -keypass changeit -keyalg rsa" +JAR="${TESTJAVA}${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JS="${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -keystore ns7.jks -storepass changeit" rm ns7.* diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/oldsig.sh --- a/jdk/test/sun/security/tools/jarsigner/oldsig.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/oldsig.sh Wed Jul 05 19:39:35 2017 +0200 @@ -70,10 +70,10 @@ ${CP} ${TESTSRC}${FS}oldsig${FS}A.jar B.jar ${CP} ${TESTSRC}${FS}oldsig${FS}A.class B.class -${TESTJAVA}${FS}bin${FS}jar uvf B.jar B.class -${TESTJAVA}${FS}bin${FS}jarsigner \ +${TESTJAVA}${FS}bin${FS}jar ${TESTTOOLVMOPTS} uvf B.jar B.class +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} \ -keystore ${TESTSRC}${FS}JarSigning.keystore \ -storepass bbbbbb \ -digestalg SHA1 \ B.jar c -${TESTJAVA}${FS}bin${FS}jarsigner -verify B.jar +${TESTJAVA}${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -verify B.jar diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/onlymanifest.sh --- a/jdk/test/sun/security/tools/jarsigner/onlymanifest.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/onlymanifest.sh Wed Jul 05 19:39:35 2017 +0200 @@ -45,10 +45,10 @@ KS=onlymanifest.jks JFILE=onlymanifest.jar -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit \ +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit \ -keystore $KS -keyalg rsa" -JAR=$TESTJAVA${FS}bin${FS}jar -JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner +JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS}" rm $KS $JFILE 2> /dev/null diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/passtype.sh --- a/jdk/test/sun/security/tools/jarsigner/passtype.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/passtype.sh Wed Jul 05 19:39:35 2017 +0200 @@ -45,9 +45,9 @@ KS=pt.jks JFILE=pt.jar -KT="$TESTJAVA${FS}bin${FS}keytool -keystore $KS -validity 300 -keyalg rsa" -JAR=$TESTJAVA${FS}bin${FS}jar -JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -keystore $KS -validity 300 -keyalg rsa" +JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS}" rm $KS $JFILE diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/samename.sh --- a/jdk/test/sun/security/tools/jarsigner/samename.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/samename.sh Wed Jul 05 19:39:35 2017 +0200 @@ -47,9 +47,9 @@ KS=samename.jks JFILE=em.jar -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS -keyalg rsa" -JAR=$TESTJAVA${FS}bin${FS}jar -JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore $KS -keyalg rsa" +JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS}" rm $KS $JFILE $SIGNEDJAR echo A > A diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/ts.sh --- a/jdk/test/sun/security/tools/jarsigner/ts.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/ts.sh Wed Jul 05 19:39:35 2017 +0200 @@ -50,10 +50,10 @@ TESTJAVA=`dirname $JAVAC_CMD`/.. fi -JAR="${TESTJAVA}${FS}bin${FS}jar" -JAVA="${TESTJAVA}${FS}bin${FS}java" -JAVAC="${TESTJAVA}${FS}bin${FS}javac" -KT="${TESTJAVA}${FS}bin${FS}keytool -keystore tsks -storepass changeit -keypass changeit -keyalg rsa -validity 200" +JAR="${TESTJAVA}${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JAVA="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS}" +JAVAC="${TESTJAVA}${FS}bin${FS}javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS}" +KT="${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -keystore tsks -storepass changeit -keypass changeit -keyalg rsa -validity 200" rm tsks echo Nothing > A @@ -87,5 +87,5 @@ $KT -alias tsbad3 -importcert $JAVAC -d . ${TESTSRC}/TimestampCheck.java -$JAVA ${TESTVMOPTS} TimestampCheck +$JAVA ${TESTVMOPTS} "-Dtest.tool.vm.opts=${TESTTOOLVMOPTS}" TimestampCheck diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/jarsigner/warnings.sh --- a/jdk/test/sun/security/tools/jarsigner/warnings.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/jarsigner/warnings.sh Wed Jul 05 19:39:35 2017 +0200 @@ -46,10 +46,10 @@ KS=warnings.jks JFILE=warnings.jar -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit \ +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit \ -keystore $KS" -JAR=$TESTJAVA${FS}bin${FS}jar -JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner -keystore $KS -storepass changeit" +JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -keystore $KS -storepass changeit" rm $KS 2> /dev/null diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/AltProviderPath.sh --- a/jdk/test/sun/security/tools/keytool/AltProviderPath.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/AltProviderPath.sh Wed Jul 05 19:39:35 2017 +0200 @@ -69,7 +69,7 @@ # the test code #genkey -${TESTJAVA}${FS}bin${FS}keytool -genkey -v -alias dummyTestCA \ +${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -genkey -v -alias dummyTestCA \ -keyalg "RSA" -keysize 1024 -sigalg "ShA1WithRSA" \ -dname "cn=Dummy Test CA, ou=JSN, o=JavaSoft, c=US" -validity 3650 \ -keypass storepass -keystore keystoreCA.dks -storepass storepass \ @@ -81,7 +81,7 @@ fi #Change keystore password -${TESTJAVA}${FS}bin${FS}keytool -storepasswd -new storepass2 \ +${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepasswd -new storepass2 \ -keystore keystoreCA.dks -storetype "dummyks" -storepass storepass \ -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES} @@ -91,7 +91,7 @@ #Change keystore key password -${TESTJAVA}${FS}bin${FS}keytool -keypasswd -alias "dummyTestCA" \ +${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -keypasswd -alias "dummyTestCA" \ -keypass storepass -new keypass -keystore keystoreCA.dks \ -storetype "dummyks" -storepass storepass2 \ -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES} @@ -101,7 +101,7 @@ fi #Export certificate -${TESTJAVA}${FS}bin${FS}keytool -v -export -rfc -alias "dummyTestCA" \ +${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -v -export -rfc -alias "dummyTestCA" \ -file "dummyTestCA.der" -keystore keystoreCA.dks -storetype "dummyks" \ -storepass storepass2 -provider "org.test.dummy.DummyProvider" \ -providerPath ${TESTCLASSES} @@ -111,7 +111,7 @@ fi #list keystore -${TESTJAVA}${FS}bin${FS}keytool -v -list -keystore keystoreCA.dks \ +${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -v -list -keystore keystoreCA.dks \ -storetype "dummyks" -storepass storepass2 \ -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES} diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/CloneKeyAskPassword.sh --- a/jdk/test/sun/security/tools/keytool/CloneKeyAskPassword.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/CloneKeyAskPassword.sh Wed Jul 05 19:39:35 2017 +0200 @@ -82,7 +82,7 @@ chmod 644 CloneKeyAskPassword.jks # run the test: attempt to clone the private key -${TESTJAVA}${FILESEP}bin${FILESEP}keytool \ +${TESTJAVA}${FILESEP}bin${FILESEP}keytool ${TESTTOOLVMOPTS} \ -keyclone \ -alias mykey \ -dest myclone \ diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/ListKeychainStore.sh --- a/jdk/test/sun/security/tools/keytool/ListKeychainStore.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/ListKeychainStore.sh Wed Jul 05 19:39:35 2017 +0200 @@ -46,7 +46,7 @@ esac PWD="xxxxxx" -KEYTOOL="${TESTJAVA}/bin/keytool -storetype KeychainStore -keystore NONE -storepass $PWD" +KEYTOOL="${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} -storetype KeychainStore -keystore NONE -storepass $PWD" TEMPORARY_P12="$TESTCLASSES/7133495.p12" TEMPORARY_KC="$TESTCLASSES/7133495.keychain" CLEANUP_P12="rm -f $TEMPORARY_P12" @@ -67,7 +67,7 @@ for i in X Y Z do - ${TESTJAVA}/bin/keytool -genkeypair \ + ${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} -genkeypair \ -storetype PKCS12 \ -keystore $TEMPORARY_P12 \ -storepass $PWD \ diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/NoExtNPE.sh --- a/jdk/test/sun/security/tools/keytool/NoExtNPE.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/NoExtNPE.sh Wed Jul 05 19:39:35 2017 +0200 @@ -67,7 +67,7 @@ ;; esac -${TESTJAVA}${FILESEP}bin${FILESEP}keytool \ +${TESTJAVA}${FILESEP}bin${FILESEP}keytool ${TESTTOOLVMOPTS} \ -list -v \ -keystore ${TESTSRC}${FILESEP}CloneKeyAskPassword.jks \ -storepass test123 diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/SecretKeyKS.sh --- a/jdk/test/sun/security/tools/keytool/SecretKeyKS.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/SecretKeyKS.sh Wed Jul 05 19:39:35 2017 +0200 @@ -68,6 +68,6 @@ # the test code -${TESTJAVA}${FS}bin${FS}keytool -list -keystore ${TESTSRC}${FS}SecretKeyKS.jks -storepass password +${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -list -keystore ${TESTSRC}${FS}SecretKeyKS.jks -storepass password exit $? diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/StandardAlgName.sh --- a/jdk/test/sun/security/tools/keytool/StandardAlgName.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/StandardAlgName.sh Wed Jul 05 19:39:35 2017 +0200 @@ -69,20 +69,20 @@ # the test code #CA -${TESTJAVA}${FS}bin${FS}keytool -genkey -v -alias pkcs12testCA -keyalg "RsA" -keysize 2048 -sigalg "ShA1wItHRSA" -dname "cn=PKCS12 Test CA, ou=Security SQE, o=JavaSoft, c=US" -validity 3650 -keypass storepass -keystore keystoreCA.jceks.data -storepass storepass -storetype jceKS 2>&1 | egrep 'RsA|ShA1wItHRSA' +${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -genkey -v -alias pkcs12testCA -keyalg "RsA" -keysize 2048 -sigalg "ShA1wItHRSA" -dname "cn=PKCS12 Test CA, ou=Security SQE, o=JavaSoft, c=US" -validity 3650 -keypass storepass -keystore keystoreCA.jceks.data -storepass storepass -storetype jceKS 2>&1 | egrep 'RsA|ShA1wItHRSA' RESULT=$? if [ $RESULT -eq 0 ]; then exit 1 else #Lead - ${TESTJAVA}${FS}bin${FS}keytool -genkey -v -alias pkcs12testLead -keyalg "rSA" -keysize 1024 -sigalg "mD5withRSA" -dname "cn=PKCS12 Test Lead, ou=Security SQE, o=JavaSoft, c=US" -validity 3650 -keypass storepass -keystore keystoreLead.jceks.data -storepass storepass -storetype jCeks 2>&1 | egrep 'rSA|mD5withRSA' + ${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -genkey -v -alias pkcs12testLead -keyalg "rSA" -keysize 1024 -sigalg "mD5withRSA" -dname "cn=PKCS12 Test Lead, ou=Security SQE, o=JavaSoft, c=US" -validity 3650 -keypass storepass -keystore keystoreLead.jceks.data -storepass storepass -storetype jCeks 2>&1 | egrep 'rSA|mD5withRSA' RESULT=$? if [ $RESULT -eq 0 ]; then exit 1 else #End User 1 - ${TESTJAVA}${FS}bin${FS}keytool -genkey -v -alias pkcs12testEndUser1 -keyalg "RSa" -keysize 1024 -sigalg "sHa1wIThRSA" -dname "cn=PKCS12 Test End User 1, ou=Security SQE, o=JavaSoft, c=US" -validity 3650 -keypass storepass -keystore keystoreEndUser1.jceks.data -storepass storepass -storetype Jceks 2>&1 | egrep 'RSa|sHa1wIThRSA' + ${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -genkey -v -alias pkcs12testEndUser1 -keyalg "RSa" -keysize 1024 -sigalg "sHa1wIThRSA" -dname "cn=PKCS12 Test End User 1, ou=Security SQE, o=JavaSoft, c=US" -validity 3650 -keypass storepass -keystore keystoreEndUser1.jceks.data -storepass storepass -storetype Jceks 2>&1 | egrep 'RSa|sHa1wIThRSA' RESULT=$? if [ $RESULT -eq 0 ]; then exit 1 diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/StorePasswordsByShell.sh --- a/jdk/test/sun/security/tools/keytool/StorePasswordsByShell.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/StorePasswordsByShell.sh Wed Jul 05 19:39:35 2017 +0200 @@ -107,7 +107,7 @@ echo "Storing user password (protected by ${i})" echo "${USER_PWD}" | \ - ${TESTJAVA}${FILESEP}bin${FILESEP}keytool ${IMPORTPASSWORD} \ + ${TESTJAVA}${FILESEP}bin${FILESEP}keytool ${TESTTOOLVMOPTS} ${IMPORTPASSWORD} \ -storetype pkcs12 -keystore mykeystore.p12 -storepass changeit \ -alias "${ALIAS_PREFIX}${i}" ${KEYALG} > /dev/null 2>&1 if [ $? -ne 0 ]; then @@ -119,7 +119,7 @@ done echo -COUNTER2=`${TESTJAVA}${FILESEP}bin${FILESEP}keytool -list -storetype pkcs12 \ +COUNTER2=`${TESTJAVA}${FILESEP}bin${FILESEP}keytool ${TESTTOOLVMOPTS} -list -storetype pkcs12 \ -keystore mykeystore.p12 -storepass changeit | grep -c "${ALIAS_PREFIX}"` RESULT="stored ${COUNTER} user passwords, detected ${COUNTER2} user passwords" diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/emptysubject.sh --- a/jdk/test/sun/security/tools/keytool/emptysubject.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/emptysubject.sh Wed Jul 05 19:39:35 2017 +0200 @@ -45,7 +45,7 @@ esac KS=emptysubject.jks -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS -keyalg rsa" +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore $KS -keyalg rsa" rm $KS diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/file-in-help.sh --- a/jdk/test/sun/security/tools/keytool/file-in-help.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/file-in-help.sh Wed Jul 05 19:39:35 2017 +0200 @@ -43,8 +43,8 @@ esac LANG=C -$TESTJAVA${FS}bin${FS}keytool -printcertreq -help 2> h1 || exit 1 -$TESTJAVA${FS}bin${FS}keytool -exportcert -help 2> h2 || exit 2 +$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -printcertreq -help 2> h1 || exit 1 +$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -exportcert -help 2> h2 || exit 2 grep "input file" h1 || exit 3 grep "output file" h2 || exit 4 diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/importreadall.sh --- a/jdk/test/sun/security/tools/keytool/importreadall.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/importreadall.sh Wed Jul 05 19:39:35 2017 +0200 @@ -49,7 +49,7 @@ ;; esac -KEYTOOL="${TESTJAVA}${FS}bin${FS}keytool -keystore importreadall.jks -storepass changeit -keypass changeit -keyalg rsa" +KEYTOOL="${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -keystore importreadall.jks -storepass changeit -keypass changeit -keyalg rsa" # In case the test is run twice in the same directory diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/newhelp.sh --- a/jdk/test/sun/security/tools/keytool/newhelp.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/newhelp.sh Wed Jul 05 19:39:35 2017 +0200 @@ -43,8 +43,8 @@ esac LANG=C -$TESTJAVA${FS}bin${FS}keytool -help 2> h1 || exit 1 -$TESTJAVA${FS}bin${FS}keytool -help -list 2> h2 || exit 2 +$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -help 2> h1 || exit 1 +$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -help -list 2> h2 || exit 2 grep Commands: h1 || exit 3 grep Options: h2 || exit 4 diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/p12importks.sh --- a/jdk/test/sun/security/tools/keytool/p12importks.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/p12importks.sh Wed Jul 05 19:39:35 2017 +0200 @@ -44,7 +44,7 @@ esac LANG=C -KT=$TESTJAVA${FS}bin${FS}keytool +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS}" # Part 1: JKS keystore with same storepass and keypass diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/printssl.sh --- a/jdk/test/sun/security/tools/keytool/printssl.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/printssl.sh Wed Jul 05 19:39:35 2017 +0200 @@ -62,7 +62,7 @@ echo "Server not started" exit 2 else - ${TESTJAVA}${FS}bin${FS}keytool -printcert -sslserver localhost:$PORT + ${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -printcert -sslserver localhost:$PORT fi ) status=$? diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/resource.sh --- a/jdk/test/sun/security/tools/keytool/resource.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/resource.sh Wed Jul 05 19:39:35 2017 +0200 @@ -62,7 +62,7 @@ esac # the test code -${TESTJAVA}${FS}bin${FS}keytool > temp_file_40875602475 2> ${NULL} +${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} > temp_file_40875602475 2> ${NULL} grep MissingResourceException temp_file_40875602475 if [ $? -eq 0 ]; then diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/selfissued.sh --- a/jdk/test/sun/security/tools/keytool/selfissued.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/selfissued.sh Wed Jul 05 19:39:35 2017 +0200 @@ -45,7 +45,7 @@ esac KS=selfsigned.jks -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS -keyalg rsa" +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore $KS -keyalg rsa" rm $KS diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/keytool/trystore.sh --- a/jdk/test/sun/security/tools/keytool/trystore.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/keytool/trystore.sh Wed Jul 05 19:39:35 2017 +0200 @@ -43,7 +43,7 @@ rm trystore.jks 2> /dev/null -KEYTOOL="${TESTJAVA}${FS}bin${FS}keytool -storetype jks -keystore trystore.jks -keyalg rsa" +KEYTOOL="${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storetype jks -keystore trystore.jks -keyalg rsa" $KEYTOOL -genkeypair -alias a -dname CN=A -storepass changeit -keypass changeit $KEYTOOL -genkeypair -alias b -dname CN=B -storepass changeit -keypass changeit diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/tools/policytool/i18n.sh --- a/jdk/test/sun/security/tools/policytool/i18n.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/tools/policytool/i18n.sh Wed Jul 05 19:39:35 2017 +0200 @@ -83,11 +83,11 @@ exit 1 fi -${TESTJAVA}${FS}bin${FS}keytool -genkeypair -alias hello -dname CN=Hello \ +${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -genkeypair -alias hello -dname CN=Hello \ -storepass changeit -keypass changeit -keystore ks echo changeit > good echo badpass > bad -${TESTJAVA}${FS}bin${FS}policytool +${TESTJAVA}${FS}bin${FS}policytool ${TESTTOOLVMOPTS} exit $? diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/validator/certreplace.sh --- a/jdk/test/sun/security/validator/certreplace.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/validator/certreplace.sh Wed Jul 05 19:39:35 2017 +0200 @@ -47,7 +47,7 @@ ;; esac -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit \ +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit \ -keypass changeit -keystore certreplace.jks -keyalg rsa" JAVAC=$COMPILEJAVA${FS}bin${FS}javac JAVA=$TESTJAVA${FS}bin${FS}java diff -r a77941f17614 -r 0d1f816217dc jdk/test/sun/security/validator/samedn.sh --- a/jdk/test/sun/security/validator/samedn.sh Wed Jul 05 19:38:36 2017 +0200 +++ b/jdk/test/sun/security/validator/samedn.sh Wed Jul 05 19:39:35 2017 +0200 @@ -47,7 +47,7 @@ ;; esac -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit \ +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit \ -keypass changeit -keystore samedn.jks -keyalg rsa" JAVAC=$COMPILEJAVA${FS}bin${FS}javac JAVA=$TESTJAVA${FS}bin${FS}java diff -r a77941f17614 -r 0d1f816217dc langtools/.hgtags --- a/langtools/.hgtags Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/.hgtags Wed Jul 05 19:39:35 2017 +0200 @@ -253,3 +253,4 @@ ea02d24b3f1dd1417132d6587dd38b056cca0be2 jdk9-b08 2d13524486b46a0f879361fbadf68fe42d02d221 jdk9-b09 7736a820af6f15cef9a1499f122e40abc83b2fbd jdk9-b10 +f04fccfbd880c819affc3ef33e0083aab9556409 jdk9-b11 diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,9 +49,9 @@ public abstract class AbstractPackageIndexWriter extends HtmlDocletWriter { /** - * Array of Packages to be documented. + * A Set of Packages to be documented. */ - protected PackageDoc[] packages; + protected SortedSet packages; /** * Constructor. Also initializes the packages variable. @@ -89,12 +89,12 @@ /** * Adds the packages list to the documentation tree. * - * @param packages an array of packagedoc objects + * @param packages a collection of packagedoc objects * @param text caption for the table * @param tableSummary summary for the table * @param body the document tree to which the packages list will be added */ - protected abstract void addPackagesList(PackageDoc[] packages, String text, + protected abstract void addPackagesList(Collection packages, String text, String tableSummary, Content body); /** @@ -141,15 +141,14 @@ * Adds package index contents. Call appropriate methods from * the sub-classes. Adds it to the body HtmlTree * - * @param packages array of packages to be documented + * @param packages a collection of packages to be documented * @param text string which will be used as the heading * @param tableSummary summary for the table * @param body the document tree to which the index contents will be added */ - protected void addIndexContents(PackageDoc[] packages, String text, + protected void addIndexContents(Collection packages, String text, String tableSummary, Content body) { - if (packages.length > 0) { - Arrays.sort(packages); + if (!packages.isEmpty()) { HtmlTree div = new HtmlTree(HtmlTag.DIV); div.addStyle(HtmlStyle.indexHeader); addAllClassesLink(div); diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -180,7 +180,7 @@ Map> map = new HashMap<>(); List list= classMap.get(classdoc.qualifiedName()); if (list != null) { - Collections.sort(list); + list.sort(Util.makeComparatorForClassUse()); for (ProgramElementDoc doc : list) { PackageDoc pkg = doc.containingPackage(); pkgSet.add(pkg); @@ -245,7 +245,7 @@ protected void addClassUse(Content contentTree) throws IOException { HtmlTree ul = new HtmlTree(HtmlTag.UL); ul.addStyle(HtmlStyle.blockList); - if (configuration.packages.length > 1) { + if (configuration.packages.size() > 1) { addPackageList(ul); addPackageAnnotationList(ul); } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java Wed Jul 05 19:39:35 2017 +0200 @@ -495,15 +495,15 @@ if (createoverview) { topFile = DocPaths.OVERVIEW_SUMMARY; } else { - if (packages.length == 1 && packages[0].name().equals("")) { + if (packages.size() == 1 && packages.first().name().equals("")) { if (root.classes().length > 0) { ClassDoc[] classarr = root.classes(); Arrays.sort(classarr); ClassDoc cd = getValidClass(classarr); topFile = DocPath.forClass(cd); } - } else { - topFile = DocPath.forPackage(packages[0]).resolve(DocPaths.PACKAGE_SUMMARY); + } else if (!packages.isEmpty()) { + topFile = DocPath.forPackage(packages.first()).resolve(DocPaths.PACKAGE_SUMMARY); } } } @@ -534,7 +534,7 @@ * packages is more than one. Sets {@link #createoverview} field to true. */ protected void setCreateOverview() { - if ((overview || packages.length > 1) && !nooverview) { + if ((overview || packages.size() > 1) && !nooverview) { createoverview = true; } } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,7 @@ public FrameOutputWriter(ConfigurationImpl configuration, DocPath filename) throws IOException { super(configuration, filename); - noOfPackages = configuration.packages.length; + noOfPackages = configuration.packages.size(); } /** diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -215,22 +215,22 @@ if (!configuration.shouldDocumentProfile(profileName)) continue; ProfilePackageIndexFrameWriter.generate(configuration, profileName); - PackageDoc[] packages = configuration.profilePackages.get( + List packages = configuration.profilePackages.get( profileName); PackageDoc prev = null, next; - for (int j = 0; j < packages.length; j++) { + for (int j = 0; j < packages.size(); j++) { // if -nodeprecated option is set and the package is marked as // deprecated, do not generate the profilename-package-summary.html // and profilename-package-frame.html pages for that package. - if (!(configuration.nodeprecated && Util.isDeprecated(packages[j]))) { - ProfilePackageFrameWriter.generate(configuration, packages[j], i); - next = (j + 1 < packages.length - && packages[j + 1].name().length() > 0) ? packages[j + 1] : null; + PackageDoc pkg = packages.get(j); + if (!(configuration.nodeprecated && Util.isDeprecated(pkg))) { + ProfilePackageFrameWriter.generate(configuration, pkg, i); + next = getNamedPackage(packages, j + 1); AbstractBuilder profilePackageSummaryBuilder = configuration.getBuilderFactory().getProfilePackageSummaryBuilder( - packages[j], prev, next, Profile.lookup(i)); + pkg, prev, next, Profile.lookup(i)); profilePackageSummaryBuilder.build(); - prev = packages[j]; + prev = pkg; } } nextProfile = (i + 1 < configuration.profiles.getProfileCount()) ? @@ -244,35 +244,47 @@ } } + PackageDoc getNamedPackage(List list, int idx) { + if (idx < list.size()) { + PackageDoc pkg = list.get(idx); + if (!pkg.name().isEmpty()) { + return pkg; + } + } + return null; + } + /** * {@inheritDoc} */ protected void generatePackageFiles(ClassTree classtree) throws Exception { - PackageDoc[] packages = configuration.packages; - if (packages.length > 1) { + Set packages = configuration.packages; + if (packages.size() > 1) { PackageIndexFrameWriter.generate(configuration); } + List pList = new ArrayList<>(configuration.packages); PackageDoc prev = null, next; - for (int i = 0; i < packages.length; i++) { + for (int i = 0; i < pList.size(); i++) { // if -nodeprecated option is set and the package is marked as // deprecated, do not generate the package-summary.html, package-frame.html // and package-tree.html pages for that package. - if (!(configuration.nodeprecated && Util.isDeprecated(packages[i]))) { - PackageFrameWriter.generate(configuration, packages[i]); - next = (i + 1 < packages.length && - packages[i + 1].name().length() > 0) ? packages[i + 1] : null; + PackageDoc pkg = pList.get(i); + if (!(configuration.nodeprecated && Util.isDeprecated(pkg))) { + PackageFrameWriter.generate(configuration, pkg); + next = getNamedPackage(pList, i + 1); //If the next package is unnamed package, skip 2 ahead if possible - next = (i + 2 < packages.length && next == null) ? packages[i + 2] : next; + if (next == null) + next = getNamedPackage(pList, i + 2); AbstractBuilder packageSummaryBuilder = configuration.getBuilderFactory().getPackageSummaryBuilder( - packages[i], prev, next); + pkg, prev, next); packageSummaryBuilder.build(); if (configuration.createtree) { PackageTreeWriter.generate(configuration, - packages[i], prev, next, + pkg, prev, next, configuration.nodeprecated); } - prev = packages[i]; + prev = pkg; } } } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java Wed Jul 05 19:39:35 2017 +0200 @@ -524,9 +524,9 @@ if (configuration.createoverview) { navList.addContent(getNavLinkContents()); } - if (configuration.packages.length == 1) { - navList.addContent(getNavLinkPackage(configuration.packages[0])); - } else if (configuration.packages.length > 1) { + if (configuration.packages.size() == 1) { + navList.addContent(getNavLinkPackage(configuration.packages.first())); + } else if (configuration.packages.size() > 1) { navList.addContent(getNavLinkPackage()); } navList.addContent(getNavLinkClass()); @@ -916,7 +916,7 @@ * @return package name content */ public Content getPackageName(PackageDoc packageDoc) { - return packageDoc == null || packageDoc.name().length() == 0 ? + return packageDoc == null || packageDoc.name().isEmpty() ? defaultPackageLabel : getPackageLabel(packageDoc.name()); } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,8 @@ package com.sun.tools.doclets.formats.html; -import java.io.*; +import java.io.IOException; +import java.util.Collection; import com.sun.javadoc.*; import com.sun.tools.doclets.formats.html.markup.*; @@ -78,7 +79,7 @@ /** * {@inheritDoc} */ - protected void addPackagesList(PackageDoc[] packages, String text, + protected void addPackagesList(Collection packages, String text, String tableSummary, Content body) { Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true, packagesLabel); @@ -106,7 +107,7 @@ protected Content getPackage(PackageDoc pd) { Content packageLinkContent; Content packageLabel; - if (pd.name().length() > 0) { + if (!pd.name().isEmpty()) { packageLabel = getPackageLabel(pd.name()); packageLinkContent = getHyperLink(pathString(pd, DocPaths.PACKAGE_FRAME), packageLabel, "", diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -111,8 +111,8 @@ protected void addIndex(Content body) { for (String groupname : groupList) { List list = groupPackageMap.get(groupname); - if (list != null && list.size() > 0) { - addIndexContents(list.toArray(new PackageDoc[list.size()]), + if (list != null && !list.isEmpty()) { + addIndexContents(list, groupname, configuration.getText("doclet.Member_Table_Summary", groupname, configuration.getText("doclet.packages")), body); } @@ -146,7 +146,7 @@ /** * {@inheritDoc} */ - protected void addPackagesList(PackageDoc[] packages, String text, + protected void addPackagesList(Collection packages, String text, String tableSummary, Content body) { Content table = HtmlTree.TABLE(HtmlStyle.overviewSummary, 0, 3, 0, tableSummary, getTableCaption(new RawHtml(text))); @@ -164,25 +164,23 @@ * @param packages Packages to which link is to be generated * @param tbody the documentation tree to which the list will be added */ - protected void addPackagesList(PackageDoc[] packages, Content tbody) { - for (int i = 0; i < packages.length; i++) { - if (packages[i] != null && packages[i].name().length() > 0) { - if (configuration.nodeprecated && Util.isDeprecated(packages[i])) - continue; - Content packageLinkContent = getPackageLink(packages[i], - getPackageName(packages[i])); - Content tdPackage = HtmlTree.TD(HtmlStyle.colFirst, packageLinkContent); - HtmlTree tdSummary = new HtmlTree(HtmlTag.TD); - tdSummary.addStyle(HtmlStyle.colLast); - addSummaryComment(packages[i], tdSummary); - HtmlTree tr = HtmlTree.TR(tdPackage); - tr.addContent(tdSummary); - if (i%2 == 0) - tr.addStyle(HtmlStyle.altColor); - else - tr.addStyle(HtmlStyle.rowColor); - tbody.addContent(tr); + protected void addPackagesList(Collection packages, Content tbody) { + boolean altColor = true; + for (PackageDoc pkg : packages) { + if (pkg != null && !pkg.name().isEmpty()) { + if (!(configuration.nodeprecated && Util.isDeprecated(pkg))) { + Content packageLinkContent = getPackageLink(pkg, getPackageName(pkg)); + Content tdPackage = HtmlTree.TD(HtmlStyle.colFirst, packageLinkContent); + HtmlTree tdSummary = new HtmlTree(HtmlTag.TD); + tdSummary.addStyle(HtmlStyle.colLast); + addSummaryComment(pkg, tdSummary); + HtmlTree tr = HtmlTree.TR(tdPackage); + tr.addContent(tdSummary); + tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); + tbody.addContent(tr); + } } + altColor = !altColor; } } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageTreeWriter.java --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageTreeWriter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageTreeWriter.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,7 +119,7 @@ Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, false, HtmlStyle.title, headContent); Content div = HtmlTree.DIV(HtmlStyle.header, heading); - if (configuration.packages.length > 1) { + if (configuration.packages.size() > 1) { addLinkToMainTree(div); } body.addContent(div); diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -135,7 +135,7 @@ protected void addPackageUse(Content contentTree) throws IOException { HtmlTree ul = new HtmlTree(HtmlTag.UL); ul.addStyle(HtmlStyle.blockList); - if (configuration.packages.length > 1) { + if (configuration.packages.size() > 1) { addPackageList(ul); } addClassList(ul); diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageIndexFrameWriter.java --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageIndexFrameWriter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageIndexFrameWriter.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,8 @@ package com.sun.tools.doclets.formats.html; -import java.io.*; +import java.io.IOException; +import java.util.List; import com.sun.javadoc.*; import com.sun.tools.javac.sym.Profiles; @@ -92,7 +93,7 @@ Content div = HtmlTree.DIV(HtmlStyle.indexContainer, heading); HtmlTree ul = new HtmlTree(HtmlTag.UL); ul.setTitle(packagesLabel); - PackageDoc[] packages = configuration.profilePackages.get(profileName); + List packages = configuration.profilePackages.get(profileName); for (PackageDoc packageDoc : packages) { if ((!(configuration.nodeprecated && Util.isDeprecated(packageDoc)))) { ul.addContent(getPackage(packageDoc, profileName)); diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/formats/html/TreeWriter.java --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TreeWriter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TreeWriter.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,8 @@ package com.sun.tools.doclets.formats.html; -import java.io.*; +import java.io.IOException; +import java.util.SortedSet; import com.sun.javadoc.*; import com.sun.tools.doclets.formats.html.markup.*; @@ -51,7 +52,7 @@ /** * Packages in this run. */ - private PackageDoc[] packages; + SortedSet packages; /** * True if there are no packages specified on the command line, @@ -67,11 +68,10 @@ * @param classtree the tree being built. */ public TreeWriter(ConfigurationImpl configuration, - DocPath filename, ClassTree classtree) - throws IOException { + DocPath filename, ClassTree classtree) throws IOException { super(configuration, filename, classtree); packages = configuration.packages; - classesonly = packages.length == 0; + classesonly = packages.isEmpty(); } /** @@ -127,7 +127,7 @@ */ protected void addPackageTreeLinks(Content contentTree) { //Do nothing if only unnamed package is used - if (packages.length == 1 && packages[0].name().length() == 0) { + if (isUnnamedPackage()) { return; } if (!classesonly) { @@ -136,21 +136,24 @@ contentTree.addContent(span); HtmlTree ul = new HtmlTree(HtmlTag.UL); ul.addStyle(HtmlStyle.horizontal); - for (int i = 0; i < packages.length; i++) { + int i = 0; + for (PackageDoc pkg : packages) { // If the package name length is 0 or if -nodeprecated option // is set and the package is marked as deprecated, do not include // the page in the list of package hierarchies. - if (packages[i].name().length() == 0 || - (configuration.nodeprecated && Util.isDeprecated(packages[i]))) { + if (pkg.name().isEmpty() || + (configuration.nodeprecated && Util.isDeprecated(pkg))) { + i++; continue; } - DocPath link = pathString(packages[i], DocPaths.PACKAGE_TREE); + DocPath link = pathString(pkg, DocPaths.PACKAGE_TREE); Content li = HtmlTree.LI(getHyperLink( - link, new StringContent(packages[i].name()))); - if (i < packages.length - 1) { + link, new StringContent(pkg.name()))); + if (i < packages.size() - 1) { li.addContent(", "); } ul.addContent(li); + i++; } contentTree.addContent(ul); } @@ -168,4 +171,8 @@ addNavLinks(true, bodyTree); return bodyTree; } + + private boolean isUnnamedPackage() { + return packages.size() == 1 && packages.first().name().isEmpty(); + } } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -289,16 +289,16 @@ public Profiles profiles; /** - * An map of the profiles to packages. + * A map of the profiles to packages. */ - public Map profilePackages; + public Map> profilePackages; /** - * An array of the packages specified on the command-line merged - * with the array of packages that contain the classes specified on the - * command-line. The array is sorted. + * A sorted set of packages specified on the command-line merged with a + * collection of packages that contain the classes specified on the + * command-line. */ - public PackageDoc[] packages; + public SortedSet packages; /** * Constructor. Constructs the message retriever with resource file. @@ -423,7 +423,7 @@ // For a profile, if there are no packages to be documented, do not add // it to profilePackages map. if (size > 0) - profilePackages.put(p.name, pkgs.toArray(new PackageDoc[pkgs.size()])); + profilePackages.put(p.name, pkgs); prev = pkgs; } @@ -432,14 +432,11 @@ showProfiles = !prev.isEmpty(); } - private void initPackageArray() { - Set set = new HashSet<>(Arrays.asList(root.specifiedPackages())); + private void initPackages() { + packages = new TreeSet<>(Arrays.asList(root.specifiedPackages())); for (ClassDoc aClass : root.specifiedClasses()) { - set.add(aClass.containingPackage()); + packages.add(aClass.containingPackage()); } - ArrayList results = new ArrayList<>(set); - Collections.sort(results); - packages = results.toArray(new PackageDoc[] {}); } /** @@ -547,7 +544,7 @@ * @throws DocletAbortException */ public void setOptions() throws Fault { - initPackageArray(); + initPackages(); setOptions(root.options()); try { initProfiles(); diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java Wed Jul 05 19:39:35 2017 +0200 @@ -29,6 +29,7 @@ import java.lang.reflect.*; import java.util.*; +import com.sun.javadoc.PackageDoc; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.util.*; @@ -63,7 +64,7 @@ * efficiency purposes. We don't want to copy the * doc files multiple times for a single package. */ - final Set containingPackagesSeen; + final Set containingPackagesSeen; /** * Shared parser for the builder XML file @@ -71,7 +72,7 @@ final LayoutParser layoutParser; Context(Configuration configuration, - Set containingPackagesSeen, + Set containingPackagesSeen, LayoutParser layoutParser) { this.configuration = configuration; this.containingPackagesSeen = containingPackagesSeen; @@ -89,7 +90,7 @@ * efficiency purposes. We don't want to copy the * doc files multiple times for a single package. */ - protected final Set containingPackagesSeen; + protected final Set containingPackagesSeen; protected final LayoutParser layoutParser; diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -133,14 +133,13 @@ private void copyDocFiles() { PackageDoc containingPackage = annotationTypeDoc.containingPackage(); if((configuration.packages == null || - Arrays.binarySearch(configuration.packages, - containingPackage) < 0) && - ! containingPackagesSeen.contains(containingPackage.name())){ + !configuration.packages.contains(containingPackage) && + !containingPackagesSeen.contains(containingPackage))){ //Only copy doc files dir if the containing package is not //documented AND if we have not documented a class from the same //package already. Otherwise, we are making duplicate copies. Util.copyDocFiles(configuration, containingPackage); - containingPackagesSeen.add(containingPackage.name()); + containingPackagesSeen.add(containingPackage); } } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java Wed Jul 05 19:39:35 2017 +0200 @@ -68,7 +68,7 @@ this.configuration = configuration; this.writerFactory = configuration.getWriterFactory(); - Set containingPackagesSeen = new HashSet<>(); + Set containingPackagesSeen = new HashSet<>(); context = new AbstractBuilder.Context(configuration, containingPackagesSeen, LayoutParser.getInstance(configuration)); } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ClassBuilder.java --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ClassBuilder.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ClassBuilder.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -271,14 +271,13 @@ private void copyDocFiles() { PackageDoc containingPackage = classDoc.containingPackage(); if((configuration.packages == null || - Arrays.binarySearch(configuration.packages, - containingPackage) < 0) && - ! containingPackagesSeen.contains(containingPackage.name())){ + !configuration.packages.contains(containingPackage)) && + ! containingPackagesSeen.contains(containingPackage)){ //Only copy doc files dir if the containing package is not //documented AND if we have not documented a class from the same //package already. Otherwise, we are making duplicate copies. Util.copyDocFiles(configuration, containingPackage); - containingPackagesSeen.add(containingPackage.name()); + containingPackagesSeen.add(containingPackage); } } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfileSummaryBuilder.java --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfileSummaryBuilder.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfileSummaryBuilder.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,8 @@ package com.sun.tools.doclets.internal.toolkit.builders; -import java.io.*; +import java.io.IOException; +import java.util.List; import com.sun.javadoc.*; import com.sun.tools.javac.jvm.Profile; @@ -165,7 +166,7 @@ * be added */ public void buildPackageSummary(XMLNode node, Content summaryContentTree) { - PackageDoc[] packages = configuration.profilePackages.get(profile.name); + List packages = configuration.profilePackages.get(profile.name); for (PackageDoc aPackage : packages) { this.pkg = aPackage; Content packageSummaryContentTree = profileWriter.getPackageSummaryHeader(this.pkg); diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DeprecatedAPIListBuilder.java --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DeprecatedAPIListBuilder.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DeprecatedAPIListBuilder.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,7 +84,7 @@ * @param configuration the current configuration of the doclet. */ private void buildDeprecatedAPIInfo(Configuration configuration) { - PackageDoc[] packages = configuration.packages; + Set packages = configuration.packages; for (PackageDoc pkg : packages) { if (Util.isDeprecated(pkg)) { getList(PACKAGE).add(pkg); diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Group.java --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Group.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Group.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -175,7 +175,7 @@ * * @param packages Packages specified on the command line. */ - public Map> groupPackages(PackageDoc[] packages) { + public Map> groupPackages(Set packages) { Map> groupPackageMap = new HashMap<>(); String defaultGroupName = (pkgNameGroupMap.isEmpty() && regExpGroupMap.isEmpty())? diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/IndexBuilder.java --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/IndexBuilder.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/IndexBuilder.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,27 +72,6 @@ protected final Object[] elements; /** - * A comparator used to sort classes and members. - * Note: Maybe this compare code belongs in the tool? - */ - private class DocComparator implements Comparator { - public int compare(Doc d1, Doc d2) { - String doc1 = d1.name(); - String doc2 = d2.name(); - int compareResult; - if ((compareResult = doc1.compareToIgnoreCase(doc2)) != 0) { - return compareResult; - } else if (d1 instanceof ProgramElementDoc && d2 instanceof ProgramElementDoc) { - doc1 = (((ProgramElementDoc) d1).qualifiedName()); - doc2 = (((ProgramElementDoc) d2).qualifiedName()); - return doc1.compareToIgnoreCase(doc2); - } else { - return 0; - } - } - } - - /** * Constructor. Build the index map. * * @param configuration the current configuration of the doclet. @@ -133,7 +112,7 @@ */ protected void sortIndexMap() { for (List docs : indexmap.values()) { - Collections.sort(docs, new DocComparator()); + docs.sort(Util.makeComparatorForIndexUse()); } } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Target; +import java.text.Collator; import java.util.*; import javax.tools.StandardLocation; @@ -49,7 +50,6 @@ * @author Jamie Ho */ public class Util { - /** * Return array of class members whose documentation is to be generated. * If the member is deprecated do not include such a member in the @@ -781,4 +781,163 @@ elt.name().contentEquals(ElementType.PARAMETER.name()) || elt.name().contentEquals(ElementType.TYPE.name()); } + + /** + * A general purpose String comparator, which compares two Strings using a Collator + * strength of "SECONDARY", thus providing optimum case insensitive comparisons in + * most Locales. + * + * @param s1 first String to compare. + * @param s2 second String to compare. + * @return a negative integer, zero, or a positive integer as the first + * argument is less than, equal to, or greater than the second. + */ + public static int compareStrings(String s1, String s2) { + Collator collator = Collator.getInstance(); + collator.setStrength(Collator.SECONDARY); + return collator.compare(s1, s2); + } + + /** + * A comparator for index file uses, this sorts first on names, then on + * parameter types and finally on the fully qualified name. + * @return a comparator for index file use + */ + public static Comparator makeComparatorForIndexUse() { + return new Util.DocComparator() { + /** + * compare two given Doc entities, first sort on name, if + * applicable on the method's parameter types, and finally on the + * fully qualified name of the entity. + * + * @param d1 - a Doc element. + * @param d2 - a Doc element. + * @return a negative integer, zero, or a positive integer as the first + * argument is less than, equal to, or greater than the second. + */ + public int compare(Doc d1, Doc d2) { + int result = compareStrings(d1.name(), d2.name()); + if (result != 0) { + return result; + } + if (d1 instanceof ExecutableMemberDoc && d2 instanceof ExecutableMemberDoc) { + result = compareExecutableMembers( + (ExecutableMemberDoc) d1, + (ExecutableMemberDoc) d2); + if (result != 0) { + return result; + } + } + if (d1 instanceof ProgramElementDoc && d2 instanceof ProgramElementDoc) { + return compareProgramElementDoc((ProgramElementDoc)d1, (ProgramElementDoc)d2); + } + return 0; + } + }; + } + + /** + * Comparator for ClassUse representations, this sorts on member names, + * fully qualified member names and then the parameter types if applicable. + * @return a comparator to sort classes and members for class use + */ + public static Comparator makeComparatorForClassUse() { + return new Util.DocComparator() { + /** + * compare two given Doc entities, first sort on name, and if + * applicable on the fully qualified name, and finally if applicable + * on the parameter types. + * @param d1 - a Doc element. + * @param d2 - a Doc element. + * @return a negative integer, zero, or a positive integer as the first + * argument is less than, equal to, or greater than the second. + */ + public int compare(Doc d1, Doc d2) { + int result = compareStrings(d1.name(), d2.name()); + if (result != 0) { + return result; + } + if (d1 instanceof ProgramElementDoc && d2 instanceof ProgramElementDoc) { + result = compareProgramElementDoc((ProgramElementDoc) d1, (ProgramElementDoc) d2); + if (result != 0) { + return result; + } + } + if (d1 instanceof ExecutableMemberDoc && d2 instanceof ExecutableMemberDoc) { + return compareExecutableMembers((ExecutableMemberDoc)d1, (ExecutableMemberDoc)d2); + } + return 0; + } + }; + } + + /** + * A general purpose comparator to sort Doc entities, basically provides the building blocks + * for creating specific comparators for an use-case. + * @param a Doc entity + */ + static abstract class DocComparator implements Comparator { + /** + * compares two parameter arrays by first comparing the length of the arrays, and + * then each Type of the parameter in the array. + * @param params1 the first parameter array. + * @param params2 the first parameter array. + * @return a negative integer, zero, or a positive integer as the first + * argument is less than, equal to, or greater than the second. + */ + protected int compareParameters(Parameter[] params1, Parameter[] params2) { + if (params1.length == 0 && params2.length == 0) { + return 0; + } + int result = Integer.compare(params1.length, params2.length); + if (result != 0) { + return result; + } + for (int i = 0; i < params1.length; i++) { + result = compareStrings(params1[i].typeName(), params2[i].typeName()); + if (result != 0) { + return result; + } + } + return 0; + } + + /** + * Compares two MemberDocs, typically the name of a method, + * field or constructor. + * @param e1 the first MemberDoc. + * @param e2 the second MemberDoc. + * @return a negative integer, zero, or a positive integer as the first + * argument is less than, equal to, or greater than the second. + */ + protected int compareMembers(MemberDoc e1, MemberDoc e2) { + return compareStrings(e1.name(), e2.name()); + } + + /** + * Compares two ExecutableMemberDocs such as methods and constructors, + * as well as the parameters the entity might take. + * @param m1 the first ExecutableMemberDoc. + * @param m2 the second ExecutableMemberDoc. + * @return a negative integer, zero, or a positive integer as the first + * argument is less than, equal to, or greater than the second. + */ + protected int compareExecutableMembers(ExecutableMemberDoc m1, ExecutableMemberDoc m2) { + int result = compareMembers(m1, m2); + if (result == 0) + result = compareParameters(m1.parameters(), m2.parameters()); + return result; + } + + /** + * Compares the fully qualified names of the entities + * @param p1 the first ProgramElementDoc. + * @param p2 the first ProgramElementDoc. + * @return a negative integer, zero, or a positive integer as the first + * argument is less than, equal to, or greater than the second. + */ + protected int compareProgramElementDoc(ProgramElementDoc p1, ProgramElementDoc p2) { + return compareStrings(p1.qualifiedName(), p2.qualifiedName()); + } + } } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/code/Source.java --- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java Wed Jul 05 19:39:35 2017 +0200 @@ -195,6 +195,9 @@ public boolean allowObjectToPrimitiveCast() { return compareTo(JDK1_7) >= 0; } + public boolean enforceThisDotInit() { + return compareTo(JDK1_7) >= 0; + } public boolean allowPoly() { return compareTo(JDK1_8) >= 0; } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Wed Jul 05 19:39:35 2017 +0200 @@ -383,7 +383,7 @@ /** A class is an inner class if it it has an enclosing instance class. */ public boolean isInner() { - return type.getEnclosingType().hasTag(CLASS); + return kind == TYP && type.getEnclosingType().hasTag(CLASS); } /** An inner class has an outer instance if it is not an interface diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/code/Types.java --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Wed Jul 05 19:39:35 2017 +0200 @@ -43,6 +43,7 @@ import com.sun.tools.javac.comp.Enter; import com.sun.tools.javac.comp.Env; import com.sun.tools.javac.jvm.ClassReader; +import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.util.*; import static com.sun.tools.javac.code.BoundKind.*; import static com.sun.tools.javac.code.Flags.*; @@ -304,8 +305,8 @@ } /** - * Is t a subtype of or convertiable via boxing/unboxing - * convertions to s? + * Is t a subtype of or convertible via boxing/unboxing + * conversions to s? */ public boolean isConvertible(Type t, Type s) { return isConvertible(t, s, noWarnings); @@ -1933,6 +1934,17 @@ * @param sym a symbol */ public Type asSuper(Type t, Symbol sym) { + /* Some examples: + * + * (Enum, Comparable) => Comparable + * (c.s.s.d.AttributeTree.ValueKind, Enum) => Enum + * (c.s.s.t.ExpressionTree, c.s.s.t.Tree) => c.s.s.t.Tree + * (j.u.List, Iterable) => + * Iterable + */ + if (sym.type == syms.objectType) { //optimization + return syms.objectType; + } return asSuper.visit(t, sym); } // where @@ -3867,9 +3879,11 @@ } return buf.reverse(); } + public Type capture(Type t) { - if (!t.hasTag(CLASS)) + if (!t.hasTag(CLASS)) { return t; + } if (t.getEnclosingType() != Type.noType) { Type capturedEncl = capture(t.getEnclosingType()); if (capturedEncl != t.getEnclosingType()) { diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Jul 05 19:39:35 2017 +0200 @@ -2141,6 +2141,11 @@ cdef.extending = clazz; } + if (resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && + isSerializable(clazztype)) { + localEnv.info.isSerializable = true; + } + attribStat(cdef, localEnv); checkLambdaCandidate(tree, cdef.sym, clazztype); @@ -2296,6 +2301,9 @@ resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK; try { Type currentTarget = pt(); + if (needsRecovery && isSerializable(currentTarget)) { + localEnv.info.isSerializable = true; + } List explicitParamTypes = null; if (that.paramKind == JCLambda.ParameterKind.EXPLICIT) { //attribute lambda parameters @@ -2700,17 +2708,20 @@ typeargtypes = attribTypes(that.typeargs, localEnv); } - Type target; Type desc; - if (pt() != Type.recoveryType) { - target = targetChecker.visit(pt(), that); - desc = types.findDescriptorType(target); + Type currentTarget = pt(); + boolean isTargetSerializable = + resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && + isSerializable(currentTarget); + if (currentTarget != Type.recoveryType) { + currentTarget = targetChecker.visit(currentTarget, that); + desc = types.findDescriptorType(currentTarget); } else { - target = Type.recoveryType; + currentTarget = Type.recoveryType; desc = fallbackDescriptorType(that); } - setFunctionalInfo(localEnv, that, pt(), desc, target, resultInfo.checkContext); + setFunctionalInfo(localEnv, that, pt(), desc, currentTarget, resultInfo.checkContext); List argtypes = desc.getParameterTypes(); Resolve.MethodCheck referenceCheck = rs.resolveMethodCheck; @@ -2761,10 +2772,10 @@ JCDiagnostic diag = diags.create(diagKind, log.currentSource(), that, "invalid.mref", Kinds.kindName(that.getMode()), detailsDiag); - if (targetError && target == Type.recoveryType) { + if (targetError && currentTarget == Type.recoveryType) { //a target error doesn't make sense during recovery stage //as we don't know what actual parameter types are - result = that.type = target; + result = that.type = currentTarget; return; } else { if (targetError) { @@ -2772,7 +2783,7 @@ } else { log.report(diag); } - result = that.type = types.createErrorType(target); + result = that.type = types.createErrorType(currentTarget); return; } } @@ -2783,7 +2794,7 @@ if (desc.getReturnType() == Type.recoveryType) { // stop here - result = that.type = target; + result = that.type = currentTarget; return; } @@ -2801,7 +2812,7 @@ //static ref with class type-args log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), diags.fragment("static.mref.with.targs")); - result = that.type = types.createErrorType(target); + result = that.type = types.createErrorType(currentTarget); return; } @@ -2810,7 +2821,7 @@ //no static bound mrefs log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), diags.fragment("static.bound.mref")); - result = that.type = types.createErrorType(target); + result = that.type = types.createErrorType(currentTarget); return; } @@ -2818,6 +2829,10 @@ // Check that super-qualified symbols are not abstract (JLS) rs.checkNonAbstract(that.pos(), that.sym); } + + if (isTargetSerializable) { + chk.checkElemAccessFromSerializableLambda(that); + } } ResultInfo checkInfo = @@ -2849,9 +2864,9 @@ resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE; checkReferenceCompatible(that, desc, refType, resultInfo.checkContext, isSpeculativeRound); if (!isSpeculativeRound) { - checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), desc, target); + checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), desc, currentTarget); } - result = check(that, target, VAL, resultInfo); + result = check(that, currentTarget, VAL, resultInfo); } catch (Types.FunctionDescriptorLookupError ex) { JCDiagnostic cause = ex.getDiagnostic(); resultInfo.checkContext.report(that, cause); @@ -3191,6 +3206,11 @@ while (env1.outer != null && !rs.isAccessible(env, env1.enclClass.sym.type, sym)) env1 = env1.outer; } + + if (env.info.isSerializable) { + chk.checkElemAccessFromSerializableLambda(tree); + } + result = checkId(tree, env1.enclClass.sym.type, sym, env, resultInfo); } @@ -3315,6 +3335,10 @@ } } + if (env.info.isSerializable) { + chk.checkElemAccessFromSerializableLambda(tree); + } + env.info.selectSuper = selectSuperPrev; result = checkId(tree, site, sym, env, resultInfo); } @@ -4181,6 +4205,11 @@ ((c.flags_field & (Flags.ENUM | Flags.COMPOUND)) == 0)) { log.error(env.tree.pos(), "enum.types.not.extensible"); } + + if (isSerializable(c.type)) { + env.info.isSerializable = true; + } + attribClassBody(env, c); chk.checkDeprecatedAnnotation(env.tree.pos(), c); @@ -4294,7 +4323,7 @@ // Check for proper use of serialVersionUID if (env.info.lint.isEnabled(LintCategory.SERIAL) && - isSerializable(c) && + isSerializable(c.type) && (c.flags() & Flags.ENUM) == 0 && checkForSerial(c)) { checkSerialVersionUID(tree, c); @@ -4334,15 +4363,15 @@ return null; } - /** check if a class is a subtype of Serializable, if that is available. */ - private boolean isSerializable(ClassSymbol c) { + /** check if a type is a subtype of Serializable, if that is available. */ + boolean isSerializable(Type t) { try { syms.serializableType.complete(); } catch (CompletionFailure e) { return false; } - return types.isSubtype(c.type, syms.serializableType); + return types.isSubtype(t, syms.serializableType); } /** Check that an appropriate serialVersionUID member is defined. */ diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/comp/AttrContext.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/AttrContext.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/AttrContext.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,6 +54,10 @@ */ boolean selectSuper = false; + /** Is the current target of lambda expression or method reference serializable? + */ + boolean isSerializable = false; + /** Are arguments to current function applications boxed into an array for varargs? */ Resolve.MethodResolutionPhase pendingResolutionPhase = null; @@ -89,6 +93,7 @@ info.enclVar = enclVar; info.returnResult = returnResult; info.defaultSuperCallSite = defaultSuperCallSite; + info.isSerializable = isSerializable; return info; } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/comp/Check.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Wed Jul 05 19:39:35 2017 +0200 @@ -81,6 +81,7 @@ private final TreeInfo treeinfo; private final JavaFileManager fileManager; private final Profile profile; + private final boolean warnOnAccessToSensitiveMembers; // The set of lint options currently in effect. It is initialized // from the context, and then is set/reset as needed by Attr as it @@ -130,6 +131,7 @@ warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts"); suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile"); enableSunApiLintControl = options.isSet("enableSunApiLintControl"); + warnOnAccessToSensitiveMembers = options.isSet("warnOnAccessToSensitiveMembers"); Target target = Target.instance(context); syntheticNameChar = target.syntheticNameChar(); @@ -513,6 +515,11 @@ public DeferredAttrContext deferredAttrContext() { return deferredAttr.emptyDeferredAttrContext; } + + @Override + public String toString() { + return "CheckContext: basicHandler"; + } }; /** Check that a given type is assignable to a given proto-type. @@ -2588,6 +2595,44 @@ } } + void checkElemAccessFromSerializableLambda(final JCTree tree) { + if (warnOnAccessToSensitiveMembers) { + Symbol sym = TreeInfo.symbol(tree); + if ((sym.kind & (VAR | MTH)) == 0) { + return; + } + + if (sym.kind == VAR) { + if ((sym.flags() & PARAMETER) != 0 || + sym.isLocal() || + sym.name == names._this || + sym.name == names._super) { + return; + } + } + + if (!types.isSubtype(sym.owner.type, syms.serializableType) && + isEffectivelyNonPublic(sym)) { + log.warning(tree.pos(), + "access.to.sensitive.member.from.serializable.element", sym); + } + } + } + + private boolean isEffectivelyNonPublic(Symbol sym) { + if (sym.packge() == syms.rootPackage) { + return false; + } + + while (sym.kind != Kinds.PCK) { + if ((sym.flags() & PUBLIC) == 0) { + return true; + } + sym = sym.owner; + } + return false; + } + /** Report a conflict between a user symbol and a synthetic symbol. */ private void syntheticError(DiagnosticPosition pos, Symbol sym) { diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Wed Jul 05 19:39:35 2017 +0200 @@ -109,6 +109,11 @@ void complete() { Assert.error("Empty deferred context!"); } + + @Override + public String toString() { + return "Empty deferred context!"; + } }; } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Wed Jul 05 19:39:35 2017 +0200 @@ -196,6 +196,7 @@ private final boolean allowImprovedRethrowAnalysis; private final boolean allowImprovedCatchAnalysis; private final boolean allowEffectivelyFinalInInnerClasses; + private final boolean enforceThisDotInit; public static Flow instance(Context context) { Flow instance = context.get(flowKey); @@ -206,7 +207,7 @@ public void analyzeTree(Env env, TreeMaker make) { new AliveAnalyzer().analyzeTree(env, make); - new AssignAnalyzer(log, syms, lint, names).analyzeTree(env); + new AssignAnalyzer(log, syms, lint, names, enforceThisDotInit).analyzeTree(env); new FlowAnalyzer().analyzeTree(env, make); new CaptureAnalyzer().analyzeTree(env, make); } @@ -238,7 +239,7 @@ //related errors, which will allow for more errors to be detected Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); try { - new AssignAnalyzer(log, syms, lint, names).analyzeTree(env); + new AssignAnalyzer(log, syms, lint, names, enforceThisDotInit).analyzeTree(env); LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer(); flowAnalyzer.analyzeTree(env, that, make); return flowAnalyzer.inferredThrownTypes; @@ -288,6 +289,7 @@ allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis(); allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis(); allowEffectivelyFinalInInnerClasses = source.allowEffectivelyFinalInInnerClasses(); + enforceThisDotInit = source.enforceThisDotInit(); } /** @@ -1422,6 +1424,8 @@ protected Names names; + final boolean enforceThisDotInit; + public static class AbstractAssignPendingExit extends BaseAnalyzer.PendingExit { final Bits inits; @@ -1444,7 +1448,7 @@ } } - public AbstractAssignAnalyzer(Bits inits, Symtab syms, Names names) { + public AbstractAssignAnalyzer(Bits inits, Symtab syms, Names names, boolean enforceThisDotInit) { this.inits = inits; uninits = new Bits(); uninitsTry = new Bits(); @@ -1454,6 +1458,7 @@ uninitsWhenFalse = new Bits(true); this.syms = syms; this.names = names; + this.enforceThisDotInit = enforceThisDotInit; } private boolean isInitialConstructor = false; @@ -2275,12 +2280,34 @@ public void visitAssign(JCAssign tree) { JCTree lhs = TreeInfo.skipParens(tree.lhs); - if (!(lhs instanceof JCIdent)) { + if (!isIdentOrThisDotIdent(lhs)) scanExpr(lhs); - } scanExpr(tree.rhs); letInit(lhs); } + private boolean isIdentOrThisDotIdent(JCTree lhs) { + if (lhs.hasTag(IDENT)) + return true; + if (!lhs.hasTag(SELECT)) + return false; + + JCFieldAccess fa = (JCFieldAccess)lhs; + return fa.selected.hasTag(IDENT) && + ((JCIdent)fa.selected).name == names._this; + } + + // check fields accessed through this. are definitely + // assigned before reading their value + public void visitSelect(JCFieldAccess tree) { + super.visitSelect(tree); + if (enforceThisDotInit && + tree.selected.hasTag(IDENT) && + ((JCIdent)tree.selected).name == names._this && + tree.sym.kind == VAR) + { + checkInit(tree.pos(), (VarSymbol)tree.sym); + } + } public void visitAssignop(JCAssignOp tree) { scanExpr(tree.lhs); @@ -2410,8 +2437,8 @@ } } - public AssignAnalyzer(Log log, Symtab syms, Lint lint, Names names) { - super(new Bits(), syms, names); + public AssignAnalyzer(Log log, Symtab syms, Lint lint, Names names, boolean enforceThisDotInit) { + super(new Bits(), syms, names, enforceThisDotInit); this.log = log; this.lint = lint; } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Wed Jul 05 19:39:35 2017 +0200 @@ -141,24 +141,24 @@ * Main inference entry point - instantiate a generic method type * using given argument types and (possibly) an expected target-type. */ - public Type instantiateMethod(Env env, - List tvars, - MethodType mt, - Attr.ResultInfo resultInfo, - Symbol msym, - List argtypes, - boolean allowBoxing, - boolean useVarargs, - Resolve.MethodResolutionContext resolveContext, - Warner warn) throws InferenceException { + Type instantiateMethod( Env env, + List tvars, + MethodType mt, + Attr.ResultInfo resultInfo, + MethodSymbol msym, + List argtypes, + boolean allowBoxing, + boolean useVarargs, + Resolve.MethodResolutionContext resolveContext, + Warner warn) throws InferenceException { //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG - final InferenceContext inferenceContext = new InferenceContext(tvars); + final InferenceContext inferenceContext = new InferenceContext(tvars); //B0 inferenceException.clear(); try { DeferredAttr.DeferredAttrContext deferredAttrContext = resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn); - resolveContext.methodCheck.argumentsAcceptable(env, deferredAttrContext, + resolveContext.methodCheck.argumentsAcceptable(env, deferredAttrContext, //B2 argtypes, mt.getParameterTypes(), warn); if (allowGraphInference && @@ -166,7 +166,8 @@ !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { //inject return constraints earlier checkWithinBounds(inferenceContext, warn); //propagation - Type newRestype = generateReturnConstraints(resultInfo, mt, inferenceContext); + Type newRestype = generateReturnConstraints(env.tree, resultInfo, //B3 + mt, inferenceContext); mt = (MethodType)types.createMethodTypeWithReturn(mt, newRestype); //propagate outwards if needed if (resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) { @@ -192,7 +193,7 @@ inferenceContext.restvars().nonEmpty() && resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { - generateReturnConstraints(resultInfo, mt, inferenceContext); + generateReturnConstraints(env.tree, resultInfo, mt, inferenceContext); inferenceContext.solveLegacy(false, warn, LegacyInferenceSteps.EQ_UPPER.steps); //maximizeInst mt = (MethodType)inferenceContext.asInstType(mt); } @@ -209,6 +210,12 @@ } else { inferenceContext.notifyChange(inferenceContext.boundedVars()); } + if (resultInfo == null) { + /* if the is no result info then we can clear the capture types + * cache without affecting any result info check + */ + inferenceContext.captureTypeCache.clear(); + } } } @@ -217,7 +224,7 @@ * call occurs in a context where a type T is expected, use the expected * type to derive more constraints on the generic method inference variables. */ - Type generateReturnConstraints(Attr.ResultInfo resultInfo, + Type generateReturnConstraints(JCTree tree, Attr.ResultInfo resultInfo, MethodType mt, InferenceContext inferenceContext) { InferenceContext rsInfoInfContext = resultInfo.checkContext.inferenceContext(); Type from = mt.getReturnType(); @@ -231,13 +238,29 @@ } } } - Type qtype1 = inferenceContext.asUndetVar(from); - Type to = returnConstraintTarget(qtype1, resultInfo.pt); + Type qtype = inferenceContext.asUndetVar(from); + Type to = resultInfo.pt; + + if (qtype.hasTag(VOID)) { + to = syms.voidType; + } else if (to.hasTag(NONE)) { + to = from.isPrimitive() ? from : syms.objectType; + } else if (qtype.hasTag(UNDETVAR)) { + if (resultInfo.pt.isReference()) { + to = generateReturnConstraintsUndetVarToReference( + tree, (UndetVar)qtype, to, resultInfo, inferenceContext); + } else { + if (to.isPrimitive()) { + to = generateReturnConstraintsPrimitive(tree, (UndetVar)qtype, to, + resultInfo, inferenceContext); + } + } + } Assert.check(allowGraphInference || !rsInfoInfContext.free(to), "legacy inference engine cannot handle constraints on both sides of a subtyping assertion"); //we need to skip capture? Warner retWarn = new Warner(); - if (!resultInfo.checkContext.compatible(qtype1, rsInfoInfContext.asUndetVar(to), retWarn) || + if (!resultInfo.checkContext.compatible(qtype, rsInfoInfContext.asUndetVar(to), retWarn) || //unchecked conversion is not allowed in source 7 mode (!allowGraphInference && retWarn.hasLint(Lint.LintCategory.UNCHECKED))) { throw inferenceException @@ -247,30 +270,96 @@ return from; } - Type returnConstraintTarget(Type from, Type to) { - if (from.hasTag(VOID)) { - return syms.voidType; - } else if (to.hasTag(NONE)) { - return from.isPrimitive() ? from : syms.objectType; - } else if (from.hasTag(UNDETVAR) && to.isPrimitive()) { - if (!allowGraphInference) { - //if legacy, just return boxed type - return types.boxedClass(to).type; + private Type generateReturnConstraintsPrimitive(JCTree tree, UndetVar from, + Type to, Attr.ResultInfo resultInfo, InferenceContext inferenceContext) { + if (!allowGraphInference) { + //if legacy, just return boxed type + return types.boxedClass(to).type; + } + //if graph inference we need to skip conflicting boxed bounds... + for (Type t : from.getBounds(InferenceBound.EQ, InferenceBound.UPPER, + InferenceBound.LOWER)) { + Type boundAsPrimitive = types.unboxedType(t); + if (boundAsPrimitive == null || boundAsPrimitive.hasTag(NONE)) { + continue; } - //if graph inference we need to skip conflicting boxed bounds... - UndetVar uv = (UndetVar)from; - for (Type t : uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) { - Type boundAsPrimitive = types.unboxedType(t); - if (boundAsPrimitive == null) continue; - if (types.isConvertible(boundAsPrimitive, to)) { - //effectively skip return-type constraint generation (compatibility) - return syms.objectType; + return generateReferenceToTargetConstraint(tree, from, to, + resultInfo, inferenceContext); + } + return types.boxedClass(to).type; + } + + private Type generateReturnConstraintsUndetVarToReference(JCTree tree, + UndetVar from, Type to, Attr.ResultInfo resultInfo, + InferenceContext inferenceContext) { + Type captureOfTo = types.capture(to); + /* T is a reference type, but is not a wildcard-parameterized type, and either + */ + if (captureOfTo == to) { //not a wildcard parameterized type + /* i) B2 contains a bound of one of the forms alpha = S or S <: alpha, + * where S is a wildcard-parameterized type, or + */ + for (Type t : from.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) { + Type captureOfBound = types.capture(t); + if (captureOfBound != t) { + return generateReferenceToTargetConstraint(tree, from, to, + resultInfo, inferenceContext); } } - return types.boxedClass(to).type; - } else { - return to; + + /* ii) B2 contains two bounds of the forms S1 <: alpha and S2 <: alpha, + * where S1 and S2 have supertypes that are two different + * parameterizations of the same generic class or interface. + */ + for (Type aLowerBound : from.getBounds(InferenceBound.LOWER)) { + for (Type anotherLowerBound : from.getBounds(InferenceBound.LOWER)) { + if (aLowerBound != anotherLowerBound && + commonSuperWithDiffParameterization(aLowerBound, anotherLowerBound)) { + /* self comment check if any lower bound may be and undetVar, + * in that case the result of this call may be a false positive. + * Should this be restricted to non free types? + */ + return generateReferenceToTargetConstraint(tree, from, to, + resultInfo, inferenceContext); + } + } + } } + + /* T is a parameterization of a generic class or interface, G, + * and B2 contains a bound of one of the forms alpha = S or S <: alpha, + * where there exists no type of the form G<...> that is a + * supertype of S, but the raw type G is a supertype of S + */ + if (to.isParameterized()) { + for (Type t : from.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) { + Type sup = types.asSuper(t, to.tsym); + if (sup != null && sup.isRaw()) { + return generateReferenceToTargetConstraint(tree, from, to, + resultInfo, inferenceContext); + } + } + } + return to; + } + + private boolean commonSuperWithDiffParameterization(Type t, Type s) { + Pair supers = getParameterizedSupers(t, s); + return (supers != null && !types.isSameType(supers.fst, supers.snd)); + } + + private Type generateReferenceToTargetConstraint(JCTree tree, UndetVar from, + Type to, Attr.ResultInfo resultInfo, + InferenceContext inferenceContext) { + inferenceContext.solve(List.of(from.qtype), new Warner()); + Type capturedType = resultInfo.checkContext.inferenceContext() + .cachedCapture(tree, from.inst, false); + if (types.isConvertible(capturedType, + resultInfo.checkContext.inferenceContext().asUndetVar(to))) { + //effectively skip additional return-type constraint generation (compatibility) + return syms.objectType; + } + return to; } /** @@ -2132,8 +2221,10 @@ * Copy variable in this inference context to the given context */ void dupTo(final InferenceContext that) { - that.inferencevars = that.inferencevars.appendList(inferencevars); - that.undetvars = that.undetvars.appendList(undetvars); + that.inferencevars = that.inferencevars.appendList( + inferencevars.diff(that.inferencevars)); + that.undetvars = that.undetvars.appendList( + undetvars.diff(that.undetvars)); //set up listeners to notify original inference contexts as //propagated vars are inferred in new context for (Type t : inferencevars) { @@ -2252,6 +2343,30 @@ return "Inference vars: " + inferencevars + '\n' + "Undet vars: " + undetvars; } + + /* Method Types.capture() generates a new type every time it's applied + * to a wildcard parameterized type. This is intended functionality but + * there are some cases when what you need is not to generate a new + * captured type but to check that a previously generated captured type + * is correct. There are cases when caching a captured type for later + * reuse is sound. In general two captures from the same AST are equal. + * This is why the tree is used as the key of the map below. This map + * stores a Type per AST. + */ + Map captureTypeCache = new HashMap<>(); + + Type cachedCapture(JCTree tree, Type t, boolean readOnly) { + Type captured = captureTypeCache.get(tree); + if (captured != null) { + return captured; + } + + Type result = types.capture(t); + if (result != t && !readOnly) { // then t is a wildcard parameterized type + captureTypeCache.put(tree, result); + } + return result; + } } final InferenceContext emptyContext = new InferenceContext(List.nil()); diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Wed Jul 05 19:39:35 2017 +0200 @@ -36,6 +36,7 @@ import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; +import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Type; @@ -50,8 +51,10 @@ import java.util.EnumMap; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Set; import static com.sun.tools.javac.comp.LambdaToMethod.LambdaSymbolKind.*; import static com.sun.tools.javac.code.Flags.*; @@ -437,13 +440,9 @@ public void visitVarDef(JCVariableDecl tree) { LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context; if (context != null && lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) { - JCExpression init = translate(tree.init); - int prevPos = make.pos; - try { - result = make.at(tree).VarDef((VarSymbol)lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym), init); - } finally { - make.at(prevPos); - } + tree.init = translate(tree.init); + tree.sym = (VarSymbol) lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym); + result = tree; } else if (context != null && lambdaContext.getSymbolMap(TYPE_VAR).containsKey(tree.sym)) { JCExpression init = translate(tree.init); VarSymbol xsym = (VarSymbol)lambdaContext.getSymbolMap(TYPE_VAR).get(tree.sym); @@ -1284,7 +1283,10 @@ @Override public void visitNewClass(JCNewClass tree) { - if (lambdaNewClassFilter(context(), tree)) { + TypeSymbol def = tree.type.tsym; + boolean inReferencedClass = currentlyInClass(def); + boolean isLocal = def.isLocal(); + if ((inReferencedClass && isLocal || lambdaNewClassFilter(context(), tree))) { TranslationContext localContext = context(); while (localContext != null) { if (localContext.tree.getTag() == LAMBDA) { @@ -1294,16 +1296,16 @@ localContext = localContext.prev; } } - if (context() != null && tree.type.tsym.owner.kind == MTH) { + if (context() != null && !inReferencedClass && isLocal) { LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context(); - captureLocalClassDefs(tree.type.tsym, lambdaContext); + captureLocalClassDefs(def, lambdaContext); } super.visitNewClass(tree); } //where void captureLocalClassDefs(Symbol csym, final LambdaTranslationContext lambdaContext) { JCClassDecl localCDef = localClassDefs.get(csym); - if (localCDef != null && localCDef.pos < lambdaContext.tree.pos) { + if (localCDef != null && lambdaContext.freeVarProcessedLocalClasses.add(csym)) { BasicFreeVarCollector fvc = lower.new BasicFreeVarCollector() { @Override void addFreeVars(ClassSymbol c) { @@ -1329,6 +1331,18 @@ fvc.scan(localCDef); } } + //where + boolean currentlyInClass(Symbol csym) { + for (Frame frame : frameStack) { + if (frame.tree.hasTag(JCTree.Tag.CLASSDEF)) { + JCClassDecl cdef = (JCClassDecl) frame.tree; + if (cdef.sym == csym) { + return true; + } + } + } + return false; + } /** * Method references to local class constructors, may, if the local @@ -1754,6 +1768,11 @@ List syntheticParams; + /** + * to prevent recursion, track local classes processed + */ + final Set freeVarProcessedLocalClasses; + LambdaTranslationContext(JCLambda tree) { super(tree); Frame frame = frameStack.head; @@ -1783,6 +1802,8 @@ translatedSymbols.put(CAPTURED_VAR, new LinkedHashMap()); translatedSymbols.put(CAPTURED_THIS, new LinkedHashMap()); translatedSymbols.put(TYPE_VAR, new LinkedHashMap()); + + freeVarProcessedLocalClasses = new HashSet<>(); } /** @@ -1893,7 +1914,7 @@ }; break; case LOCAL_VAR: - ret = new VarSymbol(sym.flags() & FINAL, name, types.erasure(sym.type), translatedSym); + ret = new VarSymbol(sym.flags() & FINAL, name, sym.type, translatedSym); ((VarSymbol) ret).pos = ((VarSymbol) sym).pos; break; case PARAM: diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jul 05 19:39:35 2017 +0200 @@ -564,7 +564,7 @@ tvars, (MethodType)mt, resultInfo, - m, + (MethodSymbol)m, argtypes, allowBoxing, useVarargs, @@ -772,6 +772,7 @@ public MethodCheck mostSpecificCheck(List actuals, boolean strict) { return nilMethodCheck; } + } /** @@ -783,6 +784,11 @@ void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) { //do nothing - actual always compatible to formals } + + @Override + public String toString() { + return "arityMethodCheck"; + } }; List dummyArgs(int length) { @@ -868,6 +874,11 @@ public MethodCheck mostSpecificCheck(List actuals, boolean strict) { return new MostSpecificCheck(strict, actuals); } + + @Override + public String toString() { + return "resolveMethodCheck"; + } }; /** @@ -899,7 +910,9 @@ @Override public boolean compatible(Type found, Type req, Warner warn) { found = pendingInferenceContext.asUndetVar(found); - req = infer.returnConstraintTarget(found, req); + if (found.hasTag(UNDETVAR) && req.isPrimitive()) { + req = types.boxedClass(req).type; + } return super.compatible(found, req, warn); } @@ -915,6 +928,11 @@ public MethodCheck mostSpecificCheck(List actuals, boolean strict) { return new MostSpecificCheck(strict, actuals); } + + @Override + public String toString() { + return "MethodReferenceCheck"; + } } /** @@ -954,6 +972,11 @@ public DeferredAttrContext deferredAttrContext() { return deferredAttrContext; } + + @Override + public String toString() { + return "MethodCheckContext"; + } } /** @@ -972,7 +995,12 @@ DeferredType dt = (DeferredType)found; return dt.check(this); } else { - return super.check(pos, chk.checkNonVoid(pos, types.capture(U(found.baseType())))); + Type uResult = U(found.baseType()); + Type capturedType = pos == null || pos.getTree() == null ? + types.capture(uResult) : + checkContext.inferenceContext() + .cachedCapture(pos.getTree(), uResult, true); + return super.check(pos, chk.checkNonVoid(pos, capturedType)); } } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/file/FSInfo.java --- a/langtools/src/share/classes/com/sun/tools/javac/file/FSInfo.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/file/FSInfo.java Wed Jul 05 19:39:35 2017 +0200 @@ -82,8 +82,10 @@ for (StringTokenizer st = new StringTokenizer(path); st.hasMoreTokens(); ) { String elt = st.nextToken(); - File f = (parent == null ? new File(elt) : new File(parent, elt)); - list.add(f); + try { + File f = parent == null ? new File(elt): new File(file.toURI().resolve(elt)); + list.add(f); + } catch (IllegalArgumentException ex) {} } return list; diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java Wed Jul 05 19:39:35 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2812,7 +2812,7 @@ } private LVTAssignAnalyzer(LVTRanges lvtRanges, Symtab syms, Names names) { - super(new LVTBits(), syms, names); + super(new LVTBits(), syms, names, false); lvtInits = (LVTBits)inits; this.lvtRanges = lvtRanges; } diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Jul 05 19:39:35 2017 +0200 @@ -1627,6 +1627,10 @@ compiler.warn.varargs.redundant.trustme.anno=\ Redundant {0} annotation. {1} +# 0: symbol +compiler.warn.access.to.sensitive.member.from.serializable.element=\ + access to sensitive member {0} from serializable element can be publicly accessible to untrusted code + ##### ## The following are tokens which are non-terminals in the language. They should diff -r a77941f17614 -r 0d1f816217dc langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Wed Jul 05 19:39:35 2017 +0200 @@ -851,6 +851,8 @@ return symbol(((JCTypeApply) tree).clazz); case ANNOTATED_TYPE: return symbol(((JCAnnotatedType) tree).underlyingType); + case REFERENCE: + return ((JCMemberReference) tree).sym; default: return null; } diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/lib/JavadocTester.java --- a/langtools/test/com/sun/javadoc/lib/JavadocTester.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/test/com/sun/javadoc/lib/JavadocTester.java Wed Jul 05 19:39:35 2017 +0200 @@ -114,6 +114,46 @@ private File outputDir; /** + * Alternatives for checking the contents of a directory. + */ + enum DirectoryCheck { + /** + * Check that the directory is empty. + */ + EMPTY((file, name) -> true), + /** + * Check that the directory does not contain any HTML files, + * such as may have been generated by a prior run of javadoc + * using this directory. + * For now, the check is only performed on the top level directory. + */ + NO_HTML_FILES((file, name) -> name.endsWith(".html")), + /** + * No check is performed on the directory contents. + */ + NONE(null) { @Override void check(File dir) { } }; + + /** The filter used to detect that files should not be present. */ + FilenameFilter filter; + + DirectoryCheck(FilenameFilter f) { + filter = f; + } + + void check(File dir) { + if (dir.isDirectory()) { + String[] contents = dir.list(filter); + if (contents == null) + throw new Error("cannot list directory: " + dir); + if (contents.length > 0) + throw new Error("directory has unexpected content: " + dir); + } + } + } + + private DirectoryCheck outputDirectoryCheck = DirectoryCheck.EMPTY; + + /** * The current subtest number. */ private static int numTestsRun = 0; @@ -206,6 +246,8 @@ } } + outputDirectoryCheck.check(outputDir); + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); PrintStream prevOut = System.out; System.setOut(new PrintStream(stdout)); @@ -232,6 +274,15 @@ } /** + * Set a filter to check the initial contents of the output directory + * before javadoc is run. + * The filter should return true for files that should not appear. + */ + public void setCheckOutputDirectoryCheck(DirectoryCheck c) { + outputDirectoryCheck = c; + } + + /** * Create new string writer buffers */ private void initOutputBuffers() { diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testDocFileDir/TestDocFileDir.java --- a/langtools/test/com/sun/javadoc/testDocFileDir/TestDocFileDir.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/test/com/sun/javadoc/testDocFileDir/TestDocFileDir.java Wed Jul 05 19:39:35 2017 +0200 @@ -86,10 +86,12 @@ */ public static void main(String[] args) { TestDocFileDir tester = new TestDocFileDir(); + tester.setCheckOutputDirectoryCheck(DirectoryCheck.NO_HTML_FILES); copyDir(SRC_DIR + "/pkg", "."); tester.run(ARGS0, TEST0, NO_TEST); copyDir(SRC_DIR + "/pkg", OUTPUT_DIR + "-1"); tester.run(ARGS1, TEST1, NO_TEST); + tester.setCheckOutputDirectoryCheck(DirectoryCheck.NONE); tester.run(ARGS2, NO_TEST, NO_TEST, FILE_TEST2, FILE_NEGATED_TEST2); tester.printSummary(); } diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testGeneratedBy/TestGeneratedBy.java --- a/langtools/test/com/sun/javadoc/testGeneratedBy/TestGeneratedBy.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/test/com/sun/javadoc/testGeneratedBy/TestGeneratedBy.java Wed Jul 05 19:39:35 2017 +0200 @@ -58,7 +58,7 @@ private static final String[] NO_TIMESTAMP_ARGS = new String[] { "-notimestamp", - "-d", OUTPUT_DIR, + "-d", OUTPUT_DIR + "-1", "-sourcepath", SRC_DIR, "pkg" }; diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testGroupOption/TestGroupOption.java --- a/langtools/test/com/sun/javadoc/testGroupOption/TestGroupOption.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/test/com/sun/javadoc/testGroupOption/TestGroupOption.java Wed Jul 05 19:39:35 2017 +0200 @@ -45,7 +45,7 @@ }; private static final String[] ARGS2 = new String[] { - "-d", OUTPUT_DIR, "-sourcepath", SRC_DIR, + "-d", OUTPUT_DIR + "-1", "-sourcepath", SRC_DIR, "-group", "Package One", "pkg1", "-group", "Package One", "pkg2", "-group", "Package One", "pkg3", diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java --- a/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java Wed Jul 05 19:39:35 2017 +0200 @@ -40,127 +40,134 @@ // Optional Element should print properly nested definition list tags // for default value. private static final String[][] TEST_ALL = { - { "pkg1/C1.html", "

    public class " +
    -                 "C1\n" +
    -                 "extends java.lang.Object\n" +
    -                 "implements java.io.Serializable
    "}, - { "pkg1/C4.html", "
    \n" + - "
    Default:
    \n" + - "
    true
    \n" + - "
    "}}; + { "pkg1/C1.html", + "
    public class C1\n" +
    +                "extends java.lang.Object\n" +
    +                "implements java.io.Serializable
    "}, + { "pkg1/C4.html", + "
    \n" + + "
    Default:
    \n" + + "
    true
    \n" + + "
    "}}; // Test for normal run of javadoc in which various ClassDocs and // serialized form should have properly nested definition list tags // enclosing comments, tags and deprecated information. private static final String[][] TEST_CMNT_DEPR = { - { "pkg1/package-summary.html", "
    \n" + - "
    Since:
    \n" + - "
    JDK1.0
    \n" + - "
    "}, - { "pkg1/C1.html", "
    \n" + - "
    Since:
    \n" + - "
    JDK1.0
    \n" + - "
    See Also:
    \n" + - "
    " + - "C2, \n" + - "" + - "Serialized Form
    \n" + - "
    "}, - { "pkg1/C1.html", "
    \n" + - "
    Since:
    \n" + - "
    1.4
    \n" + - "
    See Also:
    \n" + - "
    " + - "" + - "setUndecorated(boolean)
    \n" + - "
    "}, - { "pkg1/C1.html", "
    \n" + - "
    Parameters:
    \n" + - "
    title" + - " - the title
    \n" + - "
    test - boolean value" + - "
    \n" + - "
    Throws:
    \n" + - "
    java.lang.IllegalArgumentException - if the " + - "owner's\n" + - " GraphicsConfiguration is not from a screen " + - "device
    \n" + - "
    HeadlessException
    \n" + - "
    "}, - { "pkg1/C1.html", "
    \n" + - "
    Parameters:
    \n" + - "
    undecorated" + - " - true if no decorations are\n" + - " to be enabled;\n" + - " false " + - "if decorations are to be enabled.
    \n" + - "
    Since:" + - "
    \n" + - "
    1.4
    \n" + - "
    See Also:
    \n" + - "
    " + - "readObject()" + - "
    \n" + - "
    "}, - { "pkg1/C1.html", "
    \n" + - "
    Throws:
    \n" + - "
    java.io.IOException
    \n" + - "
    See Also:" + - "
    \n" + - "
    " + - "setUndecorated(boolean)
    \n" + - "
    "}, - { "pkg1/C2.html", "
    \n" + - "
    Parameters:" + - "
    \n" + - "
    set - boolean
    \n" + - "
    " + - "Since:
    \n" + - "
    1.4
    \n" + - "
    "}, - { "serialized-form.html", "
    \n" + - "
    Throws:" + - "
    \n" + - "
    " + - "java.io.IOException
    \n" + - "
    See Also:" + - "
    \n" + - "
    " + - "C1.setUndecorated(boolean)
    \n" + - "
    "}, + { "pkg1/package-summary.html", + "
    \n" + + "
    Since:
    \n" + + "
    JDK1.0
    \n" + + "
    "}, + { "pkg1/C1.html", + "
    \n" + + "
    Since:
    \n" + + "
    JDK1.0
    \n" + + "
    See Also:
    \n" + + "
    " + + "C2, \n" + + "" + + "Serialized Form
    \n" + + "
    "}, + { "pkg1/C1.html", + "
    \n" + + "
    Since:
    \n" + + "
    1.4
    \n" + + "
    See Also:
    \n" + + "
    " + + "setUndecorated(boolean)
    \n" + + "
    "}, + { "pkg1/C1.html", + "
    \n" + + "
    Parameters:
    \n" + + "
    title - the title
    \n" + + "
    test - boolean value" + + "
    \n" + + "
    Throws:
    \n" + + "
    java.lang.IllegalArgumentException - if the " + + "owner's\n" + + " GraphicsConfiguration is not from a screen " + + "device
    \n" + + "
    HeadlessException
    \n" + + "
    "}, + { "pkg1/C1.html", + "
    \n" + + "
    Parameters:
    \n" + + "
    undecorated" + + " - true if no decorations are\n" + + " to be enabled;\n" + + " false " + + "if decorations are to be enabled.
    \n" + + "
    Since:" + + "
    \n" + + "
    1.4
    \n" + + "
    See Also:
    \n" + + "
    " + + "readObject()" + + "
    \n" + + "
    "}, + { "pkg1/C1.html", + "
    \n" + + "
    Throws:
    \n" + + "
    java.io.IOException
    \n" + + "
    See Also:" + + "
    \n" + + "
    " + + "setUndecorated(boolean)
    \n" + + "
    "}, + { "pkg1/C2.html", + "
    \n" + + "
    Parameters:" + + "
    \n" + + "
    set - boolean
    \n" + + "
    " + + "Since:
    \n" + + "
    1.4
    \n" + + "
    "}, { "serialized-form.html", - "Deprecated." + - " As of JDK version 1.5, replaced by\n" + - " " + - "setUndecorated(boolean).\n" + - "
    This field indicates whether the C1 is " + - "undecorated.
    \n" + - " \n" + - "
    \n" + - "
    Since:
    \n" + - "
    1.4
    \n" + - "
    See Also:" + - "
    \n" + - "
    " + - "C1.setUndecorated(boolean)
    \n" + - "
    "}, + "
    \n" + + "
    Throws:" + + "
    \n" + + "
    " + + "java.io.IOException
    \n" + + "
    See Also:" + + "
    \n" + + "
    " + + "C1.setUndecorated(boolean)
    \n" + + "
    "}, { "serialized-form.html", - "Deprecated." + - " As of JDK version 1.5, replaced by\n" + - " " + - "setUndecorated(boolean).\n" + - "
    Reads the object stream.
    \n" + - "
    \n" + - "
    Throws:" + - "
    \n" + - "
    " + - "IOException
    \n" + - "
    java.io.IOException
    \n" + - "
    "}, + "Deprecated." + + " As of JDK version 1.5, replaced by\n" + + " " + + "setUndecorated(boolean).\n" + + "
    This field indicates whether the C1 is " + + "undecorated.
    \n" + + " \n" + + "
    \n" + + "
    Since:
    \n" + + "
    1.4
    \n" + + "
    See Also:" + + "
    \n" + + "
    " + + "C1.setUndecorated(boolean)
    \n" + + "
    "}, { "serialized-form.html", - "Deprecated." + - " \n" + - "
    The name for this class.
    "}}; + "Deprecated." + + " As of JDK version 1.5, replaced by\n" + + " " + + "setUndecorated(boolean).\n" + + "
    Reads the object stream.
    \n" + + "
    \n" + + "
    Throws:" + + "
    \n" + + "
    " + + "IOException
    \n" + + "
    java.io.IOException
    \n" + + "
    "}, + { "serialized-form.html", + "Deprecated." + + " \n" + + "
    The name for this class.
    "}}; // Test with -nodeprecated option. The ClassDocs should have properly nested // definition list tags enclosing comments and tags. The ClassDocs should not @@ -168,183 +175,210 @@ // should display properly nested definition list tags for comments, tags // and deprecated information. private static final String[][] TEST_NODEPR = { - { "pkg1/package-summary.html", "
    \n" + - "
    Since:
    \n" + - "
    JDK1.0
    \n" + - "
    "}, - { "pkg1/C1.html", "
    \n" + - "
    Since:" + - "
    \n" + - "
    JDK1.0
    \n" + - "
    See Also:" + - "
    \n" + - "
    " + - "C2, \n" + - "" + - "Serialized Form
    \n" + - "
    "}, - { "pkg1/C1.html", "
    \n" + - "
    Parameters:" + - "
    \n" + - "
    title - the title
    \n" + - "
    " + - "test - boolean value
    \n" + - "
    Throws:" + - "
    \n" + - "
    java.lang.IllegalArgumentException" + - " - if the owner's\n" + - " GraphicsConfiguration" + - " is not from a screen device
    \n" + - "
    " + - "HeadlessException
    \n" + - "
    "}, - { "pkg1/C1.html", "
    \n" + - "
    Parameters:" + - "
    \n" + - "
    undecorated - true" + - " if no decorations are\n" + - " to be enabled;\n" + - " false if decorations are to be enabled." + - "
    \n" + - "
    Since:
    \n" + - "
    1.4
    \n" + - "
    See Also:
    \n" + - "
    " + - "readObject()
    \n" + - "
    "}, - { "pkg1/C1.html", "
    \n" + - "
    Throws:" + - "
    \n" + - "
    java.io.IOException
    \n" + - "
    " + - "See Also:
    \n" + - "
    " + - "setUndecorated(boolean)
    \n" + - "
    "}, - { "serialized-form.html", "
    \n" + - "
    Throws:" + - "
    \n" + - "
    " + - "java.io.IOException
    \n" + - "
    See Also:" + - "
    \n" + - "
    " + - "C1.setUndecorated(boolean)
    \n" + - "
    "}, + { "pkg1/package-summary.html", + "
    \n" + + "
    Since:
    \n" + + "
    JDK1.0
    \n" + + "
    "}, + { "pkg1/C1.html", + "
    \n" + + "
    Since:" + + "
    \n" + + "
    JDK1.0
    \n" + + "
    See Also:" + + "
    \n" + + "
    " + + "C2, \n" + + "" + + "Serialized Form
    \n" + + "
    "}, + { "pkg1/C1.html", + "
    \n" + + "
    Parameters:" + + "
    \n" + + "
    title - the title
    \n" + + "
    " + + "test - boolean value
    \n" + + "
    Throws:" + + "
    \n" + + "
    java.lang.IllegalArgumentException" + + " - if the owner's\n" + + " GraphicsConfiguration" + + " is not from a screen device
    \n" + + "
    " + + "HeadlessException
    \n" + + "
    "}, + { "pkg1/C1.html", + "
    \n" + + "
    Parameters:" + + "
    \n" + + "
    undecorated - true" + + " if no decorations are\n" + + " to be enabled;\n" + + " false if decorations are to be enabled." + + "
    \n" + + "
    Since:
    \n" + + "
    1.4
    \n" + + "
    See Also:
    \n" + + "
    " + + "readObject()
    \n" + + "
    "}, + { "pkg1/C1.html", + "
    \n" + + "
    Throws:" + + "
    \n" + + "
    java.io.IOException
    \n" + + "
    " + + "See Also:
    \n" + + "
    " + + "setUndecorated(boolean)
    \n" + + "
    "}, { "serialized-form.html", - "Deprecated." + - " As of JDK version 1.5, replaced by\n" + - " " + - "setUndecorated(boolean).\n" + - "
    This field indicates whether the C1 is " + - "undecorated.
    \n" + - " \n" + - "
    \n" + - "
    Since:
    \n" + - "
    1.4
    \n" + - "
    See Also:" + - "
    \n" + - "
    " + - "C1.setUndecorated(boolean)
    \n" + - "
    "}, + "
    \n" + + "
    Throws:" + + "
    \n" + + "
    " + + "java.io.IOException
    \n" + + "
    See Also:" + + "
    \n" + + "
    " + + "C1.setUndecorated(boolean)
    \n" + + "
    "}, { "serialized-form.html", - "Deprecated." + - " As of JDK version 1.5, replaced by\n" + - " " + - "setUndecorated(boolean).\n" + - "
    Reads the object stream.
    \n" + - "
    \n" + - "
    Throws:" + - "
    \n" + - "
    " + - "IOException
    \n" + - "
    java.io.IOException
    \n" + - "
    "}, + "Deprecated." + + " As of JDK version 1.5, replaced by\n" + + " " + + "setUndecorated(boolean).\n" + + "
    This field indicates whether the C1 is " + + "undecorated.
    \n" + + " \n" + + "
    \n" + + "
    Since:
    \n" + + "
    1.4
    \n" + + "
    See Also:" + + "
    \n" + + "
    " + + "C1.setUndecorated(boolean)
    \n" + + "
    "}, { "serialized-form.html", - "Deprecated." + - " \n" + - "
    " + - "The name for this class.
    "}}; + "Deprecated." + + " As of JDK version 1.5, replaced by\n" + + " " + + "setUndecorated(boolean).\n" + + "
    Reads the object stream.
    \n" + + "
    \n" + + "
    Throws:" + + "
    \n" + + "
    " + + "IOException
    \n" + + "
    java.io.IOException
    \n" + + "
    "}, + { "serialized-form.html", + "Deprecated." + + " \n" + + "
    " + + "The name for this class.
    "}}; // Test with -nocomment and -nodeprecated options. The ClassDocs whould // not display definition lists for any member details. private static final String[][] TEST_NOCMNT_NODEPR = { { "pkg1/C1.html", - "
    public void readObject()\n" +
    -                 "                throws java.io.IOException
    \n" + - ""}, + "
    public void readObject()\n" +
    +                "                throws java.io.IOException
    \n" + + ""}, { "pkg1/C2.html", "
    public C2()
    \n" + - ""}, + ""}, { "pkg1/C1.ModalExclusionType.html", "
    public " +
    -                 "static final C1.ModalExclusionType " +
    -                 "APPLICATION_EXCLUDE
    \n" + - ""}, + "static final C1.ModalExclusionType " + + "APPLICATION_EXCLUDE\n" + + ""}, { "serialized-form.html", "
    boolean " +
    -                 "undecorated
    \n" + - "
    " + - "Deprecated. As of JDK version 1.5, replaced by\n" + - " " + - "setUndecorated(boolean).
    \n" + - ""}, + "undecorated\n" + + "
    " + + "Deprecated. As of JDK version 1.5, replaced by\n" + + " " + + "setUndecorated(boolean).
    \n" + + ""}, { "serialized-form.html", "" + - "Deprecated. As of JDK version" + - " 1.5, replaced by\n" + - " " + - "setUndecorated(boolean).\n" + - ""}}; + "Deprecated. As of JDK version" + + " 1.5, replaced by\n" + + " " + + "setUndecorated(boolean).\n" + + ""}}; // Test for valid HTML generation which should not comprise of empty // definition list tags. - private static final String[][] NEGATED_TEST = { - { "pkg1/package-summary.html", "
    "}, - { "pkg1/package-summary.html", "
    \n" + - "
    "}, - { "pkg1/C1.html", "
    "}, - { "pkg1/C1.html", "
    \n" + - "
    "}, - { "pkg1/C1.ModalExclusionType.html", "
    "}, - { "pkg1/C1.ModalExclusionType.html", "
    \n" + - "
    "}, - { "pkg1/C2.html", "
    "}, - { "pkg1/C2.html", "
    \n" + - "
    "}, - { "pkg1/C2.ModalType.html", "
    "}, - { "pkg1/C2.ModalType.html", "
    \n" + - "
    "}, - { "pkg1/C3.html", "
    "}, - { "pkg1/C3.html", "
    \n" + - "
    "}, - { "pkg1/C4.html", "
    "}, - { "pkg1/C4.html", "
    \n" + - "
    "}, - { "pkg1/C5.html", "
    "}, - { "pkg1/C5.html", "
    \n" + - "
    "}, - { "overview-tree.html", "
    "}, - { "overview-tree.html", "
    \n" + - "
    "}, - { "serialized-form.html", "
    "}, - { "serialized-form.html", "
    \n" + - "
    "}}; + private static final String[][] NEGATED_TEST_NO_C5 = { + { "pkg1/package-summary.html", + "
    "}, + { "pkg1/package-summary.html", + "
    \n" + + "
    "}, + { "pkg1/C1.html", + "
    "}, + { "pkg1/C1.html", + "
    \n" + + "
    "}, + { "pkg1/C1.ModalExclusionType.html", + "
    "}, + { "pkg1/C1.ModalExclusionType.html", + "
    \n" + + "
    "}, + { "pkg1/C2.html", + "
    "}, + { "pkg1/C2.html", + "
    \n" + + "
    "}, + { "pkg1/C2.ModalType.html", + "
    "}, + { "pkg1/C2.ModalType.html", + "
    \n" + + "
    "}, + { "pkg1/C3.html", + "
    "}, + { "pkg1/C3.html", + "
    \n" + + "
    "}, + { "pkg1/C4.html", + "
    "}, + { "pkg1/C4.html", + "
    \n" + + "
    "}, + { "overview-tree.html", + "
    "}, + { "overview-tree.html", + "
    \n" + + "
    "}, + { "serialized-form.html", + "
    "}, + { "serialized-form.html", + "
    \n" + + "
    "}}; + private static final String[][] NEGATED_TEST_C5 = { + { "pkg1/C5.html", + "
    "}, + { "pkg1/C5.html", + "
    \n" + + "
    "}}; private static final String[] ARGS1 = new String[] { - "-Xdoclint:none", "-d", OUTPUT_DIR, "-sourcepath", SRC_DIR, "pkg1"}; + "-Xdoclint:none", "-d", OUTPUT_DIR + "-1", "-sourcepath", SRC_DIR, "pkg1"}; private static final String[] ARGS2 = new String[] { - "-Xdoclint:none", "-d", OUTPUT_DIR, "-nocomment", "-sourcepath", + "-Xdoclint:none", "-d", OUTPUT_DIR + "-2", "-nocomment", "-sourcepath", SRC_DIR, "pkg1"}; private static final String[] ARGS3 = new String[] { - "-Xdoclint:none", "-d", OUTPUT_DIR, "-nodeprecated", "-sourcepath", + "-Xdoclint:none", "-d", OUTPUT_DIR + "-3", "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; private static final String[] ARGS4 = new String[] { - "-Xdoclint:none", "-d", OUTPUT_DIR, "-nocomment", "-nodeprecated", + "-Xdoclint:none", "-d", OUTPUT_DIR + "-4", "-nocomment", "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; /** @@ -353,14 +387,20 @@ */ public static void main(String[] args) { TestHtmlDefinitionListTag tester = new TestHtmlDefinitionListTag(); - tester.run(ARGS1, TEST_ALL, NEGATED_TEST); - tester.run(ARGS1, TEST_CMNT_DEPR, NEGATED_TEST); - tester.run(ARGS2, TEST_ALL, NEGATED_TEST); - tester.run(ARGS2, NO_TEST, TEST_CMNT_DEPR); - tester.run(ARGS3, TEST_ALL, NEGATED_TEST); - tester.run(ARGS3, TEST_NODEPR, TEST_NOCMNT_NODEPR); - tester.run(ARGS4, TEST_ALL, NEGATED_TEST); - tester.run(ARGS4, TEST_NOCMNT_NODEPR, TEST_CMNT_DEPR); + tester.run(ARGS1, TEST_ALL, NEGATED_TEST_NO_C5); + tester.runTestsOnHTML(NO_TEST, NEGATED_TEST_C5); + tester.runTestsOnHTML(TEST_CMNT_DEPR, NO_TEST); + + tester.run(ARGS2, TEST_ALL, NEGATED_TEST_NO_C5); + tester.runTestsOnHTML(NO_TEST, NEGATED_TEST_C5); + tester.runTestsOnHTML(NO_TEST, TEST_CMNT_DEPR); + + tester.run(ARGS3, TEST_ALL, NEGATED_TEST_NO_C5); + tester.runTestsOnHTML(TEST_NODEPR, TEST_NOCMNT_NODEPR); + + tester.run(ARGS4, TEST_ALL, NEGATED_TEST_NO_C5); + tester.runTestsOnHTML(TEST_NOCMNT_NODEPR, TEST_CMNT_DEPR); + tester.printSummary(); } } diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testHtmlStrongTag/TestHtmlStrongTag.java --- a/langtools/test/com/sun/javadoc/testHtmlStrongTag/TestHtmlStrongTag.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/test/com/sun/javadoc/testHtmlStrongTag/TestHtmlStrongTag.java Wed Jul 05 19:39:35 2017 +0200 @@ -47,16 +47,14 @@ private static final String[][] TEST2 = { { "pkg2/C2.html", "Comments:"}}; private static final String[][] NEGATED_TEST2 = { - { "pkg2/C2.html", "Method Summary"}, - { "pkg1/package-summary.html", - "Class Summary"}}; + { "pkg2/C2.html", "Method Summary"}}; private static final String[] ARGS1 = new String[] { - "-d", OUTPUT_DIR, "-sourcepath", SRC_DIR, "pkg1"}; + "-d", OUTPUT_DIR + "-1", "-sourcepath", SRC_DIR, "pkg1"}; private static final String[] ARGS2 = new String[] { - "-d", OUTPUT_DIR, "-sourcepath", SRC_DIR, "pkg2"}; + "-d", OUTPUT_DIR + "-2", "-sourcepath", SRC_DIR, "pkg2"}; /** * The entry point of the test. diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testHtmlTag/TestHtmlTag.java --- a/langtools/test/com/sun/javadoc/testHtmlTag/TestHtmlTag.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/test/com/sun/javadoc/testHtmlTag/TestHtmlTag.java Wed Jul 05 19:39:35 2017 +0200 @@ -58,13 +58,13 @@ private static final String[] ARGS1 = new String[] { - "-d", OUTPUT_DIR, "-sourcepath", SRC_DIR, "pkg1"}; + "-d", OUTPUT_DIR + "-1", "-sourcepath", SRC_DIR, "pkg1"}; private static final String[] ARGS2 = new String[] { - "-locale", "ja", "-d", OUTPUT_DIR, "-sourcepath", SRC_DIR, "pkg2"}; + "-locale", "ja", "-d", OUTPUT_DIR + "-2", "-sourcepath", SRC_DIR, "pkg2"}; private static final String[] ARGS3 = new String[] { - "-locale", "en_US", "-d", OUTPUT_DIR, "-sourcepath", SRC_DIR, "pkg1"}; + "-locale", "en_US", "-d", OUTPUT_DIR + "-3", "-sourcepath", SRC_DIR, "pkg1"}; /** * The entry point of the test. diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testLinkOption/TestLinkOption.java --- a/langtools/test/com/sun/javadoc/testLinkOption/TestLinkOption.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/test/com/sun/javadoc/testLinkOption/TestLinkOption.java Wed Jul 05 19:39:35 2017 +0200 @@ -79,8 +79,8 @@ private static final String[][] TEST2 = { { "pkg2/C2.html", - "This is a link to Class C." } }; @@ -119,7 +119,6 @@ public static void main(String[] args) { TestLinkOption tester = new TestLinkOption(); tester.run(ARGS1, TEST1, NEGATED_TEST1); - tester.run(ARGS1, TEST1, NEGATED_TEST1); tester.run(ARGS2, TEST2, NO_TEST); tester.runJavadoc(createArguments(true)); // with trailing slash tester.runJavadoc(createArguments(false)); // without trailing slash diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testNotifications/TestNotifications.java --- a/langtools/test/com/sun/javadoc/testNotifications/TestNotifications.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/test/com/sun/javadoc/testNotifications/TestNotifications.java Wed Jul 05 19:39:35 2017 +0200 @@ -67,7 +67,9 @@ tester.run(ARGS, TEST, NO_TEST); // No need to notify that the destination must be created because // it already exists. + tester.setCheckOutputDirectoryCheck(DirectoryCheck.NONE); tester.run(ARGS, NO_TEST, NEGATED_TEST); + tester.setCheckOutputDirectoryCheck(DirectoryCheck.NO_HTML_FILES); //Make sure classname is not include in javadoc usage message. tester.run(ARGS2, NO_TEST, NEGATED_TEST2); tester.printSummary(); diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testOrdering/C.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/com/sun/javadoc/testOrdering/C.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Class in an unnamed package. + */ + +public class C { + /** + * A ctor + * @param c a param + */ + public C(UsedInC c){} + + /** + * another ctor + * @param c a param + * @param s a param + */ + public C(UsedInC c, String s) {} + + /** + * yet another ctor + * @param c a param + * @param i a param + */ + public C(UsedInC c, int i) {} + + /** + * Field in C. + */ + public UsedInC fieldInC; + + /** + * Method in C. + * @param p a param + * @return UsedInC + */ + public UsedInC methodInC(UsedInC p) { return p;} + + /** + * A static method + * @param s a param + * @return UsedInC + */ + public static UsedInC ymethod(String s) {return null;} + + /** + * Another static method variant + * @param value a param + * @return UsedInC + */ + public static UsedInC ymethod(int value) {return -1;} +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testOrdering/TestOrdering.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/com/sun/javadoc/testOrdering/TestOrdering.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8039410 + * @summary test to determine if members are ordered correctly + * @author ksrini + * @library ../lib/ + * @build JavadocTester + * @build TestOrdering + * @run main TestOrdering + */ + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TestOrdering extends JavadocTester { + /** + * The entry point of the test. + * @param args the array of command line arguments. + */ + public static void main(String[] args) throws Exception { + TestOrdering tester = new TestOrdering(); + // test unnamed packages + String[] ARGS = { + "-d", OUTPUT_DIR, "-sourcepath", SRC_DIR, "-use", + SRC_DIR + "/C.java", SRC_DIR + "/UsedInC.java" + }; + tester.runJavadoc(ARGS); + checkExecutableMemberOrdering(tester.readFileToString("class-use/UsedInC.html")); + + // next test using packages + String[] ARGS1 = { + "-d", OUTPUT_DIR + "-1", "-sourcepath", SRC_DIR, "-use", + "pkg1" + }; + tester.runJavadoc(ARGS1); + checkClassUseOrdering(tester.readFileToString("pkg1/class-use/UsedClass.html")); + checkIndexPathOrdering(tester.readFileToString("index-all.html")); + } + + static void checkExecutableMemberOrdering(String usePage) { + // check constructors + int idx1 = usePage.indexOf("C.html#C-UsedInC"); + int idx2 = usePage.indexOf("C.html#C-UsedInC-int"); + int idx3 = usePage.indexOf("C.html#C-UsedInC-java.lang.String"); + if (idx1 == -1 || idx2 == -1 || idx3 == -1) { + throw new Error("ctor strings not found"); + } + if (idx1 > idx2 || idx2 > idx3 || idx1 > idx3) { + throw new Error("ctor strings are out of order"); + } + + // check methods + idx1 = usePage.indexOf("C.html#ymethod-int"); + idx2 = usePage.indexOf("C.html#ymethod-java.lang.String"); + if (idx1 == -1 || idx2 == -1) { + throw new Error("#ymethod strings not found"); + } + if (idx1 > idx2) { + throw new Error("#ymethod strings are out of order"); + } + System.out.println("Executable Member Ordering: OK"); + } + + static void checkClassUseOrdering(String usePage) { + checkClassUseOrdering(usePage, "pkg1/C#ITERATION#.html#zfield"); + checkClassUseOrdering(usePage, "pkg1/C#ITERATION#.html#fieldInC#ITERATION#"); + checkClassUseOrdering(usePage, "pkg1/C#ITERATION#.html#zmethod-pkg1.UsedClass"); + checkClassUseOrdering(usePage, "pkg1/C#ITERATION#.html#methodInC#ITERATION#"); + } + + static void checkClassUseOrdering(String usePage, String searchString) { + int lastidx = 0; + System.out.println("testing for " + searchString); + for (int i = 1; i < 5; i++) { + String s = searchString.replaceAll("#ITERATION#", Integer.toString(i)); + System.out.println(s); + int idx = usePage.indexOf(s); + if (idx < lastidx) { + throw new Error(s + ", member ordering error, last:" + lastidx + ", got:" + idx); + } + System.out.println("\tlast: " + lastidx + " got:" + idx); + lastidx = idx; + } + } + + static void checkIndexPathOrdering(String indexPage) { + String[] OrderedExpectedStrings = { + "pkg1/UsedClass.html#add-java.lang.Double", + "pkg1/ZZTop.html#add-double", + "pkg1/ZZTop.html#add-java.lang.Double", + "pkg1/UsedClass.html#add-float", + "pkg1/ZZTop.html#add-float", + "pkg1/UsedClass.html#add-int", + "pkg1/ZZTop.html#add-int", + "pkg1/UsedClass.html#add-java.lang.Integer", + "pkg1/ZZTop.html#add-java.lang.Integer", + "pkg1/UsedClass.html#add-double-double", + "pkg1/UsedClass.html#add-double-java.lang.Double", + "pkg1/ZZTop.html#add-double-double", + "pkg1/ZZTop.html#add-double-java.lang.Double" + }; + int lastidx = 0; + for (String x : OrderedExpectedStrings) { + int idx = indexPage.indexOf(x); + if (idx < lastidx) { + throw new Error(x + ", index is out of order, last:" + lastidx + ", got:" + idx); + } + System.out.println(x + ": OK"); + lastidx = idx; + } + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testOrdering/UsedInC.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/com/sun/javadoc/testOrdering/UsedInC.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * An empty class + */ +public class UsedInC {} diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testOrdering/pkg1/C1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/com/sun/javadoc/testOrdering/pkg1/C1.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg1; + +/** + * C1 + */ + +public class C1 { + + /** + * Field in C1. + */ + public UsedClass fieldInC1; + + /** + * A duplicated field + */ + public UsedClass zfield; + + /** + * Method in C1. + * @param p a param + * @return UsedClass + */ + public UsedClass methodInC1(UsedClass p) {return p;} + + /** + * A duplicated method to test ordering + * @param p a param + * @return UsedClass + */ + public UsedClass zmethod(UsedClass p) {return p;} +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testOrdering/pkg1/C2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/com/sun/javadoc/testOrdering/pkg1/C2.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg1; + +public class C2 { + + /** + * Field in C2. + */ + public UsedClass fieldInC2; + + /** + * another field + */ + public C1 field = null; + + /** + * A duplicated field + */ + public UsedClass zfield; + + /** + * Method in C2. + * @return C1 + */ + public C1 methodInC2() {return null;} + + /** + * @param c1 a param + */ + public void method(pkg1.C1 c1) {} + + /** + * Method in C2. + * @param p a param + * @return UsedClass + */ + public UsedClass methodInC2(UsedClass p) {return p;} + + /** + * A duplicated method to test ordering + * @param p a param + * @return UsedClass + */ + public UsedClass zmethod(UsedClass p) { + return p; + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testOrdering/pkg1/C3.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/com/sun/javadoc/testOrdering/pkg1/C3.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg1; + +public class C3 { + /** + * Field in C3. + */ + public UsedClass fieldInC3; + + /** + * A duplicated field + */ + public UsedClass zfield; + + /** + * Method in C3. + * @param p a param + * @return UsedClass + */ + public UsedClass methodInC3(UsedClass p) {return p;} + + /** + * A duplicated method to test ordering + * @param p a param + * @return UsedClass + */ + public UsedClass zmethod(UsedClass p) {return p;} +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testOrdering/pkg1/C4.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/com/sun/javadoc/testOrdering/pkg1/C4.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg1; + +public class C4 { + /** + * Field in C4. + */ + public UsedClass fieldInC4; + + /** + * A duplicated field + */ + public UsedClass zfield; + + /** + * Method in C4. + * @param p a param + * @return UsedClass + */ + public UsedClass methodInC4(UsedClass p) {return p;} + + /** + * A duplicated method to test ordering + * @param p a param + * @return UsedClass + */ + public UsedClass zmethod(UsedClass p) {return p;} +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testOrdering/pkg1/UsedClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/com/sun/javadoc/testOrdering/pkg1/UsedClass.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg1; +/** + * For index and class-use testing + */ +public class UsedClass { + // This is the exact order we expect to see + + /** + * @param i param + */ + public void add(int i){} + + /** + * @param i param + * @return double + */ + public int add(Integer i) {return 0;} + + /** + * @param d param + */ + public void add(double d){} + + /** + * @param d param + * @return Double + */ + public Double add(Double d) {return (double) 22/7;} + + /** + * @param f param + * @return Float + */ + public Float add(float f) {return (float) 22/7;} + + /** + * @param d1 param + * @param d2 param + * @return double + */ + public double add(double d1, double d2) {return d1 + d2;} + + /** + * @param d1 param + * @param d2 param + * @return double + */ + public double add(double d1, Double d2) {return d1 + d2;} +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testOrdering/pkg1/ZZTop.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/com/sun/javadoc/testOrdering/pkg1/ZZTop.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg1; +/** + * For index testing only + */ +public class ZZTop { + // This is the exact order we expect to see + + /** + * @param i param + */ + public void add(int i){} + + /** + * @param i param + * @return double + */ + public int add(Integer i) {return 0;} + + /** + * @param d param + */ + public void add(double d){} + + /** + * @param d param + * @return Double + */ + public Double add(Double d) {return (double) 22/7;} + + /** + * @param f param + * @return Float + */ + public Float add(float f) {return (float) 22/7;} + /** + * @param d1 param + * @param d2 param + * @return double + */ + public double add(double d1, double d2) {return d1 + d2;} + + /** + * @param d1 param + * @param d2 param + * @return double + */ + public double add(double d1, Double d2) {return d1 + d2;} +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java --- a/langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java Wed Jul 05 19:39:35 2017 +0200 @@ -115,19 +115,19 @@ private static final String[] ARGS1 = new String[] { - "-d", OUTPUT_DIR, "-sourcepath", SRC_DIR, "pkg1"}; + "-d", OUTPUT_DIR + "-1", "-sourcepath", SRC_DIR, "pkg1"}; private static final String[] ARGS2 = new String[] { - "-d", OUTPUT_DIR, "-nocomment", "-sourcepath", SRC_DIR, "pkg1"}; + "-d", OUTPUT_DIR + "-2", "-nocomment", "-sourcepath", SRC_DIR, "pkg1"}; private static final String[] ARGS3 = new String[] { - "-d", OUTPUT_DIR, "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; + "-d", OUTPUT_DIR + "-3", "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; private static final String[] ARGS4 = new String[] { - "-d", OUTPUT_DIR, "-nocomment", "-nodeprecated", "-sourcepath", + "-d", OUTPUT_DIR + "-4", "-nocomment", "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; /** diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testSinceTag/TestSinceTag.java --- a/langtools/test/com/sun/javadoc/testSinceTag/TestSinceTag.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/test/com/sun/javadoc/testSinceTag/TestSinceTag.java Wed Jul 05 19:39:35 2017 +0200 @@ -35,11 +35,11 @@ //Javadoc arguments. private static final String[] ARGS1 = new String[] { - "-d", OUTPUT_DIR, "-sourcepath", SRC_DIR, "pkg1" + "-d", OUTPUT_DIR + "-1", "-sourcepath", SRC_DIR, "pkg1" }; private static final String[] ARGS2 = new String[] { - "-d", OUTPUT_DIR, "-sourcepath", SRC_DIR, "-nosince", "pkg1" + "-d", OUTPUT_DIR + "-2", "-sourcepath", SRC_DIR, "-nosince", "pkg1" }; //Input for string search tests. diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testTypeParams/TestTypeParameters.java --- a/langtools/test/com/sun/javadoc/testTypeParams/TestTypeParameters.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/test/com/sun/javadoc/testTypeParams/TestTypeParameters.java Wed Jul 05 19:39:35 2017 +0200 @@ -39,11 +39,11 @@ //Javadoc arguments. private static final String[] ARGS1 = new String[]{ - "-d", OUTPUT_DIR, "-use", "-sourcepath", SRC_DIR, + "-d", OUTPUT_DIR + "-1", "-use", "-sourcepath", SRC_DIR, "pkg" }; private static final String[] ARGS2 = new String[]{ - "-d", OUTPUT_DIR, "-linksource", "-sourcepath", SRC_DIR, + "-d", OUTPUT_DIR + "-2", "-linksource", "-sourcepath", SRC_DIR, "pkg" }; diff -r a77941f17614 -r 0d1f816217dc langtools/test/com/sun/javadoc/testWarnings/TestWarnings.java --- a/langtools/test/com/sun/javadoc/testWarnings/TestWarnings.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/test/com/sun/javadoc/testWarnings/TestWarnings.java Wed Jul 05 19:39:35 2017 +0200 @@ -40,11 +40,11 @@ //Javadoc arguments. private static final String[] ARGS = new String[] { - "-Xdoclint:none", "-d", OUTPUT_DIR, "-sourcepath", SRC_DIR, "pkg" + "-Xdoclint:none", "-d", OUTPUT_DIR + "-1", "-sourcepath", SRC_DIR, "pkg" }; private static final String[] ARGS2 = new String[] { - "-Xdoclint:none", "-d", OUTPUT_DIR, "-private", "-sourcepath", SRC_DIR, + "-Xdoclint:none", "-d", OUTPUT_DIR + "-2", "-private", "-sourcepath", SRC_DIR, "pkg" }; @@ -78,7 +78,6 @@ public static void main(String[] args) { TestWarnings tester = new TestWarnings(); tester.run(ARGS, TEST, NEGATED_TEST); - tester.run(ARGS, TEST, NEGATED_TEST); tester.run(ARGS2, TEST2, NO_TEST); tester.printSummary(); } diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/DefiniteAssignment/T8039026.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/DefiniteAssignment/T8039026.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,21 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8039026 + * @summary Definitely unassigned field can be accessed + * @compile/fail/ref=T8039026.out -XDrawDiagnostics T8039026.java + */ + +public class T8039026 { + final int x,y,z; + final int a = this.y; // <- error + { + int b = true ? this.x : 0; // <- error + System.out.println(this.x); // <- error + this.y = 1; + } + T8039026() { + this.x = 1; // <- no error! + this.y = 1; // <- error + this.z = this.x; // <- no error + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/DefiniteAssignment/T8039026.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/DefiniteAssignment/T8039026.out Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,4 @@ +T8039026.java:10:23: compiler.err.var.might.not.have.been.initialized: y +T8039026.java:12:28: compiler.err.var.might.not.have.been.initialized: x +T8039026.java:18:13: compiler.err.var.might.already.be.assigned: y +3 errors diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/Paths/AbsolutePathTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/Paths/AbsolutePathTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8030046 + * @summary javac incorrectly handles absolute paths in manifest classpath + * @author govereau + * @library /tools/javac/lib + * @build ToolBox + * @run main AbsolutePathTest + */ + +import java.io.File; + +public class AbsolutePathTest { + public static void main(String... cmdline) throws Exception { + // compile test.Test + ToolBox.JavaToolArgs args = new ToolBox.JavaToolArgs(); + args.appendArgs("-d", "."); // this is needed to get the classfiles in test + ToolBox.javac(args.setSources("package test; public class Test{}")); + + // build test.jar containing test.Test + // we need the jars in a directory different from the working + // directory to trigger the bug. I will reuse test/ + ToolBox.jar("cf", "test/test.jar", "test/Test.class"); + + // build second jar in test directory using + // an absolute path reference to the first jar + String path = new File("test/test.jar").getAbsolutePath(); + ToolBox.mkManifestWithClassPath(null, path); + ToolBox.jar("cfm", "test/test2.jar", "MANIFEST.MF"); + + // this should not fail + args.appendArgs("-cp", "."); + ToolBox.javac(args.setSources("import test.Test; class Test2 {}")); + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/T8029102/WarnSerializableLambdaTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/T8029102/WarnSerializableLambdaTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,241 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8029102 + * @summary Enhance compiler warnings for Lambda + * Checks that the warning for accessing non public members of a class is + * fired correctly. + * @compile/fail/ref=WarnSerializableLambdaTest.out -XDrawDiagnostics -Werror -XDwarnOnAccessToSensitiveMembers WarnSerializableLambdaTest.java + */ + +import java.io.Serializable; + +public class WarnSerializableLambdaTest { + + void warnLambda() throws Exception { + SAM t3 = (SAM & Serializable)WarnSerializableLambdaTest::packageClassMethod; + SAM t4 = (SAM & Serializable)WarnSerializableLambdaTest::protectedClassMethod; + SAM t5 = (SAM & Serializable)WarnSerializableLambdaTest::privateClassMethod; + + WarnSerializableLambdaTest test = new WarnSerializableLambdaTest(); + SAM t6 = (SAM & Serializable)test::packageInstanceMethod; + SAM t7 = (SAM & Serializable)test::protectedInstanceMethod; + SAM t8 = (SAM & Serializable)test::privateInstanceMethod; + + SAM t9 = (SAM & Serializable) c -> { + + WarnSerializableLambdaTest.staticPackageField = ""; + WarnSerializableLambdaTest.staticProtectedField = ""; + WarnSerializableLambdaTest.staticPrivateField = ""; + + packageField = ""; + protectedField = ""; + privateField = ""; + + WarnSerializableLambdaTest.packageClassMethod(null); + WarnSerializableLambdaTest.protectedClassMethod(null); + WarnSerializableLambdaTest.privateClassMethod(null); + + packageInstanceMethod(null); + protectedInstanceMethod(null); + privateInstanceMethod(null); + + PrivateClass.effectivelyNonPublicStaticField = ""; + PrivateClass.effectivelyNonPublicClassMethod(); + + PrivateClass p = new PrivateClass(); + p.effectivelyNonPublicInstanceField = ""; + p.effectivelyNonPublicInstanceMethod(); + + return null; + }; + } + + private void warnAnoInnerClass() throws Exception { + new SerializableDesc() { + public void m(Object param) throws Exception { + WarnSerializableLambdaTest.staticPackageField = ""; + WarnSerializableLambdaTest.staticProtectedField = ""; + WarnSerializableLambdaTest.staticPrivateField = ""; + + packageField = ""; + protectedField = ""; + privateField = ""; + + WarnSerializableLambdaTest.packageClassMethod(null); + WarnSerializableLambdaTest.protectedClassMethod(null); + WarnSerializableLambdaTest.privateClassMethod(null); + + packageInstanceMethod(null); + protectedInstanceMethod(null); + privateInstanceMethod(null); + + PrivateClass.effectivelyNonPublicStaticField = ""; + PrivateClass.effectivelyNonPublicClassMethod(); + + PrivateClass p = new PrivateClass(); + p.effectivelyNonPublicInstanceField = ""; + p.effectivelyNonPublicInstanceMethod(); + } + }; + } + + void dontWarnLambda() throws Exception { + SAM t1 = (SAM & Serializable)WarnSerializableLambdaTest::publicClassMethod; + + WarnSerializableLambdaTest test = new WarnSerializableLambdaTest(); + SAM t2 = (SAM & Serializable)test::publicInstanceMethod; + + int[] buffer = {0}; + + SAM t3 = (SAM & Serializable) param -> { + Object localVar; + localVar = null; + param = null; + + WarnSerializableLambdaTest.staticPublicField = ""; + publicField = ""; + WarnSerializableLambdaTest.publicClassMethod(null); + publicInstanceMethod(null); + + PublicClass.effectivelyPublicStaticField = ""; + PublicClass.effectivelyPublicClassMethod(); + + PublicClass p = new PublicClass(); + p.effectivelyPublicInstanceField = ""; + p.effectivelyPublicInstanceMethod(); + + int l = buffer.length; + + return null; + }; + } + + private void dontWarnAnoInnerClass() throws Exception { + final int[] buffer = {0}; + new SerializableDesc() { + public void m(Object param) throws Exception { + Object localVar; + localVar = null; + param = null; + + WarnSerializableLambdaTest.staticPublicField = ""; + publicField = ""; + WarnSerializableLambdaTest.publicClassMethod(null); + publicInstanceMethod(null); + + PublicClass.effectivelyPublicStaticField = ""; + PublicClass.effectivelyPublicClassMethod(); + + PublicClass p = new PublicClass(); + p.effectivelyPublicInstanceField = ""; + p.effectivelyPublicInstanceMethod(); + + int l = buffer.length; + } + }; + } + + enum WarnEnum { + A { + public void m() throws Exception { + WarnSerializableLambdaTest.staticPackageField = ""; + WarnSerializableLambdaTest.staticProtectedField = ""; + WarnSerializableLambdaTest.staticPrivateField = ""; + + WarnSerializableLambdaTest test = + new WarnSerializableLambdaTest(); + + test.packageField = ""; + test.protectedField = ""; + test.privateField = ""; + + WarnSerializableLambdaTest.packageClassMethod(null); + WarnSerializableLambdaTest.protectedClassMethod(null); + WarnSerializableLambdaTest.privateClassMethod(null); + + test.packageInstanceMethod(null); + test.protectedInstanceMethod(null); + test.privateInstanceMethod(null); + + PrivateClass.effectivelyNonPublicStaticField = ""; + PrivateClass.effectivelyNonPublicClassMethod(); + + PrivateClass p = new PrivateClass(); + p.effectivelyNonPublicInstanceField = ""; + p.effectivelyNonPublicInstanceMethod(); + } + }; + + public void m() throws Exception {} + } + + static String staticPackageField; + static private String staticPrivateField; + static protected String staticProtectedField; + static public String staticPublicField; + + String packageField; + private String privateField; + protected String protectedField; + public String publicField; + + static Object packageClassMethod(String s) { + return null; + } + + static private Object privateClassMethod(String s) { + return null; + } + + static protected Object protectedClassMethod(String s) { + return null; + } + + static public Object publicClassMethod(String s) { + return null; + } + + Object packageInstanceMethod(String s) { + return null; + } + + protected Object protectedInstanceMethod(String s) { + return null; + } + + private Object privateInstanceMethod(String s) { + return null; + } + + public Object publicInstanceMethod(String s) { + return null; + } + + interface SAM { + Object apply(String s) throws Exception; + } + + interface SAM2 { + Object apply(String arg1, String arg2); + } + + class SerializableDesc implements Serializable { + public void m(Object param) throws Exception {} + } + + static private class PrivateClass { + static public String effectivelyNonPublicStaticField; + public String effectivelyNonPublicInstanceField; + + static public void effectivelyNonPublicClassMethod() {} + public void effectivelyNonPublicInstanceMethod() {} + } + + static public class PublicClass { + static public String effectivelyPublicStaticField; + public String effectivelyPublicInstanceField; + + static public void effectivelyPublicClassMethod() {} + public void effectivelyPublicInstanceMethod() {} + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/T8029102/WarnSerializableLambdaTest.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/T8029102/WarnSerializableLambdaTest.out Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,57 @@ +WarnSerializableLambdaTest.java:15:38: compiler.warn.access.to.sensitive.member.from.serializable.element: packageClassMethod(java.lang.String) +WarnSerializableLambdaTest.java:16:38: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedClassMethod(java.lang.String) +WarnSerializableLambdaTest.java:17:38: compiler.warn.access.to.sensitive.member.from.serializable.element: privateClassMethod(java.lang.String) +WarnSerializableLambdaTest.java:20:38: compiler.warn.access.to.sensitive.member.from.serializable.element: packageInstanceMethod(java.lang.String) +WarnSerializableLambdaTest.java:21:38: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedInstanceMethod(java.lang.String) +WarnSerializableLambdaTest.java:22:38: compiler.warn.access.to.sensitive.member.from.serializable.element: privateInstanceMethod(java.lang.String) +WarnSerializableLambdaTest.java:26:39: compiler.warn.access.to.sensitive.member.from.serializable.element: staticPackageField +WarnSerializableLambdaTest.java:27:39: compiler.warn.access.to.sensitive.member.from.serializable.element: staticProtectedField +WarnSerializableLambdaTest.java:28:39: compiler.warn.access.to.sensitive.member.from.serializable.element: staticPrivateField +WarnSerializableLambdaTest.java:30:13: compiler.warn.access.to.sensitive.member.from.serializable.element: packageField +WarnSerializableLambdaTest.java:31:13: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedField +WarnSerializableLambdaTest.java:32:13: compiler.warn.access.to.sensitive.member.from.serializable.element: privateField +WarnSerializableLambdaTest.java:34:39: compiler.warn.access.to.sensitive.member.from.serializable.element: packageClassMethod(java.lang.String) +WarnSerializableLambdaTest.java:35:39: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedClassMethod(java.lang.String) +WarnSerializableLambdaTest.java:36:39: compiler.warn.access.to.sensitive.member.from.serializable.element: privateClassMethod(java.lang.String) +WarnSerializableLambdaTest.java:38:13: compiler.warn.access.to.sensitive.member.from.serializable.element: packageInstanceMethod(java.lang.String) +WarnSerializableLambdaTest.java:39:13: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedInstanceMethod(java.lang.String) +WarnSerializableLambdaTest.java:40:13: compiler.warn.access.to.sensitive.member.from.serializable.element: privateInstanceMethod(java.lang.String) +WarnSerializableLambdaTest.java:42:25: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicStaticField +WarnSerializableLambdaTest.java:43:25: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicClassMethod() +WarnSerializableLambdaTest.java:46:14: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicInstanceField +WarnSerializableLambdaTest.java:47:14: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicInstanceMethod() +WarnSerializableLambdaTest.java:56:43: compiler.warn.access.to.sensitive.member.from.serializable.element: staticPackageField +WarnSerializableLambdaTest.java:57:43: compiler.warn.access.to.sensitive.member.from.serializable.element: staticProtectedField +WarnSerializableLambdaTest.java:58:43: compiler.warn.access.to.sensitive.member.from.serializable.element: staticPrivateField +WarnSerializableLambdaTest.java:60:17: compiler.warn.access.to.sensitive.member.from.serializable.element: packageField +WarnSerializableLambdaTest.java:61:17: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedField +WarnSerializableLambdaTest.java:62:17: compiler.warn.access.to.sensitive.member.from.serializable.element: privateField +WarnSerializableLambdaTest.java:64:43: compiler.warn.access.to.sensitive.member.from.serializable.element: packageClassMethod(java.lang.String) +WarnSerializableLambdaTest.java:65:43: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedClassMethod(java.lang.String) +WarnSerializableLambdaTest.java:66:43: compiler.warn.access.to.sensitive.member.from.serializable.element: privateClassMethod(java.lang.String) +WarnSerializableLambdaTest.java:68:17: compiler.warn.access.to.sensitive.member.from.serializable.element: packageInstanceMethod(java.lang.String) +WarnSerializableLambdaTest.java:69:17: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedInstanceMethod(java.lang.String) +WarnSerializableLambdaTest.java:70:17: compiler.warn.access.to.sensitive.member.from.serializable.element: privateInstanceMethod(java.lang.String) +WarnSerializableLambdaTest.java:72:29: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicStaticField +WarnSerializableLambdaTest.java:73:29: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicClassMethod() +WarnSerializableLambdaTest.java:76:18: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicInstanceField +WarnSerializableLambdaTest.java:77:18: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicInstanceMethod() +WarnSerializableLambdaTest.java:141:43: compiler.warn.access.to.sensitive.member.from.serializable.element: staticPackageField +WarnSerializableLambdaTest.java:142:43: compiler.warn.access.to.sensitive.member.from.serializable.element: staticProtectedField +WarnSerializableLambdaTest.java:143:43: compiler.warn.access.to.sensitive.member.from.serializable.element: staticPrivateField +WarnSerializableLambdaTest.java:148:21: compiler.warn.access.to.sensitive.member.from.serializable.element: packageField +WarnSerializableLambdaTest.java:149:21: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedField +WarnSerializableLambdaTest.java:150:21: compiler.warn.access.to.sensitive.member.from.serializable.element: privateField +WarnSerializableLambdaTest.java:152:43: compiler.warn.access.to.sensitive.member.from.serializable.element: packageClassMethod(java.lang.String) +WarnSerializableLambdaTest.java:153:43: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedClassMethod(java.lang.String) +WarnSerializableLambdaTest.java:154:43: compiler.warn.access.to.sensitive.member.from.serializable.element: privateClassMethod(java.lang.String) +WarnSerializableLambdaTest.java:156:21: compiler.warn.access.to.sensitive.member.from.serializable.element: packageInstanceMethod(java.lang.String) +WarnSerializableLambdaTest.java:157:21: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedInstanceMethod(java.lang.String) +WarnSerializableLambdaTest.java:158:21: compiler.warn.access.to.sensitive.member.from.serializable.element: privateInstanceMethod(java.lang.String) +WarnSerializableLambdaTest.java:160:29: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicStaticField +WarnSerializableLambdaTest.java:161:29: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicClassMethod() +WarnSerializableLambdaTest.java:164:18: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicInstanceField +WarnSerializableLambdaTest.java:165:18: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicInstanceMethod() +- compiler.err.warnings.and.werror +1 error +54 warnings diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/T8029102/WarnSerializableLambdaTestb.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/T8029102/WarnSerializableLambdaTestb.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,56 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8029102 + * @summary Enhance compiler warnings for Lambda + * Checks that the warning for accessing non public members of a class is + * fired correctly. + * @compile/fail/ref=WarnSerializableLambdaTestb.out -XDrawDiagnostics -Werror -XDwarnOnAccessToSensitiveMembers WarnSerializableLambdaTestb.java + */ + +import java.io.Serializable; + +public class WarnSerializableLambdaTestb { + public void foo(Secret1 secret) { + Object o = (Runnable & java.io.Serializable) () -> { secret.test(); }; + } + + public void bar(Secret2 secret) { + Object o = (Runnable & java.io.Serializable) () -> { secret.test(); }; + } + + private class Secret1 { + public void test() {} + } + + static private class Secret2 { + public void test() {} + } + + class TestInner { + private int j = 0; + void m() { + Serializable s = new Serializable() { + int i; + void m() { + i = 0; // don't warn + System.out.println(j); //warn + } + }; + } + } + + class TestInner2 { + class W implements Serializable { + public int p = 0; + class I { + public int r = 0; + class K implements Serializable { + void m() { + p = 1; // don't warn owner is serializable + r = 2; // warn owner is not serializable + } + } + } + } + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/T8029102/WarnSerializableLambdaTestb.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/T8029102/WarnSerializableLambdaTestb.out Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,7 @@ +WarnSerializableLambdaTestb.java:14:69: compiler.warn.access.to.sensitive.member.from.serializable.element: test() +WarnSerializableLambdaTestb.java:18:69: compiler.warn.access.to.sensitive.member.from.serializable.element: test() +WarnSerializableLambdaTestb.java:36:40: compiler.warn.access.to.sensitive.member.from.serializable.element: j +WarnSerializableLambdaTestb.java:50:25: compiler.warn.access.to.sensitive.member.from.serializable.element: r +- compiler.err.warnings.and.werror +1 error +4 warnings diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary local variable table attribute test. + * @bug 8040097 + * @library /tools/javac/lib ../lib + * @build LocalVariableTestBase TestBase InMemoryFileManager ToolBox + * @compile -g LocalVariableTableTest.java + * @run main LocalVariableTableTest + */ + +import com.sun.tools.classfile.Code_attribute; +import com.sun.tools.classfile.LocalVariableTable_attribute; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.toList; + +public class LocalVariableTableTest extends LocalVariableTestBase { + + public LocalVariableTableTest(Class clazz) { + super(clazz); + } + + public static void main(String[] args) throws IOException { + new LocalVariableTableTest(LocalVariableTableTest.class).test(); + } + + @ExpectedLocals(name = "l", type = "D") + @ExpectedLocals(name = "i", type = "J") + public static void onlyTwoCellParameters(double l, long i) { + } + + @ExpectedLocals(name = "l", type = "D") + @ExpectedLocals(name = "dl", type = "D") + @ExpectedLocals(name = "i", type = "J") + @ExpectedLocals(name = "il", type = "J") + @ExpectedLocals(name = "d", type = "J") + @ExpectedLocals(name = "ll", type = "J") + public static void onlyTwoCellLocals(double l, long i, long d) { + double dl = 1.1; + long il = 1; + long ll = 1; + } + + @Override + protected List getVariableTables(Code_attribute codeAttribute) { + return Stream.of(codeAttribute.attributes.attrs) + .filter(at -> at instanceof LocalVariableTable_attribute) + .map(at -> (LocalVariableTable_attribute) at) + .map((t) -> new LocalVariableTable(t)).collect(toList()); + } + + @ExpectedLocals(name = "l", type = "J") + @ExpectedLocals(name = "i", type = "I") + @ExpectedLocals(name = "d", type = "D") + @ExpectedLocals(name = "ll", type = "J") + @ExpectedLocals(name = "obj", type = "Ljava/lang/Object;") + @ExpectedLocals(name = "dd", type = "D") + @ExpectedLocals(name = "bb", type = "B") + @ExpectedLocals(name = "this", type = "LLocalVariableTableTest;") + public double longDoubleOverlap(long l, int i, double d) { + long ll = 1L; + Object obj = 2; + double dd = 3.0; + byte bb = 0; + return l + i + d + ll + Integer.valueOf(obj.toString()) + dd + bb; + } + + @ExpectedLocals(name = "bool", type = "Z") + @ExpectedLocals(name = "b", type = "B") + @ExpectedLocals(name = "ch", type = "C") + @ExpectedLocals(name = "sh", type = "S") + @ExpectedLocals(name = "i", type = "I") + @ExpectedLocals(name = "l", type = "J") + @ExpectedLocals(name = "d", type = "D") + @ExpectedLocals(name = "f", type = "F") + @ExpectedLocals(name = "ref", type = "Ljava/lang/Integer;") + @ExpectedLocals(name = "arr", type = "[Ljava/lang/Integer;") + @ExpectedLocals(name = "this", type = "LLocalVariableTableTest;") + public void allTypesWithoutParameters() { + boolean bool = true; + byte b = 0x1; + char ch = 'a'; + short sh = 1_1; + int i = -2; + long l = 1L; + float f = 1.1f; + double d = 0.1; + Integer ref = 2; + Integer[] arr = null; + } + + @ExpectedLocals(name = "bool", type = "Z") + @ExpectedLocals(name = "b", type = "B") + @ExpectedLocals(name = "ch", type = "C") + @ExpectedLocals(name = "sh", type = "S") + @ExpectedLocals(name = "i", type = "I") + @ExpectedLocals(name = "l", type = "J") + @ExpectedLocals(name = "d", type = "D") + @ExpectedLocals(name = "f", type = "F") + @ExpectedLocals(name = "ref", type = "Ljava/lang/Integer;") + @ExpectedLocals(name = "this", type = "LLocalVariableTableTest;") + public void allTypesWithParameters(boolean bool, byte b, char ch) { + short sh = 1_1; + int i = -2; + long l = 1L; + float f = 1.1f; + double d = 0.1; + Integer ref = 2; + } + + @ExpectedLocals(name = "list", type = "Ljava/util/List;") + @ExpectedLocals(name = "list2", type = "[Ljava/util/List;") + @ExpectedLocals(name = "p", type = "Ljava/lang/Object;") + @ExpectedLocals(name = "k", type = "Ljava/lang/Integer;") + @ExpectedLocals(name = "i", type = "I") + @ExpectedLocals(name = "this", type = "LLocalVariableTableTest;") + public , P, K extends Integer> void genericType(K k) { + T list = null; + int i = 0; + P p = null; + List[] list2 = null; + } + + @ExpectedLocals(name = "this", type = "LLocalVariableTableTest;") + @ExpectedLocals(name = "inWhile", type = "I") + @ExpectedLocals(name = "inTry", type = "D") + @ExpectedLocals(name = "inSync", type = "F") + @ExpectedLocals(name = "inDo", type = "B") + @ExpectedLocals(name = "inSwitch", type = "S") + @ExpectedLocals(name = "inFor", type = "J") + @ExpectedLocals(name = "s", type = "Ljava/util/stream/Stream;") + public void deepScope() { + { + while (true) { + int inWhile = 0; + for (long inFor : Arrays.asList(0)) { + try (Stream s = Stream.of(0)) { + double inTry = 0.0; + synchronized (this) { + float inSync = -1.0f; + do { + byte inDo = 0; + switch (1) { + default: + short inSwitch = 100; + } + } while (true); + } + } + } + } + } + } + + @ExpectedLocals(name = "i", type = "I", scope = 0) + @ExpectedLocals(name = "i", type = "J", scope = 1) + public void reuseByLong() { + { + int i = 0; + } + { + long i = 1; + } + } + + class LocalVariableTable implements VariableTable { + + final LocalVariableTable_attribute att; + + public LocalVariableTable(LocalVariableTable_attribute att) { + this.att = att; + } + + @Override + public int localVariableTableLength() { + return att.local_variable_table_length; + } + + @Override + public List entries() { + return Stream.of(att.local_variable_table).map(LocalVariableTableEntry::new).collect(toList()); + } + + @Override + public int attributeLength() { + return att.attribute_length; + } + + private class LocalVariableTableEntry implements Entry { + + final LocalVariableTable_attribute.Entry entry; + + private LocalVariableTableEntry(LocalVariableTable_attribute.Entry entry) { + this.entry = entry; + } + + @Override + public int index() { + return entry.index; + } + + @Override + public int startPC() { + return entry.start_pc; + } + + @Override + public int length() { + return entry.length; + } + + @Override + public String name() { + return getString(entry.name_index); + } + + @Override + public String type() { + return getString(entry.descriptor_index); + } + + @Override + public String toString() { + return dump(); + } + } + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTestBase.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.classfile.*; + +import java.io.IOException; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static java.lang.String.format; +import static java.util.stream.Collectors.*; + + +public abstract class LocalVariableTestBase extends TestBase { + public static final int DEFAULT_SCOPE = 0; + private final ClassFile classFile; + private final Class clazz; + + protected abstract List getVariableTables(Code_attribute codeAttribute); + + public LocalVariableTestBase(Class clazz) { + this.clazz = clazz; + try { + this.classFile = ClassFile.read(getClassFile(clazz)); + } catch (IOException | ConstantPoolException e) { + throw new IllegalArgumentException("Can't read classfile for specified class", e); + } + } + + + //info in the LocalVariableTable attribute is compared against expected info stored in annotations + public void test() throws IOException { + List testMethods = Stream.of(clazz.getDeclaredMethods()) + .filter(m -> m.getAnnotationsByType(ExpectedLocals.class).length > 0) + .collect(toList()); + int failed = 0; + for (java.lang.reflect.Method method : testMethods) { + try { + Map expectedLocals2Types = new HashMap<>(); + Map sig2scope = new HashMap<>(); + for (ExpectedLocals anno : method.getDeclaredAnnotationsByType(ExpectedLocals.class)) { + expectedLocals2Types.put(anno.name(), anno.type()); + sig2scope.put(anno.name() + "&" + anno.type(), anno.scope()); + } + + test(method.getName(), expectedLocals2Types, sig2scope); + } catch (AssertionFailedException ex) { + System.err.printf("Test %s failed.%n", method.getName()); + ex.printStackTrace(); + failed++; + } + } + if (failed > 0) + throw new RuntimeException(format("Failed %d out of %d. See logs.", failed, testMethods.size())); + } + + public void test(String methodName, Map expectedLocals2Types, Map sig2scope) + throws IOException { + + for (Method m : classFile.methods) { + String mName = getString(m.name_index); + if (methodName.equals(mName)) { + System.out.println("Testing local variable table in method " + mName); + Code_attribute code_attribute = (Code_attribute) m.attributes.get(Attribute.Code); + + List variableTables = getVariableTables(code_attribute); + generalLocalVariableTableCheck(variableTables); + + List entries = variableTables.stream() + .flatMap(table -> table.entries().stream()) + .collect(toList()); + + generalEntriesCheck(entries, code_attribute); + assertIndexesAreUnique(entries, sig2scope); + checkNamesAndTypes(entries, expectedLocals2Types); + checkDoubleAndLongIndexes(entries, sig2scope, code_attribute.max_locals); + } + } + } + + private void generalLocalVariableTableCheck(List variableTables) { + for (VariableTable localTable : variableTables) { + //only one per variable. + assertEquals(localTable.localVariableTableLength(), + localTable.entries().size(), "Incorrect local variable table length"); + //attribute length is offset(line_number_table_length) + element_size*element_count + assertEquals(localTable.attributeLength(), + 2 + (5 * 2) * localTable.localVariableTableLength(), "Incorrect attribute length"); + } + } + + private void generalEntriesCheck(List entries, Code_attribute code_attribute) { + for (VariableTable.Entry e : entries) { + assertTrue(e.index() >= 0 && e.index() < code_attribute.max_locals, + "Index " + e.index() + " out of variable array. Size of array is " + code_attribute.max_locals); + assertTrue(e.startPC() >= 0, "StartPC is less then 0. StartPC = " + e.startPC()); + assertTrue(e.length() >= 0, "Length is less then 0. Length = " + e.length()); + assertTrue(e.startPC() + e.length() <= code_attribute.code_length, + format("StartPC+Length > code length.%n" + + "%s%n" + + "code_length = %s" + , e, code_attribute.code_length)); + } + } + + private void checkNamesAndTypes(List entries, + Map expectedLocals2Types) { + Map> actualNames2Types = entries.stream() + .collect( + groupingBy(VariableTable.Entry::name, + mapping(VariableTable.Entry::type, toList()))); + for (Map.Entry name2type : expectedLocals2Types.entrySet()) { + String name = name2type.getKey(); + String type = name2type.getValue(); + + assertTrue(actualNames2Types.containsKey(name), + format("There is no record for local variable %s%nEntries: %s", name, entries)); + + assertTrue(actualNames2Types.get(name).contains(type), + format("Types are different for local variable %s%nExpected type: %s%nActual type: %s", + name, type, actualNames2Types.get(name))); + } + } + + + private void assertIndexesAreUnique(Collection entries, Map scopes) { + //check every scope separately + Map> entriesByScope = groupByScope(entries, scopes); + for (Map.Entry> mapEntry : entriesByScope.entrySet()) { + mapEntry.getValue().stream() + .collect(groupingBy(VariableTable.Entry::index)) + .entrySet() + .forEach(e -> + assertTrue(e.getValue().size() == 1, + "Multiple variables point to the same index in common scope. " + e.getValue())); + } + + } + + private void checkDoubleAndLongIndexes(Collection entries, + Map scopes, int maxLocals) { + //check every scope separately + Map> entriesByScope = groupByScope(entries, scopes); + for (List entryList : entriesByScope.values()) { + Map index2Entry = entryList.stream() + .collect(toMap(VariableTable.Entry::index, e -> e)); + + entryList.stream() + .filter(e -> "J".equals(e.type()) || "D".equals(e.type())) + .forEach(e -> { + assertTrue(e.index() + 1 < maxLocals, + format("Index %s is out of variable array. Long and double occupy 2 cells." + + " Size of array is %d", e.index() + 1, maxLocals)); + assertTrue(!index2Entry.containsKey(e.index() + 1), + format("An entry points to the second cell of long/double entry.%n%s%n%s", e, + index2Entry.get(e.index() + 1))); + }); + } + } + + private Map> groupByScope( + Collection entries, Map scopes) { + return entries.stream().collect(groupingBy(e -> scopes.getOrDefault(e.name() + "&" + e.type(), DEFAULT_SCOPE))); + } + + protected String getString(int i) { + try { + return classFile.constant_pool.getUTF8Info(i).value; + } catch (ConstantPool.InvalidIndex | ConstantPool.UnexpectedEntry ex) { + ex.printStackTrace(); + throw new AssertionFailedException("Issue while reading constant pool"); + } + } + + + interface VariableTable { + + int localVariableTableLength(); + + List entries(); + + int attributeLength(); + + interface Entry { + + int index(); + + int startPC(); + + int length(); + + String name(); + + String type(); + + default String dump() { + return format("Entry{" + + "%n name = %s" + + "%n type = %s" + + "%n index = %d" + + "%n startPC = %d" + + "%n length = %d" + + "%n}", name(), type(), index(), startPC(), length()); + } + } + } + + @Retention(RetentionPolicy.RUNTIME) + @Repeatable(Container.class) + @interface ExpectedLocals { + String name(); + + String type(); + + //variables from different scopes can share local variable table index and/or name. + int scope() default DEFAULT_SCOPE; + } + + @Retention(RetentionPolicy.RUNTIME) + @interface Container { + ExpectedLocals[] value(); + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary local variable type table attribute test. + * @bug 8040097 + * @library /tools/javac/lib ../lib + * @build LocalVariableTestBase TestBase InMemoryFileManager ToolBox + * @compile -g LocalVariableTypeTableTest.java + * @run main LocalVariableTypeTableTest + */ + +import com.sun.tools.classfile.Code_attribute; +import com.sun.tools.classfile.LocalVariableTypeTable_attribute; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.toList; + +public class LocalVariableTypeTableTest extends LocalVariableTestBase { + + public LocalVariableTypeTableTest(Class clazz) { + super(clazz); + } + + public static void main(String[] args) throws IOException { + new LocalVariableTypeTableTest(LocalVariableTypeTableTest.class).test(); + } + + @Override + protected List getVariableTables(Code_attribute codeAttribute) { + return Stream.of(codeAttribute.attributes.attrs) + .filter(at -> at instanceof LocalVariableTypeTable_attribute) + .map(at -> (LocalVariableTypeTable_attribute) at) + .map(LocalVariableTypeTable::new).collect(toList()); + } + + @ExpectedLocals(name = "list", type = "TT;") + @ExpectedLocals(name = "p", type = "[TP;") + @ExpectedLocals(name = "k", type = "TK;") + @ExpectedLocals(name = "c1", type = "Ljava/util/Collection<-Ljava/lang/Integer;>;") + @ExpectedLocals(name = "c2", type = "Ljava/util/Collection<*>;") + @ExpectedLocals(name = "c3", type = "Ljava/util/Collection<+TE;>;") + public , P, K extends Integer, E extends Supplier & Runnable> + void genericTypeWithParametersOnly(K k, T list, P[] p, + Collection c1, + Collection c2, Collection c3) { + } + + @ExpectedLocals(name = "list", type = "TT;") + @ExpectedLocals(name = "p", type = "[TP;") + @ExpectedLocals(name = "k", type = "TK;") + @ExpectedLocals(name = "c1", type = "Ljava/util/Collection<-Ljava/lang/Integer;>;") + @ExpectedLocals(name = "c2", type = "Ljava/util/Collection<*>;") + @ExpectedLocals(name = "c3", type = "Ljava/util/Collection<+TE;>;") + public , P, K extends Integer, E extends Supplier & Runnable> + void genericType(K k, T list, P[] p) { + Collection c1 = null; + Collection c2 = null; + Collection c3 = null; + } + + @ExpectedLocals(name = "list", type = "TT;") + @ExpectedLocals(name = "p", type = "[[TP;") + public , P, K extends Integer> void genericTypeWithoutParameters() { + T list = null; + list.add(1); + int i = 0; + P[][] p = null; + } + + @ExpectedLocals(name = "this", type = "LLocalVariableTypeTableTest;") + public void genericThis() { + } + + @ExpectedLocals(name = "this", type = "LLocalVariableTypeTableTest;") + @ExpectedLocals(name = "inWhile", type = "TTHIS;") + @ExpectedLocals(name = "inTry", type = "TTHIS;") + @ExpectedLocals(name = "inSync", type = "TTHIS;") + @ExpectedLocals(name = "inDo", type = "TTHIS;") + @ExpectedLocals(name = "inSwitch", type = "TTHIS;") + @ExpectedLocals(name = "inFor", type = "LLocalVariableTypeTableTest<-TTHIS;>;") + @ExpectedLocals(name = "s", type = "Ljava/util/stream/Stream<+Ljava/lang/Integer;>;") + public void deepScope() { + { + while (true) { + THIS inWhile = null; + for (LocalVariableTypeTableTest inFor : Arrays.asList(this)) { + try (Stream s = Stream.of(0)) { + THIS inTry = null; + synchronized (this) { + THIS inSync = null; + do { + THIS inDo = null; + switch (1) { + default: + THIS inSwitch = null; + } + } while (true); + } + } + } + } + } + } + + @ExpectedLocals(name = "i", type = "TTHIS;", scope = 0) + @ExpectedLocals(name = "i", type = "Ljava/util/List;", scope = 1) + public void reuseByLong() { + { + THIS i = null; + } + { + List i = null; + } + } + + class LocalVariableTypeTable implements VariableTable { + + final LocalVariableTypeTable_attribute att; + + + public LocalVariableTypeTable(LocalVariableTypeTable_attribute att) { + this.att = att; + } + + @Override + public int localVariableTableLength() { + return att.local_variable_table_length; + } + + @Override + public List entries() { + return Stream.of(att.local_variable_table).map(LocalVariableTypeTableEntry::new).collect(toList()); + } + + @Override + public int attributeLength() { + return att.attribute_length; + } + + private class LocalVariableTypeTableEntry implements Entry { + + final LocalVariableTypeTable_attribute.Entry entry; + + private LocalVariableTypeTableEntry(LocalVariableTypeTable_attribute.Entry entry) { + this.entry = entry; + } + + @Override + public int index() { + return entry.index; + } + + @Override + public int startPC() { + return entry.start_pc; + } + + @Override + public int length() { + return entry.length; + } + + @Override + public String name() { + return getString(entry.name_index); + } + + @Override + public String type() { + return getString(entry.signature_index); + } + + @Override + public String toString() { + return dump(); + } + } + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Stream; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.ToolProvider; + +import static java.lang.String.format; +import static java.util.Collections.emptyList; +import static java.util.stream.Collectors.toList; + +public class TestBase { + + public Map compile(String... sources) throws IOException, + CompilationException { + return compile(emptyList(), sources); + } + + /** + * @param options - compiler options + * @param sources + * @return map where key is className, value is corresponding ClassFile. + * @throws IOException + */ + public Map compile(List options, String... sources) throws IOException, + CompilationException { + + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + List src = Stream.of(sources).map(ToolBox.JavaSource::new).collect(toList()); + + try (InMemoryFileManager fileManager = new InMemoryFileManager(compiler.getStandardFileManager(null, null, null))) { + boolean success = compiler.getTask(null, fileManager, null, options, null, src).call(); + if (!success) throw new CompilationException("Compilation Error"); + return fileManager.getClasses(); + } + } + + public void assertEquals(Object actual, Object expected, String message) { + if (!Objects.equals(actual, expected)) + throw new AssertionFailedException(format("%s%nGot: %s, Expected: ", message, actual, expected)); + } + + public void assertNull(Object actual, String message) { + assertEquals(actual, null, message); + } + + public void assertNotNull(Object actual, String message) { + if (Objects.isNull(actual)) { + throw new AssertionFailedException(message + " : Expected not null value"); + } + } + + public void assertTrue(boolean actual, String message) { + assertEquals(actual, true, message); + } + + public File getSourceFile(String fileName) { + return new File(System.getProperty("test.src", "."), fileName); + } + + public File getClassFile(String fileName) { + return new File(System.getProperty("test.classes", TestBase.class.getResource(".").getPath()), fileName); + } + + public File getClassFile(Class clazz) { + return getClassFile(clazz.getName().replace(".", "/") + ".class"); + } + + public static class CompilationException extends Exception { + + public CompilationException(String message) { + super(message); + } + } + + public static class AssertionFailedException extends RuntimeException { + public AssertionFailedException(String message) { + super(message); + } + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/diags/examples/WarnSerializableLambda.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/diags/examples/WarnSerializableLambda.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.warn.access.to.sensitive.member.from.serializable.element +// options: -XDwarnOnAccessToSensitiveMembers + +import java.io.Serializable; + +public class WarnSerializableLambda { + interface SAM { + void apply(String s); + } + + private void m1() { + SAM s = (SAM & Serializable) c -> { + packageField = ""; + }; + } + + String packageField; +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTesta.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTesta.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8030741 + * @summary Inference: implement eager resolution of return types, consistent with JDK-8028800 + * @compile EagerReturnTypeResolutionTesta.java + */ + +public class EagerReturnTypeResolutionTesta { + + abstract class Test1{ + abstract S foo(S x, S y); + > void baz(Test1 a){} + + void bar(Test1 x, Test1 y){ + baz(foo(x, y)); + } + } + + abstract class Test2{ + abstract S foo(S x, S y); + abstract void baz(Test2 a); + + void bar(Test2 y, Test2 x){ + baz(foo(x, y)); + } + } + + abstract class Test3{ + abstract S foo(S x, S y); + , + S extends Number & Comparable> void baz(Test3 a){} + + void bar(Test3 x, Test3 y){ + baz(foo(x, y)); + } + } + + abstract class Test4 { + abstract class A0 {} + + abstract class A1 extends A0 {} + + abstract class A2 extends A0 {} + + abstract S foo(S x, S y); + abstract void baz(A0 a); + + void bar(A2 y, A1 x){ + baz(foo(x, y)); + } + } + +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,182 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8030741 + * @summary Inference: implement eager resolution of return types, consistent with JDK-8028800 + * @compile/fail/ref=EagerReturnTypeResolutionTestb.out -XDrawDiagnostics EagerReturnTypeResolutionTestb.java + * @author Dan Smith + */ + +import java.util.List; + +public class EagerReturnTypeResolutionTestb { + interface I {} + interface J extends I {} + interface K extends I {} + interface L extends I {} + + T lower(List l) { return null; } + T lower2(List l1, List l2) { return null; } + + T upper(List l) { return null; } + T upper2(List l1, List l2) { return null; } + + T eq(List l) { return null; } + T eq2(List l1, List l2) { return null; } + + void takeI(I i) {} + void takeIString(I i) {} + I iStringField; + + void takeLong(long arg) {} + long longField; + + void testSimpleCaptureOK(List> i1) { + takeI(lower(i1)); // ok* + takeI(eq(i1)); // ok* + takeI(upper(i1)); // ok, no capture + takeIString(upper(i1)); // ok + iStringField = upper(i1); // ok + } + + void testSimpleCaptureKO(List> i1) { + takeIString(lower(i1)); // ERROR + takeIString(eq(i1)); // ERROR + iStringField = lower(i1); // ERROR + iStringField = eq(i1); // ERROR + } + + void testMultiCaptureOK(List> i1, List> i2, List> i3, + List> j1, List> j2, List k1) { + /* Lines marked with JDK-8029002 should be uncommented once this bug is + * fixed + */ + takeI(lower2(i1, i2)); // ok* + takeI(lower2(i1, i3)); // ok* + takeI(upper2(i1, i3)); // ok, no capture* JDK-8029002 + + takeIString(upper2(i1, i3)); // ok, no capture + iStringField = upper2(i1, i3); // ok, no capture + + takeI(lower2(j1, j2)); // ok* + takeI(lower2(j1, k1)); // ok, no capture + takeI(upper2(j1, k1)); // ok, no capture* JDK-8029002 + + takeIString(lower2(j1, k1)); // ok, no capture + takeIString(upper2(j1, k1)); // ok, no capture + + iStringField = lower2(j1, k1); // ok, no capture + iStringField = upper2(j1, k1); // ok, no capture + takeI(lower2(j2, k1)); // ok* + } + + void testMultiCaptureKO(List> i1, List> i2, List> i3, + List> j1, List> j2, List k1) { + takeI(eq2(i1, i2)); // ERROR, bad bounds + takeI(upper2(i1, i2)); // ERROR, bad bounds + + takeIString(lower2(i1, i2)); // ERROR + takeIString(eq2(i1, i2)); // ERROR, bad bounds + takeIString(upper2(i1, i2)); // ERROR, bad bounds + + iStringField = lower2(i1, i2); // ERROR + iStringField = eq2(i1, i2); // ERROR, bad bounds + iStringField = upper2(i1, i2); // ERROR, bad bounds + + takeI(eq2(i1, i3)); // ERROR, bad bounds + takeIString(lower2(i1, i3)); // ERROR + takeIString(eq2(i1, i3)); // ERROR, bad bounds + + iStringField = lower2(i1, i3); // ERROR + iStringField = eq2(i1, i3); // ERROR, bad bounds + takeI(eq2(j1, j2)); // ERROR, bad bounds + takeI(upper2(j1, j2)); // ERROR, bad bounds + + takeIString(lower2(j1, j2)); // ERROR + takeIString(eq2(j1, j2)); // ERROR, bad bounds + takeIString(upper2(j1, j2)); // ERROR, bad bounds + + iStringField = lower2(j1, j2); // ERROR + iStringField = eq2(j1, j2); // ERROR, bad bounds + iStringField = upper2(j1, j2); // ERROR, bad bounds + + takeI(eq2(j1, k1)); // ERROR, bad bounds + takeIString(eq2(j1, k1)); // ERROR, bad bounds + iStringField = eq2(j1, k1); // ERROR, bad bounds + takeI(eq2(j2, k1)); // ERROR, bad bounds + takeI(upper2(j2, k1)); // ERROR, bad bounds; actual: no error, see JDK-8037474 + + takeIString(lower2(j2, k1)); // ERROR + takeIString(eq2(j2, k1)); // ERROR, bad bounds + takeIString(upper2(j2, k1)); // ERROR, bad bounds + + iStringField = lower2(j2, k1); // ERROR + iStringField = eq2(j2, k1); // ERROR, bad bounds + iStringField = upper2(j2, k1); // ERROR, bad bounds + } + + void testRawOK(List i1, List j1, List> l1) { + takeI(lower(i1)); // ok, unchecked + takeI(eq(i1)); // ok, unchecked + takeI(upper(i1)); // ok, no capture, not unchecked + + takeIString(lower(i1)); // ok, unchecked + takeIString(eq(i1)); // ok, unchecked + takeIString(upper(i1)); // ok, no capture, not unchecked + + iStringField = lower(i1); // ok, unchecked + iStringField = eq(i1); // ok, unchecked + iStringField = upper(i1); // ok, no capture, not unchecked + + takeI(lower(j1)); // ok, unchecked + takeI(eq(j1)); // ok, unchecked + takeI(upper(j1)); // bad bounds? -- spec is unclear + + takeIString(lower(j1)); // ok, unchecked + takeIString(eq(j1)); // ok, unchecked + takeIString(upper(j1)); // bad bounds? -- spec is unclear + + iStringField = lower(j1); // ok, unchecked + iStringField = eq(j1); // ok, unchecked + iStringField = upper(j1); // bad bounds? -- spec is unclear + + takeI(lower(l1)); // ok, unchecked + takeI(eq(l1)); // ok, unchecked + takeI(upper(l1)); // bad bounds? -- spec is unclear + + takeIString(lower(l1)); // ok, unchecked + takeIString(eq(l1)); // ok, unchecked + takeIString(upper(l1)); // bad bounds? -- spec is unclear + + iStringField = lower(l1); // ok, unchecked + iStringField = eq(l1); // ok, unchecked + iStringField = upper(l1); // bad bounds? -- spec is unclear + } + + void testPrimOK(List i1, List l1, List d1) { + takeLong(lower(i1)); // ok + takeLong(eq(i1)); // ok + takeLong(upper(i1)); // ok* + + longField = lower(i1); // ok + longField = eq(i1); // ok + longField = upper(i1); // ok* + + takeLong(lower(l1)); // ok + takeLong(eq(l1)); // ok + takeLong(upper(l1)); // ok + + longField = lower(l1); // ok + longField = eq(l1); // ok + longField = upper(l1); // ok + } + + void testPrimKO(List i1, List l1, List d1) { + takeLong(lower(d1)); // ERROR + takeLong(eq(d1)); // ERROR + takeLong(upper(d1)); // ERROR + + longField = lower(d1); // ERROR + longField = eq(d1); // ERROR + longField = upper(d1); // ERROR + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.out Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,45 @@ +EagerReturnTypeResolutionTestb.java:42:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:43:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:44:29: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:45:26: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:74:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) +EagerReturnTypeResolutionTestb.java:75:15: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:77:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I>>, EagerReturnTypeResolutionTestb.I,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:78:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) +EagerReturnTypeResolutionTestb.java:79:21: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:81:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I>>, EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:82:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) +EagerReturnTypeResolutionTestb.java:83:24: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:85:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) +EagerReturnTypeResolutionTestb.java:86:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:87:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) +EagerReturnTypeResolutionTestb.java:89:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:90:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) +EagerReturnTypeResolutionTestb.java:91:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:92:15: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J,java.lang.Object) +EagerReturnTypeResolutionTestb.java:94:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.J>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J>>, EagerReturnTypeResolutionTestb.I,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:95:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:96:21: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J,java.lang.Object) +EagerReturnTypeResolutionTestb.java:98:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J>>, EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:99:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:100:24: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J,java.lang.Object) +EagerReturnTypeResolutionTestb.java:102:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:103:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:104:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:105:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:106:9: compiler.err.cant.apply.symbol: kindname.method, takeI, EagerReturnTypeResolutionTestb.I, java.lang.Object&EagerReturnTypeResolutionTestb.J&EagerReturnTypeResolutionTestb.K, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.Integer, java.lang.Integer,java.lang.String) +EagerReturnTypeResolutionTestb.java:108:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I>>, EagerReturnTypeResolutionTestb.I,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:109:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:110:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, java.lang.Object&EagerReturnTypeResolutionTestb.J&EagerReturnTypeResolutionTestb.K, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object&EagerReturnTypeResolutionTestb.J&EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:112:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I>>, EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:113:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:114:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object&EagerReturnTypeResolutionTestb.J&EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J,java.lang.Object) +EagerReturnTypeResolutionTestb.java:174:9: compiler.err.cant.apply.symbol: kindname.method, takeLong, long, java.lang.Double, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.infer.no.conforming.instance.exists: , T, long)) +EagerReturnTypeResolutionTestb.java:175:9: compiler.err.cant.apply.symbol: kindname.method, takeLong, long, java.lang.Double, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.infer.no.conforming.instance.exists: , T, long)) +EagerReturnTypeResolutionTestb.java:176:9: compiler.err.cant.apply.symbol: kindname.method, takeLong, long, java.lang.Double, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.infer.no.conforming.instance.exists: , T, long)) +EagerReturnTypeResolutionTestb.java:178:26: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.instance.exists: , T, long) +EagerReturnTypeResolutionTestb.java:179:23: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.instance.exists: , T, long) +EagerReturnTypeResolutionTestb.java:180:26: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.instance.exists: , T, long) +- compiler.note.unchecked.filename: EagerReturnTypeResolutionTestb.java +- compiler.note.unchecked.recompile +42 errors diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/inference/EagerReturnTypeResolution/PrimitiveTypeBoxingTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/inference/EagerReturnTypeResolution/PrimitiveTypeBoxingTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,25 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8030741 + * @summary Inference: implement eager resolution of return types, consistent with JDK-8028800 + * @compile/fail/ref=PrimitiveTypeBoxingTest.out -XDrawDiagnostics PrimitiveTypeBoxingTest.java + */ + +public class PrimitiveTypeBoxingTest { + + static void foo(long arg) {} + static void bar(int arg) {} + + interface F { void get(X arg); } + + void m1(F f, Z arg) {} + void m2(Z arg, F f) {} + + void test() { + m1(PrimitiveTypeBoxingTest::foo, 23); // expected: error + m2(23, PrimitiveTypeBoxingTest::foo); // expected: error + + m1(PrimitiveTypeBoxingTest::bar, 23); // expected: success + m2(23, PrimitiveTypeBoxingTest::bar); // expected: success + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/inference/EagerReturnTypeResolution/PrimitiveTypeBoxingTest.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/inference/EagerReturnTypeResolution/PrimitiveTypeBoxingTest.out Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,3 @@ +PrimitiveTypeBoxingTest.java:19:9: compiler.err.cant.apply.symbol: kindname.method, m1, PrimitiveTypeBoxingTest.F,Z, @490,int, kindname.class, PrimitiveTypeBoxingTest, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, java.lang.Long,java.lang.Object) +PrimitiveTypeBoxingTest.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m2, Z,PrimitiveTypeBoxingTest.F, int,@559, kindname.class, PrimitiveTypeBoxingTest, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, java.lang.Long,java.lang.Object) +2 errors diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/lambda/LambdaLocalTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/LambdaLocalTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8029725 + * @summary Lambda reference to containing local class causes javac infinite recursion + * @author Robert Field + * @run main LambdaLocalTest + */ + +public class LambdaLocalTest { + interface F {void f();} + + static F f; + static StringBuffer sb = new StringBuffer(); + + static void assertEquals(Object val, Object expected) { + if (!val.equals(expected)) { + throw new AssertionError("expected '" + expected + "' got '" + val + "'"); + } + } + + public static void main(String[] args) { + class Local { + public Local() { + f = () -> new Local(); + sb.append("+"); + } + } + new Local(); + f.f(); + assertEquals(sb.toString(), "++"); + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/lambda/LambdaMultiCatchTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/LambdaMultiCatchTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8036942 + * @summary javac generates incorrect exception table for multi-catch statements inside a lambda + * @run main LambdaMultiCatchTest + */ + +import java.io.IOException; +import java.util.function.Function; + +public class LambdaMultiCatchTest { + public static void main(String[] args) { + Function fi = x -> { + String result = "nada"; + try { + switch (x) { + case "IO": throw new IOException(); + case "Illegal": throw new IllegalArgumentException(); + case "Run": throw new RuntimeException(); + } + } catch (IOException|IllegalArgumentException ex) { + result = "IO/Illegal"; + } catch (Exception ex) { + result = "Any"; + }; + return result; + }; + String val = fi.apply("Run"); + if (!val.equals("Any")) { + throw new AssertionError("Fail: Expected 'Any' but got '" + val + "'"); + } + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/lambda/LambdaOuterLocalTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/LambdaOuterLocalTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8029725 + * @summary Lambda reference to containing local class causes javac infinite recursion + * @author Robert Field + * @run main LambdaOuterLocalTest + */ + +public class LambdaOuterLocalTest { + interface F {void f();} + + static F f; + static StringBuffer sb = new StringBuffer(); + + static void assertEquals(Object val, Object expected) { + if (!val.equals(expected)) { + throw new AssertionError("expected '" + expected + "' got '" + val + "'"); + } + } + + public static void main(String[] args) { + class Local1 { + public Local1() { + class Local2 { + public Local2() { + f = () -> new Local1(); + sb.append("2"); + } + } + sb.append("1"); + new Local2(); + } + } + new Local1(); + f.f(); + assertEquals(sb.toString(), "1212"); + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/lambda/SingleLocalTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/SingleLocalTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8029852 + * @summary Bad code generated (VerifyError) when lambda instantiates + * enclosing local class and has captured variables + */ +public class SingleLocalTest { + interface F {void f();} + + static F f; + + public static void main(String[] args) { + StringBuffer sb = new StringBuffer(); + class Local1 { + public Local1() { + f = () -> new Local1(); + sb.append("1"); + } + } + new Local1(); + f.f(); + String s = sb.toString(); + if (!s.equals("11")) { + throw new AssertionError("Expected '11' got '" + s + "'"); + } + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/lib/InMemoryFileManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lib/InMemoryFileManager.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.*; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import javax.tools.*; + +import static java.util.Collections.unmodifiableMap; + +/** + * class for storing source/byte code in memory. + */ +public class InMemoryFileManager extends ForwardingJavaFileManager { + + private final Map classes = new HashMap<>(); + + public InMemoryFileManager(JavaFileManager fileManager) { + super(fileManager); + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { + + InMemoryJavaFile javaFile = new InMemoryJavaFile(className); + classes.put(className, javaFile); + return javaFile; + } + + @Override + public ClassLoader getClassLoader(Location location) { + return new ClassLoader(this.getClass().getClassLoader()) { + @Override + protected Class findClass(String name) throws ClassNotFoundException { + InMemoryJavaFile classData = classes.get(name); + if (classData == null) throw new ClassNotFoundException(name); + byte[] byteCode = classData.bos.toByteArray(); + return defineClass(name, byteCode, 0, byteCode.length); + } + }; + } + + public Map getClasses() { + return unmodifiableMap(classes); + } + + private static class InMemoryJavaFile extends SimpleJavaFileObject { + + private final ByteArrayOutputStream bos = + new ByteArrayOutputStream(); + + + protected InMemoryJavaFile(String name) { + super(URI.create("mfm:///" + name.replace('.', '/') + Kind.CLASS.extension), Kind.CLASS); + } + + @Override + public OutputStream openOutputStream() throws IOException { + return bos; + } + + @Override + public InputStream openInputStream() throws IOException { + return new ByteArrayInputStream(bos.toByteArray()); + } + } +} diff -r a77941f17614 -r 0d1f816217dc langtools/test/tools/javac/lib/ToolBox.java --- a/langtools/test/tools/javac/lib/ToolBox.java Wed Jul 05 19:38:36 2017 +0200 +++ b/langtools/test/tools/javac/lib/ToolBox.java Wed Jul 05 19:39:35 2017 +0200 @@ -851,7 +851,7 @@ * This method is intended for simple files and uses regular expressions, * so comments matching the pattern can make the method fail. */ - private static String getJavaFileNameFromSource(String source) { + static String getJavaFileNameFromSource(String source) { String className = null; Matcher matcher = publicClassPattern.matcher(source); if (matcher.find()) { @@ -902,7 +902,9 @@ .append("Main-Class: ") .append(mainClass).toString()); } - Files.write(Paths.get("MANIFEST.MF"), lines, null); + Files.write(Paths.get("MANIFEST.MF"), lines, + StandardOpenOption.CREATE, StandardOpenOption.WRITE, + StandardOpenOption.TRUNCATE_EXISTING); } /** diff -r a77941f17614 -r 0d1f816217dc make/common/JavaCompilation.gmk --- a/make/common/JavaCompilation.gmk Wed Jul 05 19:38:36 2017 +0200 +++ b/make/common/JavaCompilation.gmk Wed Jul 05 19:39:35 2017 +0200 @@ -351,7 +351,8 @@ # 3. Delete all lines starting with #. # 4. Delete empty lines. # 5. Append lines ending with \ with the next line. -# 6. Remove leading and trailing white space. +# 6. Remove leading and trailing white space. Note that tabs must be explicit +# as sed on macosx does not understand '\t'. # 7. Replace the first \= with just =. # 8. Finally it's all sorted to create a stable output. # @@ -370,7 +371,7 @@ | $(SED) -f "$(SRC_ROOT)/make/common/support/unicode2x.sed" \ | $(SED) -e '/^#/d' -e '/^$$$$/d' \ -e :a -e '/\\$$$$/N; s/\\\n//; ta' \ - -e 's/^[ \t]*//;s/[ \t]*$$$$//' \ + -e 's/^[ ]*//;s/[ ]*$$$$//' \ -e 's/\\=/=/' | LC_ALL=C $(SORT) > $$@ $(CHMOD) -f ug+w $$@ diff -r a77941f17614 -r 0d1f816217dc nashorn/.hgtags --- a/nashorn/.hgtags Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/.hgtags Wed Jul 05 19:39:35 2017 +0200 @@ -244,3 +244,4 @@ 4764920fd81d631915b13ba03b5d962ab14a50c4 jdk9-b08 27f6ea87dcbd52c4b59e34a9f18d5b3321d53fa7 jdk9-b09 0eaa55c7abe5d96023a4b38a326f411209c43f49 jdk9-b10 +4d60c3292e14aac90dc3b8232496ba4af4254cc3 jdk9-b11 diff -r a77941f17614 -r 0d1f816217dc nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java --- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Wed Jul 05 19:39:35 2017 +0200 @@ -27,16 +27,14 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.io.Reader; import java.lang.invoke.MethodHandles; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URL; -import java.nio.charset.Charset; import java.security.AccessControlContext; import java.security.AccessController; import java.security.Permissions; @@ -124,21 +122,21 @@ } } - // load engine.js and return content as a char[] + // load engine.js @SuppressWarnings("resource") - private static char[] loadEngineJSSource() { + private static Source loadEngineJSSource() { final String script = "resources/engine.js"; try { - final InputStream is = AccessController.doPrivileged( - new PrivilegedExceptionAction() { + return AccessController.doPrivileged( + new PrivilegedExceptionAction() { @Override - public InputStream run() throws Exception { + public Source run() throws IOException { final URL url = NashornScriptEngine.class.getResource(script); - return url.openStream(); + return sourceFor(NashornException.ENGINE_SCRIPT_SOURCE_NAME, url); } - }); - return Source.readFully(new InputStreamReader(is)); - } catch (final PrivilegedActionException | IOException e) { + } + ); + } catch (final PrivilegedActionException e) { if (Context.DEBUG) { e.printStackTrace(); } @@ -147,7 +145,7 @@ } // Source object for engine.js - private static final Source ENGINE_SCRIPT_SRC = new Source(NashornException.ENGINE_SCRIPT_SOURCE_NAME, loadEngineJSSource()); + private static final Source ENGINE_SCRIPT_SRC = loadEngineJSSource(); NashornScriptEngine(final NashornScriptEngineFactory factory, final ClassLoader appLoader) { this(factory, DEFAULT_OPTIONS, appLoader); @@ -282,19 +280,14 @@ private static Source makeSource(final Reader reader, final ScriptContext ctxt) throws ScriptException { try { - if (reader instanceof URLReader) { - final URL url = ((URLReader)reader).getURL(); - final Charset cs = ((URLReader)reader).getCharset(); - return new Source(url.toString(), url, cs); - } - return new Source(getScriptName(ctxt), Source.readFully(reader)); - } catch (final IOException e) { + return sourceFor(getScriptName(ctxt), reader); + } catch (IOException e) { throw new ScriptException(e); } } private static Source makeSource(final String src, final ScriptContext ctxt) { - return new Source(getScriptName(ctxt), src); + return sourceFor(getScriptName(ctxt), src); } private static String getScriptName(final ScriptContext ctxt) { diff -r a77941f17614 -r 0d1f816217dc nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java --- a/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java Wed Jul 05 19:39:35 2017 +0200 @@ -25,6 +25,8 @@ package jdk.nashorn.internal.ir.debug; +import static jdk.nashorn.internal.runtime.Source.sourceFor; + import java.util.Arrays; import java.util.List; import java.util.ArrayList; @@ -88,7 +90,7 @@ * @return JSON string representation of AST of the supplied code */ public static String parse(final ScriptEnvironment env, final String code, final String name, final boolean includeLoc) { - final Parser parser = new Parser(env, new Source(name, code), new Context.ThrowErrorManager(), env._strict); + final Parser parser = new Parser(env, sourceFor(name, code), new Context.ThrowErrorManager(), env._strict); final JSONWriter jsonWriter = new JSONWriter(includeLoc); try { final FunctionNode functionNode = parser.parse(CompilerConstants.RUN_SCRIPT.symbolName()); diff -r a77941f17614 -r 0d1f816217dc nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java --- a/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java Wed Jul 05 19:39:35 2017 +0200 @@ -27,6 +27,7 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import java.util.List; @@ -257,7 +258,7 @@ } private static void checkFunctionParameters(final String params) { - final Source src = new Source("", params); + final Source src = sourceFor("", params); final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager()); try { parser.parseFormalParameterList(); @@ -267,7 +268,7 @@ } private static void checkFunctionBody(final String funcBody) { - final Source src = new Source("", funcBody); + final Source src = sourceFor("", funcBody); final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager()); try { parser.parseFunctionBody(); diff -r a77941f17614 -r 0d1f816217dc nashorn/src/jdk/nashorn/internal/runtime/Context.java --- a/nashorn/src/jdk/nashorn/internal/runtime/Context.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/Context.java Wed Jul 05 19:39:35 2017 +0200 @@ -32,6 +32,7 @@ import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import java.io.File; import java.io.IOException; @@ -501,7 +502,7 @@ */ public Object eval(final ScriptObject initialScope, final String string, final Object callThis, final Object location, final boolean strict) { final String file = (location == UNDEFINED || location == null) ? "" : location.toString(); - final Source source = new Source(file, string); + final Source source = sourceFor(file, string); final boolean directEval = location != UNDEFINED; // is this direct 'eval' call or indirectly invoked eval? final Global global = Context.getGlobal(); @@ -568,7 +569,7 @@ public Source run() { try { final URL resURL = Context.class.getResource(resource); - return (resURL != null)? new Source(srcStr, resURL) : null; + return (resURL != null)? sourceFor(srcStr, resURL) : null; } catch (final IOException exp) { return null; } @@ -600,7 +601,7 @@ final String srcStr = (String)src; if (srcStr.startsWith(LOAD_CLASSPATH)) { URL url = getResourceURL(srcStr.substring(LOAD_CLASSPATH.length())); - source = (url != null)? new Source(url.toString(), url) : null; + source = (url != null)? sourceFor(url.toString(), url) : null; } else { final File file = new File(srcStr); if (srcStr.indexOf(':') != -1) { @@ -613,31 +614,31 @@ } catch (final MalformedURLException e) { url = file.toURI().toURL(); } - source = new Source(url.toString(), url); + source = sourceFor(url.toString(), url); } } else if (file.isFile()) { - source = new Source(srcStr, file); + source = sourceFor(srcStr, file); } } } else if (src instanceof File && ((File)src).isFile()) { final File file = (File)src; - source = new Source(file.getName(), file); + source = sourceFor(file.getName(), file); } else if (src instanceof URL) { final URL url = (URL)src; - source = new Source(url.toString(), url); + source = sourceFor(url.toString(), url); } else if (src instanceof ScriptObject) { final ScriptObject sobj = (ScriptObject)src; if (sobj.has("script") && sobj.has("name")) { final String script = JSType.toString(sobj.get("script")); final String name = JSType.toString(sobj.get("name")); - source = new Source(name, script); + source = sourceFor(name, script); } } else if (src instanceof Map) { final Map map = (Map)src; if (map.containsKey("script") && map.containsKey("name")) { final String script = JSType.toString(map.get("script")); final String name = JSType.toString(map.get("name")); - source = new Source(name, script); + source = sourceFor(name, script); } } diff -r a77941f17614 -r 0d1f816217dc nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java --- a/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java Wed Jul 05 19:39:35 2017 +0200 @@ -39,6 +39,8 @@ import jdk.nashorn.internal.runtime.arrays.ArrayIndex; import jdk.nashorn.internal.runtime.linker.Bootstrap; +import static jdk.nashorn.internal.runtime.Source.sourceFor; + /** * Utilities used by "JSON" object implementation. */ @@ -77,9 +79,7 @@ */ public static Object parse(final Object text, final Object reviver) { final String str = JSType.toString(text); - final JSONParser parser = new JSONParser( - new Source("", str), - new Context.ThrowErrorManager()); + final JSONParser parser = new JSONParser(sourceFor("", str), new Context.ThrowErrorManager()); Node node; diff -r a77941f17614 -r 0d1f816217dc nashorn/src/jdk/nashorn/internal/runtime/Source.java --- a/nashorn/src/jdk/nashorn/internal/runtime/Source.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/Source.java Wed Jul 05 19:39:35 2017 +0200 @@ -27,13 +27,16 @@ import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOError; import java.io.IOException; import java.io.InputStream; import java.io.Reader; +import java.lang.ref.WeakReference; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; +import java.net.URLConnection; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -43,13 +46,19 @@ import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Objects; +import java.util.WeakHashMap; +import jdk.nashorn.api.scripting.URLReader; import jdk.nashorn.internal.parser.Token; /** * Source objects track the origin of JavaScript entities. - * */ public final class Source { + + private static final DebugLogger DEBUG = new DebugLogger("source"); + private static final int BUF_SIZE = 8 * 1024; + private static final Cache CACHE = new Cache(); + /** * Descriptive name of the source as supplied by the user. Used for error * reporting to the user. For example, SyntaxError will use this to print message. @@ -64,11 +73,8 @@ */ private final String base; - /** Cached source content. */ - private final char[] content; - - /** Length of source content. */ - private final int length; + /** Source content */ + private final Data data; /** Cached hash code */ private int hash; @@ -76,40 +82,297 @@ /** Message digest */ private byte[] digest; - /** Source URL if available */ - private final URL url; + // Do *not* make this public, ever! Trusts the URL and content. + private Source(final String name, final String base, final Data data) { + this.name = name; + this.base = base; + this.data = data; + } + + private static synchronized Source sourceFor(final String name, final String base, final URLData data) throws IOException { + try { + final Source newSource = new Source(name, base, data); + final Source existingSource = CACHE.get(newSource); + if (existingSource != null) { + // Force any access errors + data.checkPermissionAndClose(); + return existingSource; + } else { + // All sources in cache must be fully loaded + data.load(); + CACHE.put(newSource, newSource); + return newSource; + } + } catch (RuntimeException e) { + final Throwable cause = e.getCause(); + if (cause instanceof IOException) { + throw (IOException) cause; + } + throw e; + } + } + + private static class Cache extends WeakHashMap> { + public Source get(final Source key) { + final WeakReference ref = super.get(key); + return ref == null ? null : ref.get(); + } + + public void put(final Source key, final Source value) { + assert !(value.data instanceof RawData); + put(key, new WeakReference<>(value)); + } + } + + // Wrapper to manage lazy loading + private static interface Data { + + URL url(); + + int length(); + + long lastModified(); + + char[] array(); + } + + private static class RawData implements Data { + private final char[] array; + private int hash; + + private RawData(final char[] array) { + this.array = Objects.requireNonNull(array); + } - private static final int BUFSIZE = 8 * 1024; + private RawData(final String source) { + this.array = Objects.requireNonNull(source).toCharArray(); + } + + private RawData(final Reader reader) throws IOException { + this(readFully(reader)); + } + + @Override + public int hashCode() { + int h = hash; + if (h == 0) { + h = hash = Arrays.hashCode(array); + } + return h; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof RawData) { + return Arrays.equals(array, ((RawData)obj).array); + } + return false; + } + + @Override + public String toString() { + return new String(array()); + } + + @Override + public URL url() { + return null; + } + + @Override + public int length() { + return array.length; + } + + @Override + public long lastModified() { + return 0; + } + + @Override + public char[] array() { + return array; + } + + + } + + private static class URLData implements Data { + private final URL url; + protected final Charset cs; + private int hash; + protected char[] array; + protected int length; + protected long lastModified; + + private URLData(final URL url, final Charset cs) { + this.url = Objects.requireNonNull(url); + this.cs = cs; + } - // Do *not* make this public ever! Trusts the URL and content. So has to be called - // from other public constructors. Note that this can not be some init method as - // we initialize final fields from here. - private Source(final String name, final String base, final char[] content, final URL url) { - this.name = name; - this.base = base; - this.content = content; - this.length = content.length; - this.url = url; + @Override + public int hashCode() { + int h = hash; + if (h == 0) { + h = hash = url.hashCode(); + } + return h; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof URLData)) { + return false; + } + + URLData otherData = (URLData) other; + + if (url.equals(otherData.url)) { + // Make sure both have meta data loaded + try { + if (isDeferred()) { + // Data in cache is always loaded, and we only compare to cached data. + assert !otherData.isDeferred(); + loadMeta(); + } else if (otherData.isDeferred()) { + otherData.loadMeta(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + + // Compare meta data + return this.length == otherData.length && this.lastModified == otherData.lastModified; + } + return false; + } + + @Override + public String toString() { + return new String(array()); + } + + @Override + public URL url() { + return url; + } + + @Override + public int length() { + return length; + } + + @Override + public long lastModified() { + return lastModified; + } + + @Override + public char[] array() { + assert !isDeferred(); + return array; + } + + boolean isDeferred() { + return array == null; + } + + protected void checkPermissionAndClose() throws IOException { + try (InputStream in = url.openStream()) {} + debug("permission checked for ", url); + } + + protected void load() throws IOException { + if (array == null) { + final URLConnection c = url.openConnection(); + try (InputStream in = c.getInputStream()) { + array = cs == null ? readFully(in) : readFully(in, cs); + length = array.length; + lastModified = c.getLastModified(); + debug("loaded content for ", url); + } + } + } + + protected void loadMeta() throws IOException { + if (length == 0 && lastModified == 0) { + final URLConnection c = url.openConnection(); + length = c.getContentLength(); + lastModified = c.getLastModified(); + debug("loaded metadata for ", url); + } + } + } + + private static class FileData extends URLData { + private final File file; + + private FileData(final File file, final Charset cs) { + super(getURLFromFile(file), cs); + this.file = file; + + } + + @Override + protected void checkPermissionAndClose() throws IOException { + if (!file.canRead()) { + throw new FileNotFoundException(file + " (Permission Denied)"); + } + debug("permission checked for ", file); + } + + @Override + protected void loadMeta() { + if (length == 0 && lastModified == 0) { + length = (int) file.length(); + lastModified = file.lastModified(); + debug("loaded metadata for ", file); + } + } + + @Override + protected void load() throws IOException { + if (array == null) { + array = cs == null ? readFully(file) : readFully(file, cs); + length = array.length; + lastModified = file.lastModified(); + debug("loaded content for ", file); + } + } + } + + private static void debug(final Object... msg) { + DEBUG.info(msg); + } + + private char[] data() { + return data.array(); } /** - * Constructor + * Returns an instance * * @param name source name * @param content contents as char array */ - public Source(final String name, final char[] content) { - this(name, baseName(name, null), content, null); + public static Source sourceFor(final String name, final char[] content) { + return new Source(name, baseName(name), new RawData(content)); } /** - * Constructor + * Returns an instance * * @param name source name * @param content contents as string */ - public Source(final String name, final String content) { - this(name, content.toCharArray()); + public static Source sourceFor(final String name, final String content) { + return new Source(name, baseName(name), new RawData(content)); } /** @@ -120,8 +383,8 @@ * * @throws IOException if source cannot be loaded */ - public Source(final String name, final URL url) throws IOException { - this(name, baseURL(url, null), readFully(url), url); + public static Source sourceFor(final String name, final URL url) throws IOException { + return sourceFor(name, url, null); } /** @@ -133,8 +396,8 @@ * * @throws IOException if source cannot be loaded */ - public Source(final String name, final URL url, final Charset cs) throws IOException { - this(name, baseURL(url, null), readFully(url, cs), url); + public static Source sourceFor(final String name, final URL url, final Charset cs) throws IOException { + return sourceFor(name, baseURL(url), new URLData(url, cs)); } /** @@ -145,8 +408,8 @@ * * @throws IOException if source cannot be loaded */ - public Source(final String name, final File file) throws IOException { - this(name, dirName(file, null), readFully(file), getURLFromFile(file)); + public static Source sourceFor(final String name, final File file) throws IOException { + return sourceFor(name, file, null); } /** @@ -158,8 +421,25 @@ * * @throws IOException if source cannot be loaded */ - public Source(final String name, final File file, final Charset cs) throws IOException { - this(name, dirName(file, null), readFully(file, cs), getURLFromFile(file)); + public static Source sourceFor(final String name, final File file, final Charset cs) throws IOException { + final File absFile = file.getAbsoluteFile(); + return sourceFor(name, dirName(absFile, null), new FileData(file, cs)); + } + + /** + * Returns an instance + * + * @param name source name + * @param reader reader from which source can be loaded + * @throws IOException if source cannot be loaded + */ + public static Source sourceFor(final String name, final Reader reader) throws IOException { + // Extract URL from URLReader to defer loading and reuse cached data if available. + if (reader instanceof URLReader) { + final URLReader urlReader = (URLReader) reader; + return sourceFor(name, urlReader.getURL(), urlReader.getCharset()); + } + return new Source(name, baseName(name), new RawData(reader)); } @Override @@ -167,21 +447,18 @@ if (this == obj) { return true; } - if (!(obj instanceof Source)) { return false; } - - final Source src = (Source)obj; - // Only compare content as a last resort measure - return length == src.length && Objects.equals(url, src.url) && Objects.equals(name, src.name) && Arrays.equals(content, src.content); + final Source other = (Source) obj; + return Objects.equals(name, other.name) && data.equals(other.data); } @Override public int hashCode() { int h = hash; if (h == 0) { - h = hash = Arrays.hashCode(content) ^ Objects.hashCode(name); + h = hash = data.hashCode() ^ Objects.hashCode(name); } return h; } @@ -191,7 +468,7 @@ * @return Source content. */ public String getString() { - return new String(content, 0, length); + return data.toString(); } /** @@ -203,6 +480,14 @@ } /** + * Get the last modified time of this script. + * @return Last modified time. + */ + public long getLastModified() { + return data.lastModified(); + } + + /** * Get the "directory" part of the file or "base" of the URL. * @return base of file or URL. */ @@ -217,7 +502,7 @@ * @return Source content portion. */ public String getString(final int start, final int len) { - return new String(content, start, len); + return new String(data(), start, len); } /** @@ -228,7 +513,7 @@ public String getString(final long token) { final int start = Token.descPosition(token); final int len = Token.descLength(token); - return new String(content, start, len); + return new String(data(), start, len); } /** @@ -238,7 +523,7 @@ * @return URL source or null */ public URL getURL() { - return url; + return data.url(); } /** @@ -247,8 +532,9 @@ * @return Index of first character of line. */ private int findBOLN(final int position) { + final char[] data = data(); for (int i = position - 1; i > 0; i--) { - final char ch = content[i]; + final char ch = data[i]; if (ch == '\n' || ch == '\r') { return i + 1; @@ -264,8 +550,10 @@ * @return Index of last character of line. */ private int findEOLN(final int position) { - for (int i = position; i < length; i++) { - final char ch = content[i]; + final char[] data = data(); + final int length = data.length; + for (int i = position; i < length; i++) { + final char ch = data[i]; if (ch == '\n' || ch == '\r') { return i - 1; @@ -285,11 +573,12 @@ * @return Line number. */ public int getLine(final int position) { + final char[] data = data(); // Line count starts at 1. int line = 1; for (int i = 0; i < position; i++) { - final char ch = content[i]; + final char ch = data[i]; // Works for both \n and \r\n. if (ch == '\n') { line++; @@ -320,7 +609,7 @@ // Find end of this line. final int last = findEOLN(position); - return new String(content, first, last - first + 1); + return new String(data(), first, last - first + 1); } /** @@ -328,7 +617,7 @@ * @return content */ public char[] getContent() { - return content.clone(); + return data().clone(); } /** @@ -336,19 +625,18 @@ * @return length */ public int getLength() { - return length; + return data.length(); } /** * Read all of the source until end of file. Return it as char array * - * @param reader reader opened to source stream + * @param reader reader opened to source stream * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final Reader reader) throws IOException { - final char[] arr = new char[BUFSIZE]; + final char[] arr = new char[BUF_SIZE]; final StringBuilder sb = new StringBuilder(); try { @@ -366,9 +654,8 @@ /** * Read all of the source until end of file. Return it as char array * - * @param file source file + * @param file source file * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final File file) throws IOException { @@ -381,10 +668,9 @@ /** * Read all of the source until end of file. Return it as char array * - * @param file source file + * @param file source file * @param cs Charset used to convert bytes to chars * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final File file, final Charset cs) throws IOException { @@ -393,7 +679,7 @@ } final byte[] buf = Files.readAllBytes(file.toPath()); - return (cs != null)? new String(buf, cs).toCharArray() : byteToCharArray(buf); + return (cs != null) ? new String(buf, cs).toCharArray() : byteToCharArray(buf); } /** @@ -401,7 +687,6 @@ * * @param url URL to read content from * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final URL url) throws IOException { @@ -414,7 +699,6 @@ * @param url URL to read content from * @param cs Charset used to convert bytes to chars * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final URL url, final Charset cs) throws IOException { @@ -428,7 +712,7 @@ */ public synchronized byte[] getDigest() { if (digest == null) { - + final char[] content = data(); final byte[] bytes = new byte[content.length * 2]; for (int i = 0; i < content.length; i++) { @@ -444,8 +728,8 @@ if (base != null) { md.update(base.getBytes(StandardCharsets.UTF_8)); } - if (url != null) { - md.update(url.toString().getBytes(StandardCharsets.UTF_8)); + if (getURL() != null) { + md.update(getURL().toString().getBytes(StandardCharsets.UTF_8)); } digest = md.digest(bytes); } catch (NoSuchAlgorithmException e) { @@ -461,50 +745,46 @@ * @return base URL for url */ public static String baseURL(final URL url) { - return baseURL(url, null); - } - - private static String baseURL(final URL url, final String defaultValue) { if (url.getProtocol().equals("file")) { try { final Path path = Paths.get(url.toURI()); final Path parent = path.getParent(); - return (parent != null) ? (parent + File.separator) : defaultValue; + return (parent != null) ? (parent + File.separator) : null; } catch (final SecurityException | URISyntaxException | IOError e) { - return defaultValue; + return null; } } // FIXME: is there a better way to find 'base' URL of a given URL? String path = url.getPath(); if (path.isEmpty()) { - return defaultValue; + return null; } path = path.substring(0, path.lastIndexOf('/') + 1); final int port = url.getPort(); try { return new URL(url.getProtocol(), url.getHost(), port, path).toString(); } catch (final MalformedURLException e) { - return defaultValue; + return null; } } - private static String dirName(final File file, final String defaultValue) { + private static String dirName(final File file, final String DEFAULT_BASE_NAME) { final String res = file.getParent(); - return (res != null)? (res + File.separator) : defaultValue; + return (res != null) ? (res + File.separator) : DEFAULT_BASE_NAME; } // fake directory like name - private static String baseName(final String name, final String defaultValue) { + private static String baseName(final String name) { int idx = name.lastIndexOf('/'); if (idx == -1) { idx = name.lastIndexOf('\\'); } - return (idx != -1)? name.substring(0, idx + 1) : defaultValue; + return (idx != -1) ? name.substring(0, idx + 1) : null; } private static char[] readFully(final InputStream is, final Charset cs) throws IOException { - return (cs != null)? new String(readBytes(is), cs).toCharArray() : readFully(is); + return (cs != null) ? new String(readBytes(is), cs).toCharArray() : readFully(is); } private static char[] readFully(final InputStream is) throws IOException { @@ -515,19 +795,19 @@ Charset cs = StandardCharsets.UTF_8; int start = 0; // BOM detection. - if (bytes.length > 1 && bytes[0] == (byte)0xFE && bytes[1] == (byte)0xFF) { + if (bytes.length > 1 && bytes[0] == (byte) 0xFE && bytes[1] == (byte) 0xFF) { start = 2; cs = StandardCharsets.UTF_16BE; - } else if (bytes.length > 1 && bytes[0] == (byte)0xFF && bytes[1] == (byte)0xFE) { + } else if (bytes.length > 1 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE) { start = 2; cs = StandardCharsets.UTF_16LE; - } else if (bytes.length > 2 && bytes[0] == (byte)0xEF && bytes[1] == (byte)0xBB && bytes[2] == (byte)0xBF) { + } else if (bytes.length > 2 && bytes[0] == (byte) 0xEF && bytes[1] == (byte) 0xBB && bytes[2] == (byte) 0xBF) { start = 3; cs = StandardCharsets.UTF_8; - } else if (bytes.length > 3 && bytes[0] == (byte)0xFF && bytes[1] == (byte)0xFE && bytes[2] == 0 && bytes[3] == 0) { + } else if (bytes.length > 3 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE && bytes[2] == 0 && bytes[3] == 0) { start = 4; cs = Charset.forName("UTF-32LE"); - } else if (bytes.length > 3 && bytes[0] == 0 && bytes[1] == 0 && bytes[2] == (byte)0xFE && bytes[3] == (byte)0xFF) { + } else if (bytes.length > 3 && bytes[0] == 0 && bytes[1] == 0 && bytes[2] == (byte) 0xFE && bytes[3] == (byte) 0xFF) { start = 4; cs = Charset.forName("UTF-32BE"); } @@ -536,7 +816,7 @@ } static byte[] readBytes(final InputStream is) throws IOException { - final byte[] arr = new byte[BUFSIZE]; + final byte[] arr = new byte[BUF_SIZE]; try { try (ByteArrayOutputStream buf = new ByteArrayOutputStream()) { int numBytes; diff -r a77941f17614 -r 0d1f816217dc nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java --- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Wed Jul 05 19:39:35 2017 +0200 @@ -64,7 +64,6 @@ import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Type; import jdk.internal.org.objectweb.asm.commons.InstructionAdapter; -import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; @@ -132,23 +131,18 @@ * implemented securely. */ final class JavaAdapterBytecodeGenerator { - static final Type CONTEXT_TYPE = Type.getType(Context.class); - static final Type OBJECT_TYPE = Type.getType(Object.class); - static final Type SCRIPT_OBJECT_TYPE = Type.getType(ScriptObject.class); - static final Type GLOBAL_TYPE = Type.getType(Global.class); + static final Type OBJECT_TYPE = Type.getType(Object.class); - static final String CONTEXT_TYPE_NAME = CONTEXT_TYPE.getInternalName(); static final String OBJECT_TYPE_NAME = OBJECT_TYPE.getInternalName(); static final String INIT = ""; static final String GLOBAL_FIELD_NAME = "global"; - static final String SCRIPT_OBJECT_TYPE_DESCRIPTOR = SCRIPT_OBJECT_TYPE.getDescriptor(); - static final String GLOBAL_TYPE_DESCRIPTOR = GLOBAL_TYPE.getDescriptor(); + // "global" is declared as Object instead of Global - avoid static references to internal Nashorn classes when possible. + static final String GLOBAL_TYPE_DESCRIPTOR = OBJECT_TYPE.getDescriptor(); - - static final String SET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, GLOBAL_TYPE); + static final String SET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE); static final String VOID_NOARG_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE); private static final Type SCRIPT_FUNCTION_TYPE = Type.getType(ScriptFunction.class); @@ -159,7 +153,7 @@ OBJECT_TYPE, STRING_TYPE, METHOD_TYPE_TYPE); private static final String GET_HANDLE_FUNCTION_DESCRIPTOR = Type.getMethodDescriptor(METHOD_HANDLE_TYPE, SCRIPT_FUNCTION_TYPE, METHOD_TYPE_TYPE); - private static final String GET_CLASS_INITIALIZER_DESCRIPTOR = Type.getMethodDescriptor(SCRIPT_OBJECT_TYPE); + private static final String GET_CLASS_INITIALIZER_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE); private static final Type RUNTIME_EXCEPTION_TYPE = Type.getType(RuntimeException.class); private static final Type THROWABLE_TYPE = Type.getType(Throwable.class); private static final Type UNSUPPORTED_OPERATION_TYPE = Type.getType(UnsupportedOperationException.class); @@ -171,7 +165,7 @@ private static final String UNSUPPORTED_OPERATION_TYPE_NAME = UNSUPPORTED_OPERATION_TYPE.getInternalName(); private static final String METHOD_HANDLE_TYPE_DESCRIPTOR = METHOD_HANDLE_TYPE.getDescriptor(); - private static final String GET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(GLOBAL_TYPE); + private static final String GET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE); private static final String GET_CLASS_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.getType(Class.class)); // Package used when the adapter can't be defined in the adaptee's package (either because it's sealed, or because @@ -528,11 +522,11 @@ } private static void invokeGetGlobal(final InstructionAdapter mv) { - mv.invokestatic(CONTEXT_TYPE_NAME, "getGlobal", GET_GLOBAL_METHOD_DESCRIPTOR, false); + mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getGlobal", GET_GLOBAL_METHOD_DESCRIPTOR, false); } private static void invokeSetGlobal(final InstructionAdapter mv) { - mv.invokestatic(CONTEXT_TYPE_NAME, "setGlobal", SET_GLOBAL_METHOD_DESCRIPTOR, false); + mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "setGlobal", SET_GLOBAL_METHOD_DESCRIPTOR, false); } /** diff -r a77941f17614 -r 0d1f816217dc nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java --- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Wed Jul 05 19:39:35 2017 +0200 @@ -31,6 +31,8 @@ import java.security.ProtectionDomain; import java.security.SecureClassLoader; import jdk.internal.dynalink.beans.StaticClass; +import jdk.nashorn.internal.runtime.Context; +import jdk.nashorn.internal.runtime.ScriptFunction; /** * This class encapsulates the bytecode of the adapter class and can be used to load it into the JVM as an actual Class. @@ -85,13 +87,14 @@ @Override public Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException { try { + Context.checkPackageAccess(name); return super.loadClass(name, resolve); } catch (final SecurityException se) { // we may be implementing an interface or extending a class that was // loaded by a loader that prevents package.access. If so, it'd throw // SecurityException for nashorn's classes!. For adapter's to work, we - // should be able to refer to nashorn classes. - if (name.startsWith("jdk.nashorn.internal.")) { + // should be able to refer to the few classes it needs in its implementation. + if(ScriptFunction.class.getName().equals(name) || JavaAdapterServices.class.getName().equals(name)) { return myLoader.loadClass(name); } throw se; diff -r a77941f17614 -r 0d1f816217dc nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java --- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Wed Jul 05 19:39:35 2017 +0200 @@ -247,7 +247,7 @@ } private static class AdapterInfo { - private static final ClassAndLoader SCRIPT_OBJECT_LOADER = new ClassAndLoader(ScriptObject.class, true); + private static final ClassAndLoader SCRIPT_OBJECT_LOADER = new ClassAndLoader(ScriptFunction.class, true); private final ClassLoader commonLoader; // TODO: soft reference the JavaAdapterClassLoader objects. They can be recreated when needed. diff -r a77941f17614 -r 0d1f816217dc nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java --- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java Wed Jul 05 19:39:35 2017 +0200 @@ -116,8 +116,8 @@ * static initializers. * @return the thread-local JS object used to define methods for the class being initialized. */ - public static ScriptObject getClassOverrides() { - final ScriptObject overrides = classOverrides.get(); + public static Object getClassOverrides() { + final Object overrides = classOverrides.get(); assert overrides != null; return overrides; } @@ -134,6 +134,22 @@ NO_PERMISSIONS_INVOKER.invokeExact(method, arg); } + /** + * Set the current global scope + * @param global the global scope + */ + public static void setGlobal(final Object global) { + Context.setGlobal((ScriptObject)global); + } + + /** + * Get the current global scope + * @return the current global scope + */ + public static Object getGlobal() { + return Context.getGlobal(); + } + static void setClassOverrides(ScriptObject overrides) { classOverrides.set(overrides); } diff -r a77941f17614 -r 0d1f816217dc nashorn/src/jdk/nashorn/tools/Shell.java --- a/nashorn/src/jdk/nashorn/tools/Shell.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/src/jdk/nashorn/tools/Shell.java Wed Jul 05 19:39:35 2017 +0200 @@ -25,6 +25,8 @@ package jdk.nashorn.tools; +import static jdk.nashorn.internal.runtime.Source.sourceFor; + import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -50,7 +52,6 @@ import jdk.nashorn.internal.runtime.Property; import jdk.nashorn.internal.runtime.ScriptEnvironment; import jdk.nashorn.internal.runtime.ScriptFunction; -import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.Source; import jdk.nashorn.internal.runtime.options.Options; @@ -244,7 +245,7 @@ // For each file on the command line. for (final String fileName : files) { - final FunctionNode functionNode = new Parser(env, new Source(fileName, new File(fileName)), errors).parse(); + final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors).parse(); if (errors.getNumberOfErrors() != 0) { return COMPILATION_ERROR; @@ -302,7 +303,7 @@ } final File file = new File(fileName); - final ScriptFunction script = context.compileScript(new Source(fileName, file.toURI().toURL()), global); + final ScriptFunction script = context.compileScript(sourceFor(fileName, file), global); if (script == null || errors.getNumberOfErrors() != 0) { return COMPILATION_ERROR; } @@ -405,7 +406,7 @@ // initialize with "shell.js" script try { - final Source source = new Source("", Shell.class.getResource("resources/shell.js")); + final Source source = sourceFor("", Shell.class.getResource("resources/shell.js")); context.eval(global, source.getString(), global, "", false); } catch (final Exception e) { err.println(e); diff -r a77941f17614 -r 0d1f816217dc nashorn/test/script/trusted/JDK-8006529.js --- a/nashorn/test/script/trusted/JDK-8006529.js Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/test/script/trusted/JDK-8006529.js Wed Jul 05 19:39:35 2017 +0200 @@ -113,7 +113,7 @@ var getContextMethod = Context.class.getMethod("getContext") var getEnvMethod = Context.class.getMethod("getEnv") -var SourceConstructor = Source.class.getConstructor(java.lang.String.class, java.lang.String.class) +var sourceForMethod = Source.class.getMethod("sourceFor", java.lang.String.class, java.lang.String.class) var ParserConstructor = Parser.class.getConstructor(ScriptEnvironment.class, Source.class, ErrorManager.class) var CompilerConstructor = Compiler.class.getConstructor(ScriptEnvironment.class) @@ -121,7 +121,7 @@ // source code, returns a jdk.nashorn.internal.ir.FunctionNode object // representing it. function compile(source) { - var source = SourceConstructor.newInstance("", source); + var source = sourceForMethod.invoke(null, "", source); var env = getEnvMethod.invoke(getContextMethod.invoke(null)) diff -r a77941f17614 -r 0d1f816217dc nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java --- a/nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -25,6 +25,9 @@ package jdk.nashorn.internal.codegen; +import static jdk.nashorn.internal.runtime.Source.sourceFor; +import static jdk.nashorn.internal.runtime.Source.readFully; + import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; @@ -32,7 +35,6 @@ import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ErrorManager; import jdk.nashorn.internal.runtime.ScriptFunction; -import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.Source; import jdk.nashorn.internal.runtime.options.Options; import org.testng.Assert; @@ -151,7 +153,7 @@ final boolean globalChanged = (oldGlobal != global); try { - final char[] buffer = Source.readFully(file); + final char[] buffer = readFully(file); boolean excluded = false; if (filter != null) { @@ -170,7 +172,7 @@ if (globalChanged) { Context.setGlobal(global); } - final Source source = new Source(file.getAbsolutePath(), buffer); + final Source source = sourceFor(file.getAbsolutePath(), buffer); final ScriptFunction script = context.compileScript(source, global); if (script == null || context.getErrorManager().getNumberOfErrors() > 0) { log("Compile failed: " + file.getAbsolutePath()); diff -r a77941f17614 -r 0d1f816217dc nashorn/test/src/jdk/nashorn/internal/parser/ParserTest.java --- a/nashorn/test/src/jdk/nashorn/internal/parser/ParserTest.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/internal/parser/ParserTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -25,6 +25,9 @@ package jdk.nashorn.internal.parser; +import static jdk.nashorn.internal.runtime.Source.sourceFor; +import static jdk.nashorn.internal.runtime.Source.readFully; + import java.io.File; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ErrorManager; @@ -131,7 +134,7 @@ } try { - final char[] buffer = Source.readFully(file); + final char[] buffer = readFully(file); boolean excluded = false; if (filter != null) { final String content = new String(buffer); @@ -153,7 +156,7 @@ } }; errors.setLimit(0); - final Source source = new Source(file.getAbsolutePath(), buffer); + final Source source = sourceFor(file.getAbsolutePath(), buffer); new Parser(context.getEnv(), source, errors).parse(); if (errors.getNumberOfErrors() > 0) { log("Parse failed: " + file.getAbsolutePath()); diff -r a77941f17614 -r 0d1f816217dc nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java --- a/nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -25,6 +25,7 @@ package jdk.nashorn.internal.runtime; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -107,7 +108,7 @@ } private Object eval(final Context cx, final String name, final String code) { - final Source source = new Source(name, code); + final Source source = sourceFor(name, code); final ScriptObject global = Context.getGlobal(); final ScriptFunction func = cx.compileScript(source, global); return func != null ? ScriptRuntime.apply(func, global) : null; diff -r a77941f17614 -r 0d1f816217dc nashorn/test/src/jdk/nashorn/internal/runtime/SourceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/src/jdk/nashorn/internal/runtime/SourceTest.java Wed Jul 05 19:39:35 2017 +0200 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.runtime; + +import jdk.nashorn.api.scripting.URLReader; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; +import java.util.Arrays; + +import static jdk.nashorn.internal.runtime.Source.sourceFor; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +/** + * Tests different Source representations. + */ +public class SourceTest { + + final private static String SOURCE_NAME = "source.js"; + final private static String SOURCE_STRING = "var x = 1;"; + final private static char[] SOURCE_CHARS = SOURCE_STRING.toCharArray(); + final private static String RESOURCE_PATH = "resources/load_test.js"; + final private static File SOURCE_FILE = new File("build/test/classes/jdk/nashorn/internal/runtime/" + RESOURCE_PATH); + final private static URL SOURCE_URL = SourceTest.class.getResource(RESOURCE_PATH); + + + @Test + public void testStringSource() { + testSources(sourceFor(SOURCE_NAME, SOURCE_STRING), sourceFor(SOURCE_NAME, SOURCE_STRING)); + testSources(sourceFor(SOURCE_NAME, SOURCE_STRING), sourceFor(SOURCE_NAME, SOURCE_CHARS)); + } + + @Test + public void testCharArraySource() { + testSources(sourceFor(SOURCE_NAME, SOURCE_CHARS), sourceFor(SOURCE_NAME, SOURCE_CHARS)); + testSources(sourceFor(SOURCE_NAME, SOURCE_CHARS), sourceFor(SOURCE_NAME, SOURCE_STRING)); + } + + @Test + public void testURLSource() { + try { + testSources(sourceFor(SOURCE_NAME, SOURCE_URL), sourceFor(SOURCE_NAME, SOURCE_URL)); + testSources(sourceFor(SOURCE_NAME, SOURCE_URL), sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL))); + + } catch (final IOException e) { + fail(e.toString()); + } + } + + @Test + public void testURLReaderSource() { + try { + System.err.println(SourceTest.class.getResource("")); + testSources(sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL)), sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL))); + testSources(sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL)), sourceFor(SOURCE_NAME, SOURCE_URL)); + } catch (final IOException e) { + fail(e.toString()); + } + } + + @Test + public void testReaderSource() { + try { + testSources(sourceFor(SOURCE_NAME, getReader(RESOURCE_PATH)), sourceFor(SOURCE_NAME, getReader(RESOURCE_PATH))); + } catch (final IOException e) { + fail(e.toString()); + } + } + + @Test + public void testFileSource() { + try { + testSources(sourceFor(SOURCE_NAME, SOURCE_FILE), sourceFor(SOURCE_NAME, SOURCE_FILE)); + } catch (final IOException e) { + fail(e.toString()); + } + } + + private Reader getReader(final String path) { + return new InputStreamReader(SourceTest.class.getResourceAsStream(path)); + } + + private void testSources(final Source source1, final Source source2) { + final char[] chars1 = source1.getContent(); + final char[] chars2 = source2.getContent(); + final String str1 = source1.getString(); + final String str2 = source2.getString(); + assertTrue(Arrays.equals(chars1, chars2)); + assertEquals(str1, str2); + assertEquals(source1.hashCode(), source2.hashCode()); + assertTrue(source1.equals(source2)); + // Test for immutability + Arrays.fill(source1.getContent(), (char)0); + Arrays.fill(source2.getContent(), (char)1); + assertTrue(Arrays.equals(source1.getContent(), str1.toCharArray())); + assertTrue(Arrays.equals(source1.getContent(), chars1)); + assertTrue(Arrays.equals(source1.getContent(), source2.getContent())); + } +} diff -r a77941f17614 -r 0d1f816217dc nashorn/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java --- a/nashorn/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java Wed Jul 05 19:39:35 2017 +0200 @@ -25,6 +25,7 @@ package jdk.nashorn.internal.test.framework; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import static jdk.nashorn.tools.Shell.COMPILATION_ERROR; import static jdk.nashorn.tools.Shell.RUNTIME_ERROR; import static jdk.nashorn.tools.Shell.SUCCESS; @@ -39,7 +40,6 @@ import jdk.nashorn.internal.runtime.ErrorManager; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptRuntime; -import jdk.nashorn.internal.runtime.Source; import jdk.nashorn.internal.runtime.options.Options; /** @@ -125,7 +125,7 @@ continue; } final File file = new File(fileName); - ScriptFunction script = context.compileScript(new Source(fileName, file.toURI().toURL()), global); + ScriptFunction script = context.compileScript(sourceFor(fileName, file.toURI().toURL()), global); if (script == null || errors.getNumberOfErrors() != 0) { return COMPILATION_ERROR; diff -r a77941f17614 -r 0d1f816217dc nashorn/test/src/jdk/nashorn/test/models/SourceHelper.java --- a/nashorn/test/src/jdk/nashorn/test/models/SourceHelper.java Wed Jul 05 19:38:36 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/test/models/SourceHelper.java Wed Jul 05 19:39:35 2017 +0200 @@ -46,7 +46,7 @@ } public static String readFully(final URL url) throws IOException { - return new Source(url.toString(), url).getString(); + return Source.sourceFor(url.toString(), url).getString(); } public static String readFully(final Reader reader) throws IOException {