mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-01 22:18:23 +00:00
8354553: Open source several clipboard tests batch0
Reviewed-by: serb, prr
This commit is contained in:
parent
ac17449bdb
commit
b10a304b2b
@ -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
|
||||
|
||||
156
test/jdk/java/awt/Clipboard/ClipboardSecurity.java
Normal file
156
test/jdk/java/awt/Clipboard/ClipboardSecurity.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
519
test/jdk/java/awt/Clipboard/ImageTransferTest.java
Normal file
519
test/jdk/java/awt/Clipboard/ImageTransferTest.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
173
test/jdk/java/awt/Clipboard/NoDataConversionFailureTest.java
Normal file
173
test/jdk/java/awt/Clipboard/NoDataConversionFailureTest.java
Normal 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(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user