1 /* 2 * Copyright (c) 2014, 2018, 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 @key headful 27 @bug 4870762 28 @summary tests that a drop target JVM doesn't crash if the source doesn't export 29 data in native formats. 30 @run main NoFormatsCrashTest main 31 */ 32 33 import java.awt.*; 34 import java.awt.datatransfer.*; 35 import java.awt.dnd.*; 36 import java.awt.event.*; 37 import java.io.*; 38 39 public class NoFormatsCrashTest { 40 41 final Frame frame = new Frame(); 42 private volatile Process process; 43 44 static final int FRAME_ACTIVATION_TIMEOUT = 2000; 45 46 public static void main(String[] args) { 47 if (args.length > 0 && args[0].equals("main")) { 48 NoFormatsCrashTest test = new NoFormatsCrashTest(); 49 test.init(); 50 test.start(); 51 return; 52 } 53 54 NoFormatsCrashTest test = new NoFormatsCrashTest(); 55 test.run(args); 56 } 57 58 public void run(String[] args) { 59 try { 60 if (args.length != 4) { 61 throw new RuntimeException("Incorrect command line arguments."); 62 } 63 64 int x = Integer.parseInt(args[0]); 65 int y = Integer.parseInt(args[1]); 66 int w = Integer.parseInt(args[2]); 67 int h = Integer.parseInt(args[3]); 68 69 Panel panel = new DragSourcePanel(); 70 71 frame.setTitle("Drag source frame"); 72 frame.setLocation(500, 200); 73 frame.add(panel); 74 frame.pack(); 75 frame.setVisible(true); 76 77 Thread.sleep(FRAME_ACTIVATION_TIMEOUT); 78 79 Point sourcePoint = panel.getLocationOnScreen(); 80 Dimension d = panel.getSize(); 81 sourcePoint.translate(d.width / 2, d.height / 2); 82 83 Point targetPoint = new Point(x + w / 2, y + h / 2); 84 85 Robot robot = new Robot(); 86 robot.mouseMove(sourcePoint.x, sourcePoint.y); 87 robot.keyPress(KeyEvent.VK_CONTROL); 88 robot.mousePress(InputEvent.BUTTON1_MASK); 89 for (; !sourcePoint.equals(targetPoint); 90 sourcePoint.translate(sign(targetPoint.x - sourcePoint.x), 91 sign(targetPoint.y - sourcePoint.y))) { 92 robot.mouseMove(sourcePoint.x, sourcePoint.y); 93 Thread.sleep(50); 94 } 95 robot.mouseRelease(InputEvent.BUTTON1_MASK); 96 robot.keyRelease(KeyEvent.VK_CONTROL); 97 98 Thread.sleep(FRAME_ACTIVATION_TIMEOUT); 99 100 if (process.isAlive()) { 101 process.destroy(); 102 } 103 } catch (Throwable e) { 104 e.printStackTrace(); 105 throw new RuntimeException(e); 106 } 107 } // run() 108 109 public void init() { 110 frame.setTitle("Drop target frame"); 111 frame.setLocation(200, 200); 112 113 } // init() 114 115 public void start() { 116 DropTargetPanel panel = new DropTargetPanel(); 117 frame.add(panel); 118 frame.pack(); 119 frame.setVisible(true); 120 121 try { 122 Thread.sleep(FRAME_ACTIVATION_TIMEOUT); 123 124 Point p = frame.getLocationOnScreen(); 125 Dimension d = frame.getSize(); 126 127 String javaPath = System.getProperty("java.home", ""); 128 String command = javaPath + File.separator + "bin" + 129 File.separator + "java -cp " + System.getProperty("test.classes", ".") + 130 " NoFormatsCrashTest " + 131 p.x + " " + p.y + " " + d.width + " " + d.height; 132 133 process = Runtime.getRuntime().exec(command); 134 ProcessResults pres = ProcessResults.doWaitFor(process); 135 System.err.println("Child VM return code: " + pres.exitValue); 136 137 if (pres.stderr != null && pres.stderr.length() > 0) { 138 System.err.println("========= Child VM System.err ========"); 139 System.err.print(pres.stderr); 140 System.err.println("======================================"); 141 } 142 143 if (pres.stdout != null && pres.stdout.length() > 0) { 144 System.err.println("========= Child VM System.out ========"); 145 System.err.print(pres.stdout); 146 System.err.println("======================================"); 147 } 148 149 } catch (Throwable e) { 150 e.printStackTrace(); 151 throw new RuntimeException(e); 152 } 153 154 if (panel.isTestFailed()) { 155 throw new RuntimeException(); 156 } 157 } // start() 158 159 public static int sign(int n) { 160 return n < 0 ? -1 : n > 0 ? 1 : 0; 161 } 162 } // class NoFormatsCrashTest 163 164 class TestTransferable implements Transferable { 165 166 public static DataFlavor dataFlavor = null; 167 static final Object data = new Object(); 168 169 static { 170 DataFlavor df = null; 171 try { 172 df = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + 173 "; class=java.lang.Object"); 174 } catch (ClassNotFoundException e) { 175 throw new ExceptionInInitializerError(e); 176 } 177 dataFlavor = df; 178 } 179 180 public DataFlavor[] getTransferDataFlavors() { 181 return new DataFlavor[] { dataFlavor }; 182 } 183 184 public boolean isDataFlavorSupported(DataFlavor df) { 185 return dataFlavor.equals(df); 186 } 187 188 public Object getTransferData(DataFlavor df) 189 throws UnsupportedFlavorException, IOException { 190 if (!isDataFlavorSupported(df)) { 191 throw new UnsupportedFlavorException(df); 192 } 193 return data; 194 } 195 } 196 197 class DragSourcePanel extends Panel { 198 public DragSourcePanel() { 199 final Transferable t = new TestTransferable(); 200 final DragSourceListener dsl = new DragSourceAdapter() { 201 public void dragDropEnd(DragSourceDropEvent dtde) { 202 try { 203 Thread.sleep(100); 204 } catch (InterruptedException e) { 205 e.printStackTrace(); 206 } 207 // This finishes child VM 208 System.exit(0); 209 } 210 }; 211 final DragGestureListener dgl = new DragGestureListener() { 212 public void dragGestureRecognized(DragGestureEvent dge) { 213 dge.startDrag(null, t, dsl); 214 } 215 }; 216 final DragSource ds = DragSource.getDefaultDragSource(); 217 final DragGestureRecognizer dgr = 218 ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY, 219 dgl); 220 } 221 222 public Dimension getPreferredSize() { 223 return new Dimension(100, 100); 224 } 225 } 226 227 class DropTargetPanel extends Panel { 228 private boolean testFailed = false; 229 public DropTargetPanel() { 230 final DropTargetListener dtl = new DropTargetAdapter() { 231 public void dragOver(DropTargetDragEvent dtde) { 232 try { 233 dtde.getCurrentDataFlavorsAsList(); 234 } catch (Exception e) { 235 testFailed = true; 236 e.printStackTrace(); 237 } 238 } 239 public void drop(DropTargetDropEvent dtde) { 240 dtde.rejectDrop(); 241 } 242 }; 243 final DropTarget dt = new DropTarget(this, dtl); 244 } 245 246 public boolean isTestFailed() { 247 return testFailed; 248 } 249 250 public Dimension getPreferredSize() { 251 return new Dimension(100, 100); 252 } 253 } 254 255 class ProcessResults { 256 public int exitValue; 257 public String stdout; 258 public String stderr; 259 260 public ProcessResults() { 261 exitValue = -1; 262 stdout = ""; 263 stderr = ""; 264 } 265 266 /** 267 * Method to perform a "wait" for a process and return its exit value. 268 * This is a workaround for <code>Process.waitFor()</code> never returning. 269 */ 270 public static ProcessResults doWaitFor(Process p) { 271 ProcessResults pres = new ProcessResults(); 272 273 InputStream in = null; 274 InputStream err = null; 275 276 try { 277 in = p.getInputStream(); 278 err = p.getErrorStream(); 279 280 boolean finished = false; 281 282 while (!finished) { 283 try { 284 while (in.available() > 0) { 285 pres.stdout += (char)in.read(); 286 } 287 while (err.available() > 0) { 288 pres.stderr += (char)err.read(); 289 } 290 // Ask the process for its exitValue. If the process 291 // is not finished, an IllegalThreadStateException 292 // is thrown. If it is finished, we fall through and 293 // the variable finished is set to true. 294 pres.exitValue = p.exitValue(); 295 finished = true; 296 } 297 catch (IllegalThreadStateException e) { 298 // Process is not finished yet; 299 // Sleep a little to save on CPU cycles 300 Thread.currentThread().sleep(500); 301 } 302 } 303 if (in != null) in.close(); 304 if (err != null) err.close(); 305 } 306 catch (Throwable e) { 307 System.err.println("doWaitFor(): unexpected exception"); 308 e.printStackTrace(); 309 throw new RuntimeException(e); 310 } 311 return pres; 312 } 313 }