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