
com.openfin.desktop.platform.Platform 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.platform;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.ReentrantLock;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.openfin.desktop.Application;
import com.openfin.desktop.DesktopConnection;
import com.openfin.desktop.DesktopException;
import com.openfin.desktop.EventListener;
import com.openfin.desktop.Identity;
import com.openfin.desktop.Window;
import com.openfin.desktop.WindowOptions;
import com.openfin.desktop.channel.Channel;
import com.openfin.desktop.channel.ChannelClient;
/**
* Platform manages the life cycle of windows and views in the application.
* It enables taking snapshots of itself and applying them to restore a previous configuration as well as listen to platform events.
* @author Anthony
*
*/
public final class Platform {
private final static Logger logger = LoggerFactory.getLogger(Platform.class);
private Application application;
private ChannelClient channelClient;
private ReentrantLock channelClientLock;
private Platform(Application application) {
this.application = application;
this.channelClientLock = new ReentrantLock();
}
/**
* Creates and starts a Platform and returns a wrapped and running Platform instance. The wrapped Platform methods can be used to launch content into the platform. Promise will reject if the platform is already running.
* @param desktopConnection Connection object to the AppDesktop.
* @param platformOptions The required options object, also any Application option is also a valid platform option.
* @return new CompletionStage for the platform that was started.
*/
public static CompletionStage start(DesktopConnection desktopConnection, PlatformOptions platformOptions) {
CompletableFuture> platformApiReadyCallback = new CompletableFuture<>();
logger.debug("Platform options: {}", platformOptions.getJsonCopy());
return Application.createApplication(platformOptions, desktopConnection).thenApplyAsync(app -> {
Platform platform = new Platform(app);
platform.addEventListener("platform-api-ready", actionEvent -> {
platformApiReadyCallback.complete(null);
});
app.runAsync();
return platform;
}).thenCombineAsync(platformApiReadyCallback, (platform, nothing) -> {
return platform;
});
}
/**
* Retrieves platforms's manifest and returns a wrapped and running Platform. If there is a snapshot in the manifest, it will be launched into the platform.
* @param desktopConnection Connection object to the AppDesktop.
* @param manifestUrl The URL of platform's manifest.
* @return new CompletionStage for the platform that was started.
*/
public static CompletionStage startFromManifest(DesktopConnection desktopConnection, String manifestUrl) {
CompletableFuture> platformApiReadyCallback = new CompletableFuture<>();
return Application.createFromManifestAsync(manifestUrl, desktopConnection).thenApplyAsync(app -> {
Platform platform = new Platform(app);
platform.addEventListener("platform-api-ready", actionEvent -> {
platformApiReadyCallback.complete(null);
});
app.runAsync();
return platform;
}).thenCombineAsync(platformApiReadyCallback, (platform, nothing) -> {
return platform;
});
}
/**
* Get UUID of this platform object.
* @return UUID of this platform object.
*/
public String getUuid() {
return this.application.getUuid();
}
/**
* Add a platform event listener.
* @param type event name
* @param listener event listener to be added
*/
public void addEventListener(String type, EventListener listener) {
try {
this.application.addEventListener(type, listener, null);
}
catch (DesktopException e) {
e.printStackTrace();
}
}
/**
* Remove the platform event listener
* @param type event name
* @param listener event listener to be removed.
*/
public void removeEventListener(String type, EventListener listener) {
try {
this.application.removeEventListener(type, listener, null);
}
catch (DesktopException e) {
e.printStackTrace();
}
}
/**
* Adds a snapshot to a running Platform.
*
* Can optionally close existing windows and overwrite current platform state
* with that of a snapshot.
*
* @param requestedSnapshot Url or filepath to a snapshot JSON object.
* @param opts Optional parameters to specify whether existing windows should be closed.
* @return new CompletionStage for the platform that had the snapshot applied.
*/
public CompletionStage applySnapshot(String requestedSnapshot, PlatformSnapshotOptions opts) {
JSONObject payload = new JSONObject();
payload.put("manifestUrl", requestedSnapshot);
return this.application.getConnection().sendActionAsync("get-application-manifest", payload, this)
.thenApplyAsync(ack->{
if (ack.isSuccessful()) {
return new PlatformSnapshot(ack.getJsonObject().getJSONObject("data"));
}
else {
throw new RuntimeException("error retriving snapshot, reason: " + ack.getReason());
}
})
.thenCompose(snapshot->{
return this.applySnapshot(snapshot, opts);
});
}
/**
* Adds a snapshot to a running Platform.
*
* Can optionally close existing windows and overwrite current platform state
* with that of a snapshot.
*
* @param snapshot snapshot object.
* @param opts Optional parameters to specify whether existing windows should be closed.
* @return new CompletionStage for the platform that had the snapshot applied.
*/
public CompletionStage applySnapshot(PlatformSnapshot snapshot, PlatformSnapshotOptions opts) {
return this.getChannelClient().thenCompose(client -> {
JSONObject payload = new JSONObject();
payload.put("snapshot", snapshot.getJsonCopy());
if (opts != null) {
payload.put("options", opts.getJsonCopy());
}
return client.dispatchAsync("apply-snapshot", payload);
}).thenApplyAsync(ack -> {
if (ack.isSuccessful()) {
return this;
}
else {
throw new RuntimeException("error applying platform snapshot, reason: " + ack.getReason());
}
});
}
/**
* Closes a specified view in a target window.
* @param view the view to be closed.
* @return new CompletionStage when the command is delivered.
*/
public CompletionStage closeView(PlatformView view) {
return view.getCurrentWindow().thenAcceptBothAsync(this.getChannelClient(), (win,client)->{
JSONObject payload = new JSONObject();
payload.put("target", win.getIdentity().getJsonCopy());
payload.put("opts", view.getIdentity().getJsonCopy());
client.dispatchAsync("close-view", payload);
});
}
/**
* Creates a new view and attaches it to a specified target window.
* @param viewOpts View creation options
* @param target The window to which the new view is to be attached. If no target, create a view in a new window.
* @return new CompletionStage for the platform that had the view created.
*/
public CompletionStage createView(PlatformViewOptions viewOpts, Identity target) {
return this.getChannelClient().thenCompose(client->{
JSONObject payload = new JSONObject();
payload.put("target", target == null ? null : target.getJsonCopy());
payload.put("opts", viewOpts.getJsonCopy());
return client.dispatchAsync("create-view", payload);
}).thenApplyAsync(ack->{
if (ack.isSuccessful()) {
JSONObject result = ack.getJsonObject().getJSONObject("data").getJSONObject("result");
return new PlatformView(new Identity(result.getJSONObject("identity")), this.application.getConnection());
}
else {
throw new RuntimeException("error creating platform view, reason: " + ack.getReason());
}
});
}
/**
* Creates a new Window.
* @param winOpts Window creation options
* @return new CompletionStage for the platform that had the window created.
*/
public CompletionStage createWindow(WindowOptions winOpts) {
return this.getChannelClient().thenCompose(client->{
return client.dispatchAsync("create-view-container", winOpts.getJsonCopy());
}).thenApplyAsync(ack->{
if (ack.isSuccessful()) {
JSONObject data = ack.getJsonObject().getJSONObject("data");
return Window.wrap(data.getString("uuid"), data.getString("name"), this.application.getConnection());
}
else {
throw new RuntimeException("error creating platform window, reason: " + ack.getReason());
}
});
}
/**
* Returns a snapshot of the platform in its current state.
*
* Can be used to restore an application to a previous state.
*
* @return new CompletionStage for the platform snapshot.
*/
public CompletionStage getSnapshot() {
return this.getChannelClient().thenCompose(client -> {
return client.dispatchAsync("get-snapshot", null);
}).thenApplyAsync(ack->{
if (ack.isSuccessful()) {
return new PlatformSnapshot(ack.getJsonObject().getJSONObject("data").getJSONObject("result"));
}
else {
throw new RuntimeException("error getting platform snapshot, reason: " + ack.getReason());
}
});
}
/**
* Reparents a specified view in a new target window.
* @param viewIdentity View identity
* @param targetIdentity New owner window identity
* @return new CompletionStage for the reparented view.
*/
public CompletionStage reparentView(Identity viewIdentity, Identity targetIdentity) {
if (viewIdentity.getUuid() == null) {
viewIdentity.setUuid(this.getUuid());
}
PlatformView view = PlatformView.wrap(viewIdentity, this.application.getConnection());
return view.getOptions().thenComposeAsync(viewOpts -> {
return this.createView(viewOpts, targetIdentity);
});
}
/**
* Closes current platform, all its windows, and their views.
* @return new CompletionStage when the command is delivered.
*/
public CompletionStage quit() {
return this.getChannelClient().thenAccept(client->{
//can return ack actually......
client.dispatchAsync("quit", null);
});
}
/**
* Synchronously returns a Platform object that represents an existing platform.
* @param uuid UUID of the platform.
* @param desktopConnection Connection object to the AppDesktop.
* @return Platform object with given UUID.
*/
public static Platform wrap(String uuid, DesktopConnection desktopConnection) {
return new Platform(Application.wrap(uuid, desktopConnection));
}
public CompletionStage getChannelClient() {
return CompletableFuture.supplyAsync(()->{
try {
if (channelClient == null) {
channelClientLock.lock();
if (this.channelClient == null) {
Channel channel = new Channel("custom-frame-" + this.getUuid(), this.application.getConnection());
channelClient = channel.connectAsync().get();
logger.debug("platform channel client {} created", channel.getName());
}
this.channelClientLock.unlock();
}
return channelClient;
}
catch (InterruptedException | ExecutionException e) {
throw new RuntimeException("error creating channel client: " + this.getUuid(), e);
}
});
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy