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 8081787 8136763
27  @author Mikhail Cherkasov
28  @run main/manual MacOsXFileAndMultipleFileCopingTest
29*/
30
31import javax.swing.*;
32import java.awt.*;
33import java.awt.datatransfer.*;
34import java.awt.event.ActionEvent;
35import java.awt.event.ActionListener;
36import java.net.URL;
37
38public class MacOsXFileAndMultipleFileCopingTest {
39    private static void init() {
40        String[] instructions =
41                {"Test for MacOS X only:",
42                        "1. The aim is to test that java works fine with \"application/" +
43                                "x-java-url;class=java.net.URL\"falvor and support coping of multiple files",
44                        "2. Open finder and select any file.",
45                        "3. Press CMD+C or press \"Copy\" in context menu",
46                        "4. Focus window with \"Test URL\" Button.",
47                        "5. If you see URL for selected file, then test PASSED,",
48                        "otherwise test FAILED.",
49
50                        "6. Open finder again and select several files.",
51                        "7. Press CMD+C or press \"Copy\" in context menu",
52                        "8. Focus window with \"Test multiple files coping\" Button.",
53                        "9. If you see list of selected files, then test PASSED,",
54                        "otherwise test FAILED.",
55
56                };
57
58        Sysout.createDialog();
59        Sysout.printInstructions(instructions);
60
61        final Frame frame = new Frame();
62        Panel panel = new Panel();
63        panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
64
65        frame.add(panel);
66        Button testUrlBtn = new Button("Test URL");
67        final TextArea textArea = new TextArea(5, 80);
68        testUrlBtn.addActionListener(new AbstractAction() {
69            @Override
70            public void actionPerformed(ActionEvent ae) {
71                try {
72                    Clipboard board = Toolkit.getDefaultToolkit().getSystemClipboard();
73                    URL url = (URL) board.getData(new DataFlavor("application/x-java-url;class=java.net.URL"));
74                    textArea.setText(url.toString());
75                } catch (Exception e) {
76                    throw new RuntimeException(e);
77                }
78            }
79        });
80        panel.add(testUrlBtn);
81        Button testUriList = new Button("Test multiple files coping");
82        testUriList.addActionListener(new AbstractAction() {
83            @Override
84            public void actionPerformed(ActionEvent ae) {
85                try {
86                    Clipboard board = Toolkit.getDefaultToolkit().getSystemClipboard();
87                        String files = (String) board.getData(new DataFlavor("text/uri-list;class=java.lang.String"));
88                    textArea.setText(files);
89                } catch (Exception e) {
90                    throw new RuntimeException(e);
91                }
92            }
93        });
94        panel.add(testUriList);
95        panel.add(textArea);
96        frame.setBounds(200, 200, 400, 400);
97        frame.setVisible(true);
98
99    }//End  init()
100
101
102    /*****************************************************
103     * Standard Test Machinery Section
104     * DO NOT modify anything in this section -- it's a
105     * standard chunk of code which has all of the
106     * synchronisation necessary for the test harness.
107     * By keeping it the same in all tests, it is easier
108     * to read and understand someone else's test, as
109     * well as insuring that all tests behave correctly
110     * with the test harness.
111     * There is a section following this for test-defined
112     * classes
113     ******************************************************/
114    private static boolean theTestPassed = false;
115    private static boolean testGeneratedInterrupt = false;
116    private static String failureMessage = "";
117
118    private static Thread mainThread = null;
119
120    private static int sleepTime = 300000;
121
122    public static void main(String args[]) throws InterruptedException {
123        if (!System.getProperty("os.name").startsWith("Mac")) {
124            return;
125        }
126        mainThread = Thread.currentThread();
127        try {
128            init();
129        } catch (TestPassedException e) {
130            //The test passed, so just return from main and harness will
131            // interepret this return as a pass
132            return;
133        }
134        //At this point, neither test passed nor test failed has been
135        // called -- either would have thrown an exception and ended the
136        // test, so we know we have multiple threads.
137
138        //Test involves other threads, so sleep and wait for them to
139        // called pass() or fail()
140        try {
141            Thread.sleep(sleepTime);
142            //Timed out, so fail the test
143            throw new RuntimeException("Timed out after " + sleepTime / 1000 + " seconds");
144        } catch (InterruptedException e) {
145            if (!testGeneratedInterrupt) throw e;
146
147            //reset flag in case hit this code more than once for some reason (just safety)
148            testGeneratedInterrupt = false;
149            if (theTestPassed == false) {
150                throw new RuntimeException(failureMessage);
151            }
152        }
153
154    }//main
155
156    public static synchronized void setTimeoutTo(int seconds) {
157        sleepTime = seconds * 1000;
158    }
159
160    public static synchronized void pass() {
161        Sysout.println("The test passed.");
162        Sysout.println("The test is over, hit  Ctl-C to stop Java VM");
163        //first check if this is executing in main thread
164        if (mainThread == Thread.currentThread()) {
165            //Still in the main thread, so set the flag just for kicks,
166            // and throw a test passed exception which will be caught
167            // and end the test.
168            theTestPassed = true;
169            throw new TestPassedException();
170        }
171        //pass was called from a different thread, so set the flag and interrupt
172        // the main thead.
173        theTestPassed = true;
174        testGeneratedInterrupt = true;
175        if (mainThread != null) {
176            mainThread.interrupt();
177        }
178    }//pass()
179
180    public static synchronized void fail() {
181        //test writer didn't specify why test failed, so give generic
182        fail("it just plain failed! :-)");
183    }
184
185    public static synchronized void fail(String whyFailed) {
186        Sysout.println("The test failed: " + whyFailed);
187        Sysout.println("The test is over, hit  Ctl-C to stop Java VM");
188        //check if this called from main thread
189        if (mainThread == Thread.currentThread()) {
190            //If main thread, fail now 'cause not sleeping
191            throw new RuntimeException(whyFailed);
192        }
193        theTestPassed = false;
194        testGeneratedInterrupt = true;
195        failureMessage = whyFailed;
196        mainThread.interrupt();
197    }//fail()
198
199}// class ManualMainTest
200
201//This exception is used to exit from any level of call nesting
202// when it's determined that the test has passed, and immediately
203// end the test.
204class TestPassedException extends RuntimeException {
205}
206
207//*********** End Standard Test Machinery Section **********
208
209
210/****************************************************
211 * Standard Test Machinery
212 * DO NOT modify anything below -- it's a standard
213 * chunk of code whose purpose is to make user
214 * interaction uniform, and thereby make it simpler
215 * to read and understand someone else's test.
216 ****************************************************/
217
218/**
219 This is part of the standard test machinery.
220 It creates a dialog (with the instructions), and is the interface
221 for sending text messages to the user.
222 To print the instructions, send an array of strings to Sysout.createDialog
223 WithInstructions method.  Put one line of instructions per array entry.
224 To display a message for the tester to see, simply call Sysout.println
225 with the string to be displayed.
226 This mimics System.out.println but works within the test harness as well
227 as standalone.
228 */
229
230class Sysout {
231    private static TestDialog dialog;
232    private static boolean numbering = false;
233    private static int messageNumber = 0;
234
235    public static void createDialogWithInstructions(String[] instructions) {
236        dialog = new TestDialog(new Frame(), "Instructions");
237        dialog.printInstructions(instructions);
238        dialog.setVisible(true);
239        println("Any messages for the tester will display here.");
240    }
241
242    public static void createDialog() {
243        dialog = new TestDialog(new Frame(), "Instructions");
244        String[] defInstr = {"Instructions will appear here. ", ""};
245        dialog.printInstructions(defInstr);
246        dialog.setVisible(true);
247        println("Any messages for the tester will display here.");
248    }
249
250
251    /* Enables message counting for the tester. */
252    public static void enableNumbering(boolean enable) {
253        numbering = enable;
254    }
255
256    public static void printInstructions(String[] instructions) {
257        dialog.printInstructions(instructions);
258    }
259
260
261    public static void println(String messageIn) {
262        if (numbering) {
263            messageIn = "" + messageNumber + " " + messageIn;
264            messageNumber++;
265        }
266        dialog.displayMessage(messageIn);
267    }
268
269}// Sysout  class
270
271/**
272 This is part of the standard test machinery.  It provides a place for the
273 test instructions to be displayed, and a place for interactive messages
274 to the user to be displayed.
275 To have the test instructions displayed, see Sysout.
276 To have a message to the user be displayed, see Sysout.
277 Do not call anything in this dialog directly.
278 */
279class TestDialog extends Dialog implements ActionListener {
280
281    TextArea instructionsText;
282    TextArea messageText;
283    int maxStringLength = 80;
284    Panel buttonP = new Panel();
285    Button passB = new Button("pass");
286    Button failB = new Button("fail");
287
288    //DO NOT call this directly, go through Sysout
289    public TestDialog(Frame frame, String name) {
290        super(frame, name);
291        int scrollBoth = TextArea.SCROLLBARS_BOTH;
292        instructionsText = new TextArea("", 15, maxStringLength, scrollBoth);
293        add("North", instructionsText);
294
295        messageText = new TextArea("", 5, maxStringLength, scrollBoth);
296        add("Center", messageText);
297
298        passB = new Button("pass");
299        passB.setActionCommand("pass");
300        passB.addActionListener(this);
301        buttonP.add("East", passB);
302
303        failB = new Button("fail");
304        failB.setActionCommand("fail");
305        failB.addActionListener(this);
306        buttonP.add("West", failB);
307
308        add("South", buttonP);
309        pack();
310
311        setVisible(true);
312    }// TestDialog()
313
314    //DO NOT call this directly, go through Sysout
315    public void printInstructions(String[] instructions) {
316        //Clear out any current instructions
317        instructionsText.setText("");
318
319        //Go down array of instruction strings
320
321        String printStr, remainingStr;
322        for (int i = 0; i < instructions.length; i++) {
323            //chop up each into pieces maxSringLength long
324            remainingStr = instructions[i];
325            while (remainingStr.length() > 0) {
326                //if longer than max then chop off first max chars to print
327                if (remainingStr.length() >= maxStringLength) {
328                    //Try to chop on a word boundary
329                    int posOfSpace = remainingStr.
330                            lastIndexOf(' ', maxStringLength - 1);
331
332                    if (posOfSpace <= 0) posOfSpace = maxStringLength - 1;
333
334                    printStr = remainingStr.substring(0, posOfSpace + 1);
335                    remainingStr = remainingStr.substring(posOfSpace + 1);
336                }
337                //else just print
338                else {
339                    printStr = remainingStr;
340                    remainingStr = "";
341                }
342
343                instructionsText.append(printStr + "\n");
344
345            }// while
346
347        }// for
348
349    }//printInstructions()
350
351    //DO NOT call this directly, go through Sysout
352    public void displayMessage(String messageIn) {
353        messageText.append(messageIn + "\n");
354        System.out.println(messageIn);
355    }
356
357    //catch presses of the passed and failed buttons.
358    //simply call the standard pass() or fail() static methods of
359    //ManualMainTest
360    public void actionPerformed(ActionEvent e) {
361        if (e.getActionCommand() == "pass") {
362            MacOsXFileAndMultipleFileCopingTest.pass();
363        } else {
364            MacOsXFileAndMultipleFileCopingTest.fail();
365        }
366    }
367
368}// TestDialog  class