Path: blob/master/src/java.desktop/share/classes/java/awt/Desktop.java
41152 views
/*1* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.awt;2627import java.awt.desktop.AboutEvent;28import java.awt.desktop.AboutHandler;29import java.awt.desktop.OpenFilesHandler;30import java.awt.desktop.OpenURIEvent;31import java.awt.desktop.OpenURIHandler;32import java.awt.desktop.PreferencesEvent;33import java.awt.desktop.PreferencesHandler;34import java.awt.desktop.PrintFilesHandler;35import java.awt.desktop.QuitHandler;36import java.awt.desktop.QuitStrategy;37import java.awt.desktop.SystemEventListener;38import java.awt.peer.DesktopPeer;39import java.io.File;40import java.io.FilePermission;41import java.io.IOException;42import java.net.URI;43import java.net.URISyntaxException;44import java.security.AccessController;45import java.security.PrivilegedAction;46import java.util.Objects;4748import javax.swing.JMenuBar;4950import sun.awt.SunToolkit;51import sun.security.util.SecurityConstants;5253/**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 specified59* URI;</li>60* <li>launching the user-default mail client with an optional61* {@code mailto} URI;</li>62* <li>launching a registered application to open, edit or print a63* specified file.</li>64* </ul>65*66* <p> This class provides methods corresponding to these67* operations. The methods look for the associated application68* registered on the current platform, and launch it to handle a URI69* or file. If there is no associated application or the associated70* application fails to be launched, an exception is thrown.71*72* Please see {@link Desktop.Action} for the full list of supported operations73* and capabilities.74*75* <p> An application is registered to a URI or file type.76* The mechanism of registering, accessing, and77* launching the associated application is platform-dependent.78*79* <p> Each operation is an action type represented by the {@link80* Desktop.Action} class.81*82* <p> Note: when some action is invoked and the associated83* application is executed, it will be executed on the same system as84* the one on which the Java application was launched.85*86* @see Action87*88* @since 1.689* @author Armin Chen90* @author George Zhang91*/92public class Desktop {9394/**95* Represents an action type. Each platform supports a different96* set of actions. You may use the {@link Desktop#isSupported}97* method to determine if the given action is supported by the98* current platform.99* @see java.awt.Desktop#isSupported(java.awt.Desktop.Action)100* @since 1.6101*/102public static enum Action {103/**104* Represents an "open" action.105* @see Desktop#open(java.io.File)106*/107OPEN,108/**109* Represents an "edit" action.110* @see Desktop#edit(java.io.File)111*/112EDIT,113/**114* Represents a "print" action.115* @see Desktop#print(java.io.File)116*/117PRINT,118/**119* Represents a "mail" action.120* @see Desktop#mail()121* @see Desktop#mail(java.net.URI)122*/123MAIL,124125/**126* Represents a "browse" action.127* @see Desktop#browse(java.net.URI)128*/129BROWSE,130131/**132* Represents an AppForegroundListener133* @see java.awt.desktop.AppForegroundListener134* @since 9135*/136APP_EVENT_FOREGROUND,137138/**139* Represents an AppHiddenListener140* @see java.awt.desktop.AppHiddenListener141* @since 9142*/143APP_EVENT_HIDDEN,144145/**146* Represents an AppReopenedListener147* @see java.awt.desktop.AppReopenedListener148* @since 9149*/150APP_EVENT_REOPENED,151152/**153* Represents a ScreenSleepListener154* @see java.awt.desktop.ScreenSleepListener155* @since 9156*/157APP_EVENT_SCREEN_SLEEP,158159/**160* Represents a SystemSleepListener161* @see java.awt.desktop.SystemSleepListener162* @since 9163*/164APP_EVENT_SYSTEM_SLEEP,165166/**167* Represents a UserSessionListener168* @see java.awt.desktop.UserSessionListener169* @since 9170*/171APP_EVENT_USER_SESSION,172173/**174* Represents an AboutHandler175* @see #setAboutHandler(java.awt.desktop.AboutHandler)176* @since 9177*/178APP_ABOUT,179180/**181* Represents a PreferencesHandler182* @see #setPreferencesHandler(java.awt.desktop.PreferencesHandler)183* @since 9184*/185APP_PREFERENCES,186187/**188* Represents an OpenFilesHandler189* @see #setOpenFileHandler(java.awt.desktop.OpenFilesHandler)190* @since 9191*/192APP_OPEN_FILE,193194/**195* Represents a PrintFilesHandler196* @see #setPrintFileHandler(java.awt.desktop.PrintFilesHandler)197* @since 9198*/199APP_PRINT_FILE,200201/**202* Represents an OpenURIHandler203* @see #setOpenURIHandler(java.awt.desktop.OpenURIHandler)204* @since 9205*/206APP_OPEN_URI,207208/**209* Represents a QuitHandler210* @see #setQuitHandler(java.awt.desktop.QuitHandler)211* @since 9212*/213APP_QUIT_HANDLER,214215/**216* Represents a QuitStrategy217* @see #setQuitStrategy(java.awt.desktop.QuitStrategy)218* @since 9219*/220APP_QUIT_STRATEGY,221222/**223* Represents a SuddenTermination224* @see #enableSuddenTermination()225* @since 9226*/227APP_SUDDEN_TERMINATION,228229/**230* Represents a requestForeground231* @see #requestForeground(boolean)232* @since 9233*/234APP_REQUEST_FOREGROUND,235236/**237* Represents a HelpViewer238* @see #openHelpViewer()239* @since 9240*/241APP_HELP_VIEWER,242243/**244* Represents a menu bar245* @see #setDefaultMenuBar(javax.swing.JMenuBar)246* @since 9247*/248APP_MENU_BAR,249250/**251* Represents a browse file directory252* @see #browseFileDirectory(java.io.File)253* @since 9254*/255BROWSE_FILE_DIR,256257/**258* Represents a move to trash259* @see #moveToTrash(java.io.File)260* @since 9261*/262MOVE_TO_TRASH263};264265private DesktopPeer peer;266267/**268* Suppresses default constructor for noninstantiability.269*/270private Desktop() {271Toolkit defaultToolkit = Toolkit.getDefaultToolkit();272// same cast as in isDesktopSupported()273if (defaultToolkit instanceof SunToolkit) {274peer = ((SunToolkit) defaultToolkit).createDesktopPeer(this);275}276}277278private void checkEventsProcessingPermission() {279@SuppressWarnings("removal")280SecurityManager sm = System.getSecurityManager();281if (sm != null) {282sm.checkPermission(new RuntimePermission(283"canProcessApplicationEvents"));284}285}286287/**288* Returns the {@code Desktop} instance of the current289* desktop context. On some platforms the Desktop API may not be290* supported; use the {@link #isDesktopSupported} method to291* determine if the current desktop is supported.292* @return the Desktop instance293* @throws HeadlessException if {@link294* GraphicsEnvironment#isHeadless()} returns {@code true}295* @throws UnsupportedOperationException if this class is not296* supported on the current platform297* @see #isDesktopSupported()298* @see java.awt.GraphicsEnvironment#isHeadless299*/300public static synchronized Desktop getDesktop(){301if (GraphicsEnvironment.isHeadless()) throw new HeadlessException();302if (!Desktop.isDesktopSupported()) {303throw new UnsupportedOperationException("Desktop API is not " +304"supported on the current platform");305}306307sun.awt.AppContext context = sun.awt.AppContext.getAppContext();308Desktop desktop = (Desktop)context.get(Desktop.class);309310if (desktop == null) {311desktop = new Desktop();312context.put(Desktop.class, desktop);313}314315return desktop;316}317318/**319* Tests whether this class is supported on the current platform.320* If it's supported, use {@link #getDesktop()} to retrieve an321* instance.322*323* @return {@code true} if this class is supported on the324* current platform; {@code false} otherwise325* @see #getDesktop()326*/327public static boolean isDesktopSupported(){328Toolkit defaultToolkit = Toolkit.getDefaultToolkit();329if (defaultToolkit instanceof SunToolkit) {330return ((SunToolkit)defaultToolkit).isDesktopSupported();331}332return false;333}334335/**336* Tests whether an action is supported on the current platform.337*338* <p>Even when the platform supports an action, a file or URI may339* not have a registered application for the action. For example,340* most of the platforms support the {@link Desktop.Action#OPEN}341* action. But for a specific file, there may not be an342* application registered to open it. In this case, {@link343* #isSupported(Action)} may return {@code true}, but the corresponding344* action method will throw an {@link IOException}.345*346* @param action the specified {@link Action}347* @return {@code true} if the specified action is supported on348* the current platform; {@code false} otherwise349* @see Desktop.Action350*/351public boolean isSupported(Action action) {352return peer.isSupported(action);353}354355/**356* Checks if the file is a valid file and readable.357*358* @throws SecurityException If a security manager exists and its359* {@link SecurityManager#checkRead(java.lang.String)} method360* denies read access to the file361* @throws NullPointerException if file is null362* @throws IllegalArgumentException if file doesn't exist363*/364private static void checkFileValidation(File file) {365if (!file.exists()) {366throw new IllegalArgumentException("The file: "367+ file.getPath() + " doesn't exist.");368}369}370371/**372* Checks if the action type is supported.373*374* @param actionType the action type in question375* @throws UnsupportedOperationException if the specified action type is not376* supported on the current platform377*/378private void checkActionSupport(Action actionType){379if (!isSupported(actionType)) {380throw new UnsupportedOperationException("The " + actionType.name()381+ " action is not supported on the current platform!");382}383}384385386/**387* Calls to the security manager's {@code checkPermission} method with an388* {@code AWTPermission("showWindowWithoutWarningBanner")} permission. This389* permission is needed, because we cannot add a security warning icon to390* the windows of the external native application.391*/392private void checkAWTPermission() {393@SuppressWarnings("removal")394SecurityManager sm = System.getSecurityManager();395if (sm != null) {396sm.checkPermission(new AWTPermission(397"showWindowWithoutWarningBanner"));398}399}400401/**402* Launches the associated application to open the file.403*404* <p> If the specified file is a directory, the file manager of405* the current platform is launched to open it.406*407* @param file the file to be opened with the associated application408* @throws NullPointerException if {@code file} is {@code null}409* @throws IllegalArgumentException if the specified file doesn't410* exist411* @throws UnsupportedOperationException if the current platform412* does not support the {@link Desktop.Action#OPEN} action413* @throws IOException if the specified file has no associated414* application or the associated application fails to be launched415* @throws SecurityException if a security manager exists and its416* {@link java.lang.SecurityManager#checkRead(java.lang.String)}417* method denies read access to the file, or it denies the418* {@code AWTPermission("showWindowWithoutWarningBanner")}419* permission, or the calling thread is not allowed to create a420* subprocess421* @see java.awt.AWTPermission422*/423public void open(File file) throws IOException {424file = new File(file.getPath());425checkAWTPermission();426checkExec();427checkActionSupport(Action.OPEN);428checkFileValidation(file);429430peer.open(file);431}432433/**434* Launches the associated editor application and opens a file for435* editing.436*437* @param file the file to be opened for editing438* @throws NullPointerException if the specified file is {@code null}439* @throws IllegalArgumentException if the specified file doesn't440* exist441* @throws UnsupportedOperationException if the current platform442* does not support the {@link Desktop.Action#EDIT} action443* @throws IOException if the specified file has no associated444* editor, or the associated application fails to be launched445* @throws SecurityException if a security manager exists and its446* {@link java.lang.SecurityManager#checkRead(java.lang.String)}447* method denies read access to the file, or {@link448* java.lang.SecurityManager#checkWrite(java.lang.String)} method449* denies write access to the file, or it denies the450* {@code AWTPermission("showWindowWithoutWarningBanner")}451* permission, or the calling thread is not allowed to create a452* subprocess453* @see java.awt.AWTPermission454*/455public void edit(File file) throws IOException {456file = new File(file.getPath());457checkAWTPermission();458checkExec();459checkActionSupport(Action.EDIT);460file.canWrite();461checkFileValidation(file);462if (file.isDirectory()) {463throw new IOException(file.getPath() + " is a directory");464}465peer.edit(file);466}467468/**469* Prints a file with the native desktop printing facility, using470* the associated application's print command.471*472* @param file the file to be printed473* @throws NullPointerException if the specified file is {@code474* null}475* @throws IllegalArgumentException if the specified file doesn't476* exist477* @throws UnsupportedOperationException if the current platform478* does not support the {@link Desktop.Action#PRINT} action479* @throws IOException if the specified file has no associated480* application that can be used to print it481* @throws SecurityException if a security manager exists and its482* {@link java.lang.SecurityManager#checkRead(java.lang.String)}483* method denies read access to the file, or its {@link484* java.lang.SecurityManager#checkPrintJobAccess()} method denies485* the permission to print the file, or the calling thread is not486* allowed to create a subprocess487*/488public void print(File file) throws IOException {489file = new File(file.getPath());490checkExec();491@SuppressWarnings("removal")492SecurityManager sm = System.getSecurityManager();493if (sm != null) {494sm.checkPrintJobAccess();495}496checkActionSupport(Action.PRINT);497checkFileValidation(file);498if (file.isDirectory()) {499throw new IOException(file.getPath() + " is a directory");500}501peer.print(file);502}503504/**505* Launches the default browser to display a {@code URI}.506* If the default browser is not able to handle the specified507* {@code URI}, the application registered for handling508* {@code URIs} of the specified type is invoked. The application509* is determined from the protocol and path of the {@code URI}, as510* defined by the {@code URI} class.511*512* @param uri the URI to be displayed in the user default browser513* @throws NullPointerException if {@code uri} is {@code null}514* @throws UnsupportedOperationException if the current platform515* does not support the {@link Desktop.Action#BROWSE} action516* @throws IOException if the user default browser is not found,517* or it fails to be launched, or the default handler application518* failed to be launched519* @throws SecurityException if a security manager exists and it520* denies the521* {@code AWTPermission("showWindowWithoutWarningBanner")}522* permission, or the calling thread is not allowed to create a523* subprocess524* @see java.net.URI525* @see java.awt.AWTPermission526*/527public void browse(URI uri) throws IOException {528checkAWTPermission();529checkExec();530checkActionSupport(Action.BROWSE);531Objects.requireNonNull(uri);532peer.browse(uri);533}534535/**536* Launches the mail composing window of the user default mail537* client.538*539* @throws UnsupportedOperationException if the current platform540* does not support the {@link Desktop.Action#MAIL} action541* @throws IOException if the user default mail client is not542* found, or it fails to be launched543* @throws SecurityException if a security manager exists and it544* denies the545* {@code AWTPermission("showWindowWithoutWarningBanner")}546* permission, or the calling thread is not allowed to create a547* subprocess548* @see java.awt.AWTPermission549*/550public void mail() throws IOException {551checkAWTPermission();552checkExec();553checkActionSupport(Action.MAIL);554URI mailtoURI = null;555try{556mailtoURI = new URI("mailto:?");557peer.mail(mailtoURI);558} catch (URISyntaxException e){559// won't reach here.560}561}562563/**564* Launches the mail composing window of the user default mail565* client, filling the message fields specified by a {@code566* mailto:} URI.567*568* <p> A {@code mailto:} URI can specify message fields569* including <i>"to"</i>, <i>"cc"</i>, <i>"subject"</i>,570* <i>"body"</i>, etc. See <a571* href="http://www.ietf.org/rfc/rfc2368.txt">The mailto URL572* scheme (RFC 2368)</a> for the {@code mailto:} URI specification573* details.574*575* @param mailtoURI the specified {@code mailto:} URI576* @throws NullPointerException if the specified URI is {@code577* null}578* @throws IllegalArgumentException if the URI scheme is not579* {@code "mailto"}580* @throws UnsupportedOperationException if the current platform581* does not support the {@link Desktop.Action#MAIL} action582* @throws IOException if the user default mail client is not583* found or fails to be launched584* @throws SecurityException if a security manager exists and it585* denies the586* {@code AWTPermission("showWindowWithoutWarningBanner")}587* permission, or the calling thread is not allowed to create a588* subprocess589* @see java.net.URI590* @see java.awt.AWTPermission591*/592public void mail(URI mailtoURI) throws IOException {593checkAWTPermission();594checkExec();595checkActionSupport(Action.MAIL);596if (mailtoURI == null) throw new NullPointerException();597598if (!"mailto".equalsIgnoreCase(mailtoURI.getScheme())) {599throw new IllegalArgumentException("URI scheme is not \"mailto\"");600}601602peer.mail(mailtoURI);603}604605private void checkExec() throws SecurityException {606@SuppressWarnings("removal")607SecurityManager sm = System.getSecurityManager();608if (sm != null) {609sm.checkPermission(new FilePermission("<<ALL FILES>>",610SecurityConstants.FILE_EXECUTE_ACTION));611}612}613614private void checkRead() throws SecurityException {615@SuppressWarnings("removal")616SecurityManager sm = System.getSecurityManager();617if (sm != null) {618sm.checkPermission(new FilePermission("<<ALL FILES>>",619SecurityConstants.FILE_READ_ACTION));620}621}622623private void checkQuitPermission() {624@SuppressWarnings("removal")625SecurityManager sm = System.getSecurityManager();626if (sm != null) {627sm.checkExit(0);628}629}630631/**632* Adds sub-types of {@link SystemEventListener} to listen for notifications633* from the native system.634*635* Has no effect if SystemEventListener's sub-type is unsupported on the current636* platform.637*638* @param listener listener639*640* @throws SecurityException if a security manager exists and it641* denies the642* {@code RuntimePermission("canProcessApplicationEvents")}643* permission644*645* @see java.awt.desktop.AppForegroundListener646* @see java.awt.desktop.AppHiddenListener647* @see java.awt.desktop.AppReopenedListener648* @see java.awt.desktop.ScreenSleepListener649* @see java.awt.desktop.SystemSleepListener650* @see java.awt.desktop.UserSessionListener651* @since 9652*/653public void addAppEventListener(final SystemEventListener listener) {654checkEventsProcessingPermission();655peer.addAppEventListener(listener);656}657658/**659* Removes sub-types of {@link SystemEventListener} to listen for notifications660* from the native system.661*662* Has no effect if SystemEventListener's sub-type is unsupported on the current663* platform.664*665* @param listener listener666*667* @throws SecurityException if a security manager exists and it668* denies the669* {@code RuntimePermission("canProcessApplicationEvents")}670* permission671*672* @see java.awt.desktop.AppForegroundListener673* @see java.awt.desktop.AppHiddenListener674* @see java.awt.desktop.AppReopenedListener675* @see java.awt.desktop.ScreenSleepListener676* @see java.awt.desktop.SystemSleepListener677* @see java.awt.desktop.UserSessionListener678* @since 9679*/680public void removeAppEventListener(final SystemEventListener listener) {681checkEventsProcessingPermission();682peer.removeAppEventListener(listener);683}684685/**686* Installs a handler to show a custom About window for your application.687* <p>688* Setting the {@link java.awt.desktop.AboutHandler} to {@code null} reverts it to the689* default behavior.690*691* @param aboutHandler the handler to respond to the692* {@link java.awt.desktop.AboutHandler#handleAbout(AboutEvent)} message693*694* @throws SecurityException if a security manager exists and it695* denies the696* {@code RuntimePermission("canProcessApplicationEvents")}697* permission698* @throws UnsupportedOperationException if the current platform699* does not support the {@link Desktop.Action#APP_ABOUT} action700*701* @since 9702*/703public void setAboutHandler(final AboutHandler aboutHandler) {704checkEventsProcessingPermission();705checkActionSupport(Action.APP_ABOUT);706peer.setAboutHandler(aboutHandler);707}708709/**710* Installs a handler to show a custom Preferences window for your711* application.712* <p>713* Setting the {@link PreferencesHandler} to {@code null} reverts it to714* the default behavior715*716* @param preferencesHandler the handler to respond to the717* {@link PreferencesHandler#handlePreferences(PreferencesEvent)}718*719* @throws SecurityException if a security manager exists and it720* denies the721* {@code RuntimePermission("canProcessApplicationEvents")} permission722* @throws UnsupportedOperationException if the current platform723* does not support the {@link Desktop.Action#APP_PREFERENCES} action724* @since 9725*/726public void setPreferencesHandler(final PreferencesHandler preferencesHandler) {727checkEventsProcessingPermission();728checkActionSupport(Action.APP_PREFERENCES);729peer.setPreferencesHandler(preferencesHandler);730}731732/**733* Installs the handler which is notified when the application is asked to734* open a list of files.735*736* @implNote Please note that for macOS, notifications737* are only sent if the Java app is a bundled application,738* with a {@code CFBundleDocumentTypes} array present in its739* {@code Info.plist}. Check the740* <a href="https://developer.apple.com/documentation">741* Apple Developer Documentation</a> for more information about742* {@code Info.plist}.743*744* @param openFileHandler handler745*746* @throws SecurityException if a security manager exists and its747* {@link java.lang.SecurityManager#checkRead(java.lang.String)}748* method denies read access to the files, or it denies the749* {@code RuntimePermission("canProcessApplicationEvents")}750* permission, or the calling thread is not allowed to create a751* subprocess752* @throws UnsupportedOperationException if the current platform753* does not support the {@link Desktop.Action#APP_OPEN_FILE} action754* @since 9755*/756public void setOpenFileHandler(final OpenFilesHandler openFileHandler) {757checkEventsProcessingPermission();758checkExec();759checkRead();760checkActionSupport(Action.APP_OPEN_FILE);761peer.setOpenFileHandler(openFileHandler);762}763764/**765* Installs the handler which is notified when the application is asked to766* print a list of files.767*768* @implNote Please note that for macOS, notifications769* are only sent if the Java app is a bundled application,770* with a {@code CFBundleDocumentTypes} array present in its771* {@code Info.plist}. Check the772* <a href="https://developer.apple.com/documentation">773* Apple Developer Documentation</a> for more information about774* {@code Info.plist}.775*776* @param printFileHandler handler777* @throws SecurityException if a security manager exists and its778* {@link java.lang.SecurityManager#checkPrintJobAccess()} method denies779* the permission to print or it denies the780* {@code RuntimePermission("canProcessApplicationEvents")} permission781* @throws UnsupportedOperationException if the current platform782* does not support the {@link Desktop.Action#APP_PRINT_FILE} action783* @since 9784*/785public void setPrintFileHandler(final PrintFilesHandler printFileHandler) {786checkEventsProcessingPermission();787@SuppressWarnings("removal")788SecurityManager sm = System.getSecurityManager();789if (sm != null) {790sm.checkPrintJobAccess();791}792checkActionSupport(Action.APP_PRINT_FILE);793peer.setPrintFileHandler(printFileHandler);794}795796/**797* Installs the handler which is notified when the application is asked to798* open a URL.799*800* Setting the handler to {@code null} causes all801* {@link OpenURIHandler#openURI(OpenURIEvent)} requests to be802* enqueued until another handler is set.803*804* @implNote Please note that for macOS, notifications805* are only sent if the Java app is a bundled application,806* with a {@code CFBundleDocumentTypes} array present in its807* {@code Info.plist}. Check the808* <a href="https://developer.apple.com/documentation">809* Apple Developer Documentation</a> for more information about810* {@code Info.plist}.811*812* @param openURIHandler handler813*814* {@code RuntimePermission("canProcessApplicationEvents")}815* permission, or the calling thread is not allowed to create a816* subprocess817* @throws UnsupportedOperationException if the current platform818* does not support the {@link Desktop.Action#APP_OPEN_URI} action819* @since 9820*/821public void setOpenURIHandler(final OpenURIHandler openURIHandler) {822checkEventsProcessingPermission();823checkExec();824checkActionSupport(Action.APP_OPEN_URI);825peer.setOpenURIHandler(openURIHandler);826}827828/**829* Installs the handler which determines if the application should quit. The830* handler is passed a one-shot {@link java.awt.desktop.QuitResponse} which can cancel or831* proceed with the quit. Setting the handler to {@code null} causes832* all quit requests to directly perform the default {@link QuitStrategy}.833*834* @param quitHandler the handler that is called when the application is835* asked to quit836*837* @throws SecurityException if a security manager exists and it838* will not allow the caller to invoke {@code System.exit} or it denies the839* {@code RuntimePermission("canProcessApplicationEvents")} permission840* @throws UnsupportedOperationException if the current platform841* does not support the {@link Desktop.Action#APP_QUIT_HANDLER} action842* @since 9843*/844public void setQuitHandler(final QuitHandler quitHandler) {845checkEventsProcessingPermission();846checkQuitPermission();847checkActionSupport(Action.APP_QUIT_HANDLER);848peer.setQuitHandler(quitHandler);849}850851/**852* Sets the default strategy used to quit this application. The default is853* calling SYSTEM_EXIT_0.854*855* @param strategy the way this application should be shutdown856*857* @throws SecurityException if a security manager exists and it858* will not allow the caller to invoke {@code System.exit} or it denies the859* {@code RuntimePermission("canProcessApplicationEvents")} permission860* @throws UnsupportedOperationException if the current platform861* does not support the {@link Desktop.Action#APP_QUIT_STRATEGY} action862* @see QuitStrategy863* @since 9864*/865public void setQuitStrategy(final QuitStrategy strategy) {866checkEventsProcessingPermission();867checkQuitPermission();868checkActionSupport(Action.APP_QUIT_STRATEGY);869peer.setQuitStrategy(strategy);870}871872/**873* Enables this application to be suddenly terminated.874*875* Call this method to indicate your application's state is saved, and876* requires no notification to be terminated. Letting your application877* remain terminatable improves the user experience by avoiding re-paging in878* your application when it's asked to quit.879*880* <b>Note: enabling sudden termination will allow your application to be881* quit without notifying your QuitHandler, or running any shutdown882* hooks.</b>883* E.g. user-initiated Cmd-Q, logout, restart, or shutdown requests will884* effectively "kill -KILL" your application.885*886* @throws SecurityException if a security manager exists and it887* will not allow the caller to invoke {@code System.exit} or it denies the888* {@code RuntimePermission("canProcessApplicationEvents")} permission889* @throws UnsupportedOperationException if the current platform890* does not support the {@link Desktop.Action#APP_SUDDEN_TERMINATION} action891* @see #disableSuddenTermination()892* @since 9893*/894public void enableSuddenTermination() {895checkEventsProcessingPermission();896checkQuitPermission();897checkActionSupport(Action.APP_SUDDEN_TERMINATION);898peer.enableSuddenTermination();899}900901/**902* Prevents this application from being suddenly terminated.903*904* Call this method to indicate that your application has unsaved state, and905* may not be terminated without notification.906*907* @throws SecurityException if a security manager exists and it908* will not allow the caller to invoke {@code System.exit} or it denies the909* {@code RuntimePermission("canProcessApplicationEvents")} permission910* @throws UnsupportedOperationException if the current platform911* does not support the {@link Desktop.Action#APP_SUDDEN_TERMINATION} action912* @see #enableSuddenTermination()913* @since 9914*/915public void disableSuddenTermination() {916checkEventsProcessingPermission();917checkQuitPermission();918checkActionSupport(Action.APP_SUDDEN_TERMINATION);919peer.disableSuddenTermination();920}921922/**923* Requests this application to move to the foreground.924*925* @param allWindows if all windows of this application should be moved to926* the foreground, or only the foremost one927* @throws SecurityException if a security manager exists and it denies the928* {@code RuntimePermission("canProcessApplicationEvents")} permission.929* @throws UnsupportedOperationException if the current platform930* does not support the {@link Desktop.Action#APP_REQUEST_FOREGROUND} action931* @since 9932*/933public void requestForeground(final boolean allWindows) {934checkEventsProcessingPermission();935checkActionSupport(Action.APP_REQUEST_FOREGROUND);936peer.requestForeground(allWindows);937}938939/**940* Opens the native help viewer application.941*942* @implNote Please note that for Mac OS, it opens the native help viewer943* application if a Help Book has been added to the application bundler944* and registered in the Info.plist with CFBundleHelpBookFolder945*946* @throws SecurityException if a security manager exists and it denies the947* {@code RuntimePermission("canProcessApplicationEvents")}948* permission, or it denies the949* {@code AWTPermission("showWindowWithoutWarningBanner")}950* permission, or the calling thread is not allowed to create a951* subprocess952* @throws UnsupportedOperationException if the current platform953* does not support the {@link Desktop.Action#APP_HELP_VIEWER} action954* @since 9955*/956public void openHelpViewer() {957checkAWTPermission();958checkExec();959checkEventsProcessingPermission();960checkActionSupport(Action.APP_HELP_VIEWER);961peer.openHelpViewer();962}963964/**965* Sets the default menu bar to use when there are no active frames.966*967* @param menuBar to use when no other frames are active968* @throws SecurityException if a security manager exists and it denies the969* {@code RuntimePermission("canProcessApplicationEvents")} permission.970* @throws UnsupportedOperationException if the current platform971* does not support the {@link Desktop.Action#APP_MENU_BAR} action972* @since 9973*/974public void setDefaultMenuBar(final JMenuBar menuBar) {975checkEventsProcessingPermission();976checkActionSupport(Action.APP_MENU_BAR);977978if (menuBar != null) {979Container parent = menuBar.getParent();980if (parent != null) {981parent.remove(menuBar);982menuBar.updateUI();983}984}985986peer.setDefaultMenuBar(menuBar);987}988989/**990* Opens a folder containing the {@code file} and selects it991* in a default system file manager.992* @param file the file993* @throws SecurityException If a security manager exists and its994* {@link SecurityManager#checkRead(java.lang.String)} method995* denies read access to the file or to its parent, or it denies the996* {@code AWTPermission("showWindowWithoutWarningBanner")}997* permission, or the calling thread is not allowed to create a998* subprocess999* @throws UnsupportedOperationException if the current platform1000* does not support the {@link Desktop.Action#BROWSE_FILE_DIR} action1001* @throws NullPointerException if {@code file} is {@code null}1002* @throws IllegalArgumentException if the specified file or its parent1003* doesn't exist1004* @since 91005*/1006public void browseFileDirectory(File file) {1007file = new File(file.getPath());1008checkAWTPermission();1009checkExec();1010checkActionSupport(Action.BROWSE_FILE_DIR);1011checkFileValidation(file);1012File parentFile = file.getParentFile();1013if (parentFile == null || !parentFile.exists()) {1014throw new IllegalArgumentException("Parent folder doesn't exist");1015}1016peer.browseFileDirectory(file);1017}10181019/**1020* Moves the specified file to the trash.1021*1022* @param file the file1023* @return returns true if successfully moved the file to the trash.1024* @throws SecurityException If a security manager exists and its1025* {@link SecurityManager#checkDelete(java.lang.String)} method1026* denies deletion of the file1027* @throws UnsupportedOperationException if the current platform1028* does not support the {@link Desktop.Action#MOVE_TO_TRASH} action1029* @throws NullPointerException if {@code file} is {@code null}1030* @throws IllegalArgumentException if the specified file doesn't exist1031*1032* @since 91033*/1034@SuppressWarnings("removal")1035public boolean moveToTrash(File file) {1036file = new File(file.getPath());1037SecurityManager sm = System.getSecurityManager();1038if (sm != null) {1039sm.checkDelete(file.getPath());1040}1041checkActionSupport(Action.MOVE_TO_TRASH);1042final File finalFile = file;1043AccessController.doPrivileged((PrivilegedAction<?>) () -> {1044checkFileValidation(finalFile);1045return null;1046});1047return peer.moveToTrash(file);1048}1049}105010511052