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 static void checkEventsProcessingPermission() { 275 SecurityManager sm = System.getSecurityManager(); 276 if (sm != null) { 277 sm.checkPermission(new RuntimePermission( 278 "canProcessApplicationEvents")); 279 } 280 } 281 282 /** 283 * Returns the {@code Desktop} instance of the current 284 * desktop context. On some platforms the Desktop API may not be 285 * supported; use the {@link #isDesktopSupported} method to 286 * determine if the current desktop is supported. 287 * @return the Desktop instance 288 * @throws HeadlessException if {@link 289 * GraphicsEnvironment#isHeadless()} returns {@code true} 290 * @throws UnsupportedOperationException if this class is not 291 * supported on the current platform 292 * @see #isDesktopSupported() 293 * @see java.awt.GraphicsEnvironment#isHeadless 294 */ 295 public static synchronized Desktop getDesktop(){ 296 if (GraphicsEnvironment.isHeadless()) throw new HeadlessException(); 297 if (!Desktop.isDesktopSupported()) { 298 throw new UnsupportedOperationException("Desktop API is not " + 299 "supported on the current platform"); 300 } 301 302 sun.awt.AppContext context = sun.awt.AppContext.getAppContext(); 303 Desktop desktop = (Desktop)context.get(Desktop.class); 304 305 if (desktop == null) { 306 desktop = new Desktop(); 307 context.put(Desktop.class, desktop); 308 } 309 310 return desktop; 311 } 312 313 /** 314 * Tests whether this class is supported on the current platform. 315 * If it's supported, use {@link #getDesktop()} to retrieve an 316 * instance. 317 * 318 * @return {@code true} if this class is supported on the 319 * current platform; {@code false} otherwise 320 * @see #getDesktop() 321 */ 322 public static boolean isDesktopSupported(){ 323 Toolkit defaultToolkit = Toolkit.getDefaultToolkit(); 324 if (defaultToolkit instanceof SunToolkit) { 325 return ((SunToolkit)defaultToolkit).isDesktopSupported(); 326 } 327 return false; 328 } 329 330 /** 331 * Tests whether an action is supported on the current platform. 332 * 333 * <p>Even when the platform supports an action, a file or URI may 334 * not have a registered application for the action. For example, 335 * most of the platforms support the {@link Desktop.Action#OPEN} 336 * action. But for a specific file, there may not be an 337 * application registered to open it. In this case, {@link 338 * #isSupported} may return {@code true}, but the corresponding 339 * action method will throw an {@link IOException}. 340 * 341 * @param action the specified {@link Action} 342 * @return {@code true} if the specified action is supported on 343 * the current platform; {@code false} otherwise 344 * @see Desktop.Action 345 */ 346 public boolean isSupported(Action action) { 347 return peer.isSupported(action); 348 } 349 350 /** 351 * Checks if the file is a valid file and readable. 352 * 353 * @throws SecurityException If a security manager exists and its 354 * {@link SecurityManager#checkRead(java.lang.String)} method 355 * denies read access to the file 356 * @throws NullPointerException if file is null 357 * @throws IllegalArgumentException if file doesn't exist 358 */ 359 private static void checkFileValidation(File file){ 360 if (file == null) throw new NullPointerException("File must not be null"); 361 362 if (!file.exists()) { 363 throw new IllegalArgumentException("The file: " 364 + file.getPath() + " doesn't exist."); 365 } 366 367 file.canRead(); 368 } 369 370 /** 371 * Checks if the action type is supported. 372 * 373 * @param actionType the action type in question 374 * @throws UnsupportedOperationException if the specified action type is not 375 * supported on the current platform 376 */ 377 private void checkActionSupport(Action actionType){ 378 if (!isSupported(actionType)) { 379 throw new UnsupportedOperationException("The " + actionType.name() 380 + " action is not supported on the current platform!"); 381 } 382 } 383 384 385 /** 386 * Calls to the security manager's {@code checkPermission} method with 387 * an {@code AWTPermission("showWindowWithoutWarningBanner")} 388 * permission. 389 */ 390 private void checkAWTPermission(){ 391 SecurityManager sm = System.getSecurityManager(); 392 if (sm != null) { 393 sm.checkPermission(new AWTPermission( 394 "showWindowWithoutWarningBanner")); 395 } 396 } 397 398 /** 399 * Launches the associated application to open the file. 400 * 401 * <p> If the specified file is a directory, the file manager of 402 * the current platform is launched to open it. 403 * 404 * @param file the file to be opened with the associated application 405 * @throws NullPointerException if {@code file} is {@code null} 406 * @throws IllegalArgumentException if the specified file doesn't 407 * exist 408 * @throws UnsupportedOperationException if the current platform 409 * does not support the {@link Desktop.Action#OPEN} action 410 * @throws IOException if the specified file has no associated 411 * application or the associated application fails to be launched 412 * @throws SecurityException if a security manager exists and its 413 * {@link java.lang.SecurityManager#checkRead(java.lang.String)} 414 * method denies read access to the file, or it denies the 415 * {@code AWTPermission("showWindowWithoutWarningBanner")} 416 * permission, or the calling thread is not allowed to create a 417 * subprocess 418 * @see java.awt.AWTPermission 419 */ 420 public void open(File file) throws IOException { 421 checkAWTPermission(); 422 checkExec(); 423 checkActionSupport(Action.OPEN); 424 checkFileValidation(file); 425 426 peer.open(file); 427 } 428 429 /** 430 * Launches the associated editor application and opens a file for 431 * editing. 432 * 433 * @param file the file to be opened for editing 434 * @throws NullPointerException if the specified file is {@code null} 435 * @throws IllegalArgumentException if the specified file doesn't 436 * exist 437 * @throws UnsupportedOperationException if the current platform 438 * does not support the {@link Desktop.Action#EDIT} action 439 * @throws IOException if the specified file has no associated 440 * editor, or the associated application fails to be launched 441 * @throws SecurityException if a security manager exists and its 442 * {@link java.lang.SecurityManager#checkRead(java.lang.String)} 443 * method denies read access to the file, or {@link 444 * java.lang.SecurityManager#checkWrite(java.lang.String)} method 445 * denies write access to the file, or it denies the 446 * {@code AWTPermission("showWindowWithoutWarningBanner")} 447 * permission, or the calling thread is not allowed to create a 448 * subprocess 449 * @see java.awt.AWTPermission 450 */ 451 public void edit(File file) throws IOException { 452 checkAWTPermission(); 453 checkExec(); 454 checkActionSupport(Action.EDIT); 455 file.canWrite(); 456 checkFileValidation(file); 457 458 peer.edit(file); 459 } 460 461 /** 462 * Prints a file with the native desktop printing facility, using 463 * the associated application's print command. 464 * 465 * @param file the file to be printed 466 * @throws NullPointerException if the specified file is {@code 467 * null} 468 * @throws IllegalArgumentException if the specified file doesn't 469 * exist 470 * @throws UnsupportedOperationException if the current platform 471 * does not support the {@link Desktop.Action#PRINT} action 472 * @throws IOException if the specified file has no associated 473 * application that can be used to print it 474 * @throws SecurityException if a security manager exists and its 475 * {@link java.lang.SecurityManager#checkRead(java.lang.String)} 476 * method denies read access to the file, or its {@link 477 * java.lang.SecurityManager#checkPrintJobAccess()} method denies 478 * the permission to print the file, or the calling thread is not 479 * allowed to create a subprocess 480 */ 481 public void print(File file) throws IOException { 482 checkExec(); 483 SecurityManager sm = System.getSecurityManager(); 484 if (sm != null) { 485 sm.checkPrintJobAccess(); 486 } 487 checkActionSupport(Action.PRINT); 488 checkFileValidation(file); 489 490 peer.print(file); 491 } 492 493 /** 494 * Launches the default browser to display a {@code URI}. 495 * If the default browser is not able to handle the specified 496 * {@code URI}, the application registered for handling 497 * {@code URIs} of the specified type is invoked. The application 498 * is determined from the protocol and path of the {@code URI}, as 499 * defined by the {@code URI} class. 500 * <p> 501 * If the calling thread does not have the necessary permissions, 502 * and this is invoked from within an applet, 503 * {@code AppletContext.showDocument()} is used. Similarly, if the calling 504 * does not have the necessary permissions, and this is invoked from within 505 * a Java Web Started application, {@code BasicService.showDocument()} 506 * is used. 507 * 508 * @param uri the URI to be displayed in the user default browser 509 * @throws NullPointerException if {@code uri} is {@code null} 510 * @throws UnsupportedOperationException if the current platform 511 * does not support the {@link Desktop.Action#BROWSE} action 512 * @throws IOException if the user default browser is not found, 513 * or it fails to be launched, or the default handler application 514 * failed to be launched 515 * @throws SecurityException if a security manager exists and it 516 * denies the 517 * {@code AWTPermission("showWindowWithoutWarningBanner")} 518 * permission, or the calling thread is not allowed to create a 519 * subprocess; and not invoked from within an applet or Java Web Started 520 * application 521 * @throws IllegalArgumentException if the necessary permissions 522 * are not available and the URI can not be converted to a {@code URL} 523 * @see java.net.URI 524 * @see java.awt.AWTPermission 525 * @see java.applet.AppletContext 526 */ 527 public void browse(URI uri) throws IOException { 528 SecurityException securityException = null; 529 try { 530 checkAWTPermission(); 531 checkExec(); 532 } catch (SecurityException e) { 533 securityException = e; 534 } 535 checkActionSupport(Action.BROWSE); 536 if (uri == null) { 537 throw new NullPointerException(); 538 } 539 if (securityException == null) { 540 peer.browse(uri); 541 return; 542 } 543 544 // Calling thread doesn't have necessary privileges. 545 // Delegate to DesktopBrowse so that it can work in 546 // applet/webstart. 547 URL url = null; 548 try { 549 url = uri.toURL(); 550 } catch (MalformedURLException e) { 551 throw new IllegalArgumentException("Unable to convert URI to URL", e); 552 } 553 sun.awt.DesktopBrowse db = sun.awt.DesktopBrowse.getInstance(); 554 if (db == null) { 555 // Not in webstart/applet, throw the exception. 556 throw securityException; 557 } 558 db.browse(url); 559 } 560 561 /** 562 * Launches the mail composing window of the user default mail 563 * client. 564 * 565 * @throws UnsupportedOperationException if the current platform 566 * does not support the {@link Desktop.Action#MAIL} action 567 * @throws IOException if the user default mail client is not 568 * found, or it fails to be launched 569 * @throws SecurityException if a security manager exists and it 570 * denies the 571 * {@code AWTPermission("showWindowWithoutWarningBanner")} 572 * permission, or the calling thread is not allowed to create a 573 * subprocess 574 * @see java.awt.AWTPermission 575 */ 576 public void mail() throws IOException { 577 checkAWTPermission(); 578 checkExec(); 579 checkActionSupport(Action.MAIL); 580 URI mailtoURI = null; 581 try{ 582 mailtoURI = new URI("mailto:?"); 583 peer.mail(mailtoURI); 584 } catch (URISyntaxException e){ 585 // won't reach here. 586 } 587 } 588 589 /** 590 * Launches the mail composing window of the user default mail 591 * client, filling the message fields specified by a {@code 592 * mailto:} URI. 593 * 594 * <p> A {@code mailto:} URI can specify message fields 595 * including <i>"to"</i>, <i>"cc"</i>, <i>"subject"</i>, 596 * <i>"body"</i>, etc. See <a 597 * href="http://www.ietf.org/rfc/rfc2368.txt">The mailto URL 598 * scheme (RFC 2368)</a> for the {@code mailto:} URI specification 599 * details. 600 * 601 * @param mailtoURI the specified {@code mailto:} URI 602 * @throws NullPointerException if the specified URI is {@code 603 * null} 604 * @throws IllegalArgumentException if the URI scheme is not 605 * {@code "mailto"} 606 * @throws UnsupportedOperationException if the current platform 607 * does not support the {@link Desktop.Action#MAIL} action 608 * @throws IOException if the user default mail client is not 609 * found or fails to be launched 610 * @throws SecurityException if a security manager exists and it 611 * denies the 612 * {@code AWTPermission("showWindowWithoutWarningBanner")} 613 * permission, or the calling thread is not allowed to create a 614 * subprocess 615 * @see java.net.URI 616 * @see java.awt.AWTPermission 617 */ 618 public void mail(URI mailtoURI) throws IOException { 619 checkAWTPermission(); 620 checkExec(); 621 checkActionSupport(Action.MAIL); 622 if (mailtoURI == null) throw new NullPointerException(); 623 624 if (!"mailto".equalsIgnoreCase(mailtoURI.getScheme())) { 625 throw new IllegalArgumentException("URI scheme is not \"mailto\""); 626 } 627 628 peer.mail(mailtoURI); 629 } 630 631 private void checkExec() throws SecurityException { 632 SecurityManager sm = System.getSecurityManager(); 633 if (sm != null) { 634 sm.checkPermission(new FilePermission("<<ALL FILES>>", 635 SecurityConstants.FILE_EXECUTE_ACTION)); 636 } 637 } 638 639 private void checkRead() throws SecurityException { 640 SecurityManager sm = System.getSecurityManager(); 641 if (sm != null) { 642 sm.checkPermission(new FilePermission("<<ALL FILES>>", 643 SecurityConstants.FILE_READ_ACTION)); 644 } 645 } 646 647 private void checkDelete() throws SecurityException { 648 SecurityManager sm = System.getSecurityManager(); 649 if (sm != null) { 650 sm.checkPermission(new FilePermission("<<ALL FILES>>", 651 SecurityConstants.FILE_DELETE_ACTION)); 652 } 653 } 654 655 private void checkQuitPermission() { 656 SecurityManager sm = System.getSecurityManager(); 657 if (sm != null) { 658 sm.checkExit(0); 659 } 660 } 661 662 /** 663 * Adds sub-types of {@link SystemEventListener} to listen for notifications 664 * from the native system. 665 * 666 * Has no effect if SystemEventListener's sub-type is unsupported on the current 667 * platform. 668 * 669 * @param listener listener 670 * 671 * @throws SecurityException if a security manager exists and it 672 * denies the 673 * {@code AWTPermission("showWindowWithoutWarningBanner")} or the 674 * {@code RuntimePermission("canProcessApplicationEvents")} 675 * permission 676 * 677 * @see java.awt.desktop.AppForegroundListener 678 * @see java.awt.desktop.AppHiddenListener 679 * @see java.awt.desktop.AppReopenedListener 680 * @see java.awt.desktop.ScreenSleepListener 681 * @see java.awt.desktop.SystemSleepListener 682 * @see java.awt.desktop.UserSessionListener 683 * @since 9 684 */ 685 public void addAppEventListener(final SystemEventListener listener) { 686 checkEventsProcessingPermission(); 687 checkAWTPermission(); 688 peer.addAppEventListener(listener); 689 } 690 691 /** 692 * Removes sub-types of {@link SystemEventListener} to listen for notifications 693 * from the native system. 694 * 695 * Has no effect if SystemEventListener's sub-type is unsupported on the current 696 * platform. 697 * 698 * @param listener listener 699 * 700 * @throws SecurityException if a security manager exists and it 701 * denies the 702 * {@code AWTPermission("showWindowWithoutWarningBanner")} or the 703 * {@code RuntimePermission("canProcessApplicationEvents")} 704 * permission 705 * 706 * @see java.awt.desktop.AppForegroundListener 707 * @see java.awt.desktop.AppHiddenListener 708 * @see java.awt.desktop.AppReopenedListener 709 * @see java.awt.desktop.ScreenSleepListener 710 * @see java.awt.desktop.SystemSleepListener 711 * @see java.awt.desktop.UserSessionListener 712 * @since 9 713 */ 714 public void removeAppEventListener(final SystemEventListener listener) { 715 checkEventsProcessingPermission(); 716 checkAWTPermission(); 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} )} message 728 * 729 * @throws SecurityException if a security manager exists and it 730 * denies the 731 * {@code AWTPermission("showWindowWithoutWarningBanner")} or the 732 * {@code RuntimePermission("canProcessApplicationEvents")} 733 * permission 734 * @throws UnsupportedOperationException if the current platform 735 * does not support the {@link Desktop.Action#APP_ABOUT} action 736 * 737 * @since 9 738 */ 739 public void setAboutHandler(final AboutHandler aboutHandler) { 740 checkEventsProcessingPermission(); 741 checkAWTPermission(); 742 checkActionSupport(Action.APP_ABOUT); 743 peer.setAboutHandler(aboutHandler); 744 } 745 746 /** 747 * Installs a handler to show a custom Preferences window for your 748 * application. 749 * <p> 750 * Setting the {@link PreferencesHandler} to {@code null} reverts it to 751 * the default behavior 752 * 753 * @param preferencesHandler the handler to respond to the 754 * {@link PreferencesHandler#handlePreferences(PreferencesEvent)} 755 * 756 * @throws SecurityException if a security manager exists and it 757 * denies the 758 * {@code AWTPermission("showWindowWithoutWarningBanner")} or the 759 * {@code RuntimePermission("canProcessApplicationEvents")} 760 * permission 761 * @throws UnsupportedOperationException if the current platform 762 * does not support the {@link Desktop.Action#APP_PREFERENCES} action 763 * @since 9 764 */ 765 public void setPreferencesHandler(final PreferencesHandler preferencesHandler) { 766 checkEventsProcessingPermission(); 767 checkAWTPermission(); 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 AWTPermission("showWindowWithoutWarningBanner")} or the 790 * {@code RuntimePermission("canProcessApplicationEvents")} 791 * permission, or the calling thread is not allowed to create a 792 * subprocess 793 * @throws UnsupportedOperationException if the current platform 794 * does not support the {@link Desktop.Action#APP_OPEN_FILE} action 795 * @since 9 796 */ 797 public void setOpenFileHandler(final OpenFilesHandler openFileHandler) { 798 checkEventsProcessingPermission(); 799 checkAWTPermission(); 800 checkExec(); 801 checkRead(); 802 checkActionSupport(Action.APP_OPEN_FILE); 803 peer.setOpenFileHandler(openFileHandler); 804 } 805 806 /** 807 * Installs the handler which is notified when the application is asked to 808 * print a list of files. 809 * 810 * @implNote Please note that for Mac OS, notifications 811 * are only sent if the Java app is a bundled application, 812 * with a {@code CFBundleDocumentTypes} array present in its 813 * Info.plist. See the 814 * <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference"> 815 * Info.plist Key Reference</a> for more information about adding a 816 * {@code CFBundleDocumentTypes} key to your app's Info.plist. 817 * 818 * @param printFileHandler handler 819 * @throws SecurityException if a security manager exists and its 820 * {@link java.lang.SecurityManager#checkPrintJobAccess()} method denies 821 * the permission to print or it denies the 822 * {@code RuntimePermission("canProcessApplicationEvents")} permission 823 * @throws UnsupportedOperationException if the current platform 824 * does not support the {@link Desktop.Action#APP_PRINT_FILE} action 825 * @since 9 826 */ 827 public void setPrintFileHandler(final PrintFilesHandler printFileHandler) { 828 checkEventsProcessingPermission(); 829 SecurityManager sm = System.getSecurityManager(); 830 if (sm != null) { 831 sm.checkPrintJobAccess(); 832 } 833 checkActionSupport(Action.APP_PRINT_FILE); 834 peer.setPrintFileHandler(printFileHandler); 835 } 836 837 /** 838 * Installs the handler which is notified when the application is asked to 839 * open a URL. 840 * 841 * Setting the handler to {@code null} causes all 842 * {@link OpenURIHandler#openURI(AppEvent.OpenURIEvent)} requests to be 843 * enqueued until another handler is set. 844 * 845 * @implNote Please note that for Mac OS, notifications 846 * are only sent if the Java app is a bundled application, 847 * with a {@code CFBundleDocumentTypes} array present in its 848 * Info.plist. See the 849 * <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference"> 850 * Info.plist Key Reference</a> for more information about adding a 851 * {@code CFBundleDocumentTypes} key to your app's Info.plist. 852 * 853 * @param openURIHandler handler 854 * 855 * {@code AWTPermission("showWindowWithoutWarningBanner")} or the 856 * {@code RuntimePermission("canProcessApplicationEvents")} 857 * permission, or the calling thread is not allowed to create a 858 * subprocess 859 * @throws UnsupportedOperationException if the current platform 860 * does not support the {@link Desktop.Action#APP_OPEN_URI} action 861 * @since 9 862 */ 863 public void setOpenURIHandler(final OpenURIHandler openURIHandler) { 864 checkEventsProcessingPermission(); 865 checkAWTPermission(); 866 checkExec(); 867 checkActionSupport(Action.APP_OPEN_URI); 868 peer.setOpenURIHandler(openURIHandler); 869 } 870 871 /** 872 * Installs the handler which determines if the application should quit. The 873 * handler is passed a one-shot {@link java.awt.desktop.QuitResponse} which can cancel or 874 * proceed with the quit. Setting the handler to {@code null} causes 875 * all quit requests to directly perform the default {@link QuitStrategy}. 876 * 877 * @param quitHandler the handler that is called when the application is 878 * asked to quit 879 * 880 * @throws SecurityException if a security manager exists and it 881 * will not allow the caller to invoke {@code System.exit} or it denies the 882 * {@code RuntimePermission("canProcessApplicationEvents")} permission 883 * @throws UnsupportedOperationException if the current platform 884 * does not support the {@link Desktop.Action#APP_QUIT_HANDLER} action 885 * @since 9 886 */ 887 public void setQuitHandler(final QuitHandler quitHandler) { 888 checkEventsProcessingPermission(); 889 checkQuitPermission(); 890 checkActionSupport(Action.APP_QUIT_HANDLER); 891 peer.setQuitHandler(quitHandler); 892 } 893 894 /** 895 * Sets the default strategy used to quit this application. The default is 896 * calling SYSTEM_EXIT_0. 897 * 898 * @param strategy the way this application should be shutdown 899 * 900 * @throws SecurityException if a security manager exists and it 901 * will not allow the caller to invoke {@code System.exit} or it denies the 902 * {@code RuntimePermission("canProcessApplicationEvents")} permission 903 * @throws UnsupportedOperationException if the current platform 904 * does not support the {@link Desktop.Action#APP_QUIT_STRATEGY} action 905 * @see QuitStrategy 906 * @since 9 907 */ 908 public void setQuitStrategy(final QuitStrategy strategy) { 909 checkEventsProcessingPermission(); 910 checkQuitPermission(); 911 checkActionSupport(Action.APP_QUIT_STRATEGY); 912 peer.setQuitStrategy(strategy); 913 } 914 915 /** 916 * Enables this application to be suddenly terminated. 917 * 918 * Call this method to indicate your application's state is saved, and 919 * requires no notification to be terminated. Letting your application 920 * remain terminatable improves the user experience by avoiding re-paging in 921 * your application when it's asked to quit. 922 * 923 * <b>Note: enabling sudden termination will allow your application to be 924 * quit without notifying your QuitHandler, or running any shutdown 925 * hooks.</b> 926 * E.g. user-initiated Cmd-Q, logout, restart, or shutdown requests will 927 * effectively "kill -KILL" your application. 928 * 929 * @throws SecurityException if a security manager exists and it 930 * will not allow the caller to invoke {@code System.exit} or it denies the 931 * {@code RuntimePermission("canProcessApplicationEvents")} permission 932 * @throws UnsupportedOperationException if the current platform 933 * does not support the {@link Desktop.Action#APP_SUDDEN_TERMINATION} action 934 * @see #disableSuddenTermination() 935 * @since 9 936 */ 937 public void enableSuddenTermination() { 938 checkEventsProcessingPermission(); 939 checkQuitPermission(); 940 checkActionSupport(Action.APP_SUDDEN_TERMINATION); 941 peer.enableSuddenTermination(); 942 } 943 944 /** 945 * Prevents this application from being suddenly terminated. 946 * 947 * Call this method to indicate that your application has unsaved state, and 948 * may not be terminated without notification. 949 * 950 * @throws SecurityException if a security manager exists and it 951 * will not allow the caller to invoke {@code System.exit} or it denies the 952 * {@code RuntimePermission("canProcessApplicationEvents")} permission 953 * @throws UnsupportedOperationException if the current platform 954 * does not support the {@link Desktop.Action#APP_SUDDEN_TERMINATION} action 955 * @see #enableSuddenTermination() 956 * @since 9 957 */ 958 public void disableSuddenTermination() { 959 checkEventsProcessingPermission(); 960 checkQuitPermission(); 961 checkActionSupport(Action.APP_SUDDEN_TERMINATION); 962 peer.disableSuddenTermination(); 963 } 964 965 /** 966 * Requests this application to move to the foreground. 967 * 968 * @param allWindows if all windows of this application should be moved to 969 * the foreground, or only the foremost one 970 * @throws SecurityException if a security manager exists and it denies the 971 * {@code AWTPermission("showWindowWithoutWarningBanner")} or the 972 * {@code RuntimePermission("canProcessApplicationEvents")} permission. 973 * @throws UnsupportedOperationException if the current platform 974 * does not support the {@link Desktop.Action#APP_REQUEST_FOREGROUND} action 975 * @since 9 976 */ 977 public void requestForeground(final boolean allWindows) { 978 checkEventsProcessingPermission(); 979 checkAWTPermission(); 980 checkActionSupport(Action.APP_REQUEST_FOREGROUND); 981 peer.requestForeground(allWindows); 982 } 983 984 /** 985 * Opens the native help viewer application. 986 * 987 * @implNote Please note that for Mac OS, it opens the native help viewer 988 * application if a Help Book has been added to the application bundler 989 * and registered in the Info.plist with CFBundleHelpBookFolder 990 * 991 * @throws SecurityException if a security manager exists and it denies the 992 * {@code AWTPermission("showWindowWithoutWarningBanner")} or the 993 * {@code RuntimePermission("canProcessApplicationEvents")} permission. 994 * @throws UnsupportedOperationException if the current platform 995 * does not support the {@link Desktop.Action#APP_HELP_VIEWER} action 996 * @since 9 997 */ 998 public void openHelpViewer() { 999 checkEventsProcessingPermission(); 1000 checkAWTPermission(); 1001 checkActionSupport(Action.APP_HELP_VIEWER); 1002 peer.openHelpViewer(); 1003 } 1004 1005 /** 1006 * Sets the default menu bar to use when there are no active frames. 1007 * 1008 * @implNote Aqua Look and Feel should be active to support this on Mac OS. 1009 * 1010 * @param menuBar to use when no other frames are active 1011 * @throws SecurityException if a security manager exists and it denies the 1012 * {@code AWTPermission("showWindowWithoutWarningBanner")} or the 1013 * {@code RuntimePermission("canProcessApplicationEvents")} permission. 1014 * @throws UnsupportedOperationException if the current platform 1015 * does not support the {@link Desktop.Action#APP_MENU_BAR} action 1016 * @since 9 1017 */ 1018 public void setDefaultMenuBar(final JMenuBar menuBar) { 1019 checkEventsProcessingPermission(); 1020 checkAWTPermission(); 1021 checkActionSupport(Action.APP_MENU_BAR); 1022 peer.setDefaultMenuBar(menuBar); 1023 } 1024 1025 /** 1026 * Opens a folder containing the {@code file} and selects it 1027 * in a default system file manager. 1028 * @param file the file 1029 * @throws SecurityException If a security manager exists and its 1030 * {@link SecurityManager#checkRead(java.lang.String)} method 1031 * denies read access to the file 1032 * @throws UnsupportedOperationException if the current platform 1033 * does not support the {@link Desktop.Action#BROWSE_FILE_DIR} action 1034 * @throws NullPointerException if {@code file} is {@code null} 1035 * @throws IllegalArgumentException if the specified file doesn't 1036 * exist 1037 * @since 9 1038 */ 1039 public void browseFileDirectory(File file) { 1040 checkRead(); 1041 checkActionSupport(Action.BROWSE_FILE_DIR); 1042 checkFileValidation(file); 1043 peer.browseFileDirectory(file); 1044 } 1045 1046 /** 1047 * Moves the specified file to the trash. 1048 * 1049 * @param file the file 1050 * @return returns true if successfully moved the file to the trash. 1051 * @throws SecurityException If a security manager exists and its 1052 * {@link SecurityManager#checkDelete(java.lang.String)} method 1053 * denies deletion of the file 1054 * @throws UnsupportedOperationException if the current platform 1055 * does not support the {@link Desktop.Action#MOVE_TO_TRASH} action 1056 * @throws NullPointerException if {@code file} is {@code null} 1057 * @throws IllegalArgumentException if the specified file doesn't 1058 * exist 1059 * 1060 * @since 9 1061 */ 1062 public boolean moveToTrash(final File file) { 1063 checkDelete(); 1064 checkActionSupport(Action.MOVE_TO_TRASH); 1065 checkFileValidation(file); 1066 return peer.moveToTrash(file); 1067 } 1068 }