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