1 /* 2 * Copyright (c) 2005, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.awt; 27 28 import java.awt.desktop.*; 29 import java.awt.peer.DesktopPeer; 30 import java.io.File; 31 import java.io.FilePermission; 32 import java.io.IOException; 33 import java.net.MalformedURLException; 34 import java.net.URI; 35 import java.net.URISyntaxException; 36 import java.net.URL; 37 38 import sun.awt.SunToolkit; 39 import javax.swing.JMenuBar; 40 import sun.security.util.SecurityConstants; 41 42 /** 43 * The {@code Desktop} class allows interact with various desktop capabilities. 44 * 45 * <p> Supported operations include: 46 * <ul> 47 * <li>launching the user-default browser to show a specified 48 * URI;</li> 49 * <li>launching the user-default mail client with an optional 50 * {@code mailto} URI;</li> 51 * <li>launching a registered application to open, edit or print a 52 * specified file.</li> 53 * </ul> 54 * 55 * <p> This class provides methods corresponding to these 56 * operations. The methods look for the associated application 57 * registered on the current platform, and launch it to handle a URI 58 * or file. If there is no associated application or the associated 59 * application fails to be launched, an exception is thrown. 60 * 61 * Please see {@link Desktop.Action} for the full list of supported operations 62 * and capabilities. 63 * 64 * <p> An application is registered to a URI or file type; for 65 * example, the {@code "sxi"} file extension is typically registered 66 * to StarOffice. The mechanism of registering, accessing, and 67 * launching the associated application is platform-dependent. 68 * 69 * <p> Each operation is an action type represented by the {@link 70 * Desktop.Action} class. 71 * 72 * <p> Note: when some action is invoked and the associated 73 * application is executed, it will be executed on the same system as 74 * the one on which the Java application was launched. 75 * 76 * @see Action 77 * 78 * @since 1.6 79 * @author Armin Chen 80 * @author George Zhang 81 */ 82 public class Desktop { 83 84 /** 85 * Represents an action type. Each platform supports a different 86 * set of actions. You may use the {@link Desktop#isSupported} 87 * method to determine if the given action is supported by the 88 * current platform. 89 * @see java.awt.Desktop#isSupported(java.awt.Desktop.Action) 90 * @since 1.6 91 */ 92 public static enum Action { 93 /** 94 * Represents an "open" action. 95 * @see Desktop#open(java.io.File) 96 */ 97 OPEN, 98 /** 99 * Represents an "edit" action. 100 * @see Desktop#edit(java.io.File) 101 */ 102 EDIT, 103 /** 104 * Represents a "print" action. 105 * @see Desktop#print(java.io.File) 106 */ 107 PRINT, 108 /** 109 * Represents a "mail" action. 110 * @see Desktop#mail() 111 * @see Desktop#mail(java.net.URI) 112 */ 113 MAIL, 114 115 /** 116 * Represents a "browse" action. 117 * @see Desktop#browse(java.net.URI) 118 */ 119 BROWSE, 120 121 /** 122 * Represents an AppForegroundListener 123 * @see java.awt.desktop.AppForegroundListener 124 * @since 1.9 125 */ 126 APP_EVENT_FOREGROUND, 127 128 /** 129 * Represents an AppHiddenListener 130 * @see java.awt.desktop.AppHiddenListener 131 * @since 1.9 132 */ 133 APP_EVENT_HIDDEN, 134 135 /** 136 * Represents an AppReopenedListener 137 * @see java.awt.desktop.AppReopenedListener 138 * @since 1.9 139 */ 140 APP_EVENT_REOPENED, 141 142 /** 143 * Represents a ScreenSleepListener 144 * @see java.awt.desktop.ScreenSleepListener 145 * @since 1.9 146 */ 147 APP_EVENT_SCREEN_SLEEP, 148 149 /** 150 * Represents a SystemSleepListener 151 * @see java.awt.desktop.SystemSleepListener 152 * @since 1.9 153 */ 154 APP_EVENT_SYSTEM_SLEEP, 155 156 /** 157 * Represents a UserSessionListener 158 * @see java.awt.desktop.UserSessionListener 159 * @since 1.9 160 */ 161 APP_EVENT_USER_SESSION, 162 163 /** 164 * Represents an AboutHandler 165 * @see #setAboutHandler(java.awt.desktop.AboutHandler) 166 * @since 1.9 167 */ 168 APP_ABOUT, 169 170 /** 171 * Represents a PreferencesHandler 172 * @see #setPreferencesHandler(java.awt.desktop.PreferencesHandler) 173 * @since 1.9 174 */ 175 APP_PREFERENCES, 176 177 /** 178 * Represents an OpenFilesHandler 179 * @see #setOpenFileHandler(java.awt.desktop.OpenFilesHandler) 180 * @since 1.9 181 */ 182 APP_OPEN_FILE, 183 184 /** 185 * Represents a PrintFilesHandler 186 * @see #setPrintFileHandler(java.awt.desktop.PrintFilesHandler) 187 * @since 1.9 188 */ 189 APP_PRINT_FILE, 190 191 /** 192 * Represents an OpenURIHandler 193 * @see #setOpenURIHandler(java.awt.desktop.OpenURIHandler) 194 * @since 1.9 195 */ 196 APP_OPEN_URI, 197 198 /** 199 * Represents a QuitHandler 200 * @see #setQuitHandler(java.awt.desktop.QuitHandler) 201 * @since 1.9 202 */ 203 APP_QUIT_HANDLER, 204 205 /** 206 * Represents a QuitStrategy 207 * @see #setQuitStrategy(java.awt.desktop.QuitStrategy) 208 * @since 1.9 209 */ 210 APP_QUIT_STRATEGY, 211 212 /** 213 * Represents a SuddenTermination 214 * @see #enableSuddenTermination() 215 * @since 1.9 216 */ 217 APP_SUDDEN_TERMINATION, 218 219 /** 220 * Represents a requestForeground 221 * @see #requestForeground(boolean) 222 * @since 1.9 223 */ 224 APP_REQUEST_FOREGROUND, 225 226 /** 227 * Represents a HelpViewer 228 * @see #openHelpViewer() 229 * @since 1.9 230 */ 231 APP_HELP_VIEWER, 232 233 /** 234 * Represents a menu bar 235 * @see #setDefaultMenuBar(javax.swing.JMenuBar) 236 * @since 1.9 237 */ 238 APP_MENU_BAR, 239 240 /** 241 * Represents a platform-specific full screen 242 * @see #addWindowFullScreenListener(java.awt.Window, java.awt.desktop.FullScreenListener) 243 * @see #removeWindowFullScreenListener(java.awt.Window, java.awt.desktop.FullScreenListener) 244 * @see #setWindowCanFullScreen(java.awt.Window, boolean) 245 * @see #requestToggleFullScreen(java.awt.Window) 246 * @since 1.9 247 */ 248 FULLSCREEN, 249 250 /** 251 * Represents a browse file directory 252 * @see #browseFileDirectory(java.io.File) 253 * @since 1.9 254 */ 255 BROWSE_FILE_DIR, 256 257 /** 258 * Represents a move to trash 259 * @see #moveToTrash(java.io.File) 260 * @since 1.9 261 */ 262 MOVE_TO_TRASH 263 }; 264 265 private DesktopPeer peer; 266 267 /** 268 * Suppresses default constructor for noninstantiability. 269 */ 270 private Desktop() { 271 Toolkit defaultToolkit = Toolkit.getDefaultToolkit(); 272 // same cast as in isDesktopSupported() 273 if (defaultToolkit instanceof SunToolkit) { 274 peer = ((SunToolkit) defaultToolkit).createDesktopPeer(this); 275 } 276 } 277 278 /** 279 * Returns the <code>Desktop</code> instance of the current 280 * desktop context. On some platforms the Desktop API may not be 281 * supported; use the {@link #isDesktopSupported} method to 282 * determine if the current desktop is supported. 283 * @return the Desktop instance 284 * @throws HeadlessException if {@link 285 * GraphicsEnvironment#isHeadless()} returns {@code true} 286 * @throws UnsupportedOperationException if this class is not 287 * supported on the current platform 288 * @see #isDesktopSupported() 289 * @see java.awt.GraphicsEnvironment#isHeadless 290 */ 291 public static synchronized Desktop getDesktop(){ 292 if (GraphicsEnvironment.isHeadless()) throw new HeadlessException(); 293 if (!Desktop.isDesktopSupported()) { 294 throw new UnsupportedOperationException("Desktop API is not " + 295 "supported on the current platform"); 296 } 297 298 sun.awt.AppContext context = sun.awt.AppContext.getAppContext(); 299 Desktop desktop = (Desktop)context.get(Desktop.class); 300 301 if (desktop == null) { 302 desktop = new Desktop(); 303 context.put(Desktop.class, desktop); 304 } 305 306 return desktop; 307 } 308 309 /** 310 * Tests whether this class is supported on the current platform. 311 * If it's supported, use {@link #getDesktop()} to retrieve an 312 * instance. 313 * 314 * @return <code>true</code> if this class is supported on the 315 * current platform; <code>false</code> otherwise 316 * @see #getDesktop() 317 */ 318 public static boolean isDesktopSupported(){ 319 Toolkit defaultToolkit = Toolkit.getDefaultToolkit(); 320 if (defaultToolkit instanceof SunToolkit) { 321 return ((SunToolkit)defaultToolkit).isDesktopSupported(); 322 } 323 return false; 324 } 325 326 /** 327 * Tests whether an action is supported on the current platform. 328 * 329 * <p>Even when the platform supports an action, a file or URI may 330 * not have a registered application for the action. For example, 331 * most of the platforms support the {@link Desktop.Action#OPEN} 332 * action. But for a specific file, there may not be an 333 * application registered to open it. In this case, {@link 334 * #isSupported} may return {@code true}, but the corresponding 335 * action method will throw an {@link IOException}. 336 * 337 * @param action the specified {@link Action} 338 * @return <code>true</code> if the specified action is supported on 339 * the current platform; <code>false</code> otherwise 340 * @see Desktop.Action 341 */ 342 public boolean isSupported(Action action) { 343 return peer.isSupported(action); 344 } 345 346 /** 347 * Checks if the file is a valid file and readable. 348 * 349 * @throws SecurityException If a security manager exists and its 350 * {@link SecurityManager#checkRead(java.lang.String)} method 351 * denies read access to the file 352 * @throws NullPointerException if file is null 353 * @throws IllegalArgumentException if file doesn't exist 354 */ 355 private static void checkFileValidation(File file){ 356 if (file == null) throw new NullPointerException("File must not be null"); 357 358 if (!file.exists()) { 359 throw new IllegalArgumentException("The file: " 360 + file.getPath() + " doesn't exist."); 361 } 362 363 file.canRead(); 364 } 365 366 /** 367 * Checks if the action type is supported. 368 * 369 * @param actionType the action type in question 370 * @throws UnsupportedOperationException if the specified action type is not 371 * supported on the current platform 372 */ 373 private void checkActionSupport(Action actionType){ 374 if (!isSupported(actionType)) { 375 throw new UnsupportedOperationException("The " + actionType.name() 376 + " action is not supported on the current platform!"); 377 } 378 } 379 380 381 /** 382 * Calls to the security manager's <code>checkPermission</code> method with 383 * an <code>AWTPermission("showWindowWithoutWarningBanner")</code> 384 * permission. 385 */ 386 private void checkAWTPermission(){ 387 SecurityManager sm = System.getSecurityManager(); 388 if (sm != null) { 389 sm.checkPermission(new AWTPermission( 390 "showWindowWithoutWarningBanner")); 391 } 392 } 393 394 /** 395 * Calls to the security manager's <code>checkPermission</code> method with 396 * an <code>AWTPermission("fullScreenExclusive")</code> 397 * permission. 398 */ 399 private void checkFullscreenPermission(){ 400 SecurityManager sm = System.getSecurityManager(); 401 if (sm != null) { 402 sm.checkPermission(new AWTPermission( 403 "fullScreenExclusive")); 404 } 405 } 406 407 /** 408 * Launches the associated application to open the file. 409 * 410 * <p> If the specified file is a directory, the file manager of 411 * the current platform is launched to open it. 412 * 413 * @param file the file to be opened with the associated application 414 * @throws NullPointerException if {@code file} is {@code null} 415 * @throws IllegalArgumentException if the specified file doesn't 416 * exist 417 * @throws UnsupportedOperationException if the current platform 418 * does not support the {@link Desktop.Action#OPEN} action 419 * @throws IOException if the specified file has no associated 420 * application or the associated application fails to be launched 421 * @throws SecurityException if a security manager exists and its 422 * {@link java.lang.SecurityManager#checkRead(java.lang.String)} 423 * method denies read access to the file, or it denies the 424 * <code>AWTPermission("showWindowWithoutWarningBanner")</code> 425 * permission, or the calling thread is not allowed to create a 426 * subprocess 427 * @see java.awt.AWTPermission 428 */ 429 public void open(File file) throws IOException { 430 checkAWTPermission(); 431 checkExec(); 432 checkActionSupport(Action.OPEN); 433 checkFileValidation(file); 434 435 peer.open(file); 436 } 437 438 /** 439 * Launches the associated editor application and opens a file for 440 * editing. 441 * 442 * @param file the file to be opened for editing 443 * @throws NullPointerException if the specified file is {@code null} 444 * @throws IllegalArgumentException if the specified file doesn't 445 * exist 446 * @throws UnsupportedOperationException if the current platform 447 * does not support the {@link Desktop.Action#EDIT} action 448 * @throws IOException if the specified file has no associated 449 * editor, or the associated application fails to be launched 450 * @throws SecurityException if a security manager exists and its 451 * {@link java.lang.SecurityManager#checkRead(java.lang.String)} 452 * method denies read access to the file, or {@link 453 * java.lang.SecurityManager#checkWrite(java.lang.String)} method 454 * denies write access to the file, or it denies the 455 * <code>AWTPermission("showWindowWithoutWarningBanner")</code> 456 * permission, or the calling thread is not allowed to create a 457 * subprocess 458 * @see java.awt.AWTPermission 459 */ 460 public void edit(File file) throws IOException { 461 checkAWTPermission(); 462 checkExec(); 463 checkActionSupport(Action.EDIT); 464 file.canWrite(); 465 checkFileValidation(file); 466 467 peer.edit(file); 468 } 469 470 /** 471 * Prints a file with the native desktop printing facility, using 472 * the associated application's print command. 473 * 474 * @param file the file to be printed 475 * @throws NullPointerException if the specified file is {@code 476 * null} 477 * @throws IllegalArgumentException if the specified file doesn't 478 * exist 479 * @throws UnsupportedOperationException if the current platform 480 * does not support the {@link Desktop.Action#PRINT} action 481 * @throws IOException if the specified file has no associated 482 * application that can be used to print it 483 * @throws SecurityException if a security manager exists and its 484 * {@link java.lang.SecurityManager#checkRead(java.lang.String)} 485 * method denies read access to the file, or its {@link 486 * java.lang.SecurityManager#checkPrintJobAccess()} method denies 487 * the permission to print the file, or the calling thread is not 488 * allowed to create a subprocess 489 */ 490 public void print(File file) throws IOException { 491 checkExec(); 492 SecurityManager sm = System.getSecurityManager(); 493 if (sm != null) { 494 sm.checkPrintJobAccess(); 495 } 496 checkActionSupport(Action.PRINT); 497 checkFileValidation(file); 498 499 peer.print(file); 500 } 501 502 /** 503 * Launches the default browser to display a {@code URI}. 504 * If the default browser is not able to handle the specified 505 * {@code URI}, the application registered for handling 506 * {@code URIs} of the specified type is invoked. The application 507 * is determined from the protocol and path of the {@code URI}, as 508 * defined by the {@code URI} class. 509 * <p> 510 * If the calling thread does not have the necessary permissions, 511 * and this is invoked from within an applet, 512 * {@code AppletContext.showDocument()} is used. Similarly, if the calling 513 * does not have the necessary permissions, and this is invoked from within 514 * a Java Web Started application, {@code BasicService.showDocument()} 515 * is used. 516 * 517 * @param uri the URI to be displayed in the user default browser 518 * @throws NullPointerException if {@code uri} is {@code null} 519 * @throws UnsupportedOperationException if the current platform 520 * does not support the {@link Desktop.Action#BROWSE} action 521 * @throws IOException if the user default browser is not found, 522 * or it fails to be launched, or the default handler application 523 * failed to be launched 524 * @throws SecurityException if a security manager exists and it 525 * denies the 526 * <code>AWTPermission("showWindowWithoutWarningBanner")</code> 527 * permission, or the calling thread is not allowed to create a 528 * subprocess; and not invoked from within an applet or Java Web Started 529 * application 530 * @throws IllegalArgumentException if the necessary permissions 531 * are not available and the URI can not be converted to a {@code URL} 532 * @see java.net.URI 533 * @see java.awt.AWTPermission 534 * @see java.applet.AppletContext 535 */ 536 public void browse(URI uri) throws IOException { 537 SecurityException securityException = null; 538 try { 539 checkAWTPermission(); 540 checkExec(); 541 } catch (SecurityException e) { 542 securityException = e; 543 } 544 checkActionSupport(Action.BROWSE); 545 if (uri == null) { 546 throw new NullPointerException(); 547 } 548 if (securityException == null) { 549 peer.browse(uri); 550 return; 551 } 552 553 // Calling thread doesn't have necessary privileges. 554 // Delegate to DesktopBrowse so that it can work in 555 // applet/webstart. 556 URL url = null; 557 try { 558 url = uri.toURL(); 559 } catch (MalformedURLException e) { 560 throw new IllegalArgumentException("Unable to convert URI to URL", e); 561 } 562 sun.awt.DesktopBrowse db = sun.awt.DesktopBrowse.getInstance(); 563 if (db == null) { 564 // Not in webstart/applet, throw the exception. 565 throw securityException; 566 } 567 db.browse(url); 568 } 569 570 /** 571 * Launches the mail composing window of the user default mail 572 * client. 573 * 574 * @throws UnsupportedOperationException if the current platform 575 * does not support the {@link Desktop.Action#MAIL} action 576 * @throws IOException if the user default mail client is not 577 * found, or it fails to be launched 578 * @throws SecurityException if a security manager exists and it 579 * denies the 580 * <code>AWTPermission("showWindowWithoutWarningBanner")</code> 581 * permission, or the calling thread is not allowed to create a 582 * subprocess 583 * @see java.awt.AWTPermission 584 */ 585 public void mail() throws IOException { 586 checkAWTPermission(); 587 checkExec(); 588 checkActionSupport(Action.MAIL); 589 URI mailtoURI = null; 590 try{ 591 mailtoURI = new URI("mailto:?"); 592 peer.mail(mailtoURI); 593 } catch (URISyntaxException e){ 594 // won't reach here. 595 } 596 } 597 598 /** 599 * Launches the mail composing window of the user default mail 600 * client, filling the message fields specified by a {@code 601 * mailto:} URI. 602 * 603 * <p> A <code>mailto:</code> URI can specify message fields 604 * including <i>"to"</i>, <i>"cc"</i>, <i>"subject"</i>, 605 * <i>"body"</i>, etc. See <a 606 * href="http://www.ietf.org/rfc/rfc2368.txt">The mailto URL 607 * scheme (RFC 2368)</a> for the {@code mailto:} URI specification 608 * details. 609 * 610 * @param mailtoURI the specified {@code mailto:} URI 611 * @throws NullPointerException if the specified URI is {@code 612 * null} 613 * @throws IllegalArgumentException if the URI scheme is not 614 * <code>"mailto"</code> 615 * @throws UnsupportedOperationException if the current platform 616 * does not support the {@link Desktop.Action#MAIL} action 617 * @throws IOException if the user default mail client is not 618 * found or fails to be launched 619 * @throws SecurityException if a security manager exists and it 620 * denies the 621 * <code>AWTPermission("showWindowWithoutWarningBanner")</code> 622 * permission, or the calling thread is not allowed to create a 623 * subprocess 624 * @see java.net.URI 625 * @see java.awt.AWTPermission 626 */ 627 public void mail(URI mailtoURI) throws IOException { 628 checkAWTPermission(); 629 checkExec(); 630 checkActionSupport(Action.MAIL); 631 if (mailtoURI == null) throw new NullPointerException(); 632 633 if (!"mailto".equalsIgnoreCase(mailtoURI.getScheme())) { 634 throw new IllegalArgumentException("URI scheme is not \"mailto\""); 635 } 636 637 peer.mail(mailtoURI); 638 } 639 640 private void checkExec() throws SecurityException { 641 SecurityManager sm = System.getSecurityManager(); 642 if (sm != null) { 643 sm.checkPermission(new FilePermission("<<ALL FILES>>", 644 SecurityConstants.FILE_EXECUTE_ACTION)); 645 } 646 } 647 648 private void checkRead() throws SecurityException { 649 SecurityManager sm = System.getSecurityManager(); 650 if (sm != null) { 651 sm.checkPermission(new FilePermission("<<ALL FILES>>", 652 SecurityConstants.FILE_READ_ACTION)); 653 } 654 } 655 656 private void checkWrite() throws SecurityException { 657 SecurityManager sm = System.getSecurityManager(); 658 if (sm != null) { 659 sm.checkPermission(new FilePermission("<<ALL FILES>>", 660 SecurityConstants.FILE_WRITE_ACTION)); 661 } 662 } 663 664 /** 665 * Adds sub-types of {@link SystemEventListener} to listen for notifications 666 * from the native system. 667 * 668 * Has no effect if SystemEventListener's sub-type is unsupported on the current 669 * platform. 670 * 671 * @param listener listener 672 * @see AppForegroundListener 673 * @see AppHiddenListener 674 * @see AppReopenedListener 675 * @see ScreenSleepListener 676 * @see SystemSleepListener 677 * @see UserSessionListener 678 * @since 1.9 679 */ 680 public void addAppEventListener(final SystemEventListener listener) { 681 peer.addAppEventListener(listener); 682 } 683 684 /** 685 * Removes sub-types of {@link SystemEventListener} to listen for notifications 686 * from the native system. 687 * 688 * Has no effect if SystemEventListener's sub-type is unsupported on the current 689 * platform. 690 * 691 * @param listener listener 692 * @see AppForegroundListener 693 * @see AppHiddenListener 694 * @see AppReopenedListener 695 * @see ScreenSleepListener 696 * @see SystemSleepListener 697 * @see UserSessionListener 698 * @since 1.9 699 */ 700 public void removeAppEventListener(final SystemEventListener listener) { 701 peer.removeAppEventListener(listener); 702 } 703 704 /** 705 * Installs a handler to show a custom About window for your application. 706 * <p> 707 * Setting the {@link AboutHandler} to <code>null</code> reverts it to the 708 * default behavior. 709 * 710 * @param aboutHandler the handler to respond to the 711 * @throws UnsupportedOperationException if the current platform 712 * does not support the {@link Desktop.Action#APP_ABOUT} action 713 * {@link AboutHandler#handleAbout} )} message 714 * @since 1.9 715 */ 716 public void setAboutHandler(final AboutHandler aboutHandler) { 717 checkActionSupport(Action.APP_ABOUT); 718 peer.setAboutHandler(aboutHandler); 719 } 720 721 /** 722 * Installs a handler to show a custom Preferences window for your 723 * application. 724 * <p> 725 * Setting the {@link PreferencesHandler} to <code>null</code> reverts it to 726 * the default behavior 727 * 728 * @param preferencesHandler the handler to respond to the 729 * @throws UnsupportedOperationException if the current platform 730 * does not support the {@link Desktop.Action#APP_PREFERENCES} action 731 * {@link PreferencesHandler#handlePreferences(PreferencesEvent)} 732 * @since 1.9 733 */ 734 public void setPreferencesHandler(final PreferencesHandler preferencesHandler) { 735 checkActionSupport(Action.APP_PREFERENCES); 736 peer.setPreferencesHandler(preferencesHandler); 737 } 738 739 /** 740 * Installs the handler which is notified when the application is asked to 741 * open a list of files. 742 * 743 * @implNote Please note that for Mac OS, notifications 744 * are only sent if the Java app is a bundled application, 745 * with a {@code CFBundleDocumentTypes} array present in its 746 * Info.plist. See the 747 * <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference"> 748 * Info.plist Key Reference</a> for more information about adding a 749 * {@code CFBundleDocumentTypes} key to your app's Info.plist. 750 * 751 * @param openFileHandler handler 752 * @throws UnsupportedOperationException if the current platform 753 * does not support the {@link Desktop.Action#APP_OPEN_FILE} action 754 * @since 1.9 755 */ 756 public void setOpenFileHandler(final OpenFilesHandler openFileHandler) { 757 checkActionSupport(Action.APP_OPEN_FILE); 758 peer.setOpenFileHandler(openFileHandler); 759 } 760 761 /** 762 * Installs the handler which is notified when the application is asked to 763 * print a list of files. 764 * 765 * @implNote Please note that for Mac OS, notifications 766 * are only sent if the Java app is a bundled application, 767 * with a {@code CFBundleDocumentTypes} array present in its 768 * Info.plist. See the 769 * <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference"> 770 * Info.plist Key Reference</a> for more information about adding a 771 * {@code CFBundleDocumentTypes} key to your app's Info.plist. 772 * 773 * @param printFileHandler handler 774 * @throws UnsupportedOperationException if the current platform 775 * does not support the {@link Desktop.Action#APP_PRINT_FILE} action 776 * @since 1.9 777 */ 778 public void setPrintFileHandler(final PrintFilesHandler printFileHandler) { 779 checkActionSupport(Action.APP_PRINT_FILE); 780 peer.setPrintFileHandler(printFileHandler); 781 } 782 783 /** 784 * Installs the handler which is notified when the application is asked to 785 * open a URL. 786 * 787 * Setting the handler to <code>null</code> causes all 788 * {@link OpenURIHandler#openURI(AppEvent.OpenURIEvent)} requests to be 789 * enqueued until another handler is set. 790 * 791 * @implNote Please note that for Mac OS, notifications 792 * are only sent if the Java app is a bundled application, 793 * with a {@code CFBundleDocumentTypes} array present in its 794 * Info.plist. See the 795 * <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference"> 796 * Info.plist Key Reference</a> for more information about adding a 797 * {@code CFBundleDocumentTypes} key to your app's Info.plist. 798 * 799 * @param openURIHandler handler 800 * @throws UnsupportedOperationException if the current platform 801 * does not support the {@link Desktop.Action#APP_OPEN_URI} action 802 * @since 1.9 803 */ 804 public void setOpenURIHandler(final OpenURIHandler openURIHandler) { 805 checkActionSupport(Action.APP_OPEN_URI); 806 peer.setOpenURIHandler(openURIHandler); 807 } 808 809 /** 810 * Installs the handler which determines if the application should quit. The 811 * handler is passed a one-shot {@link QuitResponse} which can cancel or 812 * proceed with the quit. Setting the handler to <code>null</code> causes 813 * all quit requests to directly perform the default {@link QuitStrategy}. 814 * 815 * @param quitHandler the handler that is called when the application is 816 * asked to quit 817 * @throws UnsupportedOperationException if the current platform 818 * does not support the {@link Desktop.Action#APP_QUIT_HANDLER} action 819 * @since 1.9 820 */ 821 public void setQuitHandler(final QuitHandler quitHandler) { 822 checkActionSupport(Action.APP_QUIT_HANDLER); 823 peer.setQuitHandler(quitHandler); 824 } 825 826 /** 827 * Sets the default strategy used to quit this application. The default is 828 * calling SYSTEM_EXIT_0. 829 * 830 * @param strategy the way this application should be shutdown 831 * @throws UnsupportedOperationException if the current platform 832 * does not support the {@link Desktop.Action#APP_QUIT_STRATEGY} action 833 * @see QuitStrategy 834 * @since 1.9 835 */ 836 public void setQuitStrategy(final QuitStrategy strategy) { 837 checkActionSupport(Action.APP_QUIT_STRATEGY); 838 peer.setQuitStrategy(strategy); 839 } 840 841 /** 842 * Enables this application to be suddenly terminated. 843 * 844 * Call this method to indicate your application's state is saved, and 845 * requires no notification to be terminated. Letting your application 846 * remain terminatable improves the user experience by avoiding re-paging in 847 * your application when it's asked to quit. 848 * 849 * <b>Note: enabling sudden termination will allow your application to be 850 * quit without notifying your QuitHandler, or running any shutdown 851 * hooks.</b> 852 * E.g. user-initiated Cmd-Q, logout, restart, or shutdown requests will 853 * effectively "kill -KILL" your application. 854 * 855 * @throws UnsupportedOperationException if the current platform 856 * does not support the {@link Desktop.Action#APP_SUDDEN_TERMINATION} action 857 * @see #disableSuddenTermination() 858 * @since 1.9 859 */ 860 public void enableSuddenTermination() { 861 checkActionSupport(Action.APP_SUDDEN_TERMINATION); 862 peer.enableSuddenTermination(); 863 } 864 865 /** 866 * Prevents this application from being suddenly terminated. 867 * 868 * Call this method to indicate that your application has unsaved state, and 869 * may not be terminated without notification. 870 * 871 * @throws UnsupportedOperationException if the current platform 872 * does not support the {@link Desktop.Action#APP_SUDDEN_TERMINATION} action 873 * @see #enableSuddenTermination() 874 * @since 1.9 875 */ 876 public void disableSuddenTermination() { 877 checkActionSupport(Action.APP_SUDDEN_TERMINATION); 878 peer.disableSuddenTermination(); 879 } 880 881 /** 882 * Requests this application to move to the foreground. 883 * 884 * @param allWindows if all windows of this application should be moved to 885 * the foreground, or only the foremost one 886 * @throws SecurityException if a security manager exists and it denies the 887 * <code>AWTPermission("showWindowWithoutWarningBanner")</code> permission. 888 * @throws UnsupportedOperationException if the current platform 889 * does not support the {@link Desktop.Action#APP_REQUEST_FOREGROUND} action 890 * @since 1.9 891 */ 892 public void requestForeground(final boolean allWindows) { 893 checkAWTPermission(); 894 checkActionSupport(Action.APP_REQUEST_FOREGROUND); 895 peer.requestForeground(allWindows); 896 } 897 898 /** 899 * Opens the native help viewer application. 900 * 901 * @throws SecurityException if a security manager exists and it denies the 902 * <code>AWTPermission("showWindowWithoutWarningBanner")</code> permission. 903 * @throws UnsupportedOperationException if the current platform 904 * does not support the {@link Desktop.Action#APP_HELP_VIEWER} action 905 * @since 1.9 906 */ 907 public void openHelpViewer() { 908 checkAWTPermission(); 909 checkActionSupport(Action.APP_HELP_VIEWER); 910 peer.openHelpViewer(); 911 } 912 913 /** 914 * Sets the default menu bar to use when there are no active frames. 915 * 916 * @implNote Aqua Look and Feel should be active to support this on Mac OS. 917 * 918 * @param menuBar to use when no other frames are active 919 * @throws SecurityException if a security manager exists and it denies the 920 * <code>AWTPermission("showWindowWithoutWarningBanner")</code> permission. 921 * @throws UnsupportedOperationException if the current platform 922 * does not support the {@link Desktop.Action#APP_MENU_BAR} action 923 * @since 1.9 924 */ 925 public void setDefaultMenuBar(final JMenuBar menuBar) { 926 checkAWTPermission(); 927 checkActionSupport(Action.APP_MENU_BAR); 928 peer.setDefaultMenuBar(menuBar); 929 } 930 931 /** 932 * Attaches a {@link FullScreenListener} to the specified top-level 933 * {@link Window}. 934 * 935 * @param window to attach the {@link FullScreenListener} to 936 * @param listener to be notified when a full screen event occurs 937 * @throws SecurityException if a security manager exists and it denies the 938 * <code>AWTPermission("showWindowWithoutWarningBanner")</code> 939 * and <code>AWTPermission("fullScreenExclusive")</code> 940 * permission. 941 * @throws IllegalArgumentException if window is not a 942 * {@link javax.swing.JFrame} or a {@link javax.swing.JDialog} 943 * @throws UnsupportedOperationException if the current platform 944 * does not support the {@link Desktop.Action#FULLSCREEN} action 945 * @since 1.9 946 */ 947 public void addWindowFullScreenListener(final Window window, 948 final FullScreenListener listener) { 949 checkAWTPermission(); 950 checkFullscreenPermission(); 951 checkActionSupport(Action.FULLSCREEN); 952 peer.addWindowFullScreenListener(window, listener); 953 } 954 955 /** 956 * Removes a {@link FullScreenListener} from the specified top-level 957 * {@link Window}. 958 * 959 * @param window to remove the {@link FullScreenListener} from 960 * @param listener to be removed 961 * @throws SecurityException if a security manager exists and it denies the 962 * <code>AWTPermission("showWindowWithoutWarningBanner")</code> 963 * and <code>AWTPermission("fullScreenExclusive")</code> 964 * permission. 965 * @throws IllegalArgumentException if window is not a 966 * {@link javax.swing.JFrame} or a {@link javax.swing.JDialog} 967 * @throws UnsupportedOperationException if the current platform 968 * does not support the {@link Desktop.Action#FULLSCREEN} action 969 * @since 1.9 970 */ 971 public void removeWindowFullScreenListener(final Window window, 972 final FullScreenListener listener) { 973 checkAWTPermission(); 974 checkFullscreenPermission(); 975 checkActionSupport(Action.FULLSCREEN); 976 peer.removeWindowFullScreenListener(window, listener); 977 } 978 979 /** 980 * Marks a {@link Window} as able to animate into or out of full screen 981 * mode. 982 * 983 * Only top-level {@link Window}s which are a 984 * {@link javax.swing.JFrame} or a {@link javax.swing.JDialog} 985 * are able to be animated into and out of full screen mode. The {@link Window} 986 * must be marked as full screen-able before the native peer is created with 987 * {@link Component#addNotify()}. 988 * 989 * @param window window 990 * @param canFullScreen flag 991 * @throws SecurityException if a security manager exists and it denies the 992 * <code>AWTPermission("showWindowWithoutWarningBanner")</code> 993 * and <code>AWTPermission("fullScreenExclusive")</code> 994 * permission. 995 * @throws IllegalArgumentException if window is not a 996 * {@link javax.swing.JFrame} or a {@link javax.swing.JDialog} 997 * @throws UnsupportedOperationException if the current platform 998 * does not support the {@link Desktop.Action#FULLSCREEN} action 999 * @since 1.9 1000 */ 1001 public void setWindowCanFullScreen(final Window window, 1002 final boolean canFullScreen) { 1003 checkAWTPermission(); 1004 checkFullscreenPermission(); 1005 checkActionSupport(Action.FULLSCREEN); 1006 peer.setWindowCanFullScreen(window, canFullScreen); 1007 } 1008 1009 /** 1010 * Requests that a {@link Window} should get into or out of full screen 1011 * mode. Only {@link Window}s marked as full screenable by 1012 * {@link #setWindowCanFullScreen(Window, boolean)} can be toggled. 1013 * 1014 * @param window to animate into or out of full screen mode 1015 * @throws SecurityException if a security manager exists and it denies the 1016 * <code>AWTPermission("showWindowWithoutWarningBanner")</code> 1017 * and <code>AWTPermission("fullScreenExclusive")</code> 1018 * permission. 1019 * @throws UnsupportedOperationException if the current platform 1020 * does not support the {@link Desktop.Action#FULLSCREEN} action 1021 * @since 1.9 1022 */ 1023 public void requestToggleFullScreen(final Window window) { 1024 checkAWTPermission(); 1025 checkFullscreenPermission(); 1026 checkActionSupport(Action.FULLSCREEN); 1027 peer.requestToggleFullScreen(window); 1028 } 1029 1030 1031 /** 1032 * Opens a folder containing the {@code file} and selects it 1033 * in a default system file manager. 1034 * @param file the file 1035 * @throws SecurityException If a security manager exists and its 1036 * {@link SecurityManager#checkRead(java.lang.String)} method 1037 * denies read access to the file 1038 * @throws UnsupportedOperationException if the current platform 1039 * does not support the {@link Desktop.Action#BROWSE_FILE_DIR} action 1040 * @throws NullPointerException if {@code file} is {@code null} 1041 * @throws IllegalArgumentException if the specified file doesn't 1042 * exist 1043 * @since 1.9 1044 */ 1045 public void browseFileDirectory(File file) { 1046 checkRead(); 1047 checkActionSupport(Action.BROWSE_FILE_DIR); 1048 checkFileValidation(file); 1049 peer.browseFileDirectory(file); 1050 } 1051 1052 /** 1053 * Moves the specified file to the trash. 1054 * 1055 * @param file the file 1056 * @return returns true if successfully moved the file to the trash. 1057 * @throws SecurityException If a security manager exists and its 1058 * {@link SecurityManager#checkWrite(java.lang.String)} method 1059 * denies write access to the file 1060 * @throws UnsupportedOperationException if the current platform 1061 * does not support the {@link Desktop.Action#MOVE_TO_TRASH} action 1062 * @throws NullPointerException if {@code file} is {@code null} 1063 * @throws IllegalArgumentException if the specified file doesn't 1064 * exist 1065 * 1066 * @since 1.9 1067 */ 1068 public boolean moveToTrash(final File file) { 1069 checkWrite(); 1070 checkActionSupport(Action.MOVE_TO_TRASH); 1071 checkFileValidation(file); 1072 return peer.moveToTrash(file); 1073 } 1074 }