undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View file

@ -0,0 +1,103 @@
/*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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
* @key headful
* @bug 6866751
* @summary J2SE_Swing_Reg: the caret disappears when moving to the end of the line.
* @author Semyon Sadetsky
*/
import javax.swing.*;
import java.awt.*;
public class bug6866751 {
private static JFrame frame;
private static JTextArea area;
public static void main(String[] args) throws Exception {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame = new JFrame();
frame.setUndecorated(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setup(frame);
}
});
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
int width = area.getWidth();
double caretX =
area.getCaret().getMagicCaretPosition().getX();
if (width < caretX + 1) {
throw new RuntimeException(
"Width of the area (" + width +
") is less than caret x-position " +
caretX + 1);
}
area.putClientProperty("caretWidth", 10);
frame.pack();
}
});
new Robot().waitForIdle();
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
int width = area.getWidth();
double caretX =
area.getCaret().getMagicCaretPosition().getX();
if (width < caretX + 10) {
throw new RuntimeException(
"Width of the area (" + width +
") is less than caret x-position " +
caretX + 10);
}
}
});
System.out.println("ok");
} finally {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
if (frame != null) { frame.dispose(); }
}
});
}
}
static void setup(JFrame frame) {
area = new JTextArea();
frame.getContentPane().add(new JScrollPane(area));
area.setText(
"mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm");
area.getCaret().setDot(area.getText().length() + 1);
frame.setSize(300, 200);
frame.setVisible(true);
area.requestFocus();
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import javax.swing.JComboBox;
/*
* @test
* @bug 8015336
* @summary No NPE for BasicComboBoxEditor.setItem(null)
* @author Sergey Malenkov
*/
public class Test8015336 {
public static void main(String[] args) throws Exception {
new JComboBox().getEditor().setItem(new Test8015336());
}
@Override
public String toString() {
return null;
}
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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
@key headful
@bug 6709913
@summary Verifies BasicComboBoxUI.isPopupVisible does not return NPE
@run main BasicComboNPE
*/
import javax.swing.SwingUtilities;
import javax.swing.JComboBox;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.ComboBoxModel;
import java.awt.IllegalComponentStateException;
public class BasicComboNPE extends JComboBox
{
public static void main(String[] args) {
for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
try {
System.out.println("Test for LookAndFeel " + laf.getClassName());
UIManager.setLookAndFeel(laf.getClassName());
new BasicComboNPE().getModel();
} catch (IllegalComponentStateException | ClassNotFoundException | InstantiationException |
IllegalAccessException | UnsupportedLookAndFeelException e ) {
//System.out.println(e);
}
}
}
@Override
public ComboBoxModel getModel()
{
setPopupVisible(false);
isPopupVisible();
return super.getModel();
}
}

View file

@ -0,0 +1,174 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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
* @key headful
* @bug 7072653 8144161 8176448
* @summary JComboBox popup mispositioned if its height exceeds the screen height
* @run main bug7072653
*/
import java.awt.FlowLayout;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.Window;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
public class bug7072653 {
private static JComboBox combobox;
private static JFrame frame;
private static Robot robot;
public static void main(String[] args) throws Exception {
robot = new Robot();
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
UIManager.LookAndFeelInfo[] lookAndFeelArray =
UIManager.getInstalledLookAndFeels();
for (GraphicsDevice sd : ge.getScreenDevices()) {
for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) {
executeCase(lookAndFeelItem.getClassName(), sd);
robot.waitForIdle();
}
}
}
private static void executeCase(String lookAndFeelString, GraphicsDevice sd)
throws Exception {
if (tryLookAndFeel(lookAndFeelString)) {
SwingUtilities.invokeAndWait(() -> {
try {
setup(lookAndFeelString, sd);
test();
} catch (Exception ex) {
throw new RuntimeException(ex);
} finally {
frame.dispose();
}
});
}
}
private static void setup(String lookAndFeelString, GraphicsDevice sd)
throws Exception {
GraphicsConfiguration gc = sd.getDefaultConfiguration();
Rectangle gcBounds = gc.getBounds();
frame = new JFrame("JComboBox Test " + lookAndFeelString, gc);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 200);
frame.getContentPane().setLayout(new FlowLayout());
frame.setLocation(
gcBounds.x + gcBounds.width / 2 - frame.getWidth() / 2,
gcBounds.y + gcBounds.height / 2 - frame.getHeight() / 2);
combobox = new JComboBox(new DefaultComboBoxModel() {
@Override
public Object getElementAt(int index) {
return "Element " + index;
}
@Override
public int getSize() {
return 400;
}
});
combobox.setMaximumRowCount(400);
combobox.putClientProperty("JComboBox.isPopDown", true);
frame.getContentPane().add(combobox);
frame.setVisible(true);
robot.delay(3000); // wait some time to stabilize the size of the
// screen insets after the window is shown
combobox.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
int height = 0;
for (Window window : JFrame.getWindows()) {
if (Window.Type.POPUP == window.getType()) {
if (window.getOwner().isVisible()) {
height = window.getSize().height;
break;
}
}
}
GraphicsConfiguration gc = combobox.getGraphicsConfiguration();
Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
int gcHeight = gc.getBounds().height;
gcHeight = gcHeight - insets.top - insets.bottom;
if (height == gcHeight) {
return;
}
String exception = "Popup window height "
+ "For LookAndFeel" + lookAndFeelString + " is wrong"
+ "\nShould be " + gcHeight + ", Actually " + height;
throw new RuntimeException(exception);
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
});
}
private static void test() throws Exception {
combobox.setPopupVisible(true);
combobox.setPopupVisible(false);
}
private static boolean tryLookAndFeel(String lookAndFeelString)
throws Exception {
try {
UIManager.setLookAndFeel(
lookAndFeelString);
} catch (UnsupportedLookAndFeelException
| ClassNotFoundException
| InstantiationException
| IllegalAccessException e) {
return false;
}
return true;
}
}

View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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
* @key headful
* @bug 8154069
* @summary Jaws reads wrong values from comboboxes when no element is selected
* @run main Bug8154069
*/
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleSelection;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
public class Bug8154069 {
private static JFrame frame;
private static volatile Exception exception = null;
public static void main(String args[]) throws Exception {
try {
try {
UIManager.setLookAndFeel(new NimbusLookAndFeel());
} catch (Exception e) {
throw new RuntimeException(e);
}
SwingUtilities.invokeAndWait(() -> {
frame = new JFrame();
String[] petStrings = { "Bird", "Cat" };
JComboBox<String> cb = new JComboBox<>(petStrings);
cb.setSelectedIndex(1); // select Cat
frame.add(cb);
frame.pack();
try {
cb.setSelectedIndex(-1);
int i = cb.getSelectedIndex();
if (i != -1) {
throw new RuntimeException("getSelectedIndex is not -1");
}
Object o = cb.getSelectedItem();
if (o != null) {
throw new RuntimeException("getSelectedItem is not null");
}
AccessibleContext ac = cb.getAccessibleContext();
AccessibleSelection as = ac.getAccessibleSelection();
int count = as.getAccessibleSelectionCount();
if (count != 0) {
throw new RuntimeException("getAccessibleSelection count is not 0");
}
Accessible a = as.getAccessibleSelection(0);
if (a != null) {
throw new RuntimeException("getAccessibleSelection(0) is not null");
}
} catch (Exception e) {
exception = e;
}
});
if (exception != null) {
System.out.println("Test failed: " + exception.getMessage());
throw exception;
} else {
System.out.println("Test passed.");
}
} finally {
SwingUtilities.invokeAndWait(() -> {
if (frame != null) { frame.dispose(); }
});
}
}
}

View file

@ -0,0 +1,169 @@
/*
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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.EventQueue;
import java.awt.FlowLayout;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.UIManager;
/**
* @test
* @key headful
* @bug 8176448
* @run main/timeout=600 JComboBoxPopupLocation
*/
public final class JComboBoxPopupLocation {
private static final int SIZE = 300;
public static final String PROPERTY_NAME = "JComboBox.isPopDown";
private static volatile Robot robot;
private static volatile JComboBox<String> comboBox;
private static volatile JFrame frame;
public static void main(final String[] args) throws Exception {
robot = new Robot();
robot.setAutoDelay(100);
robot.setAutoWaitForIdle(true);
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] sds = ge.getScreenDevices();
UIManager.LookAndFeelInfo[] lookAndFeelArray =
UIManager.getInstalledLookAndFeels();
for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) {
System.setProperty(PROPERTY_NAME, "true");
step(sds, lookAndFeelItem);
if (lookAndFeelItem.getClassName().contains("Aqua")) {
System.setProperty(PROPERTY_NAME, "false");
step(sds, lookAndFeelItem);
}
}
}
private static void step(GraphicsDevice[] sds,
UIManager.LookAndFeelInfo lookAndFeelItem)
throws Exception {
UIManager.setLookAndFeel(lookAndFeelItem.getClassName());
Point left = null;
for (final GraphicsDevice sd : sds) {
GraphicsConfiguration gc = sd.getDefaultConfiguration();
Rectangle bounds = gc.getBounds();
if (left == null || left.x > bounds.x) {
left = new Point(bounds.x, bounds.y + bounds.height / 2);
}
Point point = new Point(bounds.x, bounds.y);
Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
while (point.y < bounds.y + bounds.height - insets.bottom - SIZE ) {
while (point.x < bounds.x + bounds.width - insets.right - SIZE) {
try {
EventQueue.invokeAndWait(() -> {
setup(point);
});
robot.waitForIdle();
robot.delay(500);
test(comboBox);
robot.waitForIdle();
validate(comboBox);
robot.waitForIdle();
point.translate(bounds.width / 5, 0);
} finally {
dispose();
}
}
point.setLocation(bounds.x, point.y + bounds.height / 5);
}
}
if (left != null) {
final Point finalLeft = left;
finalLeft.translate(-50, 0);
try {
EventQueue.invokeAndWait(() -> {
setup(finalLeft);
});
robot.waitForIdle();
robot.delay(500);
test(comboBox);
robot.waitForIdle();
validate(comboBox);
} finally {
dispose();
}
}
}
private static void dispose() throws Exception {
EventQueue.invokeAndWait(() -> {
if (frame != null) {
frame.dispose();
}
});
}
private static void setup(final Point tmp) {
comboBox = new JComboBox<>();
for (int i = 1; i < 7; i++) {
comboBox.addItem("Long-long-long-long-long text in the item-" + i);
}
String property = System.getProperty(PROPERTY_NAME);
comboBox.putClientProperty(PROPERTY_NAME, Boolean.valueOf(property));
frame = new JFrame();
frame.setAlwaysOnTop(true);
frame.setLayout(new FlowLayout());
frame.add(comboBox);
frame.pack();
frame.setSize(frame.getWidth(), SIZE);
frame.setVisible(true);
frame.setLocation(tmp.x, tmp.y);
}
private static void test(final JComboBox comboBox) throws Exception {
Point pt = comboBox.getLocationOnScreen();
robot.mouseMove(pt.x + comboBox.getWidth() / 2,
pt.y + comboBox.getHeight() / 2);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
int x = pt.x + comboBox.getWidth() / 2;
int y = pt.y + comboBox.getHeight() / 2 + 70;
robot.mouseMove(x, y);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
}
private static void validate(final JComboBox comboBox) throws Exception {
EventQueue.invokeAndWait(() -> {
if (comboBox.getSelectedIndex() == 0) {
throw new RuntimeException();
}
});
}
}

View file

@ -0,0 +1,273 @@
/*
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import javax.swing.JFileChooser;
/*
* @test
* @bug 8323670 8307091 8240690
* @requires os.family == "mac" | os.family == "linux"
* @summary Verifies thread-safety of BasicDirectoryModel (JFileChooser)
* @run main/othervm/timeout=480 -Djava.awt.headless=true ConcurrentModification
*/
public final class ConcurrentModification extends ThreadGroup {
/** Initial number of files. */
private static final long NUMBER_OF_FILES = 50;
/** Maximum number of files created on a timer tick. */
private static final long LIMIT_FILES = 10;
/** Timer period (delay) for creating new files. */
private static final long TIMER_PERIOD = 250;
/**
* Number of threads running {@code fileChooser.rescanCurrentDirectory()}.
*/
private static final int NUMBER_OF_THREADS = 5;
/** Number of repeated calls to {@code rescanCurrentDirectory}. */
private static final int NUMBER_OF_REPEATS = 2_000;
/** Maximum amount a thread waits before initiating rescan. */
private static final long LIMIT_SLEEP = 100;
/** The barrier to start all the scanner threads simultaneously. */
private static final CyclicBarrier start = new CyclicBarrier(NUMBER_OF_THREADS);
/** The barrier to wait for all the scanner threads to complete, plus main thread. */
private static final CyclicBarrier end = new CyclicBarrier(NUMBER_OF_THREADS + 1);
/** List of scanner threads. */
private static final List<Thread> threads = new ArrayList<>(NUMBER_OF_THREADS);
/**
* Stores an exception caught by any of the threads.
* If more exceptions are caught, they're added as suppressed exceptions.
*/
private static final AtomicReference<Throwable> exception =
new AtomicReference<>();
/**
* Stores an {@code IOException} thrown while removing the files.
*/
private static final AtomicReference<IOException> ioException =
new AtomicReference<>();
public static void main(String[] args) throws Throwable {
try {
// Start the test in its own thread group to catch and handle
// all thrown exceptions, in particular in
// BasicDirectoryModel.FilesLoader which is created by Swing.
ThreadGroup threadGroup = new ConcurrentModification();
Thread runner = new Thread(threadGroup,
ConcurrentModification::wrapper,
"Test Runner");
runner.start();
runner.join();
} catch (Throwable throwable) {
handleException(throwable);
}
if (ioException.get() != null) {
System.err.println("An error occurred while removing files:");
ioException.get().printStackTrace();
}
if (exception.get() != null) {
throw exception.get();
}
}
private static void wrapper() {
final long timeStart = System.currentTimeMillis();
try {
runTest(timeStart);
} catch (Throwable throwable) {
handleException(throwable);
} finally {
System.out.printf("Duration: %,d\n",
(System.currentTimeMillis() - timeStart));
}
}
private static void runTest(final long timeStart) throws Throwable {
final Path temp = Files.createDirectory(Paths.get("fileChooser-concurrency-" + timeStart));
final Timer timer = new Timer("File creator");
try {
createFiles(temp);
final JFileChooser fc = new JFileChooser(temp.toFile());
IntStream.range(0, NUMBER_OF_THREADS)
.forEach(i -> {
Thread thread = new Thread(new Scanner(fc));
threads.add(thread);
thread.start();
});
timer.scheduleAtFixedRate(new CreateFilesTimerTask(temp),
0, TIMER_PERIOD);
end.await();
} catch (Throwable e) {
threads.forEach(Thread::interrupt);
throw e;
} finally {
timer.cancel();
deleteFiles(temp);
deleteFile(temp);
}
}
private ConcurrentModification() {
super("bdmConcurrency");
}
@Override
public void uncaughtException(Thread t, Throwable e) {
handleException(t, e);
}
private static void handleException(Throwable throwable) {
handleException(Thread.currentThread(), throwable);
}
private static void handleException(final Thread thread,
final Throwable throwable) {
System.err.println("Exception in " + thread.getName() + ": "
+ throwable.getClass()
+ (throwable.getMessage() != null
? ": " + throwable.getMessage()
: ""));
if (!exception.compareAndSet(null, throwable)) {
exception.get().addSuppressed(throwable);
}
threads.stream()
.filter(t -> t != thread)
.forEach(Thread::interrupt);
}
private record Scanner(JFileChooser fileChooser)
implements Runnable {
@Override
public void run() {
try {
start.await();
int counter = 0;
try {
do {
fileChooser.rescanCurrentDirectory();
Thread.sleep((long) (Math.random() * LIMIT_SLEEP));
} while (++counter < NUMBER_OF_REPEATS
&& !Thread.interrupted());
} catch (InterruptedException e) {
// Just exit the loop
}
} catch (Throwable throwable) {
handleException(throwable);
} finally {
try {
end.await();
} catch (InterruptedException | BrokenBarrierException e) {
handleException(e);
}
}
}
}
private static void createFiles(final Path parent) {
createFiles(parent, 0, NUMBER_OF_FILES);
}
private static void createFiles(final Path parent,
final long start,
final long end) {
LongStream.range(start, end)
.forEach(n -> createFile(parent.resolve(n + ".file")));
}
private static void createFile(final Path file) {
try {
Files.createFile(file);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static void deleteFiles(final Path parent) throws IOException {
try (var stream = Files.walk(parent)) {
stream.filter(p -> p != parent)
.forEach(ConcurrentModification::deleteFile);
}
}
private static void deleteFile(final Path file) {
try {
Files.delete(file);
} catch (IOException e) {
if (!ioException.compareAndSet(null, e)) {
ioException.get().addSuppressed(e);
}
}
}
private static final class CreateFilesTimerTask extends TimerTask {
private final Path temp;
private long no;
public CreateFilesTimerTask(Path temp) {
this.temp = temp;
no = NUMBER_OF_FILES;
}
@Override
public void run() {
try {
long count = (long) (Math.random() * LIMIT_FILES);
createFiles(temp, no, no + count);
no += count;
} catch (Throwable t) {
handleException(t);
}
}
}
}

View file

@ -0,0 +1,277 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import javax.swing.JFileChooser;
/*
* @test
* @bug 8325179
* @requires os.family == "windows"
* @summary Verifies there's only one BasicDirectoryModel.FilesLoader thread
* at any given moment
* @run main/othervm -Djava.awt.headless=true LoaderThreadCount
*/
public final class LoaderThreadCount extends ThreadGroup {
/** Initial number of files. */
private static final long NUMBER_OF_FILES = 500;
/**
* Number of threads running {@code fileChooser.rescanCurrentDirectory()}.
*/
private static final int NUMBER_OF_THREADS = 5;
/** Number of snapshots with live threads. */
private static final int SNAPSHOTS = 20;
/** The barrier to synchronise scanner threads and capturing live threads. */
private static final CyclicBarrier start = new CyclicBarrier(NUMBER_OF_THREADS + 1);
/** List of scanner threads. */
private static final List<Thread> threads = new ArrayList<>(NUMBER_OF_THREADS);
/**
* Stores an exception caught by any of the threads.
* If more exceptions are caught, they're added as suppressed exceptions.
*/
private static final AtomicReference<Throwable> exception =
new AtomicReference<>();
/**
* Stores an {@code IOException} thrown while removing the files.
*/
private static final AtomicReference<IOException> ioException =
new AtomicReference<>();
public static void main(String[] args) throws Throwable {
try {
// Start the test in its own thread group to catch and handle
// all thrown exceptions, in particular in
// BasicDirectoryModel.FilesLoader which is created by Swing.
ThreadGroup threadGroup = new LoaderThreadCount();
Thread runner = new Thread(threadGroup,
LoaderThreadCount::wrapper,
"Test Runner");
runner.start();
runner.join();
} catch (Throwable throwable) {
handleException(throwable);
}
if (ioException.get() != null) {
System.err.println("An error occurred while removing files:");
ioException.get().printStackTrace();
}
if (exception.get() != null) {
throw exception.get();
}
}
private static void wrapper() {
final long timeStart = System.currentTimeMillis();
try {
runTest(timeStart);
} catch (Throwable throwable) {
handleException(throwable);
} finally {
System.out.printf("Duration: %,d\n",
(System.currentTimeMillis() - timeStart));
}
}
private static void runTest(final long timeStart) throws Throwable {
final Path temp = Files.createDirectory(Paths.get("fileChooser-concurrency-" + timeStart));
try {
createFiles(temp);
final JFileChooser fc = new JFileChooser(temp.toFile());
threads.addAll(Stream.generate(() -> new Thread(new Scanner(fc)))
.limit(NUMBER_OF_THREADS)
.toList());
threads.forEach(Thread::start);
// Create snapshots of live threads
List<Thread[]> threadsCapture =
Stream.generate(LoaderThreadCount::getThreadSnapshot)
.limit(SNAPSHOTS)
.toList();
threads.forEach(Thread::interrupt);
List<Long> loaderCount =
threadsCapture.stream()
.map(ta -> Arrays.stream(ta)
.filter(Objects::nonNull)
.map(Thread::getName)
.filter(tn -> tn.startsWith("Basic L&F File Loading Thread"))
.count())
.filter(c -> c > 0)
.toList();
if (loaderCount.isEmpty()) {
throw new RuntimeException("Invalid results: no loader threads detected");
}
System.out.println("Number of snapshots: " + loaderCount.size());
long ones = loaderCount.stream()
.filter(n -> n == 1)
.count();
long twos = loaderCount.stream()
.filter(n -> n == 2)
.count();
long count = loaderCount.stream()
.filter(n -> n > 2)
.count();
System.out.println("Number of snapshots where number of loader threads:");
System.out.println(" = 1: " + ones);
System.out.println(" = 2: " + twos);
System.out.println(" > 2: " + count);
if (count > loaderCount.size() / 2) {
throw new RuntimeException("Detected " + count + " snapshots "
+ "with several loading threads");
}
} catch (Throwable e) {
threads.forEach(Thread::interrupt);
throw e;
} finally {
deleteFiles(temp);
deleteFile(temp);
}
}
private static Thread[] getThreadSnapshot() {
try {
start.await();
// Allow for the scanner threads to initiate re-scanning
Thread.sleep(10);
Thread[] array = new Thread[Thread.activeCount()];
Thread.currentThread()
.getThreadGroup()
.enumerate(array, false);
// Additional delay between captures
Thread.sleep(500);
return array;
} catch (InterruptedException | BrokenBarrierException e) {
handleException(e);
throw new RuntimeException("getThreadSnapshot is interrupted");
}
}
private LoaderThreadCount() {
super("bdmConcurrency");
}
@Override
public void uncaughtException(Thread t, Throwable e) {
handleException(t, e);
}
private static void handleException(Throwable throwable) {
handleException(Thread.currentThread(), throwable);
}
private static void handleException(final Thread thread,
final Throwable throwable) {
System.err.println("Exception in " + thread.getName() + ": "
+ throwable.getClass()
+ (throwable.getMessage() != null
? ": " + throwable.getMessage()
: ""));
if (!exception.compareAndSet(null, throwable)) {
exception.get().addSuppressed(throwable);
}
threads.stream()
.filter(t -> t != thread)
.forEach(Thread::interrupt);
}
private record Scanner(JFileChooser fileChooser)
implements Runnable {
@Override
public void run() {
try {
do {
start.await();
fileChooser.rescanCurrentDirectory();
} while (!Thread.interrupted());
} catch (InterruptedException | BrokenBarrierException e) {
// Just exit the loop
}
}
}
private static void createFiles(final Path parent) {
LongStream.range(0, LoaderThreadCount.NUMBER_OF_FILES)
.mapToObj(n -> parent.resolve(n + ".file"))
.forEach(LoaderThreadCount::createFile);
}
private static void createFile(final Path file) {
try {
Files.createFile(file);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static void deleteFiles(final Path parent) throws IOException {
try (var stream = Files.walk(parent)) {
stream.filter(p -> p != parent)
.forEach(LoaderThreadCount::deleteFile);
}
}
private static void deleteFile(final Path file) {
try {
Files.delete(file);
} catch (IOException e) {
if (!ioException.compareAndSet(null, e)) {
ioException.get().addSuppressed(e);
}
}
}
}

View file

@ -0,0 +1,376 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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 javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.font.NumericShaper;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicGraphicsUtils;
import javax.swing.plaf.metal.MetalLookAndFeel;
/**
* @test
* @bug 8132119 8168992 8169897 8207941
* @author Alexandr Scherbatiy
* @summary Provide public API for text related methods in SwingBasicGraphicsUtils2
*/
public class bug8132119 {
private static final int WIDTH = 50;
private static final int HEIGHT = 50;
private static final Color DRAW_COLOR = Color.RED;
private static final Color BACKGROUND_COLOR = Color.GREEN;
private static final NumericShaper NUMERIC_SHAPER = NumericShaper.getShaper(
NumericShaper.ARABIC);
public static void main(String[] args) throws Exception {
SwingUtilities.invokeAndWait(bug8132119::testStringMethods);
}
private static void testStringMethods() {
setMetalLAF();
testStringWidth();
testStringClip();
testDrawEmptyString();
testDrawString(false);
testDrawString(true);
checkNullArguments();
}
private static void testStringWidth() {
String str = "12345678910\u036F";
JComponent comp = createComponent(str);
Font font = comp.getFont();
FontMetrics fontMetrics = comp.getFontMetrics(font);
float stringWidth = BasicGraphicsUtils.getStringWidth(comp, fontMetrics, str);
if (stringWidth == fontMetrics.stringWidth(str)) {
throw new RuntimeException("Numeric shaper is not used!");
}
if (stringWidth != getLayoutWidth(str, font, NUMERIC_SHAPER)) {
throw new RuntimeException("Wrong text width!");
}
}
private static void testStringClip() {
String str = "1234567890";
JComponent comp = createComponent(str);
FontMetrics fontMetrics = comp.getFontMetrics(comp.getFont());
int width = (int) BasicGraphicsUtils.getStringWidth(comp, fontMetrics, str);
String clip = BasicGraphicsUtils.getClippedString(comp, fontMetrics, str, width);
checkClippedString(str, clip, str);
clip = BasicGraphicsUtils.getClippedString(comp, fontMetrics, str, width + 1);
checkClippedString(str, clip, str);
clip = BasicGraphicsUtils.getClippedString(comp, fontMetrics, str, -1);
checkClippedString(str, clip, "...");
clip = BasicGraphicsUtils.getClippedString(comp, fontMetrics, str, 0);
checkClippedString(str, clip, "...");
clip = BasicGraphicsUtils.getClippedString(comp, fontMetrics,
str, width - width / str.length());
int endIndex = str.length() - 3;
checkClippedString(str, clip, str.substring(0, endIndex) + "...");
}
private static void checkClippedString(String str, String res, String golden) {
if (!golden.equals(res)) {
throw new RuntimeException(String.format("The string '%s' is not "
+ "properly clipped. The result is '%s' instead of '%s'",
str, res, golden));
}
}
private static void testDrawEmptyString() {
JLabel label = new JLabel();
BufferedImage buffImage = createBufferedImage(50, 50);
Graphics2D g2 = buffImage.createGraphics();
g2.setColor(DRAW_COLOR);
BasicGraphicsUtils.drawString(null, g2, null, 0, 0);
BasicGraphicsUtils.drawString(label, g2, null, 0, 0);
BasicGraphicsUtils.drawString(null, g2, "", 0, 0);
BasicGraphicsUtils.drawString(label, g2, "", 0, 0);
BasicGraphicsUtils.drawStringUnderlineCharAt(null, g2, null, 3, 0, 0);
BasicGraphicsUtils.drawStringUnderlineCharAt(label, g2, null, 3, 0, 0);
BasicGraphicsUtils.drawStringUnderlineCharAt(null, g2, "", 3, 0, 0);
BasicGraphicsUtils.drawStringUnderlineCharAt(label, g2, "", 3, 0, 0);
g2.dispose();
checkImageIsEmpty(buffImage);
}
private static void testDrawString(boolean underlined) {
String str = "AOB";
JComponent comp = createComponent(str);
BufferedImage buffImage = createBufferedImage(WIDTH, HEIGHT);
Graphics2D g2 = buffImage.createGraphics();
g2.setColor(DRAW_COLOR);
g2.setFont(comp.getFont());
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
FontMetrics fontMetrices = comp.getFontMetrics(comp.getFont());
float width = BasicGraphicsUtils.getStringWidth(comp, fontMetrices, str);
int y = 3 * HEIGHT / 4;
if (underlined) {
BasicGraphicsUtils.drawStringUnderlineCharAt(comp, g2, str, 1, 0, y);
} else {
BasicGraphicsUtils.drawString(comp, g2, str, 0, y);
}
g2.dispose();
float xx = 0;
if (underlined) {
xx = BasicGraphicsUtils.getStringWidth(comp, fontMetrices, "A") +
BasicGraphicsUtils.getStringWidth(comp, fontMetrices, "O")/2 - 5;
} else {
xx = BasicGraphicsUtils.getStringWidth(comp, fontMetrices, "A") +
BasicGraphicsUtils.getStringWidth(comp, fontMetrices, "O")/2;
}
checkImageContainsSymbol(buffImage, (int) xx, underlined ? 3 : 2);
}
private static void checkNullArguments() {
Graphics2D g = null;
try {
String text = "Test";
JComponent component = new JLabel(text);
BufferedImage img = createBufferedImage(100, 100);
g = img.createGraphics();
checkNullArguments(component, g, text);
} finally {
g.dispose();
}
}
private static void checkNullArguments(JComponent comp, Graphics2D g,
String text) {
checkNullArgumentsDrawString(comp, g, text);
checkNullArgumentsDrawStringUnderlineCharAt(comp, g, text);
checkNullArgumentsGetClippedString(comp, text);
checkNullArgumentsGetStringWidth(comp, text);
}
private static void checkNullArgumentsDrawString(JComponent comp, Graphics2D g,
String text) {
float x = 50;
float y = 50;
BasicGraphicsUtils.drawString(null, g, text, x, y);
BasicGraphicsUtils.drawString(comp, g, null, x, y);
try {
BasicGraphicsUtils.drawString(comp, null, text, x, y);
} catch (NullPointerException e) {
return;
}
throw new RuntimeException("NPE is not thrown");
}
private static void checkNullArgumentsDrawStringUnderlineCharAt(
JComponent comp, Graphics2D g, String text) {
int x = 50;
int y = 50;
BasicGraphicsUtils.drawStringUnderlineCharAt(null, g, text, 1, x, y);
BasicGraphicsUtils.drawStringUnderlineCharAt(comp, g, null, 1, x, y);
try {
BasicGraphicsUtils.drawStringUnderlineCharAt(comp, null, text, 1, x, y);
} catch (NullPointerException e) {
return;
}
throw new RuntimeException("NPE is not thrown");
}
private static void checkNullArgumentsGetClippedString(
JComponent comp, String text) {
FontMetrics fontMetrics = comp.getFontMetrics(comp.getFont());
BasicGraphicsUtils.getClippedString(null, fontMetrics, text, 1);
String result = BasicGraphicsUtils.getClippedString(comp, fontMetrics, null, 1);
if (!"".equals(result)) {
throw new RuntimeException("Empty string is not returned!");
}
try {
BasicGraphicsUtils.getClippedString(comp, null, text, 1);
} catch (NullPointerException e) {
return;
}
throw new RuntimeException("NPE is not thrown");
}
private static void checkNullArgumentsGetStringWidth(JComponent comp,
String text) {
FontMetrics fontMetrics = comp.getFontMetrics(comp.getFont());
BasicGraphicsUtils.getStringWidth(null, fontMetrics, text);
float result = BasicGraphicsUtils.getStringWidth(comp, fontMetrics, null);
if (result != 0) {
throw new RuntimeException("The string length is not 0");
}
try {
BasicGraphicsUtils.getStringWidth(comp, null, text);
} catch (NullPointerException e) {
return;
}
throw new RuntimeException("NPE is not thrown");
}
private static void setMetalLAF() {
try {
UIManager.setLookAndFeel(new MetalLookAndFeel());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static JComponent createComponent(String str) {
JComponent comp = new JLabel(str);
comp.setSize(WIDTH, HEIGHT);
comp.putClientProperty(TextAttribute.NUMERIC_SHAPING, NUMERIC_SHAPER);
comp.setFont(getFont());
return comp;
}
private static String getFontName(String fn, String[] fontNames) {
String fontName = null;
for (String name : fontNames) {
if (fn.equals(name)) {
fontName = name;
break;
}
}
return fontName;
}
private static Font getFont() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontNames = ge.getAvailableFontFamilyNames();
// We do not have Arial on all systems so provide some reasonable fallbacks.
// In case the fallbacks are not available as well, choose as last fallback
// the first font - however this might be a problematic choice.
String fontName = getFontName("Arial", fontNames);
if (fontName == null) {
fontName = getFontName("Bitstream Charter", fontNames);
if (fontName == null) {
fontName = getFontName("Dialog", fontNames);
if (fontName == null) {
fontName = fontNames[0];
System.out.println("warning - preferred fonts not on the system, fall back to first font " + fontName);
}
}
}
return new Font(fontName, Font.PLAIN, 30);
}
private static float getLayoutWidth(String text, Font font, NumericShaper shaper) {
HashMap map = new HashMap();
map.put(TextAttribute.FONT, font);
map.put(TextAttribute.NUMERIC_SHAPING, shaper);
FontRenderContext frc = new FontRenderContext(null, false, false);
TextLayout layout = new TextLayout(text, map, frc);
return layout.getAdvance();
}
private static void checkImageIsEmpty(BufferedImage buffImage) {
int background = BACKGROUND_COLOR.getRGB();
for (int i = 0; i < buffImage.getWidth(); i++) {
for (int j = 0; j < buffImage.getHeight(); j++) {
if (background != buffImage.getRGB(i, j)) {
throw new RuntimeException("Image is not empty!");
}
}
}
}
private static void checkImageContainsSymbol(BufferedImage buffImage,
int x, int intersections) {
int background = BACKGROUND_COLOR.getRGB();
boolean isBackground = true;
int backgroundChangesCount = 0;
for (int y = 0; y < buffImage.getHeight(); y++) {
if (!(isBackground ^ (background != buffImage.getRGB(x, y)))) {
isBackground = !isBackground;
backgroundChangesCount++;
}
}
if (backgroundChangesCount != intersections * 2) {
try {
ImageIO.write(buffImage, "png", new File("image.png"));
} catch (Exception e) {}
throw new RuntimeException("String is not properly drawn!");
}
}
private static BufferedImage createBufferedImage(int width, int height) {
BufferedImage bufffImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufffImage.createGraphics();
g.setColor(BACKGROUND_COLOR);
g.fillRect(0, 0, width, height);
g.dispose();
return bufffImage;
}
}

View file

@ -0,0 +1,77 @@
/*
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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 4198822
* @summary Tests that the bottom line drawn by
* BasicGraphicsUtils.drawEtchedRect extends to the end.
* @run main DrawEtchedRectTest
*/
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.plaf.basic.BasicGraphicsUtils;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
public class DrawEtchedRectTest {
private static final int WIDTH = 200;
private static final int HEIGHT = 200;
private static final int RANGE = 10;
public static void main(String[] args) throws Exception {
// Draw etched rectangle to a BufferedImage
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, TYPE_INT_ARGB);
Graphics2D g2d = image.createGraphics();
Component sq = new Component() {
public void paint(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH, HEIGHT);
BasicGraphicsUtils.drawEtchedRect(g, 0, 0, WIDTH, HEIGHT,
Color.black, Color.black,
Color.black, Color.black);
}
};
sq.paint(g2d);
g2d.dispose();
// Check if connected at bottom-right corner
int c1;
int c2;
for (int i = 1; i < RANGE; i++) {
c1 = image.getRGB(WIDTH - i, HEIGHT - 1);
c2 = image.getRGB(WIDTH - 1, HEIGHT - i);
if (c1 == Color.WHITE.getRGB() || c2 == Color.WHITE.getRGB()) {
ImageIO.write(image, "png", new File("failImage.png"));
throw new RuntimeException("Bottom line is not connected!");
}
}
}
}

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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 4228104
* @summary Tests work of BODY BACKGROUND tag in HTML renderer
* @library /java/awt/regtesthelpers
* @build PassFailJFrame
* @run main/manual bug4228104
*/
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class bug4228104 {
static final String INSTRUCTIONS = """
There should be an image displaying dukes under the rows of digits.
If you can see it, the test PASSES. Otherwise, the test FAILS.
""";
public static void main(String[] args) throws Exception {
PassFailJFrame.builder()
.title("bug4228104 Test Instructions")
.instructions(INSTRUCTIONS)
.columns(40)
.testUI(bug4228104::createUI)
.build()
.awaitAndCheck();
}
static JFrame createUI() {
JFrame f = new JFrame("Background HTML Text Test");
String dir = System.getProperty("test.src",
System.getProperty("user.dir"));
String htmlText1 =
"<html><BODY BACKGROUND=\"file:" + dir
+ "/duke.gif\">\n" +
"<br>111111111111111111" +
"<br>111111111111111111" +
"<br>111111111111111111" +
"<br>111111111111111111" +
"<br>111111111111111111" +
"<br>111111111111111111" +
"<br>111111111111111111" +
"<br>111111111111111111" +
"<br>111111111111111111";
JLabel button1 = new JLabel(htmlText1);
f.add(button1, BorderLayout.NORTH);
f.setSize(200, 200);
return f;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -0,0 +1,113 @@
/*
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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
* @key headful
* @bug 4251579
* @summary Tests if style sheets are working in JLabel
* @run main bug4251579
*/
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Robot;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.JLabel;
public class bug4251579 {
private static JLabel htmlComponent;
private static JFrame mainFrame;
public static void main(String[] args) throws Exception {
final Robot robot = new Robot();
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
robot.waitForIdle();
robot.delay(1000);
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
boolean passed = false;
Point p = htmlComponent.getLocationOnScreen();
Dimension d = htmlComponent.getSize();
int x0 = p.x;
int y = p.y + d.height / 2;
for (int x = x0; x < x0 + d.width; x++) {
if (robot.getPixelColor(x, y).equals(Color.blue)) {
passed = true;
break;
}
}
if (!passed) {
throw new RuntimeException("Test failed.");
}
}
});
} finally {
SwingUtilities.invokeAndWait(() -> {
if (mainFrame != null) {
mainFrame.dispose();
}
});
}
}
private static void createAndShowGUI() {
String htmlText =
"<html>"
+ "<head><style> .blue{ color:blue; } </style></head>"
+ "<body"
+ "<P class=\"blue\"> should be rendered with BLUE class definition</P>"
+ "</body>";
mainFrame = new JFrame("bug4251579");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
htmlComponent = new JLabel(htmlText);
mainFrame.getContentPane().add(htmlComponent);
mainFrame.setLocationRelativeTo(null);
mainFrame.pack();
mainFrame.setVisible(true);
}
}

View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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
* @key headful
* @bug 4960629 7124238
* @summary Tests if font for html text on widgets in correct.
* @author Denis Sharypov
* @run main bug4960629
*/
import java.awt.Font;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.AttributeSet;
import javax.swing.text.View;
import javax.swing.text.html.StyleSheet;
import javax.swing.text.html.HTMLDocument;
public class bug4960629 {
private boolean passed = false;
private JLabel label = null;
private JFrame f = null;
public void createAndShowGUI() throws Exception {
try {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
label = new JLabel("<html><P>This is a test of the</P></html>");
System.out.println("UIManager.getLookAndFeel()"
+ UIManager.getLookAndFeel().getClass());
f = new JFrame();
f.getContentPane().add(label);
f.pack();
f.setVisible(true);
test();
} finally {
if (f != null) { f.dispose(); }
}
}
bug4960629() throws InvocationTargetException, InterruptedException {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
try {
createAndShowGUI();
} catch (Exception e) {
throw new RuntimeException("Exception "
+ e.getMessage());
}
}
});
}
private void test() {
View root = ((View)label.getClientProperty(BasicHTML.propertyKey))
.getView(0);
int n = root.getViewCount();
View v = root.getView(n - 1);
AttributeSet attrs = v.getAttributes();
StyleSheet ss = ((HTMLDocument) v.getDocument()).getStyleSheet();
Font font = ss.getFont(attrs);
System.out.println(font.getSize());
passed = (font.getSize() == 12);
if(!passed) {
throw new RuntimeException("Test failed.");
}
}
public static void main(String args[]) throws Throwable {
new bug4960629();
}
}

View file

@ -0,0 +1,120 @@
/*
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import static java.awt.image.BufferedImage.TYPE_INT_RGB;
/*
* @test
* @bug 4248210
* @key headful
* @summary Tests that HTML in JLabel is painted using LAF-defined
foreground color
* @run main bug4248210
*/
public class bug4248210 {
private static final Color labelColor = Color.red;
public static void main(String[] args) throws Exception {
for (UIManager.LookAndFeelInfo laf :
UIManager.getInstalledLookAndFeels()) {
if (!(laf.getName().contains("Motif") || laf.getName().contains("GTK"))) {
System.out.println("Testing LAF: " + laf.getName());
SwingUtilities.invokeAndWait(() -> test(laf));
}
}
}
private static void test(UIManager.LookAndFeelInfo laf) {
setLookAndFeel(laf);
if (UIManager.getLookAndFeel() instanceof NimbusLookAndFeel) {
// reset "basic" properties
UIManager.getDefaults().put("Label.foreground", null);
// set "synth - nimbus" properties
UIManager.getDefaults().put("Label[Enabled].textForeground", labelColor);
} else {
// reset "synth - nimbus" properties
UIManager.getDefaults().put("Label[Enabled].textForeground", null);
// set "basic" properties
UIManager.getDefaults().put("Label.foreground", labelColor);
}
JLabel label = new JLabel("<html><body>\u2588 \u2588 \u2588 \u2588</body></html>");
label.setSize(150, 30);
BufferedImage img = paintToImage(label);
if (!chkImgForegroundColor(img)) {
try {
ImageIO.write(img, "png", new File("Label_" + laf.getName() + ".png"));
} catch (IOException ignored) {}
throw new RuntimeException("JLabel not painted with LAF defined " +
"foreground color");
}
System.out.println("Test Passed");
}
private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) {
try {
UIManager.setLookAndFeel(laf.getClassName());
} catch (UnsupportedLookAndFeelException ignored) {
System.out.println("Unsupported LAF: " + laf.getClassName());
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException e) {
throw new RuntimeException(e);
}
}
private static BufferedImage paintToImage(JComponent content) {
BufferedImage im = new BufferedImage(content.getWidth(), content.getHeight(),
TYPE_INT_RGB);
Graphics2D g = (Graphics2D) im.getGraphics();
g.setBackground(Color.WHITE);
g.clearRect(0, 0, content.getWidth(), content.getHeight());
content.paint(g);
g.dispose();
return im;
}
private static boolean chkImgForegroundColor(BufferedImage img) {
for (int x = 0; x < img.getWidth(); ++x) {
for (int y = 0; y < img.getHeight(); ++y) {
if (img.getRGB(x, y) == labelColor.getRGB()) {
return true;
}
}
}
return false;
}
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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 4331515
* @requires (os.family == "windows")
* @summary System menu of an internal frame shouldn't have duplicated items in Win L&F
* @library /java/awt/regtesthelpers
* @build PassFailJFrame
* @run main/manual bug4331515
*/
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.UIManager;
public class bug4331515 {
static final String INSTRUCTIONS = """
Open the system menu of internal frame "JIF" placed in the frame "Test".
If this menu contains duplicates of some items then test FAILS, else
test PASSES.
""";
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
PassFailJFrame.builder()
.title("bug4331515 Test Instructions")
.instructions(INSTRUCTIONS)
.columns(40)
.testUI(bug4331515::createUI)
.build()
.awaitAndCheck();
}
static JFrame createUI() {
JFrame fr = new JFrame("System Menu in JIF Test");
JDesktopPane dp = new JDesktopPane();
fr.setContentPane(dp);
JInternalFrame jif = new JInternalFrame("JIF", true, true, true, true);
dp.add(jif);
jif.setBounds(20, 20, 120, 100);
jif.setVisible(true);
fr.setSize(200, 200);
return fr;
}
}

View file

@ -0,0 +1,176 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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
* @key headful
* @bug 7172652
* @summary With JDK 1.7 text field does not obtain focus when using mnemonic Alt/Key combin
* @author Semyon Sadetsky
* @requires (os.family == "windows")
* @library /test/lib
* @build jdk.test.lib.Platform
* @run main bug7172652
*/
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.KeyEvent;
import jdk.test.lib.Platform;
public class bug7172652 {
private static JMenu menu;
private static JFrame frame;
private static Boolean selected;
public static void main(String[] args) throws Exception {
if (!Platform.isWindows()) {
System.out.println("ok");
return;
}
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
setup();
}
});
test();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
frame.dispose();
}
});
}
private static void test() throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
menu.getModel().addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
selected = menu.isSelected();
}
});
}
});
Robot robot = new Robot();
robot.setAutoDelay(200);
robot.keyPress(KeyEvent.VK_ALT);
robot.keyPress(KeyEvent.VK_F);
robot.keyRelease(KeyEvent.VK_F);
robot.keyRelease(KeyEvent.VK_ALT);
robot.waitForIdle();
if( selected != null ) {
throw new RuntimeException("Menu is notified selected= " + selected);
}
robot.keyPress(KeyEvent.VK_ALT);
robot.keyPress(KeyEvent.VK_F);
robot.keyRelease(KeyEvent.VK_F);
robot.keyRelease(KeyEvent.VK_ALT);
if( selected != null ) {
throw new RuntimeException("Menu is notified selected= " + selected);
}
robot.waitForIdle();
robot.keyPress(KeyEvent.VK_ALT);
robot.keyPress(KeyEvent.VK_F);
robot.keyRelease(KeyEvent.VK_F);
robot.keyRelease(KeyEvent.VK_ALT);
if( selected != null ) {
throw new RuntimeException("Menu is notified selected= " + selected);
}
robot.waitForIdle();
robot.keyPress(KeyEvent.VK_ALT);
robot.keyPress(KeyEvent.VK_F);
robot.keyRelease(KeyEvent.VK_F);
robot.keyRelease(KeyEvent.VK_ALT);
if( selected != null ) {
throw new RuntimeException("Menu is notified selected= " + selected);
}
robot.waitForIdle();
System.out.printf("ok");
}
private static void setup() {
JLabel firstLbl = new JLabel("First name");
JLabel lastLbl = new JLabel("Last name");
JMenuBar menuBar = new JMenuBar();
JTextField firstTxtFld = new JTextField(20);
JTextField lastTxtFld = new JTextField(20);
JDesktopPane desktopPane = new JDesktopPane();
JInternalFrame iframe = new JInternalFrame("A frame", true, true, true, true);
// Set an initial size
iframe.setSize(200, 220);
// By default, internal frames are not visible; make it visible
iframe.setVisible(true);
JPanel pane = new JPanel();
pane.setLayout(new FlowLayout());
pane.add(firstLbl);
pane.add(firstTxtFld);
pane.add(lastLbl);
pane.add(lastTxtFld);
firstLbl.setLabelFor(firstTxtFld);
firstLbl.setDisplayedMnemonic('F');
lastLbl.setLabelFor(lastTxtFld);
lastLbl.setDisplayedMnemonic('L');
iframe.getContentPane().add(pane);
iframe.setJMenuBar(menuBar);
menu = new JMenu("FirstMenu");
//m.setMnemonic('i');
menuBar.add(menu);
desktopPane.add(iframe);
frame = new JFrame();
frame.setUndecorated(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(desktopPane);
frame.setSize(300, 300);
frame.setVisible(true);
}
}

View file

@ -0,0 +1,106 @@
/*
* Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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
* @key headful
* @bug 4983388 8015600
* @summary shortcuts on menus do not work on JDS
* @library ../../../../regtesthelpers
* @build Util
* @run main bug4983388
*/
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.util.concurrent.CountDownLatch;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import static java.util.concurrent.TimeUnit.SECONDS;
public class bug4983388 {
static JFrame frame;
private static final CountDownLatch menuSelected = new CountDownLatch(1);
private static class TestMenuListener implements MenuListener {
@Override
public void menuCanceled(MenuEvent e) {}
@Override
public void menuDeselected(MenuEvent e) {}
@Override
public void menuSelected(MenuEvent e) {
System.out.println("menuSelected");
menuSelected.countDown();
}
}
private static void createAndShowGUI() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("File");
menu.setMnemonic('F');
menuBar.add(menu);
menu.addMenuListener(new TestMenuListener());
frame = new JFrame("bug4983388");
frame.setJMenuBar(menuBar);
frame.setLocationRelativeTo(null);
frame.setSize(250, 100);
frame.setVisible(true);
}
public static void main(String[] args) throws Exception {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
} catch (UnsupportedLookAndFeelException | ClassNotFoundException ex) {
System.err.println("GTKLookAndFeel is not supported on this platform. "
+ "Using default LaF for this platform.");
}
SwingUtilities.invokeAndWait(bug4983388::createAndShowGUI);
Robot robot = new Robot();
robot.setAutoDelay(50);
robot.waitForIdle();
robot.delay(500);
Util.hitMnemonics(robot, KeyEvent.VK_F);
try {
if (!menuSelected.await(1, SECONDS)) {
throw new RuntimeException("shortcuts on menus do not work");
}
} finally {
SwingUtilities.invokeAndWait(frame::dispose);
}
}
}

View file

@ -0,0 +1,112 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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
* @key headful
* @bug 6827800
* @summary Test to check hidden default button does not respond to 'Enter' key
* @run main HiddenDefaultButtonTest
*/
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class HiddenDefaultButtonTest {
private static int ButtonClickCount = 0;
private static JFrame frame;
private static void createGUI() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Default button");
button.setDefaultCapable(true);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ButtonClickCount++;
}
});
frame.add(button);
button.setVisible(false);
frame.getRootPane().setDefaultButton(button);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static void disposeTestUI() throws Exception {
SwingUtilities.invokeAndWait(() -> {
frame.dispose();
});
}
private static void test() throws Exception {
// Create Robot
Robot testRobot = new Robot();
testRobot.waitForIdle();
testRobot.keyPress(KeyEvent.VK_ENTER);
testRobot.delay(20);
testRobot.keyRelease(KeyEvent.VK_ENTER);
testRobot.delay(200);
testRobot.keyPress(KeyEvent.VK_ENTER);
testRobot.delay(20);
testRobot.keyRelease(KeyEvent.VK_ENTER);
testRobot.waitForIdle();
if (ButtonClickCount != 0) {
disposeTestUI();
throw new RuntimeException("DefaultButton is pressed even if it is invisible");
}
}
public static void main(String[] args) throws Exception {
// create UI
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
HiddenDefaultButtonTest.createGUI();
}
});
// Test default button press by pressing EnterKey using Robot
test();
// dispose UI
HiddenDefaultButtonTest.disposeTestUI();
}
}

View file

@ -0,0 +1,190 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
/*
* @test
* @bug 8166591 8173876
* @key headful
* @summary [macos 10.12] Trackpad scrolling of text on OS X 10.12 Sierra
* is very fast (Trackpad, Retina only)
* @requires (os.family == "windows" | os.family == "mac")
* @run main/manual/othervm TooMuchWheelRotationEventsTest
*/
public class TooMuchWheelRotationEventsTest {
private static volatile boolean testResult = false;
private static volatile CountDownLatch countDownLatch;
private static final String INSTRUCTIONS = " INSTRUCTIONS:\n"
+ " Try to check the issue with trackpad\n"
+ "\n"
+ " If the trackpad is not supported, press PASS\n"
+ "\n"
+ " Use the trackpad to slightly scroll the JTextArea horizontally and vertically.\n"
+ " If the text area is scrolled too fast press FAIL, else press PASS.";
public static void main(String args[]) throws Exception {
countDownLatch = new CountDownLatch(1);
SwingUtilities.invokeLater(TooMuchWheelRotationEventsTest::createUI);
countDownLatch.await(15, TimeUnit.MINUTES);
if (!testResult) {
throw new RuntimeException("Test fails!");
}
}
private static void createUI() {
final JFrame mainFrame = new JFrame("Trackpad scrolling test");
GridBagLayout layout = new GridBagLayout();
JPanel mainControlPanel = new JPanel(layout);
JPanel resultButtonPanel = new JPanel(layout);
GridBagConstraints gbc = new GridBagConstraints();
JPanel testPanel = createTestPanel();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
mainControlPanel.add(testPanel, gbc);
JTextArea instructionTextArea = new JTextArea();
instructionTextArea.setText(INSTRUCTIONS);
instructionTextArea.setEditable(false);
instructionTextArea.setBackground(Color.white);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
mainControlPanel.add(instructionTextArea, gbc);
JButton passButton = new JButton("Pass");
passButton.setActionCommand("Pass");
passButton.addActionListener((ActionEvent e) -> {
testResult = true;
mainFrame.dispose();
countDownLatch.countDown();
});
JButton failButton = new JButton("Fail");
failButton.setActionCommand("Fail");
failButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mainFrame.dispose();
countDownLatch.countDown();
}
});
gbc.gridx = 0;
gbc.gridy = 0;
resultButtonPanel.add(passButton, gbc);
gbc.gridx = 1;
gbc.gridy = 0;
resultButtonPanel.add(failButton, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
mainControlPanel.add(resultButtonPanel, gbc);
mainFrame.add(mainControlPanel);
mainFrame.pack();
mainFrame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
mainFrame.dispose();
countDownLatch.countDown();
}
});
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
private static JPanel createTestPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
JTextArea textArea = new JTextArea(20, 20);
textArea.setText(getLongString());
JScrollPane scrollPane = new JScrollPane(textArea);
panel.add(scrollPane);
return panel;
}
private static String getLongString() {
String lowCaseString = getLongString('a', 'z');
String upperCaseString = getLongString('A', 'Z');
String digitsString = getLongString('0', '9');
int repeat = 30;
StringBuilder lowCaseBuilder = new StringBuilder();
StringBuilder upperCaseBuilder = new StringBuilder();
StringBuilder digitsBuilder = new StringBuilder();
for (int i = 0; i < repeat; i++) {
lowCaseBuilder.append(lowCaseString).append(' ');
upperCaseBuilder.append(upperCaseString).append(' ');
digitsBuilder.append(digitsString).append(' ');
}
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 200; i++) {
builder.append(upperCaseBuilder).append('\n')
.append(lowCaseBuilder).append('\n')
.append(digitsBuilder).append("\n\n\n");
}
return builder.toString();
}
private static String getLongString(char c1, char c2) {
char[] chars = new char[c2 - c1 + 1];
for (char i = c1; i <= c2; i++) {
chars[i - c1] = i;
}
return new String(chars);
}
}

View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 6632810
* @summary javax.swing.plaf.basic.BasicScrollPaneUI.getBaseline(JComponent, int, int) doesn't throw NPE and IAE
* @author Pavel Porvatov
*/
import javax.swing.*;
import javax.swing.plaf.basic.BasicScrollPaneUI;
public class Test6632810 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
BasicScrollPaneUI ui = new BasicScrollPaneUI();
ui.installUI(new JScrollPane());
try {
ui.getBaseline(null, 1, 1);
throw new RuntimeException("getBaseline(null, 1, 1) does not throw NPE");
} catch (NullPointerException e) {
// Ok
}
int[][] illegelParams = new int[][]{
{-1, 1,},
{1, -1,},
{-1, -1,},
};
for (int[] illegelParam : illegelParams) {
try {
int width = illegelParam[0];
int height = illegelParam[1];
ui.getBaseline(new JScrollPane(), width, height);
throw new RuntimeException("getBaseline(new JScrollPane(), " + width + ", " + height +
") does not throw IAE");
} catch (IllegalArgumentException e) {
// Ok
}
}
}
});
}
}

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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 4220108
* @summary JSlider in JInternalFrame should be painted correctly
* @library /java/awt/regtesthelpers
* @build PassFailJFrame
* @run main/manual bug4220108
*/
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JSlider;
public class bug4220108 {
static final String INSTRUCTIONS = """
If you see a slider in the internal frame, then the test PASSES.
Otherwise the test FAILS.
""";
public static void main(String[] args) throws Exception {
PassFailJFrame.builder()
.title("bug4220108 Test Instructions")
.instructions(INSTRUCTIONS)
.columns(40)
.testUI(bug4220108::createUI)
.build()
.awaitAndCheck();
}
static JFrame createUI() {
JFrame f = new JFrame("Internal Frame Slider Test");
f.setLayout(new FlowLayout());
JDesktopPane desktop = new JDesktopPane();
f.setContentPane(desktop);
JInternalFrame iFrame =
new JInternalFrame("Slider Frame", true, true, true, true);
JSlider sl = new JSlider();
iFrame.add(sl);
iFrame.add(new JLabel("Label"), BorderLayout.SOUTH);
desktop.add(iFrame);
iFrame.pack();
iFrame.setVisible(true);
f.setSize(300, 200);
return f;
}
}

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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 javax.swing.JColorChooser;
import javax.swing.UIManager;
import jtreg.SkippedException;
/*
* @test
* @bug 4419255
* @library /java/awt/regtesthelpers /test/lib
* @build PassFailJFrame
* @summary Tests if Metal Slider's thumb isn't clipped
* @run main/manual bug4419255
*/
public class bug4419255 {
public static void main(String[] args) throws Exception {
// ColorChooser UI design is different for GTK L&F.
// There is no RGB tab available for GTK L&F, skip the testing.
if (UIManager.getLookAndFeel().getName().contains("GTK")) {
throw new SkippedException("Test not applicable for GTK L&F");
}
String instructions = """
Choose RGB tab. If sliders' thumbs are painted correctly
(top is not clipped, black line is visible),
then test passed. Otherwise it failed.""";
PassFailJFrame.builder()
.title("bug4419255")
.instructions(instructions)
.columns(40)
.testUI(bug4419255::createColorChooser)
.build()
.awaitAndCheck();
}
private static JColorChooser createColorChooser() {
return new JColorChooser(Color.BLUE);
}
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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 4165874
* @summary Adds a MouseListener to the splitpane divider.
* @library /java/awt/regtesthelpers
* @build PassFailJFrame
* @run main/manual AddMouseListenerTest
*/
import java.awt.Component;
import java.awt.event.MouseAdapter;
import javax.swing.JFrame;
import javax.swing.JSplitPane;
public class AddMouseListenerTest {
static final String INSTRUCTIONS = """
Try dragging the split pane divider, if you can, click PASS,
else click FAIL.
""";
public static void main(String[] args) throws Exception {
PassFailJFrame.builder()
.title("AddMouseListenerTest Test Instructions")
.instructions(INSTRUCTIONS)
.columns(40)
.testUI(AddMouseListenerTest::createUI)
.build()
.awaitAndCheck();
}
static JFrame createUI() {
JFrame f = new JFrame("JSplitPane With ActionListener Test");
JSplitPane sp = new JSplitPane();
sp.setContinuousLayout(true);
Component[] children = sp.getComponents();
for (int counter = children.length - 1; counter >= 0; counter--) {
children[counter].addMouseListener(new MouseAdapter() {});
}
f.getContentPane().add(sp);
f.setSize(400, 400);
return f;
}
}

View file

@ -0,0 +1,87 @@
/*
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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 4199666
* @summary Makes sure initial negative size of a component does not confuse
* JSplitPane.
* @library /java/awt/regtesthelpers
* @build PassFailJFrame
* @run main/manual NegativeSizeTest
*/
import java.awt.BorderLayout;
import java.awt.CardLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
public class NegativeSizeTest {
static final String INSTRUCTIONS = """
Click on the 'Show JSplitPane' button. If two buttons appear,
click PASS, otherwise click FAIL.
""";
public static void main(String[] args) throws Exception {
PassFailJFrame.builder()
.title("NegativeSizeTest Test Instructions")
.instructions(INSTRUCTIONS)
.columns(40)
.testUI(NegativeSizeTest::createUI)
.build()
.awaitAndCheck();
}
static JFrame createUI() {
JFrame f = new JFrame("Negative Size Test");
CardLayout cardLayout = new CardLayout();
JPanel mainPanel = new JPanel(cardLayout);
JSplitPane splitPane = new JSplitPane();
splitPane.setContinuousLayout(true);
JPanel splitContainer = new JPanel(new BorderLayout());
splitContainer.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
splitContainer.add(splitPane, BorderLayout.CENTER);
if (false) {
mainPanel.add(splitContainer, "split");
mainPanel.add(new JPanel(), "blank");
}
else {
mainPanel.add(new JPanel(), "blank");
mainPanel.add(splitContainer, "split");
}
f.add(mainPanel, BorderLayout.CENTER);
JButton button = new JButton("Show JSplitPane");
button.addActionListener(e -> cardLayout.show(mainPanel, "split"));
f.add(button, BorderLayout.SOUTH);
f.setSize(400, 300);
return f;
}
}

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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 4208549
* @summary Makes sure preferred size returned by layout managers used by
* JSplitPane is correct.
* @library /java/awt/regtesthelpers
* @build PassFailJFrame
* @run main/manual PreferredSizeLayoutTest
*/
import java.awt.Container;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JSplitPane;
public class PreferredSizeLayoutTest {
static final String INSTRUCTIONS = """
If the buttons in the JSplitpanes do not have '...' in them,
click PASS, otherwise click FAIL.
""";
public static void main(String[] args) throws Exception {
PassFailJFrame.builder()
.title("PreferredSizeLayoutTest Test Instructions")
.instructions(INSTRUCTIONS)
.columns(40)
.testUI(PreferredSizeLayoutTest::createUI)
.build()
.awaitAndCheck();
}
static JFrame createUI() {
JFrame f = new JFrame("Preferred Size Layout Test");
Container parent = f.getContentPane();
JSplitPane sp = new JSplitPane();
parent.setLayout(new FlowLayout());
sp.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
parent.add(sp);
sp = new JSplitPane();
sp.setOrientation(JSplitPane.VERTICAL_SPLIT);
parent.add(sp);
f.setSize(400, 300);
return f;
}
}

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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 6657026 7190595
* @summary Tests shared BasicSplitPaneUI in different application contexts
* @author Sergey Malenkov
* @modules java.desktop/sun.awt
*/
import sun.awt.SunToolkit;
import java.awt.event.ActionEvent;
import java.util.Set;
import javax.swing.JSplitPane;
import javax.swing.plaf.basic.BasicSplitPaneUI;
public class Test6657026 extends BasicSplitPaneUI implements Runnable {
public static void main(String[] args) throws InterruptedException {
if (new JSplitPane().getFocusTraversalKeys(0).isEmpty()){
throw new Error("unexpected traversal keys");
}
new JSplitPane() {
public void setFocusTraversalKeys(int id, Set keystrokes) {
keystrokes.clear();
super.setFocusTraversalKeys(id, keystrokes);
}
};
if (new JSplitPane().getFocusTraversalKeys(0).isEmpty()) {
throw new Error("shared traversal keys");
}
KEYBOARD_DIVIDER_MOVE_OFFSET = -KEYBOARD_DIVIDER_MOVE_OFFSET;
ThreadGroup group = new ThreadGroup("$$$");
Thread thread = new Thread(group, new Test6657026());
thread.start();
thread.join();
}
public void run() {
SunToolkit.createNewAppContext();
if (new JSplitPane().getFocusTraversalKeys(0).isEmpty()) {
throw new Error("shared traversal keys");
}
JSplitPane pane = new JSplitPane();
pane.setUI(this);
createFocusListener().focusGained(null); // allows actions
test(pane, "positiveIncrement", 3);
test(pane, "negativeIncrement", 0);
}
private static void test(JSplitPane pane, String action, int expected) {
ActionEvent event = new ActionEvent(pane, expected, action);
pane.getActionMap().get(action).actionPerformed(event);
int actual = pane.getDividerLocation();
if (actual != expected) {
throw new Error(actual + ", but expected " + expected);
}
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import javax.swing.JButton;
import javax.swing.JTabbedPane;
import java.awt.Component;
import static javax.swing.SwingUtilities.invokeAndWait;
/*
* @test
* @bug 4873983 6943780
* @summary Tests JTabbedPane with SCROLL_TAB_LAYOUT
* @author Sergey Malenkov
*/
public class Test6943780 implements Runnable, Thread.UncaughtExceptionHandler {
public static void main(String[] args) throws Exception {
invokeAndWait(new Test6943780());
}
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
throwable.printStackTrace();
throw new RuntimeException(throwable);
}
@Override
public void run() {
JTabbedPane pane = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
pane.addTab("first", new JButton("first"));
pane.addTab("second", new JButton("second"));
for (Component component : pane.getComponents()) {
component.setSize(100, 100);
}
}
}

View file

@ -0,0 +1,73 @@
/*
* Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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 6394566
* @key headful
* @summary Tests that ESC moves the focus from the header to the table
* @library ../../../../regtesthelpers
* @build SwingTestHelper JRobot
* @run main bug6394566
*/
import java.awt.Component;
import java.awt.event.KeyEvent;
import java.awt.event.FocusEvent;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.JTableHeader;
import javax.swing.table.DefaultTableModel;
public class bug6394566 extends SwingTestHelper {
private JTable table;
private JTableHeader header;
public static void main(String[] args) throws Throwable {
new bug6394566().run(args);
}
protected Component createContentPane() {
table = new JTable(new DefaultTableModel(2, 2));
header = table.getTableHeader();
return new JScrollPane(table);
}
public void onEDT10() {
// Give the table the focus.
requestAndWaitForFocus(table);
}
//First, give the header focus using F8 on the JTable.
//This will fail prior to mustang b72.
public void onEDT20() {
waitForEvent(header, FocusEvent.FOCUS_GAINED); //set up focus listener
robot.hitKey(KeyEvent.VK_F8);
}
//Next, give the table back the focus using ESC.
//This will fail prior to the build with this bugfix.
public void onEDT30() {
waitForEvent(table, FocusEvent.FOCUS_GAINED); //set up focus listener
robot.hitKey(KeyEvent.VK_ESCAPE);
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @key headful
* @bug 8001470
* @summary JTextField's size is computed incorrectly when it contains Indic or Thai characters
* @author Semyon Sadetsky
*/
import javax.swing.*;
import java.awt.*;
public class bug8001470 {
private static JFrame frame;
private static JTextField textField1;
private static JTextField textField2;
public static void main(String[] args) throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
frame = new JFrame("JTextField Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel container = (JPanel) frame.getContentPane();
container.setLayout(new GridLayout(2,1));
textField1 = new JTextField("\u0e01");
textField2 = new JTextField("\u0c01");
container.add(textField1);
container.add(textField2);
frame.setVisible(true);
frame.pack();
}
});
if( textField1.getHeight() < 10 || textField2.getHeight() < 10 )
throw new Exception("Wrong field height");
System.out.println("ok");
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
frame.dispose();
}
});
}
}

View file

@ -0,0 +1,94 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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
* @key headful
* @bug 4231444 8354646
* @summary Password fields' ActionMap needs to replace
* DefaultEditorKit.selectWordAction with
* DefaultEditorKit.selectLineAction.
*
* @run main PasswordSelectionWordTest
*/
import javax.swing.Action;
import javax.swing.JPasswordField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.basic.BasicTextUI;
import javax.swing.text.DefaultEditorKit;
import java.awt.event.ActionEvent;
public class PasswordSelectionWordTest {
public static void main(String[] args) throws Exception {
for (UIManager.LookAndFeelInfo laf :
UIManager.getInstalledLookAndFeels()) {
System.out.println("Testing LAF: " + laf.getClassName());
SwingUtilities.invokeAndWait(() -> {
if (setLookAndFeel(laf)) {
runTest();
}
});
}
}
private static boolean setLookAndFeel(UIManager.LookAndFeelInfo laf) {
try {
UIManager.setLookAndFeel(laf.getClassName());
return true;
} catch (UnsupportedLookAndFeelException e) {
System.err.println("Skipping unsupported look and feel:");
e.printStackTrace();
return false;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void runTest() {
String str = "one two three";
JPasswordField field = new JPasswordField(str);
if (!(field.getUI() instanceof BasicTextUI)) {
throw new RuntimeException("Unexpected condition: JPasswordField UI was " + field.getUI());
}
System.out.println("Testing " + field.getUI());
// do something (anything) to initialize the Views:
field.setSize(100, 100);
field.addNotify();
Action action = field.getActionMap().get(
DefaultEditorKit.selectWordAction);
action.actionPerformed(new ActionEvent(field, 0, ""));
int selectionStart = field.getSelectionStart();
int selectionEnd = field.getSelectionEnd();
System.out.println("selectionStart = " + selectionStart);
System.out.println("selectionEnd = " + selectionEnd);
if (selectionStart != 0 || selectionEnd != str.length()) {
throw new RuntimeException("selectionStart = " + selectionStart +
" and selectionEnd = " + selectionEnd);
}
}
}

View file

@ -0,0 +1,87 @@
/*
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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 4305622
* @summary MetalToolBarUI.installUI invokeLater causes flickering
* @library /java/awt/regtesthelpers
* @build PassFailJFrame
* @run main/manual bug4305622
*/
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.border.LineBorder;
public class bug4305622 {
private static JFrame fr;
static final String INSTRUCTIONS = """
Press button "Create ToolBar" at frame "Create ToolBar Test".
If you see any flickering during creating of toolbar
then the test FAILS, otherwise the test PASSES.
""";
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
PassFailJFrame.builder()
.title("bug4305622 Test Instructions")
.instructions(INSTRUCTIONS)
.columns(40)
.testUI(bug4305622::createUI)
.build()
.awaitAndCheck();
}
static JFrame createUI() {
fr = new JFrame("Create ToolBar Test");
JButton button = new JButton("Create ToolBar");
button.addActionListener(ae -> addToolBar());
fr.add(button, BorderLayout.SOUTH);
fr.setSize(400, 400);
return fr;
}
static void addToolBar() {
fr.repaint();
fr.revalidate();
JToolBar toolbar = new JToolBar();
JButton btn = new JButton("Button 1");
btn.setBorder(new LineBorder(Color.red, 30));
toolbar.add(btn);
btn = new JButton("Button 2");
btn.setBorder(new LineBorder(Color.red, 30));
toolbar.add(btn);
toolbar.updateUI();
fr.add(toolbar, BorderLayout.NORTH);
}
}

View file

@ -0,0 +1,73 @@
/*
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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 4331392
* @summary Tests if BasicToolBarUI has bogus logic that prevents vertical
* toolbars from docking
* @library /java/awt/regtesthelpers
* @build PassFailJFrame
* @run main/manual bug4331392
*/
import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JToolBar;
public class bug4331392 {
static final String INSTRUCTIONS = """
Try to dock the toolbar across all the edges of frame. If you succeed,
then the test PASSES. Otherwise, it FAILS.
""";
public static void main(String[] args) throws Exception {
PassFailJFrame.builder()
.title("bug4331392 Test Instructions")
.instructions(INSTRUCTIONS)
.columns(40)
.testUI(bug4331392::createUI)
.build()
.awaitAndCheck();
}
static JFrame createUI() {
JFrame frame = new JFrame("JToolBar Docking Test");
Container c = frame.getContentPane();
JToolBar tbar = new JToolBar(JToolBar.VERTICAL);
tbar.add(new JButton("A"));
tbar.add(new JButton("B"));
tbar.add(new JButton("C"));
JButton b = new JButton("Hello");
c.add(b, BorderLayout.CENTER);
c.add(tbar, BorderLayout.EAST);
frame.setSize(300, 300);
return frame;
}
}

View file

@ -0,0 +1,172 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @key headful
* @bug 8023474
* @summary Tests that the first mouse press starts editing in JTree
* @author Dmitry Markov
* @run main bug8023474
*/
import javax.swing.*;
import javax.swing.event.CellEditorListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
import java.awt.*;
import java.awt.event.InputEvent;
import java.util.EventObject;
public class bug8023474 {
private static JTree tree;
public static void main(String[] args) throws Exception {
Robot robot = new Robot();
robot.setAutoDelay(50);
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
createAndShowGUI();
}
});
robot.waitForIdle();
Point point = getRowPointToClick(1);
robot.mouseMove(point.x, point.y);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.waitForIdle();
Boolean result = (Boolean)tree.getCellEditor().getCellEditorValue();
if (!result) {
throw new RuntimeException("Test Failed!");
}
}
private static void createAndShowGUI() {
try {
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (Exception e) {
throw new RuntimeException(e);
}
DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
DefaultMutableTreeNode item = new DefaultMutableTreeNode("item");
DefaultMutableTreeNode subItem = new DefaultMutableTreeNode("subItem");
root.add(item);
item.add(subItem);
DefaultTreeModel model = new DefaultTreeModel(root);
tree = new JTree(model);
tree.setCellEditor(new Editor());
tree.setEditable(true);
tree.setRowHeight(30);
tree.setCellRenderer(new CheckboxCellRenderer());
JFrame frame = new JFrame("bug8023474");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(tree));
frame.setSize(400, 300);
frame.setVisible(true);
}
private static Point getRowPointToClick(final int row) throws Exception {
final Point[] result = new Point[1];
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
Rectangle rect = tree.getRowBounds(row);
Point point = new Point(rect.x + 10, rect.y + rect.height / 2);
SwingUtilities.convertPointToScreen(point, tree);
result[0] = point;
}
});
return result[0];
}
private static class Editor extends JPanel implements TreeCellEditor {
private JCheckBox checkbox;
public Editor() {
setOpaque(false);
checkbox = new JCheckBox();
add(checkbox);
}
public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected,
boolean expanded, boolean leaf, int row) {
checkbox.setText(value.toString());
checkbox.setSelected(false);
return this;
}
public Object getCellEditorValue() {
return checkbox.isSelected();
}
public boolean isCellEditable(EventObject anEvent) {
return true;
}
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
public boolean stopCellEditing() {
return true;
}
public void cancelCellEditing() {
}
public void addCellEditorListener(CellEditorListener l) {
}
public void removeCellEditorListener(CellEditorListener l) {
}
}
private static class CheckboxCellRenderer extends JPanel implements TreeCellRenderer {
private JCheckBox checkbox;
public CheckboxCellRenderer() {
setOpaque(false);
checkbox = new JCheckBox();
add(checkbox);
}
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
checkbox.setText(value.toString());
checkbox.setSelected(false);
return this;
}
}
}

View file

@ -0,0 +1,221 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along 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 6507038
* @key headful
* @summary Verifies memory leak in BasicTreeUI TreeCellRenderer
* @run main TreeCellRendererLeakTest
*/
import java.awt.BorderLayout;
import java.awt.Component;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
public final class TreeCellRendererLeakTest {
private static JFrame frame;
private JPanel jPanel1;
private JPanel jPanel2;
private JScrollPane jScrollPane1;
private JTabbedPane jTabbedPane1;
private JTree jTree1;
private DefaultMutableTreeNode defTreeNode;
private DefaultTreeModel model;
private static final CountDownLatch testDone = new CountDownLatch(1);
// Access to referenceList and referenceQueue is guarded by referenceList
private static final List<Reference<JLabel>> referenceList = new ArrayList<>(50);
private static final ReferenceQueue<JLabel> referenceQueue = new ReferenceQueue<>();
// Custom TreeCellRenderer
public static final class TreeCellRenderer extends DefaultTreeCellRenderer {
public TreeCellRenderer() {}
// Create a new JLabel every time
@Override
public Component getTreeCellRendererComponent(
JTree tree,
Object value,
boolean sel,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
JLabel label = new JLabel();
label.setText("TreeNode: " + value.toString());
if (sel) {
label.setBackground(getBackgroundSelectionColor());
} else {
label.setBackground(getBackgroundNonSelectionColor());
}
synchronized (referenceList) {
referenceList.add(new PhantomReference<>(label, referenceQueue));
}
return label;
}
}
public TreeCellRendererLeakTest() {
initComponents();
jTree1.setCellRenderer(new TreeCellRenderer());
Thread updateThread = new Thread(this::runChanges);
updateThread.setDaemon(true);
updateThread.start();
Thread infoThread = new Thread(this::runInfo);
infoThread.setDaemon(true);
infoThread.start();
}
private void initComponents() {
jTabbedPane1 = new JTabbedPane();
jPanel1 = new JPanel();
jScrollPane1 = new JScrollPane();
jTree1 = new JTree();
jPanel2 = new JPanel();
jPanel1.setLayout(new BorderLayout());
jScrollPane1.setViewportView(jTree1);
jPanel1.add(jScrollPane1, BorderLayout.CENTER);
jTabbedPane1.addTab("tab1", jPanel1);
jPanel2.setLayout(new BorderLayout());
jTabbedPane1.addTab("tab2", jPanel2);
jTabbedPane1.setSelectedIndex(1);
model = (DefaultTreeModel) jTree1.getModel();
TreeNode root = (TreeNode) model.getRoot();
defTreeNode = (DefaultMutableTreeNode) model.getChild(root, 0);
frame = new JFrame();
frame.getContentPane().add(jTabbedPane1, java.awt.BorderLayout.CENTER);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}// </editor-fold>
public static void main(String[] args) throws Exception {
try {
SwingUtilities.invokeAndWait(() -> {
new TreeCellRendererLeakTest();
});
testDone.await();
} finally {
SwingUtilities.invokeAndWait(() -> {
if (frame != null) {
frame.dispose();
}
});
}
}
// Periodically cause a nodeChanged() for one of the nodes
public void runChanges() {
long count = 0;
long time = System.currentTimeMillis();
long tm = System.currentTimeMillis();
while ((tm - time) < (15 * 1000)) {
final long currentCount = count;
try {
SwingUtilities.invokeAndWait(() -> {
defTreeNode.setUserObject("runcount " + currentCount);
model.nodeChanged(defTreeNode);
});
count++;
Thread.sleep(1000);
tm = System.currentTimeMillis();
System.out.println("time elapsed " + (tm - time)/1000 + " s");
} catch (InterruptedException ex) {
break;
} catch (Exception e) {
e.printStackTrace();
}
}
testDone.countDown();
}
// Print number of uncollected JLabels
public void runInfo() {
final long time = System.currentTimeMillis();
long removedLabels = 0;
while ((System.currentTimeMillis() - time) < (15 * 1000)) {
System.gc();
int start;
int removed = 0;
int left;
// Remove dead references
synchronized (referenceList) {
start = referenceList.size();
Reference<?> ref;
while ((ref = referenceQueue.poll()) != null) {
referenceList.remove(ref);
removed++;
}
left = referenceList.size();
}
removedLabels += removed;
System.out.println("Live JLabels: " + start + " - " + removed + " = " + left);
System.out.println("All time removed: " + removedLabels);
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
break;
}
}
System.out.println("\nCleaned up labels: " + removedLabels);
if (removedLabels == 0) {
throw new RuntimeException("TreeCellRenderer component leaked");
}
}
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 6984643
* @summary Unable to instantiate JFileChooser with a minimal BasicL&F descendant installed
* @author Pavel Porvatov
*/
import javax.swing.*;
import javax.swing.plaf.basic.BasicLookAndFeel;
public class Test6984643 {
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(new BasicLookAndFeel() {
public String getName() {
return "A name";
}
public String getID() {
return "An id";
}
public String getDescription() {
return "A description";
}
public boolean isNativeLookAndFeel() {
return false;
}
public boolean isSupportedLookAndFeel() {
return true;
}
});
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
new JFileChooser();
}
});
}
}