/* * Copyright (c) 2003, 2023, 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 4859006 @summary tests that MIME formats are mapped to flavors properly on X11 @requires (os.family == "linux") @key headful @run main MimeFormatsTest */ import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.FlavorMap; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.SystemFlavorMap; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.nio.charset.StandardCharsets; public class MimeFormatsTest implements ClipboardOwner { public static final DataFlavor TEST_FLAVOR = new DataFlavor( "text/test;charset=UTF-8;class=java.io.InputStream", null); public static class TextTransferable implements Transferable { private final String text; public TextTransferable(String text) { this.text = text; } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (!isDataFlavorSupported(TEST_FLAVOR)) { throw new UnsupportedFlavorException(flavor); } return new ByteArrayInputStream( text.getBytes(StandardCharsets.UTF_8)); } public DataFlavor[] getTransferDataFlavors(){ return new DataFlavor[] { TEST_FLAVOR }; } public boolean isDataFlavorSupported(DataFlavor flavor) { return TEST_FLAVOR.equals(flavor); } } public static final String DATA = "\u0440\u0443\u0441\u0441\u043a\u0438\u0439"; private String testData = null; private static final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); public void childRun() { Transferable t = clipboard.getContents(null); String data = ""; try { data = (String)t.getTransferData(DataFlavor.stringFlavor); } catch (Exception e) { e.printStackTrace(); } System.err.println("contents size=" + data.length()); for (int i = 0; i < data.length(); i++) { System.err.println(" char[" + i + "]=" + (int) data.charAt(i)); } ClipboardOwner owner = new ClipboardOwner() { public void lostOwnership(Clipboard clipboard, Transferable contents) { System.err.println("%d exit".formatted( System.currentTimeMillis())); System.err.println("Exiting"); System.exit(0); } }; clipboard.setContents(new StringSelection(data + data), owner); Object lock = new Object(); synchronized (lock) { // Wait to let the parent retrieve the contents. try { System.err.println("%d wait".formatted( System.currentTimeMillis())); lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public void start() { FlavorMap fm = SystemFlavorMap.getDefaultFlavorMap(); if (fm instanceof SystemFlavorMap) { SystemFlavorMap sfm = (SystemFlavorMap)fm; String mimeNative = "text/plain;charset=UTF-8"; sfm.setNativesForFlavor(TEST_FLAVOR, new String[] { mimeNative }); sfm.setFlavorsForNative(mimeNative, new DataFlavor[] { TEST_FLAVOR }); } else { System.err.println("WARNING: system flavor map: " + fm); return; } clipboard.setContents(new TextTransferable(DATA), this); try { String javaPath = System.getProperty("java.home", ""); String[] command = { javaPath + File.separator + "bin" + File.separator + "java", "-cp", System.getProperty("test.classes", "."), "Child" }; Process process = Runtime.getRuntime().exec(command); ProcessResults pres = ProcessResults.doWaitFor(process); int returnCode = pres.exitValue; if (pres.stderr != null && pres.stderr.length() > 0) { System.err.println("========= Child VM System.err ========"); System.err.print(pres.stderr); System.err.println("======================================"); } if (pres.stdout != null && pres.stdout.length() > 0) { System.err.println("========= Child VM System.out ========"); System.err.print(pres.stdout); System.err.println("======================================"); } System.err.println("Child return code=" + returnCode); } catch (Throwable e) { e.printStackTrace(); } System.err.println("Received data size=" + testData.length()); for (int i = 0; i < testData.length(); i++) { System.err.println(" char[" + i + "]=" + (int)testData.charAt(i)); } if (!testData.equals(DATA + DATA)) { throw new RuntimeException(); } } public void lostOwnership(Clipboard clip, Transferable contents) { Runnable r = new Runnable() { public void run() { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } Transferable t = clipboard.getContents(null); try { InputStream is = (InputStream)t.getTransferData(TEST_FLAVOR); Reader r = new InputStreamReader(is, StandardCharsets.UTF_8); StringBuffer sb = new StringBuffer(); int ch = 0; while ((ch = r.read()) != -1) { System.err.println("ch=" + ch); sb.append((char)ch); } testData = sb.toString(); } catch (Exception e) { e.printStackTrace(); } clipboard.setContents(new TextTransferable(""), null); } }; new Thread(r).start(); } public static void main(String[] args) { if (!System.getProperty("os.name").startsWith("Linux")) { return; } MimeFormatsTest mimeFormatsTest = new MimeFormatsTest(); mimeFormatsTest.start(); } } class Child { public static void main(String[] args) { MimeFormatsTest test = new MimeFormatsTest(); test.childRun(); } } class ProcessResults { public int exitValue; public String stdout; public String stderr; public ProcessResults() { exitValue = -1; stdout = ""; stderr = ""; } /** * Method to perform a "wait" for a process and return its exit value. * This is a workaround for Process.waitFor() never returning. */ public static ProcessResults doWaitFor(Process p) { ProcessResults pres = new ProcessResults(); InputStream in = null; InputStream err = null; try { in = p.getInputStream(); err = p.getErrorStream(); boolean finished = false; while (!finished) { try { while (in.available() > 0) { pres.stdout += (char)in.read(); } while (err.available() > 0) { pres.stderr += (char)err.read(); } // Ask the process for its exitValue. If the process // is not finished, an IllegalThreadStateException // is thrown. If it is finished, we fall through and // the variable finished is set to true. pres.exitValue = p.exitValue(); finished = true; } catch (IllegalThreadStateException e) { // Process is not finished yet; // Sleep a little to save on CPU cycles Thread.currentThread().sleep(500); } } if (in != null) in.close(); if (err != null) err.close(); } catch (Throwable e) { System.err.println("doWaitFor(): unexpected exception"); e.printStackTrace(); } return pres; } }