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