8354553: Open source several clipboard tests batch0

Reviewed-by: serb, prr
This commit is contained in:
Alexander Zvegintsev 2025-04-23 23:03:22 +00:00
parent ac17449bdb
commit b10a304b2b
5 changed files with 1079 additions and 0 deletions

View File

@ -261,6 +261,10 @@ java/awt/Clipboard/PasteNullToTextComponentsTest.java 8234140 macosx-all,windows
java/awt/Clipboard/NoOwnerNoTargetsTest.java 8234140 macosx-all
java/awt/Clipboard/LostOwnershipChainTest/SystemClipboard2ProcTest.java 8234140 macosx-all
java/awt/Clipboard/HTMLTransferTest/HTMLTransferTest.java 8017454 macosx-all
java/awt/Clipboard/ClipboardSecurity.java 8054809 macosx-all
java/awt/Clipboard/GetAltContentsTest/SystemClipboardTest.java 8234140 macosx-all
java/awt/Clipboard/ImageTransferTest.java 8030710 generic-all
java/awt/Clipboard/NoDataConversionFailureTest.java 8234140 macosx-all
java/awt/Frame/MiscUndecorated/RepaintTest.java 8266244 macosx-aarch64
java/awt/Modal/FileDialog/FileDialogAppModal1Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogAppModal2Test.java 7186009 macosx-all

View File

@ -0,0 +1,156 @@
/*
* 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 4274061
* @summary Tests that Transferable.getTransferData() and
* SelectionOwner.lostOwnership is not called on Toolkit thread.
* @key headful
* @library /test/lib
* @run main ClipboardSecurity
*/
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
public class ClipboardSecurity {
static Clipboard clip = null;
public static final CountDownLatch latch = new CountDownLatch(1);
public static volatile boolean hasError = false;
public static void main(String[] args) throws Exception {
if (args.length == 0) {
ClipboardSecurity clipboardSecurity = new ClipboardSecurity();
clipboardSecurity.start();
return;
}
try {
clip = Toolkit.getDefaultToolkit().getSystemClipboard();
if ( clip == null ) {
throw (new RuntimeException("Clipboard is null"));
}
Transferable data = clip.getContents(null);
if ( data == null ) {
throw (new RuntimeException("Data is null"));
}
System.out.println("Clipboard contents: " + data);
// First check - getTransferData
try {
String contData =
(String) data.getTransferData(DataFlavor.stringFlavor);
} catch (UnsupportedFlavorException | IOException exc) {
throw(new RuntimeException("Couldn't get transfer data - "
+ exc.getMessage()));
}
// Second check - lostOwnership
MyClass clipData = new MyClass("clipbard test data");
clip.setContents(clipData, clipData);
System.out.println("exit 0");
System.exit(0);
} catch (RuntimeException exc) {
System.err.println(exc.getMessage());
System.out.println("exit 2");
System.exit(2);
}
}
public void start() throws Exception {
clip = Toolkit.getDefaultToolkit().getSystemClipboard();
if (clip == null) {
throw (new RuntimeException("Clipboard is null"));
}
MyClass clipData = new MyClass("clipboard test data");
clip.setContents(clipData, clipData);
ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(
ClipboardSecurity.class.getName(),
"child"
);
Process process = ProcessTools.startProcess("Child", pb);
OutputAnalyzer outputAnalyzer = new OutputAnalyzer(process);
if (!process.waitFor(15, TimeUnit.SECONDS)) {
process.destroyForcibly();
throw new TimeoutException("Timed out waiting for Child");
}
System.out.println("WAIT COMPLETE");
outputAnalyzer.shouldHaveExitValue(0);
if (!latch.await(10, TimeUnit.SECONDS)) {
throw new RuntimeException("timed out");
}
if (hasError) {
throw new RuntimeException("Detected call on Toolkit thread");
}
System.out.println("Passed.");
}
}
class MyClass extends StringSelection implements ClipboardOwner {
MyClass(String title) {
super(title);
}
private void checkIsCorrectThread(String reason) {
System.out.println("Checking " + reason + " for thread "
+ Thread.currentThread().getName());
String name = Thread.currentThread().getName();
if (name.equals("AWT-Windows") || name.equals("AWT-Motif")) {
ClipboardSecurity.hasError = true;
System.err.println(reason + " is called on Toolkit thread!");
}
}
public void lostOwnership(Clipboard clip, Transferable cont) {
checkIsCorrectThread("lostOwnership");
ClipboardSecurity.latch.countDown();
System.out.println("lost ownership on "
+ Thread.currentThread().getName() + " thread");
}
public Object getTransferData(DataFlavor flav)
throws UnsupportedFlavorException, IOException {
System.out.println("getTransferData on "
+ Thread.currentThread().getName() + " thread");
checkIsCorrectThread("getTransferData");
return super.getTransferData(flav);
}
}

View File

@ -0,0 +1,227 @@
/*
* Copyright (c) 2003, 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 4287795 4790833
* @summary tests new Clipboard methods: getAvailableDataFlavors,
* isDataFlavorAvailable, getData
* @key headful
* @library /test/lib
* @run main SystemClipboardTest
*/
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
public class SystemClipboardTest {
private static final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
private static final String contentsText = "contents text";
public void start() throws Exception {
Util.setClipboardContents(clipboard, new StringSelection(contentsText), new ClipboardOwner() {
public void lostOwnership(Clipboard clpbrd, Transferable cntnts) {
check(); // clipboard data retrieved from the system clipboard
Util.setClipboardContents(clipboard, new StringSelection(contentsText), null);
}
});
check(); // JVM-local clipboard data
ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(
SystemClipboardTest.class.getName(),
"child"
);
Process process = ProcessTools.startProcess("Child", pb);
OutputAnalyzer outputAnalyzer = new OutputAnalyzer(process);
if (!process.waitFor(15, TimeUnit.SECONDS)) {
process.destroyForcibly();
throw new TimeoutException("Timed out waiting for Child");
}
outputAnalyzer.shouldHaveExitValue(0);
}
private void check() {
boolean failed = false;
Transferable contents = Util.getClipboardContents(clipboard, null);
Set<DataFlavor> flavorsT = new HashSet<>(Arrays.asList(contents.getTransferDataFlavors()));
Set<DataFlavor> flavorsA = new HashSet<>(Arrays.asList(Util.getClipboardAvailableDataFlavors(clipboard)));
System.err.println("getAvailableDataFlavors(): " + flavorsA);
if (!flavorsA.equals(flavorsT)) {
failed = true;
System.err.println("FAILURE: getAvailableDataFlavors() returns incorrect " +
"DataFlavors: " + flavorsA + "\nwhile getContents()." +
"getTransferDataFlavors() return: " + flavorsT);
}
if (!Util.isClipboardDataFlavorAvailable(clipboard, DataFlavor.stringFlavor)) {
failed = true;
System.err.println("FAILURE: isDataFlavorAvailable(DataFlavor.stringFlavor) " +
"returns false");
}
Object data = null;
try {
data = Util.getClipboardData(clipboard, DataFlavor.stringFlavor);
} catch (UnsupportedFlavorException exc) {
failed = true;
exc.printStackTrace();
} catch (IOException exc) {
failed = true;
exc.printStackTrace();
}
System.err.println("getData(): " + data);
if (!contentsText.equals(data)) {
failed = true;
System.err.println("FAILURE: getData() returns: " + data +
", that is not equal to: \"" + contentsText + "\"");
}
if (failed) {
throw new RuntimeException("test failed, for details see output above");
}
}
public static void main(String[] args) throws Exception {
if (args.length == 0) {
SystemClipboardTest systemClipboardTest = new SystemClipboardTest();
systemClipboardTest.start();
return;
}
System.err.println("child VM: setting clipboard contents");
CountDownLatch latch = new CountDownLatch(1);
Util.setClipboardContents(clipboard, new StringSelection(contentsText),
(clpbrd, cntnts) -> {
System.err.println("child VM: success");
latch.countDown();
});
if (!latch.await(15, TimeUnit.SECONDS)) {
throw new RuntimeException("child VM failed");
}
}
}
class Util {
public static void setClipboardContents(Clipboard cb,
Transferable contents,
ClipboardOwner owner) {
while (true) {
try {
cb.setContents(contents, owner);
return;
} catch (IllegalStateException ise) {
ise.printStackTrace();
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
public static Transferable getClipboardContents(Clipboard cb,
Object requestor) {
while (true) {
try {
return cb.getContents(requestor);
} catch (IllegalStateException ise) {
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
public static Object getClipboardData(Clipboard cb, DataFlavor flavor)
throws IOException, UnsupportedFlavorException {
while (true) {
try {
return cb.getData(flavor);
} catch (IllegalStateException ise) {
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
public static DataFlavor[] getClipboardAvailableDataFlavors(Clipboard cb) {
while (true) {
try {
return cb.getAvailableDataFlavors();
} catch (IllegalStateException ise) {
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
public static boolean isClipboardDataFlavorAvailable(Clipboard cb,
DataFlavor flavor) {
while (true) {
try {
return cb.isDataFlavorAvailable(flavor);
} catch (IllegalStateException ise) {
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
}

View File

@ -0,0 +1,519 @@
/*
* Copyright (c) 2002, 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 4397404 4720930
* @summary tests that images of all supported native image formats
* are transferred properly
* @key headful
* @library /test/lib
* @run main ImageTransferTest
*/
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.SystemFlavorMap;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.image.BufferedImage;
import java.awt.image.MemoryImageSource;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
public class ImageTransferTest {
public static final int CODE_NOT_RETURNED = 100;
public static final int CODE_CONSUMER_TEST_FAILED = 101;
public static final int CODE_FAILURE = 102;
private TImageProducer imPr;
private int returnCode = CODE_NOT_RETURNED;
public static void main(String[] args) throws Exception {
ImageTransferTest imageTransferTest = new ImageTransferTest();
imageTransferTest.init();
imageTransferTest.start();
}
public void init() {
imPr = new TImageProducer();
imPr.begin();
}
public void start() throws Exception {
String formats = "";
String iniMsg = "Testing all native image formats from \n" +
"SystemFlavorMap.getNativesForFlavor(DataFlavor.imageFlavor) \n";
for (int i = 0; i < imPr.formats.length; i++) {
formats += (imPr.formats[i] + " ");
}
System.out.println(iniMsg + formats);
ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(
TImageConsumer.class.getName(), formats
);
Process process = ProcessTools.startProcess("Child", pb);
OutputAnalyzer outputAnalyzer = new OutputAnalyzer(process);
if (!process.waitFor(15, TimeUnit.SECONDS)) {
process.destroyForcibly();
returnCode = CODE_NOT_RETURNED;
} else {
returnCode = outputAnalyzer.getExitValue();
}
switch (returnCode) {
case CODE_NOT_RETURNED:
throw new RuntimeException("Child VM: failed to start");
case CODE_FAILURE:
throw new RuntimeException("Child VM: abnormal termination");
case CODE_CONSUMER_TEST_FAILED:
throw new RuntimeException("test failed: images in some " +
"native formats are not transferred properly: " +
"see output of child VM");
default:
boolean failed = false;
String passedFormats = "";
String failedFormats = "";
for (int i = 0; i < imPr.passedArray.length; i++) {
if (imPr.passedArray[i]) passedFormats += imPr.formats[i] + " ";
else {
failed = true;
failedFormats += imPr.formats[i] + " ";
}
}
if (failed) {
throw new RuntimeException("test failed: images in following " +
"native formats are not transferred properly: " +
failedFormats);
} else {
System.err.println("images in following native formats are " +
"transferred properly: " + passedFormats);
}
}
}
}
abstract class ImageTransferer implements ClipboardOwner {
static final String S_PASSED = "Y";
static final String S_FAILED = "N";
static final String S_BEGIN = "B";
static final String S_BEGIN_ANSWER = "BA";
static final String S_END = "E";
Image image;
Clipboard clipboard;
String[] formats;
int fi; // next format index
ImageTransferer() {
clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
image = createImage();
}
abstract void notifyTransferSuccess(boolean status);
private static Image createImage() {
int w = 100;
int h = 100;
int[] pix = new int[w * h];
int index = 0;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int red = 127;
int green = 127;
int blue = y > h / 2 ? 127 : 0;
int alpha = 255;
if (x < w / 4 && y < h / 4) {
alpha = 0;
red = 0;
}
pix[index++] = (alpha << 24) | (red << 16) | (green << 8) | blue;
}
}
return Toolkit.getDefaultToolkit().
createImage(new MemoryImageSource(w, h, pix, 0, w));
}
static String[] retrieveFormatsToTest() {
SystemFlavorMap sfm = (SystemFlavorMap)SystemFlavorMap.getDefaultFlavorMap();
java.util.List ln = sfm.getNativesForFlavor(DataFlavor.imageFlavor);
String osName = System.getProperty("os.name").toLowerCase();
String sMETAFILEPICT = "METAFILEPICT";
if (osName.indexOf("win") >= 0 && !ln.contains(sMETAFILEPICT)) {
// for test failing on JDK without this fix
ln.add(sMETAFILEPICT);
}
return (String[])ln.toArray(new String[ln.size()]);
}
static void leaveFormat(String format) {
SystemFlavorMap sfm = (SystemFlavorMap)SystemFlavorMap.getDefaultFlavorMap();
sfm.setFlavorsForNative(format,
new DataFlavor[] { DataFlavor.imageFlavor });
sfm.setNativesForFlavor(DataFlavor.imageFlavor,
new String[] { format });
}
boolean areImagesIdentical(Image im1, Image im2) {
if (formats[fi].equals("JFIF") || formats[fi].equals("image/jpeg") ||
formats[fi].equals("GIF") || formats[fi].equals("image/gif")) {
// JFIF and GIF are lossy formats
return true;
}
int[] ib1 = getImageData(im1);
int[] ib2 = getImageData(im2);
if (ib1.length != ib2.length) {
return false;
}
if (formats[fi].equals("PNG") ||
formats[fi].equals("image/png") ||
formats[fi].equals("image/x-png")) {
// check alpha as well
for (int i = 0; i < ib1.length; i++) {
if (ib1[i] != ib2[i]) {
System.err.println("different pixels: " +
Integer.toHexString(ib1[i]) + " " +
Integer.toHexString(ib2[i]));
return false;
}
}
} else {
for (int i = 0; i < ib1.length; i++) {
if ((ib1[i] & 0x00FFFFFF) != (ib2[i] & 0x00FFFFFF)) {
System.err.println("different pixels: " +
Integer.toHexString(ib1[i]) + " " +
Integer.toHexString(ib2[i]));
return false;
}
}
}
return true;
}
private static int[] getImageData(Image image) {
int width = image.getWidth(null);
int height = image.getHeight(null);
BufferedImage bimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = bimage.createGraphics();
try {
g2d.drawImage(image, 0, 0, width, height, null);
} finally {
g2d.dispose();
}
return bimage.getRGB(0, 0, width, height, null, 0, width);
}
static void setClipboardContents(Clipboard cb,
Transferable contents,
ClipboardOwner owner) {
synchronized (cb) {
boolean set = false;
while (!set) {
try {
cb.setContents(contents, owner);
set = true;
} catch (IllegalStateException ise) {
try { Thread.sleep(100); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
}
static Transferable getClipboardContents(Clipboard cb,
Object requestor) {
synchronized (cb) {
while (true) {
try {
Transferable t = cb.getContents(requestor);
return t;
} catch (IllegalStateException ise) {
try { Thread.sleep(100); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
}
}
class TImageProducer extends ImageTransferer {
boolean[] passedArray;
private boolean isFirstCallOfLostOwnership = true;
TImageProducer() {
formats = retrieveFormatsToTest();
passedArray = new boolean[formats.length];
}
void begin() {
setClipboardContents(clipboard, new StringSelection(S_BEGIN), this);
}
public void lostOwnership(Clipboard cb, Transferable contents) {
System.err.println("PRODUCER: lost clipboard ownership");
Transferable t = getClipboardContents(cb, null);
if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
String msg = null;
// for test going on if t.getTransferData() will throw an exception
if (isFirstCallOfLostOwnership) {
isFirstCallOfLostOwnership = false;
msg = S_BEGIN_ANSWER;
} else {
msg = S_PASSED;
}
try {
msg = (String)t.getTransferData(DataFlavor.stringFlavor);
System.err.println("received message: " + msg);
} catch (Exception e) {
System.err.println("Can't getTransferData-message: " + e);
}
if (msg.equals(S_PASSED)) {
notifyTransferSuccess(true);
} else if (msg.equals(S_FAILED)) {
notifyTransferSuccess(false);
} else if (!msg.equals(S_BEGIN_ANSWER)) {
throw new RuntimeException("wrong message in " +
"TImageProducer.lostOwnership(): " + msg +
" (possibly due to bug 4683804)");
}
} else {
throw new RuntimeException("DataFlavor.stringFlavor is not " +
"supported by transferable in " +
"TImageProducer.lostOwnership()");
}
if (fi < formats.length) {
System.err.println("testing native image format " + formats[fi] +
"...");
leaveFormat(formats[fi]);
setClipboardContents(cb, new ImageSelection(image), this);
} else {
setClipboardContents(cb, new StringSelection(S_END), null);
}
}
void notifyTransferSuccess(boolean status) {
passedArray[fi] = status;
fi++;
}
}
class TImageConsumer extends ImageTransferer {
private static final Object LOCK = new Object();
private static boolean failed;
public void lostOwnership(Clipboard cb, Transferable contents) {
System.err.println("CONSUMER: lost clipboard ownership");
Transferable t = getClipboardContents(cb, null);
if (t.isDataFlavorSupported(DataFlavor.imageFlavor)) {
Image im = null; //? image;
try {
im = (Image) t.getTransferData(DataFlavor.imageFlavor);
} catch (Exception e) {
System.err.println("Can't getTransferData-image: " + e);
notifyTransferSuccess(false);
}
if (im == null) {
System.err.println("getTransferData returned null");
notifyTransferSuccess(false);
} else if (areImagesIdentical(image, im)) {
notifyTransferSuccess(true);
} else {
System.err.println("transferred image is different from " +
"initial image");
notifyTransferSuccess(false);
}
} else if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
// all image formats have been processed
try {
String msg = (String) t.getTransferData(DataFlavor.stringFlavor);
System.err.println("received message: " + msg);
} catch (Exception e) {
System.err.println("Can't getTransferData-message: " + e);
}
synchronized (LOCK) {
LOCK.notifyAll();
}
} else {
System.err.println("imageFlavor is not supported by transferable");
notifyTransferSuccess(false);
}
}
void notifyTransferSuccess(boolean status) {
if (status) {
System.err.println("format passed: " + formats[fi]);
setClipboardContents(clipboard, new StringSelection(S_PASSED), this);
} else {
failed = true;
System.err.println("format failed: " + formats[fi]);
setClipboardContents(clipboard, new StringSelection(S_FAILED), this);
}
if (fi < formats.length - 1) {
leaveFormat(formats[++fi]);
}
}
public static void main(String[] args) {
try {
TImageConsumer ic = new TImageConsumer();
ic.formats = args;
leaveFormat(ic.formats[0]);
synchronized (LOCK) {
ic.setClipboardContents(ic.clipboard,
new StringSelection(S_BEGIN_ANSWER), ic);
LOCK.wait();
}
if (failed) System.exit(ImageTransferTest.CODE_CONSUMER_TEST_FAILED);
} catch (Throwable e) {
e.printStackTrace();
System.exit(ImageTransferTest.CODE_FAILURE);
}
}
}
/**
* A <code>Transferable</code> which implements the capability required
* to transfer an <code>Image</code>.
*
* This <code>Transferable</code> properly supports
* <code>DataFlavor.imageFlavor</code>.
* and all equivalent flavors.
* No other <code>DataFlavor</code>s are supported.
*
* @see java.awt.datatransfer.DataFlavor.imageFlavor
*/
class ImageSelection implements Transferable {
private static final int IMAGE = 0;
private static final DataFlavor[] flavors = { DataFlavor.imageFlavor };
private Image data;
/**
* Creates a <code>Transferable</code> capable of transferring
* the specified <code>String</code>.
*/
public ImageSelection(Image data) {
this.data = data;
}
/**
* Returns an array of flavors in which this <code>Transferable</code>
* can provide the data. <code>DataFlavor.stringFlavor</code>
* is properly supported.
* Support for <code>DataFlavor.plainTextFlavor</code> is
* <b>deprecated</b>.
*
* @return an array of length one, whose element is <code>DataFlavor.
* imageFlavor</code>
*/
public DataFlavor[] getTransferDataFlavors() {
// returning flavors itself would allow client code to modify
// our internal behavior
return (DataFlavor[])flavors.clone();
}
/**
* Returns whether the requested flavor is supported by this
* <code>Transferable</code>.
*
* @param flavor the requested flavor for the data
* @return true if <code>flavor</code> is equal to
* <code>DataFlavor.imageFlavor</code>;
* false if <code>flavor</code>
* is not one of the above flavors
* @throws NullPointerException if flavor is <code>null</code>
*/
public boolean isDataFlavorSupported(DataFlavor flavor) {
for (int i = 0; i < flavors.length; i++) {
if (flavor.equals(flavors[i])) {
return true;
}
}
return false;
}
/**
* Returns the <code>Transferable</code>'s data in the requested
* <code>DataFlavor</code> if possible. If the desired flavor is
* <code>DataFlavor.imageFlavor</code>, or an equivalent flavor,
* the <code>Image</code> representing the selection is
* returned.
*
* @param flavor the requested flavor for the data
* @return the data in the requested flavor, as outlined above
* @throws UnsupportedFlavorException if the requested data flavor is
* not equivalent to <code>DataFlavor.imageFlavor</code>
* @throws IOException if an IOException occurs while retrieving the data.
* By default, <code>ImageSelection</code> never throws
* this exception, but a subclass may.
* @throws NullPointerException if flavor is <code>null</code>
*/
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, java.io.IOException
{
if (flavor.equals(flavors[IMAGE])) {
return (Object)data;
} else {
throw new UnsupportedFlavorException(flavor);
}
}
}

View File

@ -0,0 +1,173 @@
/*
* Copyright (c) 2002, 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 4558797
* @summary Tests that there is no data conversion failure when two applications
* exchange data via system clipboard
* @key headful
* @library /test/lib
* @run main NoDataConversionFailureTest
*/
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
public class NoDataConversionFailureTest {
public static void main(String[] args) throws Exception {
SystemClipboardOwner.run();
if (SystemClipboardOwner.failed) {
throw new RuntimeException("test failed: can not get transfer data");
} else {
System.err.println("test passed");
}
}
}
class SystemClipboardOwner implements ClipboardOwner {
static volatile boolean failed;
private static final Object LOCK = new Object();
private static final int CHAIN_LENGTH = 15;
private final static Clipboard clipboard =
Toolkit.getDefaultToolkit().getSystemClipboard();
private int m;
private final int id;
public SystemClipboardOwner(int m) { this.m = m; id = m; }
public void lostOwnership(Clipboard cb, Transferable contents) {
System.err.println(id + " lost clipboard ownership");
Transferable t = getClipboardContents(cb, null);
// for test passing if t.getTransferData() will throw an exception
String msg = String.valueOf(m + 1);
try {
msg = (String) t.getTransferData(DataFlavor.stringFlavor);
} catch (IOException e) {
failed = true;
System.err.println(id + " can't getTransferData: " + e);
} catch (Exception e) {
System.err.println(id + " can't getTransferData: " + e);
}
System.err.println(id + " Clipboard.getContents(): " + msg);
if (!msg.equals(String.valueOf(m + 1))) {
System.err.println("Clipboard.getContents() returned incorrect contents!");
}
m += 2;
if (m <= CHAIN_LENGTH) {
System.err.println(id + " Clipboard.setContents(): " + m);
setClipboardContents(cb, new StringSelection(m + ""), this);
}
if (m >= CHAIN_LENGTH) {
synchronized (LOCK) {
LOCK.notifyAll();
}
}
}
public static void run() throws Exception {
SystemClipboardOwner cbo1 = new SystemClipboardOwner(0);
System.err.println(cbo1.m + " Clipboard.setContents(): " + cbo1.m);
setClipboardContents(clipboard, new StringSelection(cbo1.m + ""),
cbo1);
ProcessBuilder pb = ProcessTools
.createTestJavaProcessBuilder(SystemClipboardOwner.class.getName());
Process process = ProcessTools.startProcess("Child", pb);
OutputAnalyzer outputAnalyzer = new OutputAnalyzer(process);
if (!process.waitFor(15, TimeUnit.SECONDS)) {
process.destroyForcibly();
throw new TimeoutException("Timed out waiting for Child");
}
if (cbo1.m < CHAIN_LENGTH) {
System.err.println("chain of calls of lostOwnership() broken!");
}
outputAnalyzer.shouldHaveExitValue(0);
}
public static void main(String[] args) throws InterruptedException {
SystemClipboardOwner cbo2 = new SystemClipboardOwner(1);
System.err.println(cbo2.m + " Clipboard.setContents(): " + cbo2.m);
synchronized (LOCK) {
setClipboardContents(clipboard, new StringSelection(cbo2.m + ""),
cbo2);
LOCK.wait();
}
}
private static void setClipboardContents(Clipboard cb,
Transferable contents,
ClipboardOwner owner) {
synchronized (cb) {
boolean set = false;
while (!set) {
try {
cb.setContents(contents, owner);
set = true;
} catch (IllegalStateException ise) {
try { Thread.sleep(100); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
}
private static Transferable getClipboardContents(Clipboard cb,
Object requestor) {
synchronized (cb) {
while (true) {
try {
Transferable t = cb.getContents(requestor);
return t;
} catch (IllegalStateException ise) {
try { Thread.sleep(100); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
}
}