ClipboardInterVMTest.java revision 12677:a4299d47bd00
1/*
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25  @test
26  @bug 8071668
27  @summary Check whether clipboard see changes from external process after taking ownership
28  @author Anton Nashatyrev: area=datatransfer
29  @library /lib/testlibrary
30  @build jdk.testlibrary.Utils
31  @run main ClipboardInterVMTest
32*/
33
34import jdk.testlibrary.Utils;
35
36import java.awt.*;
37import java.awt.datatransfer.*;
38import java.io.BufferedReader;
39import java.io.File;
40import java.io.IOException;
41import java.io.Reader;
42import java.util.ArrayList;
43import java.util.Arrays;
44import java.util.List;
45import java.util.concurrent.CountDownLatch;
46import java.util.concurrent.TimeUnit;
47
48public class ClipboardInterVMTest {
49
50    static CountDownLatch lostOwnershipMonitor = new CountDownLatch(1);
51    static CountDownLatch flavorChangedMonitor = new CountDownLatch(1);
52    static Process process;
53
54    public static void main(String[] args) throws Throwable {
55        Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
56
57        if (args.length > 0) {
58            System.out.println("Changing clip...");
59            clip.setContents(new StringSelection("pong"), null);
60            System.out.println("done");
61            // keeping this process running for a while since on Mac the clipboard
62            // will be invalidated via NSApplicationDidBecomeActiveNotification
63            // callback in the main process after this child process finishes
64            Thread.sleep(60 * 1000);
65            return;
66        };
67
68
69        clip.setContents(new CustomSelection(), new ClipboardOwner() {
70            @Override
71            public void lostOwnership(Clipboard clipboard, Transferable contents) {
72                System.out.println("ClipboardInterVMTest.lostOwnership");
73                lostOwnershipMonitor.countDown();
74            }
75        });
76
77        clip.addFlavorListener(new FlavorListener() {
78            @Override
79            public void flavorsChanged(FlavorEvent e) {
80                System.out.println("ClipboardInterVMTest.flavorsChanged");
81                flavorChangedMonitor.countDown();
82            }
83        });
84
85        System.out.println("Starting external clipborad modifier...");
86        new Thread(() -> runTest(ClipboardInterVMTest.class.getCanonicalName(), "pong")).start();
87
88        String content = "";
89        long startTime = System.currentTimeMillis();
90        while (System.currentTimeMillis() - startTime < 30 * 1000) {
91            Transferable c = clip.getContents(null);
92            if (c.isDataFlavorSupported(DataFlavor.plainTextFlavor)) {
93                Reader reader = DataFlavor.plainTextFlavor.getReaderForText(c);
94                content = new BufferedReader(reader).readLine();
95                System.out.println(content);
96                if (content.equals("pong")) {
97                    break;
98                }
99            }
100            Thread.sleep(200);
101        }
102
103        if (!lostOwnershipMonitor.await(10, TimeUnit.SECONDS)) {
104            throw new RuntimeException("No LostOwnership event received.");
105        };
106
107        if (!flavorChangedMonitor.await(10, TimeUnit.SECONDS)) {
108            throw new RuntimeException("No LostOwnership event received.");
109        };
110
111        if (!content.equals("pong")) {
112            throw new RuntimeException("Content was not passed.");
113        }
114
115        process.destroy();
116
117        System.out.println("Passed.");
118    }
119
120    private static void runTest(String main, String... args)  {
121
122        try {
123            List<String> opts = new ArrayList<>();
124            opts.add(getJavaExe());
125            opts.addAll(Arrays.asList(Utils.getTestJavaOpts()));
126            opts.add("-cp");
127            opts.add(System.getProperty("test.class.path", System.getProperty("java.class.path")));
128
129            opts.add(main);
130            opts.addAll(Arrays.asList(args));
131
132            ProcessBuilder pb = new ProcessBuilder(opts.toArray(new String[0]));
133            process = pb.start();
134        } catch (Throwable throwable) {
135            throw new RuntimeException(throwable);
136        }
137    }
138
139    private static String getJavaExe() throws IOException {
140        File p  = new File(System.getProperty("java.home"), "bin");
141        File j = new File(p, "java");
142        if (!j.canRead()) {
143            j = new File(p, "java.exe");
144        }
145        if (!j.canRead()) {
146            throw new RuntimeException("Can't find java executable in " + p);
147        }
148        return j.getCanonicalPath();
149    }
150
151    static class CustomSelection implements Transferable {
152        private static final DataFlavor[] flavors = { DataFlavor.allHtmlFlavor };
153
154        public DataFlavor[] getTransferDataFlavors() {
155            return flavors;
156        }
157
158        public boolean isDataFlavorSupported(DataFlavor flavor) {
159            return flavors[0].equals(flavor);
160        }
161
162        public Object getTransferData(DataFlavor flavor)
163                throws UnsupportedFlavorException, java.io.IOException {
164            if (isDataFlavorSupported(flavor)) {
165                return "ping";
166            } else {
167                throw new UnsupportedFlavorException(flavor);
168            }
169        }
170    }
171}
172