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 private void checkEventsProcessingPermission() { 275 SecurityManager sm = System.getSecurityManager(); 276 if (sm != null) { 277 sm.checkPermission(new RuntimePermission( 278 "canProcessApplicationEvents")); 279 } 280 } 281 282 private static Desktop desktop; 283 284 /** 285 * Returns the {@code Desktop} instance of the current 286 * desktop context. On some platforms the Desktop API may not be 287 * supported; use the {@link #isDesktopSupported} method to 288 * determine if the current desktop is supported. 289 * @return the Desktop instance 290 * @throws HeadlessException if {@link 291 * GraphicsEnvironment#isHeadless()} returns {@code true} 292 * @throws UnsupportedOperationException if this class is not 293 * supported on the current platform 294 * @see #isDesktopSupported() 295 * @see java.awt.GraphicsEnvironment#isHeadless 296 */ 297 public static synchronized Desktop getDesktop(){ 298 if (GraphicsEnvironment.isHeadless()) throw new HeadlessException(); 299 if (!Desktop.isDesktopSupported()) { 300 throw new UnsupportedOperationException("Desktop API is not " + 301 "supported on the current platform"); 302 } 303 304 sun.awt.AppContext context = sun.awt.AppContext.getAppContext(); 305 306 Desktop desktop = (context == null) 307 ? Desktop.desktop 308 : (Desktop)context.get(Desktop.class); 309 310 if (desktop == null) { 311 desktop = new Desktop(); 312 if (context != null) { 313 context.put(Desktop.class, desktop); 314 } else { 315 Desktop.desktop = desktop; 316 } 317 } 318 319 return desktop; 320 } 321 322 /** 323 * Tests whether this class is supported on the current platform. 324 * If it's supported, use {@link #getDesktop()} to retrieve an 325 * instance. 326 * 327 * @return {@code true} if this class is supported on the 328 * current platform; {@code false} otherwise 329 * @see #getDesktop() 330 */ 331 public static boolean isDesktopSupported(){ 332 Toolkit defaultToolkit = Toolkit.getDefaultToolkit(); 333 if (defaultToolkit instanceof SunToolkit) { 334 return ((SunToolkit)defaultToolkit).isDesktopSupported(); 335 } 336 return false; 337 } 338 339 /** 340 * Tests whether an action is supported on the current platform. 341 * 342 * <p>Even when the platform supports an action, a file or URI may 343 * not have a registered application for the action. For example, 344 * most of the platforms support the {@link Desktop.Action#OPEN} 345 * action. But for a specific file, there may not be an 346 * application registered to open it. In this case, {@link 347 * #isSupported} may return {@code true}, but the corresponding 348 * action method will throw an {@link IOException}. 349 * 350 * @param action the specified {@link Action} 351 * @return {@code true} if the specified action is supported on 352 * the current platform; {@code false} otherwise 353 * @see Desktop.Action 354 */ 355 public boolean isSupported(Action action) { 356 return peer.isSupported(action); 357 } 358 359 /** 360 * Checks if the file is a valid file and readable. 361 * 362 * @throws SecurityException If a security manager exists and its 363 * {@link SecurityManager#checkRead(java.lang.String)} method 364 * denies read access to the file 365 * @throws NullPointerException if file is null 366 * @throws IllegalArgumentException if file doesn't exist 367 */ 368 private static void checkFileValidation(File file){ 369 if (file == null) throw new NullPointerException("File must not be null"); 370 371 if (!file.exists()) { 372 throw new IllegalArgumentException("The file: " 373 + file.getPath() + " doesn't exist."); 374 } 375 376 file.canRead(); 377 } 378 379 /** 380 * Checks if the action type is supported. 381 * 382 * @param actionType the action type in question 383 * @throws UnsupportedOperationException if the specified action type is not 384 * supported on the current platform 385 */ 386 private void checkActionSupport(Action actionType){ 387 if (!isSupported(actionType)) { 388 throw new UnsupportedOperationException("The " + actionType.name() 389 + " action is not supported on the current platform!"); 390 } 391 } 392 393 394 /** 395 * Calls to the security manager's {@code checkPermission} method with 396 * an {@code AWTPermission("showWindowWithoutWarningBanner")} 397 * permission. 398 */ 399 private void checkAWTPermission(){ 400 SecurityManager sm = System.getSecurityManager(); 401 if (sm != null) { 402 sm.checkPermission(new AWTPermission( 403 "showWindowWithoutWarningBanner")); 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")} 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")} 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")} 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")} 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:} 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"} 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")} 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 checkDelete() throws SecurityException { 657 SecurityManager sm = System.getSecurityManager(); 658 if (sm != null) { 659 sm.checkPermission(new FilePermission("<<ALL FILES>>", 660 SecurityConstants.FILE_DELETE_ACTION)); 661 } 662 } 663 664 private void checkQuitPermission() { 665 SecurityManager sm = System.getSecurityManager(); 666 if (sm != null) { 667 sm.checkExit(0); 668 } 669 } 670 671 /** 672 * Adds sub-types of {@link SystemEventListener} to listen for notifications 673 * from the native system. 674 * 675 * Has no effect if SystemEventListener's sub-type is unsupported on the current 676 * platform. 677 * 678 * @param listener listener 679 * 680 * @throws SecurityException if a security manager exists and it 681 * denies the 682 * {@code RuntimePermission("canProcessApplicationEvents")} 683 * permission 684 * 685 * @see java.awt.desktop.AppForegroundListener 686 * @see java.awt.desktop.AppHiddenListener 687 * @see java.awt.desktop.AppReopenedListener 688 * @see java.awt.desktop.ScreenSleepListener 689 * @see java.awt.desktop.SystemSleepListener 690 * @see java.awt.desktop.UserSessionListener 691 * @since 9 692 */ 693 public void addAppEventListener(final SystemEventListener listener) { 694 checkEventsProcessingPermission(); 695 peer.addAppEventListener(listener); 696 } 697 698 /** 699 * Removes sub-types of {@link SystemEventListener} to listen for notifications 700 * from the native system. 701 * 702 * Has no effect if SystemEventListener's sub-type is unsupported on the current 703 * platform. 704 * 705 * @param listener listener 706 * 707 * @throws SecurityException if a security manager exists and it 708 * denies the 709 * {@code RuntimePermission("canProcessApplicationEvents")} 710 * permission 711 * 712 * @see java.awt.desktop.AppForegroundListener 713 * @see java.awt.desktop.AppHiddenListener 714 * @see java.awt.desktop.AppReopenedListener 715 * @see java.awt.desktop.ScreenSleepListener 716 * @see java.awt.desktop.SystemSleepListener 717 * @see java.awt.desktop.UserSessionListener 718 * @since 9 719 */ 720 public void removeAppEventListener(final SystemEventListener listener) { 721 checkEventsProcessingPermission(); 722 peer.removeAppEventListener(listener); 723 } 724 725 /** 726 * Installs a handler to show a custom About window for your application. 727 * <p> 728 * Setting the {@link java.awt.desktop.AboutHandler} to {@code null} reverts it to the 729 * default behavior. 730 * 731 * @param aboutHandler the handler to respond to the 732 * {@link java.awt.desktop.AboutHandler#handleAbout} )} message 733 * 734 * @throws SecurityException if a security manager exists and it 735 * denies the 736 * {@code RuntimePermission("canProcessApplicationEvents")} 737 * permission 738 * @throws UnsupportedOperationException if the current platform 739 * does not support the {@link Desktop.Action#APP_ABOUT} action 740 * 741 * @since 9 742 */ 743 public void setAboutHandler(final AboutHandler aboutHandler) { 744 checkEventsProcessingPermission(); 745 checkActionSupport(Action.APP_ABOUT); 746 peer.setAboutHandler(aboutHandler); 747 } 748 749 /** 750 * Installs a handler to show a custom Preferences window for your 751 * application. 752 * <p> 753 * Setting the {@link PreferencesHandler} to {@code null} reverts it to 754 * the default behavior 755 * 756 * @param preferencesHandler the handler to respond to the 757 * {@link PreferencesHandler#handlePreferences(PreferencesEvent)} 758 * 759 * @throws SecurityException if a security manager exists and it 760 * denies the 761 * {@code RuntimePermission("canProcessApplicationEvents")} permission 762 * @throws UnsupportedOperationException if the current platform 763 * does not support the {@link Desktop.Action#APP_PREFERENCES} action 764 * @since 9 765 */ 766 public void setPreferencesHandler(final PreferencesHandler preferencesHandler) { 767 checkEventsProcessingPermission(); 768 checkActionSupport(Action.APP_PREFERENCES); 769 peer.setPreferencesHandler(preferencesHandler); 770 } 771 772 /** 773 * Installs the handler which is notified when the application is asked to 774 * open a list of files. 775 * 776 * @implNote Please note that for Mac OS, notifications 777 * are only sent if the Java app is a bundled application, 778 * with a {@code CFBundleDocumentTypes} array present in its 779 * Info.plist. See the 780 * <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference"> 781 * Info.plist Key Reference</a> for more information about adding a 782 * {@code CFBundleDocumentTypes} key to your app's Info.plist. 783 * 784 * @param openFileHandler handler 785 * 786 * @throws SecurityException if a security manager exists and its 787 * {@link java.lang.SecurityManager#checkRead(java.lang.String)} 788 * method denies read access to the files, or it denies the 789 * {@code RuntimePermission("canProcessApplicationEvents")} 790 * permission, or the calling thread is not allowed to create a 791 * subprocess 792 * @throws UnsupportedOperationException if the current platform 793 * does not support the {@link Desktop.Action#APP_OPEN_FILE} action 794 * @since 9 795 */ 796 public void setOpenFileHandler(final OpenFilesHandler openFileHandler) { 797 checkEventsProcessingPermission(); 798 checkExec(); 799 checkRead(); 800 checkActionSupport(Action.APP_OPEN_FILE); 801 peer.setOpenFileHandler(openFileHandler); 802 } 803 804 /** 805 * Installs the handler which is notified when the application is asked to 806 * print a list of files. 807 * 808 * @implNote Please note that for Mac OS, notifications 809 * are only sent if the Java app is a bundled application, 810 * with a {@code CFBundleDocumentTypes} array present in its 811 * Info.plist. See the 812 * <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference"> 813 * Info.plist Key Reference</a> for more information about adding a 814 * {@code CFBundleDocumentTypes} key to your app's Info.plist. 815 * 816 * @param printFileHandler handler 817 * @throws SecurityException if a security manager exists and its 818 * {@link java.lang.SecurityManager#checkPrintJobAccess()} method denies 819 * the permission to print or it denies the 820 * {@code RuntimePermission("canProcessApplicationEvents")} permission 821 * @throws UnsupportedOperationException if the current platform 822 * does not support the {@link Desktop.Action#APP_PRINT_FILE} action 823 * @since 9 824 */ 825 public void setPrintFileHandler(final PrintFilesHandler printFileHandler) { 826 checkEventsProcessingPermission(); 827 SecurityManager sm = System.getSecurityManager(); 828 if (sm != null) { 829 sm.checkPrintJobAccess(); 830 } 831 checkActionSupport(Action.APP_PRINT_FILE); 832 peer.setPrintFileHandler(printFileHandler); 833 } 834 835 /** 836 * Installs the handler which is notified when the application is asked to 837 * open a URL. 838 * 839 * Setting the handler to {@code null} causes all 840 * {@link OpenURIHandler#openURI(AppEvent.OpenURIEvent)} requests to be 841 * enqueued until another handler is set. 842 * 843 * @implNote Please note that for Mac OS, notifications 844 * are only sent if the Java app is a bundled application, 845 * with a {@code CFBundleDocumentTypes} array present in its 846 * Info.plist. See the 847 * <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference"> 848 * Info.plist Key Reference</a> for more information about adding a 849 * {@code CFBundleDocumentTypes} key to your app's Info.plist. 850 * 851 * @param openURIHandler handler 852 * 853 * {@code RuntimePermission("canProcessApplicationEvents")} 854 * permission, or the calling thread is not allowed to create a 855 * subprocess 856 * @throws UnsupportedOperationException if the current platform 857 * does not support the {@link Desktop.Action#APP_OPEN_URI} action 858 * @since 9 859 */ 860 public void setOpenURIHandler(final OpenURIHandler openURIHandler) { 861 checkEventsProcessingPermission(); 862 checkExec(); 863 checkActionSupport(Action.APP_OPEN_URI); 864 peer.setOpenURIHandler(openURIHandler); 865 } 866 867 /** 868 * Installs the handler which determines if the application should quit. The 869 * handler is passed a one-shot {@link java.awt.desktop.QuitResponse} which can cancel or 870 * proceed with the quit. Setting the handler to {@code null} causes 871 * all quit requests to directly perform the default {@link QuitStrategy}. 872 * 873 * @param quitHandler the handler that is called when the application is 874 * asked to quit 875 * 876 * @throws SecurityException if a security manager exists and it 877 * will not allow the caller to invoke {@code System.exit} or it denies the 878 * {@code RuntimePermission("canProcessApplicationEvents")} permission 879 * @throws UnsupportedOperationException if the current platform 880 * does not support the {@link Desktop.Action#APP_QUIT_HANDLER} action 881 * @since 9 882 */ 883 public void setQuitHandler(final QuitHandler quitHandler) { 884 checkEventsProcessingPermission(); 885 checkQuitPermission(); 886 checkActionSupport(Action.APP_QUIT_HANDLER); 887 peer.setQuitHandler(quitHandler); 888 } 889 890 /** 891 * Sets the default strategy used to quit this application. The default is 892 * calling SYSTEM_EXIT_0. 893 * 894 * @param strategy the way this application should be shutdown 895 * 896 * @throws SecurityException if a security manager exists and it 897 * will not allow the caller to invoke {@code System.exit} or it denies the 898 * {@code RuntimePermission("canProcessApplicationEvents")} permission 899 * @throws UnsupportedOperationException if the current platform 900 * does not support the {@link Desktop.Action#APP_QUIT_STRATEGY} action 901 * @see QuitStrategy 902 * @since 9 903 */ 904 public void setQuitStrategy(final QuitStrategy strategy) { 905 checkEventsProcessingPermission(); 906 checkQuitPermission(); 907 checkActionSupport(Action.APP_QUIT_STRATEGY); 908 peer.setQuitStrategy(strategy); 909 } 910 911 /** 912 * Enables this application to be suddenly terminated. 913 * 914 * Call this method to indicate your application's state is saved, and 915 * requires no notification to be terminated. Letting your application 916 * remain terminatable improves the user experience by avoiding re-paging in 917 * your application when it's asked to quit. 918 * 919 * <b>Note: enabling sudden termination will allow your application to be 920 * quit without notifying your QuitHandler, or running any shutdown 921 * hooks.</b> 922 * E.g. user-initiated Cmd-Q, logout, restart, or shutdown requests will 923 * effectively "kill -KILL" your application. 924 * 925 * @throws SecurityException if a security manager exists and it 926 * will not allow the caller to invoke {@code System.exit} or it denies the 927 * {@code RuntimePermission("canProcessApplicationEvents")} permission 928 * @throws UnsupportedOperationException if the current platform 929 * does not support the {@link Desktop.Action#APP_SUDDEN_TERMINATION} action 930 * @see #disableSuddenTermination() 931 * @since 9 932 */ 933 public void enableSuddenTermination() { 934 checkEventsProcessingPermission(); 935 checkQuitPermission(); 936 checkActionSupport(Action.APP_SUDDEN_TERMINATION); 937 peer.enableSuddenTermination(); 938 } 939 940 /** 941 * Prevents this application from being suddenly terminated. 942 * 943 * Call this method to indicate that your application has unsaved state, and 944 * may not be terminated without notification. 945 * 946 * @throws SecurityException if a security manager exists and it 947 * will not allow the caller to invoke {@code System.exit} or it denies the 948 * {@code RuntimePermission("canProcessApplicationEvents")} permission 949 * @throws UnsupportedOperationException if the current platform 950 * does not support the {@link Desktop.Action#APP_SUDDEN_TERMINATION} action 951 * @see #enableSuddenTermination() 952 * @since 9 953 */ 954 public void disableSuddenTermination() { 955 checkEventsProcessingPermission(); 956 checkQuitPermission(); 957 checkActionSupport(Action.APP_SUDDEN_TERMINATION); 958 peer.disableSuddenTermination(); 959 } 960 961 /** 962 * Requests this application to move to the foreground. 963 * 964 * @param allWindows if all windows of this application should be moved to 965 * the foreground, or only the foremost one 966 * @throws SecurityException if a security manager exists and it denies the 967 * {@code RuntimePermission("canProcessApplicationEvents")} permission. 968 * @throws UnsupportedOperationException if the current platform 969 * does not support the {@link Desktop.Action#APP_REQUEST_FOREGROUND} action 970 * @since 9 971 */ 972 public void requestForeground(final boolean allWindows) { 973 checkEventsProcessingPermission(); 974 checkActionSupport(Action.APP_REQUEST_FOREGROUND); 975 peer.requestForeground(allWindows); 976 } 977 978 /** 979 * Opens the native help viewer application. 980 * 981 * @implNote Please note that for Mac OS, it opens the native help viewer 982 * application if a Help Book has been added to the application bundler 983 * and registered in the Info.plist with CFBundleHelpBookFolder 984 * 985 * @throws SecurityException if a security manager exists and it denies the 986 * {@code RuntimePermission("canProcessApplicationEvents")} permission. 987 * @throws UnsupportedOperationException if the current platform 988 * does not support the {@link Desktop.Action#APP_HELP_VIEWER} action 989 * @since 9 990 */ 991 public void openHelpViewer() { 992 checkEventsProcessingPermission(); 993 checkActionSupport(Action.APP_HELP_VIEWER); 994 peer.openHelpViewer(); 995 } 996 997 /** 998 * Sets the default menu bar to use when there are no active frames. 999 * 1000 * @implNote Aqua Look and Feel should be active to support this on Mac OS. 1001 * 1002 * @param menuBar to use when no other frames are active 1003 * @throws SecurityException if a security manager exists and it denies the 1004 * {@code RuntimePermission("canProcessApplicationEvents")} permission. 1005 * @throws UnsupportedOperationException if the current platform 1006 * does not support the {@link Desktop.Action#APP_MENU_BAR} action 1007 * @since 9 1008 */ 1009 public void setDefaultMenuBar(final JMenuBar menuBar) { 1010 checkEventsProcessingPermission(); 1011 checkActionSupport(Action.APP_MENU_BAR); 1012 peer.setDefaultMenuBar(menuBar); 1013 } 1014 1015 /** 1016 * Opens a folder containing the {@code file} and selects it 1017 * in a default system file manager. 1018 * @param file the file 1019 * @throws SecurityException If a security manager exists and its 1020 * {@link SecurityManager#checkRead(java.lang.String)} method 1021 * denies read access to the file 1022 * @throws UnsupportedOperationException if the current platform 1023 * does not support the {@link Desktop.Action#BROWSE_FILE_DIR} action 1024 * @throws NullPointerException if {@code file} is {@code null} 1025 * @throws IllegalArgumentException if the specified file doesn't 1026 * exist 1027 * @since 9 1028 */ 1029 public void browseFileDirectory(File file) { 1030 checkRead(); 1031 checkActionSupport(Action.BROWSE_FILE_DIR); 1032 checkFileValidation(file); 1033 peer.browseFileDirectory(file); 1034 } 1035 1036 /** 1037 * Moves the specified file to the trash. 1038 * 1039 * @param file the file 1040 * @return returns true if successfully moved the file to the trash. 1041 * @throws SecurityException If a security manager exists and its 1042 * {@link SecurityManager#checkDelete(java.lang.String)} method 1043 * denies deletion of the file 1044 * @throws UnsupportedOperationException if the current platform 1045 * does not support the {@link Desktop.Action#MOVE_TO_TRASH} action 1046 * @throws NullPointerException if {@code file} is {@code null} 1047 * @throws IllegalArgumentException if the specified file doesn't 1048 * exist 1049 * 1050 * @since 9 1051 */ 1052 public boolean moveToTrash(final File file) { 1053 checkDelete(); 1054 checkActionSupport(Action.MOVE_TO_TRASH); 1055 checkFileValidation(file); 1056 return peer.moveToTrash(file); 1057 } 1058 }