com.openfin.desktop.Application Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openfin-desktop-java-adapter Show documentation
Show all versions of openfin-desktop-java-adapter Show documentation
The Java API for OpenFin Runtime
package com.openfin.desktop;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* An object representing the Application.
* Allows the developer to execute, show and close an application,
* as well as show and hide an icon on Desktop. Also provides access
* to the Window object for the main application window to control
* window state such as the ability to minimize, maximize, restore, etc.
* @since 10/29/12
*/
public class Application {
private final static Logger logger = LoggerFactory.getLogger(Application.class.getName());
DesktopConnection connection;
ApplicationOptions options;
JSONObject noParamPayload,
resizeToPayload,
resizeByPayload,
moveToPayload,
moveByPayload,
dockWindowPayload,
eventListenerPayload;
Window window;
String uuid;
EventListener trayIconClickListener;
String manifestUrl;
/**
* Attaches an Application object to an application that already exists
* @param uuid The UUID of the Application to wrap
* @param connection Connection object to the AppDesktop
* @return Application Object
* @see DesktopConnection
*/
public static Application wrap(String uuid, DesktopConnection connection) {
return new Application(uuid, connection);
}
/**
* Attaches an Application object to an application that already exists
* @param uuid The UUID of the Application to wrap
* @param connection Connection object to the AppDesktop
* @see DesktopConnection
*/
private Application(String uuid, DesktopConnection connection) {
this.uuid = uuid;
this.connection = connection;
initialize();
}
/**
* Application Constructor
* @param options Settings of the application
* @param connection Connection object to the AppDesktop.
* @param listener function that is called if the method succeeds.
* @see ApplicationOptions
* @see DesktopConnection
* @see AckListener
*/
public Application(ApplicationOptions options, DesktopConnection connection, AckListener listener) {
this.options = options;
this.connection = connection;
uuid = this.options.getUUID();
initialize();
connection.sendAction("create-application", this.options.getJsonCopy(), listener, this);
}
public static CompletableFuture createApplication(ApplicationOptions options, DesktopConnection connection) {
return connection.sendActionAsync("create-application", options.getJsonCopy(), Application.class).thenApplyAsync(ack -> {
if (ack.isSuccessful()) {
Application app = Application.wrap(options.getUUID(), connection);
return app;
}
else {
throw new RuntimeException("error creating appliction, reason: " + ack.getReason());
}
});
}
/**
* Runs the application
*
* @throws DesktopException if application fails to run
* @see DesktopException
*/
public void run() throws DesktopException {
this.runAsync();
}
public CompletableFuture runAsync() {
JSONObject payload = new JSONObject();
payload.put("uuid", uuid);
payload.put("manifestUrl", manifestUrl);
return connection.sendActionAsync("run-application", payload, this).thenApplyAsync(ack -> {
if (ack.isSuccessful()) {
return Application.this;
}
else {
throw new RuntimeException("unable to run application, reason: " + ack.getReason());
}
});
}
/**
* Runs the application with a listener that gets called if the method succeeds
* @param listener The listener that gets called if the method succeeds
* @see AckListener
*/
public void run(AckListener listener) {
JSONObject payload = new JSONObject();
payload.put("uuid", uuid);
payload.put("manifestUrl", manifestUrl);
connection.sendAction("run-application", payload, listener, this);
}
/**
* Restarts the application
*
* @throws DesktopException if application fails to restart
* @see DesktopException
*/
public void restart() throws DesktopException {
connection.sendAction("restart-application", noParamPayload);
}
/**
* Restarts the application with a listener that gets called if the method succeeds
* @param listener The listener that gets called if the method succeeds
* @see AckListener
*/
public void restart(AckListener listener) {
connection.sendAction("restart-application", noParamPayload, listener, this);
}
/**
* Closes the application and any child windows created by the application
*
* @throws DesktopException if application fails to close
* @see DesktopException
*/
public void close() throws DesktopException {
connection.sendAction("close-application", noParamPayload);
}
/**
* Closes the application with a listener that gets called if the method succeeds
* @param listener The listener that gets called if the method succeeds
* @see AckListener
* @deprecated use close() instead.
*/
public void close(AckListener listener) {
try {
this.close();
} catch (Exception ex) {
logger.error("Error close app", ex);
}
}
/**
* Closes the application with a listener that gets called if the method succeeds
* @param force When true the close can not be prevented through the window event 'close-requested'. If force is false, AckListener is being ignored
* @param listener The listener that gets called if the method succeeds
* @throws DesktopException if application fails to close
* @see AckListener
*/
public void close(Boolean force, AckListener listener) throws DesktopException {
JSONObject payload = new JSONObject();
try {
if (force != null) {
payload.put("force", force);
}
payload.put("uuid", getUuid());
connection.sendAction("close-application", payload, listener, this);
} catch (Exception e) {
logger.error("Error closing application", e);
throw new DesktopException(e);
}
}
/**
* Closes the application by terminating its process.
*
* @throws DesktopException if application fails to terminate
* @see DesktopException
*/
public void terminate() throws DesktopException {
connection.sendAction("terminate-application", noParamPayload);
}
/**
* Closes the application by terminating its process.
* @param listener The listener that gets called if the method succeeds
* @see AckListener
*/
public void terminate(AckListener listener) {
connection.sendAction("terminate-application", noParamPayload, listener, this);
}
/**
* Waits for a hanging application. This method can be called in response to an application "not-responding" to allow the application
* to continue and to generate another "not-responding" message after a certain period of time.
*
* @throws DesktopException if application fails to wait for a hanging application
* @see DesktopException
*/
public void waitFor() throws DesktopException {
connection.sendAction("wait-for-hung-application", noParamPayload);
}
/**
* Waits for a hanging application. This method can be called in response to an application "not-responding" to allow the application
* to continue and to generate another "not-responding" message after a certain period of time.
* @param listener The listener that gets called if the method succeeds
* @see AckListener
*/
public void waitFor(AckListener listener) {
connection.sendAction("wait-for-hung-application", noParamPayload, listener, this);
}
/**
*
* Retrieves the JSON manifest that was used to create the application.
* Invokes the error callback if the application was not created from a manifest.
* AckListener is called and passed an Ack containing the JSONObject manifest
* that was used to create the application.
*
* @param listener The listener that gets called if the method succeeds
* @see AckListener
*/
public void getManifest(AckListener listener) {
connection.sendAction("get-application-manifest", noParamPayload, listener, this);
}
/*
public void dockWindow(String hwnd, String name) {
try {
connection.sendAction("dock-window", dockWindowPayload
.put("hwnd", hwnd)
.put("name", name));
} catch (JSONException e) {
e.printStackTrace();
}
}
public void unDockWindow(String hwnd, String name, int x, int y) {
try {
connection.sendAction("undock-window", dockWindowPayload
.put("hwnd", hwnd)
.put("name", name)
.put("x", x)
.put("y", y));
} catch (JSONException e) {
e.printStackTrace();
}
} */
/**
* Returns an instance to the main Window of the application.
* @return the main Window
*/
public Window getWindow() {
return window;
}
/**
* Get the ApplicationOptions object for the application
* @return ApplicationOptions object
*/
public ApplicationOptions getOptions() {
return this.options;
}
/**
* Get UUID of this Application
* @return UUID
*/
public String getUuid() {
return uuid;
}
/**
* Returns the applications connection object
* @return DesktopConnection object
* @see DesktopConnection
*/
public DesktopConnection getConnection() {
return connection;
}
/**
* Allocates and prepares internal JObjects and wraps the Applications main window
*/
private void initialize() {
try {
noParamPayload = new JSONObject();
resizeToPayload = new JSONObject();
resizeByPayload = new JSONObject();
moveToPayload = new JSONObject();
moveByPayload = new JSONObject();
dockWindowPayload = new JSONObject();
noParamPayload.put("uuid", uuid);
resizeToPayload.put("uuid", uuid);
resizeByPayload.put("uuid", uuid);
moveToPayload.put("uuid", uuid);
moveByPayload.put("uuid", uuid);
dockWindowPayload.put("uuid", uuid);
} catch (JSONException e) {
logger.error("Error initializing application", e);
}
window = new Window(this);
}
private void addEventListener(JSONObject subscriptionObject,
EventListener listener,
AckListener callback) {
this.connection.addEventCallback(subscriptionObject,
listener,
callback,
this);
}
/**
* Registers an event listener on the specified event.
* Supported system event types are:
* closed
* crashed
* error
* not-responding
* out-of-memory
* responding
* started
* run-requested
* @param type Event type
* @param listener A listener that is called whenever an event of the specified type occurs
* @param callback A function that is called if the method succeeds
* @throws DesktopException if this methos fails to add event listener
* @see EventListener
* @see ActionEvent
*/
public void addEventListener(String type,
EventListener listener,
AckListener callback) throws DesktopException {
try {
logger.debug("addEventListener " + type);
if (eventListenerPayload == null) {
eventListenerPayload = new JSONObject();
eventListenerPayload.put("topic", "application");
eventListenerPayload.put("uuid", getUuid());
}
eventListenerPayload.put("type", type);
addEventListener(eventListenerPayload, listener, callback);
} catch (Exception e) {
logger.error("Error adding event listener", e);
throw new DesktopException(e);
}
}
/**
* Removes a previously registered event listener from the specified event
* @param type Event type
* @param listener A listener to remove
* @param callback AckListener for the request
* @throws DesktopException if this methd fails to remove an event listener
* @see EventListener
* @see ActionEvent
*/
public void removeEventListener(String type,
EventListener listener,
AckListener callback) throws DesktopException {
try {
logger.debug("removeEventListener " + type);
if (eventListenerPayload == null) {
eventListenerPayload = new JSONObject();
eventListenerPayload.put("topic", "application");
eventListenerPayload.put("uuid", getUuid());
}
eventListenerPayload.put("type", type);
this.connection.removeEventCallback(eventListenerPayload, listener, callback, this);
} catch (Exception e) {
logger.error("Error Removing event listener", e);
throw new DesktopException(e);
}
}
/**
* Adds a customizable icon in the system tray and notifies the application when clicked
*
* @param iconUrl Image URL to be used as the icon
* @param listener will be called whenever an event of the specified type occurs. It is passed an event object containing information related to the event
* @param callback AckListener for the request
* @throws DesktopException if this methed fails to set tray icon
* @see EventListener
* @see ActionEvent
*/
public void setTrayIcon(String iconUrl, EventListener listener, AckListener callback) throws DesktopException {
// Remove a prior listener if present.
if (this.trayIconClickListener != null) {
this.removeEventListener("tray-icon-clicked", this.trayIconClickListener, null);
}
// track this listner for future removal
this.trayIconClickListener = listener;
if (listener != null) {
this.addEventListener("tray-icon-clicked", listener, callback);
}
try {
JSONObject payload = new JSONObject();
payload.put("uuid", getUuid());
payload.put("name", getUuid());
payload.put("enabledIcon", iconUrl);
payload.put("disabledIcon", iconUrl);
payload.put("hoverIcon", iconUrl);
connection.sendAction("set-tray-icon", payload, callback, this);
} catch (Exception e) {
logger.error("Error setting tray icon", e);
throw new DesktopException(e);
}
}
/**
* Removes the application’s icon from the tray.
*
* @param callback AckListener for the request
* @throws DesktopException if this method fails to remove tray icn
*/
public void removeTrayIcon(AckListener callback) throws DesktopException {
// Remove a prior listener if present.
if (this.trayIconClickListener != null) {
this.removeEventListener("tray-icon-clicked", this.trayIconClickListener, null);
this.trayIconClickListener = null;
}
try {
JSONObject payload = new JSONObject();
payload.put("uuid", getUuid());
payload.put("name", getUuid());
connection.sendAction("remove-tray-icon", payload, callback, this);
} catch (Exception e) {
logger.error("Error removing tray icon", e);
throw new DesktopException(e);
}
}
/**
* Create a child window of this application
*
* @param windowOptions WindowOptions object for the requested child window.
* @param callback AckListener for the request
* @throws DesktopException if this method fails to create a child window
*/
public void createChildWindow(WindowOptions windowOptions, AckListener callback) throws DesktopException {
try {
JSONObject payload = new JSONObject();
payload.put("targetUuid", getUuid());
payload.put("windowOptions", windowOptions.getJsonCopy());
connection.sendAction("create-child-window", payload, callback, this);
} catch (Exception e) {
logger.error("Error creating child window", e);
throw new DesktopException(e);
}
}
/**
* Retrieves an array of active window groups for all of the application's windows. Each group is represented as an array of wrapped fin.desktop.Windows.
* An empty list is returned if the window is not in a group.
* The calling window is included in the resulting List.
*
* @param groupHandler A class that receives a list of wrapped windows in the same group.
* @see AsyncCallback
* @param callback AckListener for the request
* @see AckListener
*/
public void getGroups(final AsyncCallback>> groupHandler, final AckListener callback) {
if (groupHandler != null) {
JSONObject payload = new JSONObject();
payload.put("uuid", this.uuid);
payload.put("crossApp", true); // cross app group supported
connection.sendAction("get-application-groups", payload, new AckListener() {
@Override
public void onSuccess(Ack ack) {
List> list = new ArrayList>();
try {
JSONObject value = ack.getJsonObject();
if (value != null) {
JSONArray array = value.getJSONArray("data");
for (int i = 0; i < array.length(); i++) {
JSONArray subArray = array.getJSONArray(i);
if (subArray != null && subArray.length() > 0) {
List subGroup = new ArrayList();
list.add(subGroup);
for (int k = 0; k < subArray.length(); k++) {
JSONObject item = subArray.getJSONObject(k);
subGroup.add(Window.wrap(item.getString("uuid"), item.getString("windowName"), connection));
}
}
}
}
groupHandler.onSuccess(list);
} catch (Exception e) {
logger.error("Error processing group", e);
}
}
@Override
public void onError(Ack ack) {
DesktopUtils.errorAck(callback, ack);
}
}, this);
}
}
/**
* Wraps an existing window using the specified name
*
* @param name The name of the window that is being wrapped
* @return The wrapped window
* @see Window
*/
public Window wrapWindow(String name) {
return Window.wrap(this.getUuid(), name, this.connection);
}
public static CompletableFuture createFromManifestAsync(String manifestUrl, DesktopConnection connection) {
JSONObject payload = new JSONObject();
payload.put("manifestUrl", manifestUrl);
return connection.sendActionAsync("get-application-manifest", payload, Application.class).thenApplyAsync(ack -> {
if (ack.isSuccessful()) {
JSONObject appManifest = (JSONObject) ack.getData();
JSONObject platformData = appManifest.optJSONObject("platform");
String uuid = platformData == null ? appManifest.getJSONObject("startup_app").getString("uuid") : platformData.getString("uuid");
Application app = Application.wrap(uuid, connection);
app.uuid = uuid;
app.manifestUrl = manifestUrl;
return app;
}
else {
throw new RuntimeException(ack.getReason());
}
});
}
/**
* Retrieves application's manifest and returns a wrapped application.
*
* @param manifestUrl
* The URL of app's manifest
* @param callback
* The callback that receives the wrapped {@link Application} object
* @see AsyncCallback
* @param listener
* The AckListener for the request
* @see AckListener
* @param connection
* The connection to openfin Runtime
* @throws DesktopException if application fails to be created
* @see DesktopException
*/
public static void createFromManifest(final String manifestUrl, final AsyncCallback callback,
final AckListener listener, final DesktopConnection connection) throws DesktopException {
createFromManifestAsync(manifestUrl, connection).thenAccept(app -> {
if (app != null && callback != null) {
callback.onSuccess(app);
}
});
}
/**
* Retrieves an list of wrapped fin.desktop.Windows for each of the
* application’s child windows
*
* @param callback
* The callback that receives a list of wrapped {@link Window}
* objects
* @see AsyncCallback
* @param listener
* AckListener for the request
* @see AckListener
*/
public void getChildWindows(final AsyncCallback> callback, final AckListener listener) {
AckListener mainCallback = null;
if (callback != null) {
mainCallback = new AckListener() {
@Override
public void onSuccess(Ack ack) {
try {
JSONArray data = (JSONArray) ack.getData();
List list = new ArrayList<>();
for (Object o : data) {
String winName = (String) o;
list.add(Window.wrap(uuid, winName, connection));
}
callback.onSuccess(list);
}
catch (Exception ex) {
logger.error("Error calling onSuccess", ex);
}
}
@Override
public void onError(Ack ack) {
DesktopUtils.errorAck(listener, ack);
}
};
}
connection.sendAction("get-child-windows", noParamPayload, listener, Application.class);
}
public CompletableFuture> getChildWindows() {
return connection.sendActionAsync("get-child-windows", noParamPayload, this).thenApplyAsync(ack->{
ArrayList windows = new ArrayList<>();
if (ack.isSuccessful()) {
JSONArray childWins = ack.getJsonObject().getJSONArray("data");
for (int i=0; i callback, final AckListener listener) {
AckListener mainCallback = null;
if (callback != null) {
mainCallback = new AckListener() {
@Override
public void onSuccess(Ack ack) {
try {
callback.onSuccess((JSONObject) ack.getData());
}
catch (Exception ex) {
logger.error("Error calling onSuccess", ex);
}
}
@Override
public void onError(Ack ack) {
DesktopUtils.errorAck(listener, ack);
}
};
}
connection.sendAction("get-info", noParamPayload, mainCallback, Application.class);
}
/**
* Retrieves UUID of the application that launches this application.
*
* @param callback
* The UUID of the parent application
* @see AsyncCallback
* @param listener
* AckListener for the request
* @see AckListener
*/
public void getParentUuid(final AsyncCallback callback, final AckListener listener) {
AckListener mainCallback = null;
if (callback != null) {
mainCallback = new AckListener() {
@Override
public void onSuccess(Ack ack) {
try {
callback.onSuccess((String) ack.getData());
}
catch (Exception ex) {
logger.error("Error calling onSuccess", ex);
}
}
@Override
public void onError(Ack ack) {
DesktopUtils.errorAck(listener, ack);
}
};
}
connection.sendAction("get-parent-application", noParamPayload, mainCallback, Application.class);
}
/**
* Retrieves information about the custom icon the application previously set in the system tray via setTrayIcon().
*
* @param callback
* tray icon info
* @see AsyncCallback
* @param listener
* AckListener for the request
* @see AckListener
*/
public void getTrayIconInfo(final AsyncCallback callback, final AckListener listener) {
AckListener mainCallback = null;
if (callback != null) {
mainCallback = new AckListener() {
@Override
public void onSuccess(Ack ack) {
try {
callback.onSuccess((JSONObject) ack.getData());
}
catch (Exception ex) {
logger.error("Error calling onSuccess", ex);
}
}
@Override
public void onError(Ack ack) {
DesktopUtils.errorAck(listener, ack);
}
};
}
connection.sendAction("get-tray-icon-info", noParamPayload, mainCallback, Application.class);
}
/**
* Determines if the application is currently running.
*
* @param callback
* if the application is currently running
* @see AsyncCallback
* @param listener
* AckListener for the request
* @see AckListener
*/
public void isRunning(final AsyncCallback callback, final AckListener listener) {
AckListener mainCallback = null;
if (callback != null) {
mainCallback = new AckListener() {
@Override
public void onSuccess(Ack ack) {
try {
callback.onSuccess((Boolean) ack.getData());
}
catch (Exception ex) {
logger.error("Error calling onSuccess", ex);
}
}
@Override
public void onError(Ack ack) {
DesktopUtils.errorAck(listener, ack);
}
};
}
connection.sendAction("is-application-running", noParamPayload, mainCallback, Application.class);
}
/**
* Ferries a custom payload to the RVM.
*
* @param customData
* the custom data
* @param listener
* AckListener for the request
* @see AckListener
* @deprecated use registerUser() instead.
*/
public void registerCustomData(JSONObject customData, final AckListener listener) {
logger.warn("Function is deprecated; use registerUser instead.");
}
/**
* Manually registers a user with the licensing service. The only data sent by this call is userName and appName.
*
* @param username username to be passed to the RVM.
* @param appName app name to be passed to the RVM.
* @param listener
* AckListener for the request
* @see AckListener
*/
public void registerUser(String username, String appName, final AckListener listener) {
JSONObject payload = new JSONObject();
payload.put("uuid", getUuid());
payload.put("userName", username);
payload.put("appName", appName);
connection.sendAction("register-user", payload, listener, this);
}
}