diff --git a/.gitignore b/.gitignore index d8cfc34..1925acf 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ hs_err_pid* # IDEA *.iml .idea/** -target/** \ No newline at end of file +target/** +/target/ diff --git a/README.md b/README.md index b208789..a724e32 100644 --- a/README.md +++ b/README.md @@ -26,114 +26,139 @@ Source code for the example is located in /src/main/java/com/openfin/desktop/dem 1. Create connection object: - this.desktopConnection = new DesktopConnection("OpenFinDesktopDemo"); - - This code just creates an instance of DesktopConnection and it does not try to connect to runtime. +```java + this.desktopConnection = new DesktopConnection("OpenFinDesktopDemo"); +``` + This code just creates an instance of DesktopConnection and it does not try to connect to runtime. 2. Launch and connect to stable version of OpenFin runtime: - // create an instance of RuntimeConfiguration and configure Runtime by setting properties in RuntimeConfiguration - this.runtimeConfiguration = new RuntimeConfiguration(); - // launch and connect to OpenFin Runtime - desktopConnection.connect(this.runtimeConfiguration, listener, 10000); - +```java + // create an instance of RuntimeConfiguration and configure Runtime by setting properties in RuntimeConfiguration + this.runtimeConfiguration = new RuntimeConfiguration(); + // launch and connect to OpenFin Runtime + desktopConnection.connect(this.runtimeConfiguration, listener, 10000); +``` listener is an instance of DesktopStateListener which provides callback on status of connections to runtime. 3. Create new application when clicking on Create App: - Application app = new Application(options, desktopConnection, new AckListener() { - @Override - public void onSuccess(Ack ack) { - Application application = (Application) ack.getSource(); - application.run(); // run the app - } - @Override - public void onError(Ack ack) { - } - }); - + ```java + Application app = new Application(options, desktopConnection, new AckListener() { + @Override + public void onSuccess(Ack ack) { + Application application = (Application) ack.getSource(); + application.run(); // run the app + } + @Override + public void onError(Ack ack) { + } + }); +``` options is an instance of ApplicationOptions, which is populated from App Create dialog. AckListener interface provides callback for the operation. Once the application is created successfully, you can take actions on its window: 4. Change opacity: - WindowOptions options = new WindowOptions(); - options.setOpacity(newOpacityValue); - application.getWindow().updateOptions(options, null); +```java + WindowOptions options = new WindowOptions(); + options.setOpacity(newOpacityValue); + application.getWindow().updateOptions(options, null); +``` 5. Change Window size - application.getWindow().resizeBy(10, 10, "top-left"); - +```java + application.getWindow().resizeBy(10, 10, "top-left"); +``` 6. Publishes messages to a topic with InterApplicationBus - org.json.JSONObject message = createSomeJsonMessage(); - desktopConnection.getInterApplicationBus().publish("someTopic", message); +```java + org.json.JSONObject message = createSomeJsonMessage(); + desktopConnection.getInterApplicationBus().publish("someTopic", message); +``` 7. Subscribes to a topic with InterApplicationBus - desktopConnection.getInterApplicationBus().subscribe("*", "someTopic", new BusListener() { - public void onMessageReceived(String sourceUuid, String topic, Object payload) { - JSONObject message = (JSONObject) payload; - } - }); +```java + desktopConnection.getInterApplicationBus().subscribe("*", "someTopic", new BusListener() { + public void onMessageReceived(String sourceUuid, String topic, Object payload) { + JSONObject message = (JSONObject) payload; + } + }); +``` -## Run the example of docking Java Swing window with HTML5 application +## Run the example of embedding HTML5 application into a Java Swing window 1. Clone this repository -2. Go to release directory and start docking.bat - -3. Once the java app starts, click on "Launch OpenFin" button, which should start OpenFin Runtime and "Hello OpenFin" HTML5 demo app. The java app will wait and try to connect to OpenFin Runtime. - -4. After clicking "Dock to HTML5 app" button, you can move either window to see docking effect. - -5. Click "Undock from HTML5 app" to undock 2 windows - -## Source Code Review for docking windows - -Source code for the example is located in /src/main/java/com/openfin/desktop/demo/OpenFinDockingDemo.java. This example uses Snap&Dock library from https://github.com/openfin/java-snap-and-dock +2. Go to release directory and start embed.bat ( the default embedded url is https://openfin.co. Pass the url you wish to load if you want something different e.g. embed.bat https://www.mydomain.com ) -1. Create connection object: - - this.desktopConnection = new DesktopConnection("OpenFinDockingDemo", "localhost", port); +3. Once the java app starts, click on "Launch OpenFin" button, which should start OpenFin Runtime and embed the OpenFin application that points to https://openfin.co (or your custom url if you specified one) - This code just creates an instance and it does not try to connect to runtime. +4. Click "Shutdown OpenFin" button to close HTML5 application and the Java Swing window -2. Launch and connect to stable version of OpenFin runtime: +If there is a problem rendering the url please check your windows display settings to see ensure scaling is set to 100%. - desktopConnection.connectToVersion("stable", listener, 60); - - listener is an instance of DesktopStateListener which provides callback on status of connections to runtime. +## Source Code Review for embedded OpenFin application -3. Once Runtime is running, an instance of DockingManager is create with +Source code for the example is located in /src/main/java/com/openfin/desktop/demo/WindowEmbedDemo.java - this.dockingManager = new DockingManager(this.desktopConnection, javaParentAppUuid); +1. create a canvas and place it where the HTML5 application should be embedded. -4. Any OpenFin window can be registered with DockingManager with +```java + embedCanvas = new java.awt.Canvas(); + panel.add(embedCanvas, BorderLayout.CENTER); +``` - dockingManager.registerWindow(openFinWindow); +2. listen to the canvas resize event, and resize embedded HTML5 application accordingly. -5. Any Java window can be registered with DockingManager with +```java + embedCanvas.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent event) { + super.componentResized(event); + Dimension newSize = event.getComponent().getSize(); + try { + if (startupHtml5app != null) { + startupHtml5app.getWindow().embedComponentSizeChange((int)newSize.getWidth(), (int)newSize.getHeight()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); +``` - dockingManager.registerJavaWindow(javaWindowName, jFrame, AckListener); - -6. An application can receive dock and undock events from DockingManger with +3. launch and connect to OpenFin runtime - desktopConnection.getInterApplicationBus().subscribe("*", "window-docked", EventListener); - desktopConnection.getInterApplicationBus().subscribe("*", "window-undocked", EventListener); +```java + this.desktopConnection = new DesktopConnection(appUuid); + DesktopStateListener listener = new DesktopStateListener() {...}; + RuntimeConfiguration configuration = new RuntimeConfiguration(); + configuration.setRuntimeVersion(desktopVersion); + desktopConnection.connect(configuration, listener, 60); +``` -7. An application can request DockingManager to undock a window with: +4. create HTML5 application - JSONObject msg = new JSONObject(); - msg.put("applicationUuid", javaParentAppUuid); - msg.put("windowName", javaWindowName); - desktopConnection.getInterApplicationBus().publish("undock-window", msg); +```java + ApplicationOptions options = new ApplicationOptions(startupUuid, startupUuid, openfin_app_url); + WindowOptions mainWindowOptions = new WindowOptions(); + options.setMainWindowOptions(mainWindowOptions); + DemoUtils.runApplication(options, this.desktopConnection, new AckListener() {...}); +``` +5. embed HTML5 application into the canvas -Once the demo is running, Windows snap while being draggted close to other windows. Snapped windows dock on mounse release. +```java + startupHtml5app = Application.wrap(this.startupUuid, this.desktopConnection); + Window html5Wnd = startupHtml5app.getWindow(); + long parentHWndId = Native.getComponentID(this.embedCanvas); + html5Wnd.embedInto(parentHWndId, this.embedCanvas.getWidth(), this.embedCanvas.getHeight(), new AckListener() {...}); +``` ## More Info More information and API documentation can be found at https://openfin.co/java-api/ @@ -142,6 +167,16 @@ More information and API documentation can be found at https://openfin.co/java-a * This is a starter example and intended to demonstrate to app providers a sample of how to approach an implementation. There are potentially other ways to approach it and alternatives could be considered. * Its possible that the repo is not actively maintained. +## License +MIT + +The code in this repository is covered by the included license. + +However, if you run this code, it may call on the OpenFin RVM or OpenFin Runtime, which are covered by OpenFin’s Developer, Community, and Enterprise licenses. You can learn more about OpenFin licensing at the links listed below or just email us at support@openfin.co with questions. + +https://openfin.co/developer-agreement/
+https://openfin.co/licensing/ + ## Support Please enter an issue in the repo for any questions or problems.
Alternatively, please contact us at support@openfin.co diff --git a/RELEASENOTES-ADAPTER.md b/RELEASENOTES-ADAPTER.md index 0cffbc1..61be86c 100644 --- a/RELEASENOTES-ADAPTER.md +++ b/RELEASENOTES-ADAPTER.md @@ -1,8 +1,42 @@ +# Version 7.2.1 +## New Features +* Add support for FDC3 service + +# Version 7.1.3 +## New Features +* Add support for the new notification service +* DesktopStateListener.onError is called for exceptions from websocket + +# Version 7.1.2 +## Bug Fixes + +* Fixed an issue with dependencies + +# Version 7.1.1 + +## New Features +* Added Channel API +* Launch pre-installed RVM directly to improve performance +* Better naming of local app manifest file +* Requires JDK1.8+ + +## Bug Fixes + +* Fixed an issue with synchronization in InterApplicationBus.send -# Version 6.0.2.2-SNAPSHOT +# Version 7.0.2 + +## Bug Fixes +* Fixed an issue with setting timeout if RuntimeConfiguration.setRuntimePort is called. + +# Version 7.0.1 ## New Features * Improved thread safety with concurrent collection classes. +* Added error message to DesktopStateListener.onClose (breaking change) +* Added OpenFinRuntime.getRuntimeInfo +* Added OpenFinRuntime.getRvmInfo +* Improved thread safety with concurrent collection classes. ## Bug Fixes * Fixed an issue with passing arguments in System.launchExternalProcess @@ -31,7 +65,7 @@ * Add browser-style navigation to Window class * Add support for fallbackVersion of Runtime * Add support for non-persistent connections to Runtime -* Improve suppot for app assets +* Improve support for app assets ## Bug Fixes * Fixed an issue with loop of re-connecting to Runtime diff --git a/pom.xml b/pom.xml index 123b4ba..d5e3e4c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ co.openfin openfin-desktop-java-example - 6.0.1.2 + 9.0.1 jar openfin-desktop-java-example @@ -58,12 +58,7 @@ co.openfin openfin-desktop-java-adapter - 6.0.2.2-SNAPSHOT - - - co.openfin - openfin-snap-dock - 1.0.0.1 + 9.2.0 tablelayout diff --git a/release/app.asar b/release/app.asar new file mode 100644 index 0000000..2102789 Binary files /dev/null and b/release/app.asar differ diff --git a/release/busdemo.html b/release/busdemo.html new file mode 100644 index 0000000..342de28 --- /dev/null +++ b/release/busdemo.html @@ -0,0 +1,61 @@ + + + Inter Application Bus demo + + + + + + + +

Demo for Inter Application Bus

+
+
+
+ +
+
+ +
+ + + \ No newline at end of file diff --git a/release/channel.bat b/release/channel.bat new file mode 100644 index 0000000..492c1d2 --- /dev/null +++ b/release/channel.bat @@ -0,0 +1,9 @@ +@ECHO OFF +REM This program is an example of channel API. It can be run as channel provider or client +REM Channel name: ChannelExample +REM usage: channel.bat [ provider | client ] +set mode=%1 +IF "%~1" == "" set mode=provider +echo Channel type set to: %mode% +java -cp lib/hamcrest-core-1.3.jar;lib/hamcrest-library-1.1.jar;lib/jetty-client-9.4.18.v20190429.jar;lib/jetty-http-9.4.18.v20190429.jar;lib/jetty-io-9.4.18.v20190429.jar;lib/jetty-util-9.4.18.v20190429.jar;lib/jetty-xml-9.4.18.v20190429.jar;lib/jna-4.5.1.jar;lib/jna-platform-4.5.1.jar;lib/json-20160810.jar;lib/junit-4.11.jar;lib/mockito-core-1.9.5.jar;lib/objenesis-1.0.jar;lib/openfin-desktop-java-adapter-9.0.1-SNAPSHOT.jar;lib/openfin-desktop-java-example-9.0.1.jar;lib/slf4j-api-1.7.21.jar;lib/slf4j-jdk14-1.6.1.jar;lib/slf4j-log4j12-1.7.18.jar;lib/TableLayout-20050920.jar;lib/websocket-api-9.4.18.v20190429.jar;lib/websocket-client-9.4.18.v20190429.jar;lib/websocket-common-9.4.18.v20190429.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.demo.version=stable com.openfin.desktop.demo.ChannelExample %mode% + diff --git a/release/docking.bat b/release/docking.bat deleted file mode 100644 index 05bafb0..0000000 --- a/release/docking.bat +++ /dev/null @@ -1,6 +0,0 @@ -if "%1" == "" ( -set MainClass="com.openfin.desktop.demo.OpenFinDockingDemo" -) else ( -set MainClass="%1" -) -java -cp openfin-desktop-java-example-6.0.0.3.jar;openfin-desktop-java-adapter-6.0.0.3-SNAPSHOT.jar;openfin-snap-dock-1.0.0.1.jar;TableLayout-20050920.jar;jna-4.1.0.jar;jna-platform-4.1.0.jar;json-20140107.jar;slf4j-api-1.7.5.jar;slf4j-jdk14-1.6.1.jar;websocket-api-9.3.12.v20160915.jar;websocket-client-9.3.12.v20160915.jar;websocket-common-9.3.12.v20160915.jar;jetty-io-9.3.12.v20160915.jar;jetty-util-9.3.12.v20160915.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.demo.version=5.44.12.27 -Dcom.openfin.temp=%LocalAppData%\OpenFin\temp %MainClass% diff --git a/release/embed.bat b/release/embed.bat index 4597884..6533229 100644 --- a/release/embed.bat +++ b/release/embed.bat @@ -1 +1,5 @@ -java -cp openfin-desktop-java-example-6.0.1.2.jar;openfin-desktop-java-adapter-6.0.2.1-SNAPSHOT.jar;TableLayout-20050920.jar;jna-4.5.1.jar;jna-platform-4.5.1.jar;json-20140107.jar;slf4j-api-1.7.5.jar;slf4j-jdk14-1.6.1.jar;websocket-api-9.3.12.v20160915.jar;websocket-client-9.3.12.v20160915.jar;websocket-common-9.3.12.v20160915.jar;jetty-io-9.3.12.v20160915.jar;jetty-util-9.3.12.v20160915.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.demo.embed.URL=https://openfin.co -Dcom.openfin.demo.version=stable com.openfin.desktop.demo.WindowEmbedDemo +@ECHO OFF +set url=%1 +IF "%~1" == "" set url=https://openfin.co +echo Embedded url set to: %url% +java -cp lib/hamcrest-core-1.3.jar;lib/hamcrest-library-1.1.jar;lib/jetty-client-9.4.18.v20190429.jar;lib/jetty-http-9.4.18.v20190429.jar;lib/jetty-io-9.4.18.v20190429.jar;lib/jetty-util-9.4.18.v20190429.jar;lib/jetty-xml-9.4.18.v20190429.jar;lib/jna-4.5.1.jar;lib/jna-platform-4.5.1.jar;lib/json-20160810.jar;lib/junit-4.11.jar;lib/log4j-1.2.17.jar;lib/mockito-core-1.9.5.jar;lib/objenesis-1.0.jar;lib/openfin-desktop-java-adapter-9.0.1-SNAPSHOT.jar;lib/openfin-desktop-java-example-9.0.1.jar;lib/slf4j-api-1.7.21.jar;lib/slf4j-jdk14-1.6.1.jar;lib/slf4j-log4j12-1.7.18.jar;lib/TableLayout-20050920.jar;lib/websocket-api-9.4.18.v20190429.jar;lib/websocket-client-9.4.18.v20190429.jar;lib/websocket-common-9.4.18.v20190429.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.demo.embed.URL=%URL% -Dcom.openfin.demo.version=stable com.openfin.desktop.demo.WindowEmbedDemo diff --git a/release/embedTVB.bat b/release/embedTVB.bat deleted file mode 100644 index 9e1983a..0000000 --- a/release/embedTVB.bat +++ /dev/null @@ -1 +0,0 @@ -java -cp openfin-desktop-java-example-5.44.3.1.jar;openfin-desktop-java-adapter-5.44.3.1.jar;TableLayout-20050920.jar;jna-4.1.0.jar;jna-platform-4.1.0.jar;json-20140107.jar;slf4j-api-1.7.5.jar;slf4j-jdk14-1.6.1.jar -Dcom.openfin.demo.embedWaitTime=1000 com.openfin.desktop.demo.TVBEmbedDemo diff --git a/release/fxdemo.bat b/release/fxdemo.bat index 953b5ff..e37e8fd 100644 --- a/release/fxdemo.bat +++ b/release/fxdemo.bat @@ -1 +1 @@ -java -cp openfin-desktop-java-example-6.0.1.1.jar;openfin-desktop-java-adapter-6.0.1.2-SNAPSHOT.jar;TableLayout-20050920.jar;jna-4.1.0.jar;jna-platform-4.1.0.jar;json-20140107.jar;slf4j-api-1.7.5.jar;slf4j-jdk14-1.6.1.jar;websocket-api-9.3.12.v20160915.jar;websocket-client-9.3.12.v20160915.jar;websocket-common-9.3.12.v20160915.jar;jetty-io-9.3.12.v20160915.jar;jetty-util-9.3.12.v20160915.jar -Djava.util.logging.config.file=logging.properties com.openfin.desktop.demo.FxDemo +java -cp lib/hamcrest-core-1.3.jar;lib/hamcrest-library-1.1.jar;lib/jetty-client-9.4.18.v20190429.jar;lib/jetty-http-9.4.18.v20190429.jar;lib/jetty-io-9.4.18.v20190429.jar;lib/jetty-util-9.4.18.v20190429.jar;lib/jetty-xml-9.4.18.v20190429.jar;lib/jna-4.5.1.jar;lib/jna-platform-4.5.1.jar;lib/json-20160810.jar;lib/junit-4.11.jar;lib/log4j-1.2.17.jar;lib/mockito-core-1.9.5.jar;lib/objenesis-1.0.jar;lib/openfin-desktop-java-adapter-8.0.8.jar;lib/openfin-desktop-java-example-7.1.1-tests.jar;lib/openfin-desktop-java-example-7.1.1.jar;lib/openfin-snap-dock-1.0.0.1.jar;lib/slf4j-api-1.7.21.jar;lib/slf4j-jdk14-1.6.1.jar;lib/slf4j-log4j12-1.7.18.jar;lib/TableLayout-20050920.jar;lib/websocket-api-9.4.18.v20190429.jar;lib/websocket-client-9.4.18.v20190429.jar;lib/websocket-common-9.4.18.v20190429.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.demo.embed.URL=https://openfin.co com.openfin.desktop.demo.FxDemo diff --git a/release/jetty-io-9.3.12.v20160915.jar b/release/jetty-io-9.3.12.v20160915.jar deleted file mode 100644 index e83d5ca..0000000 Binary files a/release/jetty-io-9.3.12.v20160915.jar and /dev/null differ diff --git a/release/jetty-util-9.3.12.v20160915.jar b/release/jetty-util-9.3.12.v20160915.jar deleted file mode 100644 index 57366eb..0000000 Binary files a/release/jetty-util-9.3.12.v20160915.jar and /dev/null differ diff --git a/release/jna-4.1.0.jar b/release/jna-4.1.0.jar deleted file mode 100644 index 9bbb63d..0000000 Binary files a/release/jna-4.1.0.jar and /dev/null differ diff --git a/release/jna-4.2.2.jar b/release/jna-4.2.2.jar deleted file mode 100644 index a943670..0000000 Binary files a/release/jna-4.2.2.jar and /dev/null differ diff --git a/release/jna-platform-4.1.0.jar b/release/jna-platform-4.1.0.jar deleted file mode 100644 index b4ce438..0000000 Binary files a/release/jna-platform-4.1.0.jar and /dev/null differ diff --git a/release/jna-platform-4.2.2.jar b/release/jna-platform-4.2.2.jar deleted file mode 100644 index f3a9fd2..0000000 Binary files a/release/jna-platform-4.2.2.jar and /dev/null differ diff --git a/release/json-20140107.jar b/release/json-20140107.jar deleted file mode 100644 index 9037768..0000000 Binary files a/release/json-20140107.jar and /dev/null differ diff --git a/release/junit.bat b/release/junit.bat index 3d255c4..b79d81f 100644 --- a/release/junit.bat +++ b/release/junit.bat @@ -6,4 +6,4 @@ set RuntimeVersion="stable" set RuntimeVersion="%1" ) -java -cp openfin-desktop-java-example-6.0.1.2-tests.jar;openfin-desktop-java-adapter-6.0.2.2-SNAPSHOT.jar;TableLayout-20050920.jar;jna-4.5.1.jar;jna-platform-4.5.1.jar;json-20160810.jar;slf4j-api-1.7.5.jar;slf4j-jdk14-1.6.1.jar;junit-4.11.jar;hamcrest-core-1.3.jar;hamcrest-core-1.3.jar;hamcrest-library-1.1.jar;mockito-core-1.9.5.jar;websocket-api-9.3.12.v20160915.jar;websocket-client-9.3.12.v20160915.jar;websocket-common-9.3.12.v20160915.jar;jetty-io-9.3.12.v20160915.jar;jetty-util-9.3.12.v20160915.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.test.runtime.version=%RuntimeVersion% org.junit.runner.JUnitCore com.openfin.desktop.AllTests +java -cp lib/hamcrest-core-1.3.jar;lib/hamcrest-library-1.1.jar;lib/jetty-client-9.4.18.v20190429.jar;lib/jetty-http-9.4.18.v20190429.jar;lib/jetty-io-9.4.18.v20190429.jar;lib/jetty-util-9.4.18.v20190429.jar;lib/jetty-xml-9.4.18.v20190429.jar;lib/jna-4.5.1.jar;lib/jna-platform-4.5.1.jar;lib/json-20160810.jar;lib/junit-4.11.jar;lib/log4j-1.2.17.jar;lib/mockito-core-1.9.5.jar;lib/objenesis-1.0.jar;lib/openfin-desktop-java-adapter-9.2.0.jar;lib/openfin-desktop-java-example-9.2.1-tests.jar;lib/slf4j-api-1.7.21.jar;lib/slf4j-jdk14-1.6.1.jar;lib/slf4j-log4j12-1.7.18.jar;lib/TableLayout-20050920.jar;lib/websocket-api-9.4.18.v20190429.jar;lib/websocket-client-9.4.18.v20190429.jar;lib/websocket-common-9.4.18.v20190429.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.test.runtime.version=%RuntimeVersion% org.junit.runner.JUnitCore com.openfin.desktop.AllTests diff --git a/release/junit2.bat b/release/junit2.bat deleted file mode 100644 index bd01c9b..0000000 --- a/release/junit2.bat +++ /dev/null @@ -1 +0,0 @@ -java -cp openfin-desktop-java-example-5.44.2.4.jar;openfin-desktop-java-adapter-5.44.2.4.jar;TableLayout-20050920.jar;jna-4.1.0.jar;jna-platform-4.1.0.jar;json-20140107.jar;slf4j-api-1.7.5.jar;slf4j-jdk14-1.6.1.jar;junit-4.11.jar;hamcrest-core-1.3.jar;hamcrest-core-1.3.jar;hamcrest-library-1.1.jar;mockito-core-1.9.5.jar -Djava.util.logging.config.file=logging.properties org.junit.runner.JUnitCore com.openfin.desktop.demo.OpenFinWindowTest \ No newline at end of file diff --git a/release/launchExternal.html b/release/launchExternal.html new file mode 100644 index 0000000..18ba220 --- /dev/null +++ b/release/launchExternal.html @@ -0,0 +1,45 @@ + + + LaunchExternalProcess example + + + + + + +

LaunchExternalProcess example

+
+
+
+ Full Path + +
+ + + \ No newline at end of file diff --git a/release/layout.html b/release/layout.html new file mode 100644 index 0000000..eba023b --- /dev/null +++ b/release/layout.html @@ -0,0 +1,30 @@ + + + Openfin Layouts Example + + + + + + +

Openfin Layouts Library is included via script tag in this window. Accessible with global var OpenfinLayouts

+
+ +
+ \ No newline at end of file diff --git a/release/layoutclient1.json b/release/layoutclient1.json new file mode 100644 index 0000000..6b155ac --- /dev/null +++ b/release/layoutclient1.json @@ -0,0 +1,29 @@ +{ + "startup_app": { + "name": "Layout Client1", + "uuid": "Layout Client1", + "defaultTop": 100, + "defaultLeft": 100, + "defaultWidth": 420, + "defaultHeight": 420, + "url": "http://localhost:8888/busdemo.html", + "resizable": true, + "autoShow": true, + "saveWindowState": false, + "contextMenu": true + }, + "services": [{ + "manifestUrl": "https://cdn.openfin.co/services/openfin/layouts/1.0.0/app.json", + "name": "layouts", + "config": { + "features": { + "tab": true, + "dock": true + } + } + }], + "runtime": { + "arguments": "--v=1 --security-realm=java-test --enable-mesh ", + "version": "9.61.38.40" + } +} \ No newline at end of file diff --git a/release/layoutclient2.json b/release/layoutclient2.json new file mode 100644 index 0000000..0dae2b4 --- /dev/null +++ b/release/layoutclient2.json @@ -0,0 +1,29 @@ +{ + "startup_app": { + "name": "Layout Client2", + "uuid": "Layout Client2", + "defaultTop": 600, + "defaultLeft": 100, + "defaultWidth": 420, + "defaultHeight": 420, + "url": "http://localhost:8888/busdemo.html", + "resizable": true, + "autoShow": true, + "saveWindowState": false, + "contextMenu": true + }, + "services": [{ + "manifestUrl": "https://cdn.openfin.co/services/openfin/layouts/1.0.0/app.json", + "name": "layouts", + "config": { + "features": { + "tab": true, + "dock": true + } + } + }], + "runtime": { + "arguments": "--v=1 --security-realm=java-test --enable-mesh ", + "version": "9.61.38.40" + } +} \ No newline at end of file diff --git a/release/TableLayout-20050920.jar b/release/lib/TableLayout-20050920.jar similarity index 100% rename from release/TableLayout-20050920.jar rename to release/lib/TableLayout-20050920.jar diff --git a/release/hamcrest-core-1.3.jar b/release/lib/hamcrest-core-1.3.jar similarity index 100% rename from release/hamcrest-core-1.3.jar rename to release/lib/hamcrest-core-1.3.jar diff --git a/release/hamcrest-library-1.1.jar b/release/lib/hamcrest-library-1.1.jar similarity index 100% rename from release/hamcrest-library-1.1.jar rename to release/lib/hamcrest-library-1.1.jar diff --git a/release/lib/jetty-client-9.4.18.v20190429.jar b/release/lib/jetty-client-9.4.18.v20190429.jar new file mode 100644 index 0000000..b3868e1 Binary files /dev/null and b/release/lib/jetty-client-9.4.18.v20190429.jar differ diff --git a/release/lib/jetty-http-9.4.18.v20190429.jar b/release/lib/jetty-http-9.4.18.v20190429.jar new file mode 100644 index 0000000..e2e6282 Binary files /dev/null and b/release/lib/jetty-http-9.4.18.v20190429.jar differ diff --git a/release/lib/jetty-io-9.4.18.v20190429.jar b/release/lib/jetty-io-9.4.18.v20190429.jar new file mode 100644 index 0000000..56acc56 Binary files /dev/null and b/release/lib/jetty-io-9.4.18.v20190429.jar differ diff --git a/release/lib/jetty-util-9.4.18.v20190429.jar b/release/lib/jetty-util-9.4.18.v20190429.jar new file mode 100644 index 0000000..b80bfe8 Binary files /dev/null and b/release/lib/jetty-util-9.4.18.v20190429.jar differ diff --git a/release/lib/jetty-xml-9.4.18.v20190429.jar b/release/lib/jetty-xml-9.4.18.v20190429.jar new file mode 100644 index 0000000..51aa9a5 Binary files /dev/null and b/release/lib/jetty-xml-9.4.18.v20190429.jar differ diff --git a/release/jna-4.5.1.jar b/release/lib/jna-4.5.1.jar similarity index 100% rename from release/jna-4.5.1.jar rename to release/lib/jna-4.5.1.jar diff --git a/release/jna-platform-4.5.1.jar b/release/lib/jna-platform-4.5.1.jar similarity index 100% rename from release/jna-platform-4.5.1.jar rename to release/lib/jna-platform-4.5.1.jar diff --git a/release/json-20160810.jar b/release/lib/json-20160810.jar similarity index 100% rename from release/json-20160810.jar rename to release/lib/json-20160810.jar diff --git a/release/junit-4.11.jar b/release/lib/junit-4.11.jar similarity index 100% rename from release/junit-4.11.jar rename to release/lib/junit-4.11.jar diff --git a/release/log4j-1.2.17.jar b/release/lib/log4j-1.2.17.jar similarity index 100% rename from release/log4j-1.2.17.jar rename to release/lib/log4j-1.2.17.jar diff --git a/release/mockito-core-1.9.5.jar b/release/lib/mockito-core-1.9.5.jar similarity index 100% rename from release/mockito-core-1.9.5.jar rename to release/lib/mockito-core-1.9.5.jar diff --git a/release/lib/objenesis-1.0.jar b/release/lib/objenesis-1.0.jar new file mode 100644 index 0000000..7813d7b Binary files /dev/null and b/release/lib/objenesis-1.0.jar differ diff --git a/release/lib/openfin-desktop-java-adapter-9.2.0.jar b/release/lib/openfin-desktop-java-adapter-9.2.0.jar new file mode 100644 index 0000000..8e5fff9 Binary files /dev/null and b/release/lib/openfin-desktop-java-adapter-9.2.0.jar differ diff --git a/release/lib/openfin-desktop-java-example-9.0.1.jar b/release/lib/openfin-desktop-java-example-9.0.1.jar new file mode 100644 index 0000000..e4c2bae Binary files /dev/null and b/release/lib/openfin-desktop-java-example-9.0.1.jar differ diff --git a/release/lib/openfin-desktop-java-example-9.2.1-tests.jar b/release/lib/openfin-desktop-java-example-9.2.1-tests.jar new file mode 100644 index 0000000..2611d69 Binary files /dev/null and b/release/lib/openfin-desktop-java-example-9.2.1-tests.jar differ diff --git a/release/lib/openfin-desktop-java-example-9.2.2.jar b/release/lib/openfin-desktop-java-example-9.2.2.jar new file mode 100644 index 0000000..dea5aac Binary files /dev/null and b/release/lib/openfin-desktop-java-example-9.2.2.jar differ diff --git a/release/lib/slf4j-api-1.7.21.jar b/release/lib/slf4j-api-1.7.21.jar new file mode 100644 index 0000000..2a5c33e Binary files /dev/null and b/release/lib/slf4j-api-1.7.21.jar differ diff --git a/release/slf4j-jdk14-1.6.1.jar b/release/lib/slf4j-jdk14-1.6.1.jar similarity index 100% rename from release/slf4j-jdk14-1.6.1.jar rename to release/lib/slf4j-jdk14-1.6.1.jar diff --git a/release/slf4j-log4j12-1.7.18.jar b/release/lib/slf4j-log4j12-1.7.18.jar similarity index 100% rename from release/slf4j-log4j12-1.7.18.jar rename to release/lib/slf4j-log4j12-1.7.18.jar diff --git a/release/lib/websocket-api-9.4.18.v20190429.jar b/release/lib/websocket-api-9.4.18.v20190429.jar new file mode 100644 index 0000000..36b50c3 Binary files /dev/null and b/release/lib/websocket-api-9.4.18.v20190429.jar differ diff --git a/release/lib/websocket-client-9.4.18.v20190429.jar b/release/lib/websocket-client-9.4.18.v20190429.jar new file mode 100644 index 0000000..705d984 Binary files /dev/null and b/release/lib/websocket-client-9.4.18.v20190429.jar differ diff --git a/release/lib/websocket-common-9.4.18.v20190429.jar b/release/lib/websocket-common-9.4.18.v20190429.jar new file mode 100644 index 0000000..b72c12e Binary files /dev/null and b/release/lib/websocket-common-9.4.18.v20190429.jar differ diff --git a/release/manifest.bat b/release/manifest.bat new file mode 100644 index 0000000..4ba01e9 --- /dev/null +++ b/release/manifest.bat @@ -0,0 +1 @@ +java -cp lib/hamcrest-core-1.3.jar;lib/hamcrest-library-1.1.jar;lib/jetty-client-9.4.18.v20190429.jar;lib/jetty-http-9.4.18.v20190429.jar;lib/jetty-io-9.4.18.v20190429.jar;lib/jetty-util-9.4.18.v20190429.jar;lib/jetty-xml-9.4.18.v20190429.jar;lib/jna-4.5.1.jar;lib/jna-platform-4.5.1.jar;lib/json-20160810.jar;lib/junit-4.11.jar;lib/log4j-1.2.17.jar;lib/mockito-core-1.9.5.jar;lib/objenesis-1.0.jar;lib/openfin-desktop-java-adapter-8.0.8.jar;lib/openfin-desktop-java-example-7.1.1-tests.jar;lib/openfin-desktop-java-example-7.1.1.jar;lib/openfin-snap-dock-1.0.0.1.jar;lib/slf4j-api-1.7.21.jar;lib/slf4j-jdk14-1.6.1.jar;lib/slf4j-log4j12-1.7.18.jar;lib/TableLayout-20050920.jar;lib/websocket-api-9.4.18.v20190429.jar;lib/websocket-client-9.4.18.v20190429.jar;lib/websocket-common-9.4.18.v20190429.jar -Djava.util.logging.config.file=logging.properties com.openfin.desktop.demo.LaunchManifestDemo diff --git a/release/notification.bat b/release/notification.bat new file mode 100644 index 0000000..89db9a2 --- /dev/null +++ b/release/notification.bat @@ -0,0 +1,2 @@ +java -cp lib/hamcrest-core-1.3.jar;lib/hamcrest-library-1.1.jar;lib/jetty-client-9.4.18.v20190429.jar;lib/jetty-http-9.4.18.v20190429.jar;lib/jetty-io-9.4.18.v20190429.jar;lib/jetty-util-9.4.18.v20190429.jar;lib/jetty-xml-9.4.18.v20190429.jar;lib/jna-4.5.1.jar;lib/jna-platform-4.5.1.jar;lib/json-20160810.jar;lib/junit-4.11.jar;lib/mockito-core-1.9.5.jar;lib/objenesis-1.0.jar;lib/openfin-desktop-java-adapter-8.0.11-SNAPSHOT.jar;lib/openfin-desktop-java-example-7.1.1-tests.jar;lib/openfin-desktop-java-example-7.1.1.jar;lib/openfin-snap-dock-1.0.0.1.jar;lib/slf4j-api-1.7.21.jar;lib/slf4j-jdk14-1.6.1.jar;lib/slf4j-log4j12-1.7.18.jar;lib/TableLayout-20050920.jar;lib/websocket-api-9.4.18.v20190429.jar;lib/websocket-client-9.4.18.v20190429.jar;lib/websocket-common-9.4.18.v20190429.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.temp=%LocalAppData%\OpenFin\temp -Dcom.openfin.demo.version=stable com.openfin.desktop.demo.NotificationServiceDemo + diff --git a/release/openfin-desktop-java-adapter-5.44.2.3.jar b/release/openfin-desktop-java-adapter-5.44.2.3.jar deleted file mode 100644 index 074065a..0000000 Binary files a/release/openfin-desktop-java-adapter-5.44.2.3.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-5.44.2.4.jar b/release/openfin-desktop-java-adapter-5.44.2.4.jar deleted file mode 100644 index 399f780..0000000 Binary files a/release/openfin-desktop-java-adapter-5.44.2.4.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-5.44.2.5.jar b/release/openfin-desktop-java-adapter-5.44.2.5.jar deleted file mode 100644 index 2e570d7..0000000 Binary files a/release/openfin-desktop-java-adapter-5.44.2.5.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-5.44.3.1.jar b/release/openfin-desktop-java-adapter-5.44.3.1.jar deleted file mode 100644 index ac62295..0000000 Binary files a/release/openfin-desktop-java-adapter-5.44.3.1.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-5.44.3.2.jar b/release/openfin-desktop-java-adapter-5.44.3.2.jar deleted file mode 100644 index 492f963..0000000 Binary files a/release/openfin-desktop-java-adapter-5.44.3.2.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-5.44.3.3.jar b/release/openfin-desktop-java-adapter-5.44.3.3.jar deleted file mode 100644 index e9b3a09..0000000 Binary files a/release/openfin-desktop-java-adapter-5.44.3.3.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-6.0.0.1-SNAPSHOT.jar b/release/openfin-desktop-java-adapter-6.0.0.1-SNAPSHOT.jar deleted file mode 100644 index 98fef84..0000000 Binary files a/release/openfin-desktop-java-adapter-6.0.0.1-SNAPSHOT.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-6.0.0.1.jar b/release/openfin-desktop-java-adapter-6.0.0.1.jar deleted file mode 100644 index 990d0dc..0000000 Binary files a/release/openfin-desktop-java-adapter-6.0.0.1.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-6.0.0.2.jar b/release/openfin-desktop-java-adapter-6.0.0.2.jar deleted file mode 100644 index 34c1b03..0000000 Binary files a/release/openfin-desktop-java-adapter-6.0.0.2.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-6.0.0.3-SNAPSHOT.jar b/release/openfin-desktop-java-adapter-6.0.0.3-SNAPSHOT.jar deleted file mode 100644 index 111e8b6..0000000 Binary files a/release/openfin-desktop-java-adapter-6.0.0.3-SNAPSHOT.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-6.0.1.0.jar b/release/openfin-desktop-java-adapter-6.0.1.0.jar deleted file mode 100644 index df4120a..0000000 Binary files a/release/openfin-desktop-java-adapter-6.0.1.0.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-6.0.1.1-SNAPSHOT.jar b/release/openfin-desktop-java-adapter-6.0.1.1-SNAPSHOT.jar deleted file mode 100644 index d59fd2c..0000000 Binary files a/release/openfin-desktop-java-adapter-6.0.1.1-SNAPSHOT.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-6.0.1.2-SNAPSHOT.jar b/release/openfin-desktop-java-adapter-6.0.1.2-SNAPSHOT.jar deleted file mode 100644 index dc6d562..0000000 Binary files a/release/openfin-desktop-java-adapter-6.0.1.2-SNAPSHOT.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-6.0.1.2.jar b/release/openfin-desktop-java-adapter-6.0.1.2.jar deleted file mode 100644 index 6f2b7e8..0000000 Binary files a/release/openfin-desktop-java-adapter-6.0.1.2.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-6.0.1.3-SNAPSHOT.jar b/release/openfin-desktop-java-adapter-6.0.1.3-SNAPSHOT.jar deleted file mode 100644 index 025fa91..0000000 Binary files a/release/openfin-desktop-java-adapter-6.0.1.3-SNAPSHOT.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-6.0.2.1-SNAPSHOT.jar b/release/openfin-desktop-java-adapter-6.0.2.1-SNAPSHOT.jar deleted file mode 100644 index ae28b0d..0000000 Binary files a/release/openfin-desktop-java-adapter-6.0.2.1-SNAPSHOT.jar and /dev/null differ diff --git a/release/openfin-desktop-java-adapter-6.0.2.2-SNAPSHOT.jar b/release/openfin-desktop-java-adapter-6.0.2.2-SNAPSHOT.jar deleted file mode 100644 index 9478eca..0000000 Binary files a/release/openfin-desktop-java-adapter-6.0.2.2-SNAPSHOT.jar and /dev/null differ diff --git a/release/openfin-desktop-java-example-5.44.2.3-tests.jar b/release/openfin-desktop-java-example-5.44.2.3-tests.jar deleted file mode 100644 index 468c459..0000000 Binary files a/release/openfin-desktop-java-example-5.44.2.3-tests.jar and /dev/null differ diff --git a/release/openfin-desktop-java-example-5.44.2.3.jar b/release/openfin-desktop-java-example-5.44.2.3.jar deleted file mode 100644 index 0ec76c5..0000000 Binary files a/release/openfin-desktop-java-example-5.44.2.3.jar and /dev/null differ diff --git a/release/openfin-desktop-java-example-5.44.2.4-tests.jar b/release/openfin-desktop-java-example-5.44.2.4-tests.jar deleted file mode 100644 index 2c14ef6..0000000 Binary files a/release/openfin-desktop-java-example-5.44.2.4-tests.jar and /dev/null differ diff --git a/release/openfin-desktop-java-example-5.44.2.4.jar b/release/openfin-desktop-java-example-5.44.2.4.jar deleted file mode 100644 index 19cfa05..0000000 Binary files a/release/openfin-desktop-java-example-5.44.2.4.jar and /dev/null differ diff --git a/release/openfin-desktop-java-example-5.44.3.1-tests.jar b/release/openfin-desktop-java-example-5.44.3.1-tests.jar deleted file mode 100644 index 6f9988f..0000000 Binary files a/release/openfin-desktop-java-example-5.44.3.1-tests.jar and /dev/null differ diff --git a/release/openfin-desktop-java-example-5.44.3.1.jar b/release/openfin-desktop-java-example-5.44.3.1.jar deleted file mode 100644 index 590d3ef..0000000 Binary files a/release/openfin-desktop-java-example-5.44.3.1.jar and /dev/null differ diff --git a/release/openfin-desktop-java-example-6.0.0.1-tests.jar b/release/openfin-desktop-java-example-6.0.0.1-tests.jar deleted file mode 100644 index 2925bc9..0000000 Binary files a/release/openfin-desktop-java-example-6.0.0.1-tests.jar and /dev/null differ diff --git a/release/openfin-desktop-java-example-6.0.0.1.jar b/release/openfin-desktop-java-example-6.0.0.1.jar deleted file mode 100644 index 885f622..0000000 Binary files a/release/openfin-desktop-java-example-6.0.0.1.jar and /dev/null differ diff --git a/release/openfin-desktop-java-example-6.0.0.3-tests.jar b/release/openfin-desktop-java-example-6.0.0.3-tests.jar deleted file mode 100644 index fcfe95f..0000000 Binary files a/release/openfin-desktop-java-example-6.0.0.3-tests.jar and /dev/null differ diff --git a/release/openfin-desktop-java-example-6.0.0.3.jar b/release/openfin-desktop-java-example-6.0.0.3.jar deleted file mode 100644 index aff7827..0000000 Binary files a/release/openfin-desktop-java-example-6.0.0.3.jar and /dev/null differ diff --git a/release/openfin-desktop-java-example-6.0.1.1-tests.jar b/release/openfin-desktop-java-example-6.0.1.1-tests.jar deleted file mode 100644 index b8c87cf..0000000 Binary files a/release/openfin-desktop-java-example-6.0.1.1-tests.jar and /dev/null differ diff --git a/release/openfin-desktop-java-example-6.0.1.1.jar b/release/openfin-desktop-java-example-6.0.1.1.jar deleted file mode 100644 index e23f633..0000000 Binary files a/release/openfin-desktop-java-example-6.0.1.1.jar and /dev/null differ diff --git a/release/openfin-desktop-java-example-6.0.1.2-tests.jar b/release/openfin-desktop-java-example-6.0.1.2-tests.jar deleted file mode 100644 index e84f156..0000000 Binary files a/release/openfin-desktop-java-example-6.0.1.2-tests.jar and /dev/null differ diff --git a/release/openfin-desktop-java-example-6.0.1.2.jar b/release/openfin-desktop-java-example-6.0.1.2.jar deleted file mode 100644 index 8d78383..0000000 Binary files a/release/openfin-desktop-java-example-6.0.1.2.jar and /dev/null differ diff --git a/release/openfin-snap-dock-1.0.0.0.jar b/release/openfin-snap-dock-1.0.0.0.jar deleted file mode 100644 index e983c88..0000000 Binary files a/release/openfin-snap-dock-1.0.0.0.jar and /dev/null differ diff --git a/release/openfin-snap-dock-1.0.0.1.jar b/release/openfin-snap-dock-1.0.0.1.jar deleted file mode 100644 index 4f8e8ae..0000000 Binary files a/release/openfin-snap-dock-1.0.0.1.jar and /dev/null differ diff --git a/release/profile.bat b/release/profile.bat new file mode 100644 index 0000000..9e1cf11 --- /dev/null +++ b/release/profile.bat @@ -0,0 +1,2 @@ +java -Xmx100m -Xms100m -cp lib/hamcrest-core-1.3.jar;lib/hamcrest-library-1.1.jar;lib/jetty-client-9.4.18.v20190429.jar;lib/jetty-http-9.4.18.v20190429.jar;lib/jetty-io-9.4.18.v20190429.jar;lib/jetty-util-9.4.18.v20190429.jar;lib/jetty-xml-9.4.18.v20190429.jar;lib/jna-4.5.1.jar;lib/jna-platform-4.5.1.jar;lib/json-20160810.jar;lib/junit-4.11.jar;lib/mockito-core-1.9.5.jar;lib/objenesis-1.0.jar;lib/openfin-desktop-java-adapter-9.2.3-SNAPSHOT.jar;lib/openfin-desktop-java-example-9.0.1-tests.jar;lib/openfin-desktop-java-example-9.2.2.jar;lib/slf4j-api-1.7.21.jar;lib/slf4j-jdk14-1.6.1.jar;lib/slf4j-log4j12-1.7.18.jar;lib/TableLayout-20050920.jar;lib/websocket-api-9.4.18.v20190429.jar;lib/websocket-client-9.4.18.v20190429.jar;lib/websocket-common-9.4.18.v20190429.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.temp=%LocalAppData%\OpenFin\temp -Dcom.openfin.demo.version=stable -Dcom.openfin.demo.licenseKey=123456 com.openfin.desktop.demo.MemoryProfile + diff --git a/release/publisher.bat b/release/publisher.bat index a783a3f..abc104f 100644 --- a/release/publisher.bat +++ b/release/publisher.bat @@ -1 +1 @@ -java -cp openfin-desktop-java-example-6.0.0.1.jar;openfin-desktop-java-adapter-6.0.0.1-SNAPSHOT.jar;TableLayout-20050920.jar;jna-4.1.0.jar;jna-platform-4.1.0.jar;json-20140107.jar;slf4j-api-1.7.5.jar;slf4j-jdk14-1.6.1.jar;junit-4.11.jar;hamcrest-core-1.3.jar;hamcrest-core-1.3.jar;hamcrest-library-1.1.jar;mockito-core-1.9.5.jar;websocket-api-9.3.12.v20160915.jar;websocket-client-9.3.12.v20160915.jar;websocket-common-9.3.12.v20160915.jar;jetty-io-9.3.12.v20160915.jar;jetty-util-9.3.12.v20160915.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.demo.runtime.version=canary -Dcom.openfin.demo.publish.frequency=2000 -Dcom.openfin.demo.publish.size=2048 com.openfin.desktop.demo.PubSubTest publisher \ No newline at end of file +java -cp lib/hamcrest-core-1.3.jar;lib/hamcrest-library-1.1.jar;lib/jetty-client-9.4.18.v20190429.jar;lib/jetty-http-9.4.18.v20190429.jar;lib/jetty-io-9.4.18.v20190429.jar;lib/jetty-util-9.4.18.v20190429.jar;lib/jetty-xml-9.4.18.v20190429.jar;lib/jna-4.5.1.jar;lib/jna-platform-4.5.1.jar;lib/json-20160810.jar;lib/junit-4.11.jar;lib/mockito-core-1.9.5.jar;lib/objenesis-1.0.jar;lib/openfin-desktop-java-adapter-8.0.8.jar;lib/openfin-desktop-java-example-7.1.1-tests.jar;lib/openfin-desktop-java-example-7.1.1.jar;lib/openfin-snap-dock-1.0.0.1.jar;lib/slf4j-api-1.7.21.jar;lib/slf4j-jdk14-1.6.1.jar;lib/slf4j-log4j12-1.7.18.jar;lib/TableLayout-20050920.jar;lib/websocket-api-9.4.18.v20190429.jar;lib/websocket-client-9.4.18.v20190429.jar;lib/websocket-common-9.4.18.v20190429.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.demo.runtime.version=canary -Dcom.openfin.demo.publish.frequency=2000 -Dcom.openfin.demo.publish.size=2048 com.openfin.desktop.demo.PubSubTest publisher diff --git a/release/run.bat b/release/run.bat index 786792b..adb4460 100644 --- a/release/run.bat +++ b/release/run.bat @@ -1,2 +1,2 @@ -java -cp openfin-desktop-java-example-6.0.1.2.jar;openfin-desktop-java-adapter-6.0.2.1-SNAPSHOT.jar;TableLayout-20050920.jar;jna-4.5.1.jar;jna-platform-4.5.1.jar;json-20140107.jar;slf4j-api-1.7.5.jar;slf4j-jdk14-1.6.1.jar;websocket-api-9.3.12.v20160915.jar;websocket-client-9.3.12.v20160915.jar;websocket-common-9.3.12.v20160915.jar;jetty-io-9.3.12.v20160915.jar;jetty-util-9.3.12.v20160915.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.temp=%LocalAppData%\OpenFin\temp -Dcom.openfin.demo.version=stable com.openfin.desktop.demo.OpenFinDesktopDemo +java -cp lib/hamcrest-core-1.3.jar;lib/hamcrest-library-1.1.jar;lib/jetty-client-9.4.18.v20190429.jar;lib/jetty-http-9.4.18.v20190429.jar;lib/jetty-io-9.4.18.v20190429.jar;lib/jetty-util-9.4.18.v20190429.jar;lib/jetty-xml-9.4.18.v20190429.jar;lib/jna-4.5.1.jar;lib/jna-platform-4.5.1.jar;lib/json-20160810.jar;lib/junit-4.11.jar;lib/mockito-core-1.9.5.jar;lib/objenesis-1.0.jar;lib/openfin-desktop-java-adapter-9.0.1-SNAPSHOT.jar;lib/openfin-desktop-java-example-9.0.1-tests.jar;lib/openfin-desktop-java-example-9.0.1.jar;lib/slf4j-api-1.7.21.jar;lib/slf4j-jdk14-1.6.1.jar;lib/slf4j-log4j12-1.7.18.jar;lib/TableLayout-20050920.jar;lib/websocket-api-9.4.18.v20190429.jar;lib/websocket-client-9.4.18.v20190429.jar;lib/websocket-common-9.4.18.v20190429.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.temp=%LocalAppData%\OpenFin\temp -Dcom.openfin.demo.version=stable -Dcom.openfin.demo.licenseKey=123456 com.openfin.desktop.demo.OpenFinDesktopDemo diff --git a/release/run.sh b/release/run.sh index 592a904..624679c 100755 --- a/release/run.sh +++ b/release/run.sh @@ -13,5 +13,5 @@ #fi #node cli.js -l -c $configFile -java -cp openfin-desktop-java-example-6.0.1.2.jar:openfin-desktop-java-adapter-6.0.1.3-SNAPSHOT.jar:TableLayout-20050920.jar:jna-4.2.2.jar:jna-platform-4.2.2.jar:json-20140107.jar:slf4j-api-1.7.5.jar:slf4j-jdk14-1.6.1.jar:websocket-api-9.3.12.v20160915.jar:websocket-client-9.3.12.v20160915.jar:websocket-common-9.3.12.v20160915.jar:jetty-io-9.3.12.v20160915.jar:jetty-util-9.3.12.v20160915.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.installer.location=/path-to-openfin-cli/start.sh -Dcom.openfin.demo.version=8.56.27.22 com.openfin.desktop.demo.OpenFinDesktopDemo +java -cp openfin-desktop-java-example-7.1.1.jar;openfin-desktop-java-adapter-7.1.2.jar:TableLayout-20050920.jar:jna-4.2.2.jar:jna-platform-4.2.2.jar:json-20140107.jar:slf4j-api-1.7.5.jar:slf4j-jdk14-1.6.1.jar:websocket-api-9.3.12.v20160915.jar:websocket-client-9.3.12.v20160915.jar:websocket-common-9.3.12.v20160915.jar:jetty-io-9.3.12.v20160915.jar:jetty-util-9.3.12.v20160915.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.installer.location=/path-to-openfin-cli/start.sh -Dcom.openfin.demo.version=8.56.27.22 com.openfin.desktop.demo.OpenFinDesktopDemo diff --git a/release/slf4j-api-1.7.5.jar b/release/slf4j-api-1.7.5.jar deleted file mode 100644 index 8f004d3..0000000 Binary files a/release/slf4j-api-1.7.5.jar and /dev/null differ diff --git a/release/stockflux.json b/release/stockflux.json new file mode 100644 index 0000000..4043700 --- /dev/null +++ b/release/stockflux.json @@ -0,0 +1,30 @@ +{ + "startup_app": { + "name": "StockFlux", + "uuid": "StockFlux", + "maxWidth": 0, + "maxHeight": 0, + "defaultWidth": 0, + "defaultHeight": 0, + "frame": false, + "showTaskbarIcon": false, + "url": "http://scottlogic.github.io/StockFlux/master/parent.html", + "autoShow": false, + "applicationIcon": "http://scottlogic.github.io/StockFlux/master/favicon.ico" + }, + "services": [{ + "manifestUrl": "https://cdn.openfin.co/services/openfin/layouts/1.0.0/app.json", + "name": "layouts", + "config": { + "features": { + "tab": false, + "dock": true + } + } + }], + "runtime": { + "arguments": "--enable-aggressive-domstorage-flushing", + "version": "9.61.38.40" + }, + "splashScreenImage": "http://scottlogic.github.io/StockFlux/master/splashscreen.png" +} \ No newline at end of file diff --git a/release/subscriber.bat b/release/subscriber.bat index bd776ec..b93d3ab 100644 --- a/release/subscriber.bat +++ b/release/subscriber.bat @@ -1 +1 @@ -java -cp openfin-desktop-java-example-6.0.0.1.jar;openfin-desktop-java-adapter-6.0.0.1-SNAPSHOT.jar;TableLayout-20050920.jar;jna-4.1.0.jar;jna-platform-4.1.0.jar;json-20140107.jar;slf4j-api-1.7.5.jar;slf4j-jdk14-1.6.1.jar;junit-4.11.jar;hamcrest-core-1.3.jar;hamcrest-core-1.3.jar;hamcrest-library-1.1.jar;mockito-core-1.9.5.jar;websocket-api-9.3.12.v20160915.jar;websocket-client-9.3.12.v20160915.jar;websocket-common-9.3.12.v20160915.jar;jetty-io-9.3.12.v20160915.jar;jetty-util-9.3.12.v20160915.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.demo.runtime.version=canary com.openfin.desktop.demo.PubSubTest subscriber \ No newline at end of file +java -cp lib/hamcrest-core-1.3.jar;lib/hamcrest-library-1.1.jar;lib/jetty-client-9.4.18.v20190429.jar;lib/jetty-http-9.4.18.v20190429.jar;lib/jetty-io-9.4.18.v20190429.jar;lib/jetty-util-9.4.18.v20190429.jar;lib/jetty-xml-9.4.18.v20190429.jar;lib/jna-4.5.1.jar;lib/jna-platform-4.5.1.jar;lib/json-20160810.jar;lib/junit-4.11.jar;lib/mockito-core-1.9.5.jar;lib/objenesis-1.0.jar;lib/openfin-desktop-java-adapter-8.0.8.jar;lib/openfin-desktop-java-example-7.1.1-tests.jar;lib/openfin-desktop-java-example-7.1.1.jar;lib/openfin-snap-dock-1.0.0.1.jar;lib/slf4j-api-1.7.21.jar;lib/slf4j-jdk14-1.6.1.jar;lib/slf4j-log4j12-1.7.18.jar;lib/TableLayout-20050920.jar;lib/websocket-api-9.4.18.v20190429.jar;lib/websocket-client-9.4.18.v20190429.jar;lib/websocket-common-9.4.18.v20190429.jar -Djava.util.logging.config.file=logging.properties -Dcom.openfin.demo.runtime.version=canary com.openfin.desktop.demo.PubSubTest subscriber diff --git a/release/testWindowPosition.bat b/release/testWindowPosition.bat index 65cdfc7..9060f08 100644 --- a/release/testWindowPosition.bat +++ b/release/testWindowPosition.bat @@ -1 +1 @@ -java -cp openfin-desktop-java-example-5.44.2.3-tests.jar;openfin-desktop-java-adapter-5.44.2.3.jar;TableLayout-20050920.jar;jna-4.1.0.jar;jna-platform-4.1.0.jar;json-20140107.jar;slf4j-api-1.7.5.jar;slf4j-jdk14-1.6.1.jar;junit-4.11.jar;hamcrest-core-1.3.jar;hamcrest-core-1.3.jar;hamcrest-library-1.1.jar;mockito-core-1.9.5.jar -Djava.util.logging.config.file=logging.properties org.junit.runner.JUnitCore com.openfin.desktop.WindowPositionTest +java -cp lib/hamcrest-core-1.3.jar;lib/hamcrest-library-1.1.jar;lib/jetty-client-9.4.18.v20190429.jar;lib/jetty-http-9.4.18.v20190429.jar;lib/jetty-io-9.4.18.v20190429.jar;lib/jetty-util-9.4.18.v20190429.jar;lib/jetty-xml-9.4.18.v20190429.jar;lib/jna-4.5.1.jar;lib/jna-platform-4.5.1.jar;lib/json-20160810.jar;lib/junit-4.11.jar;lib/log4j-1.2.17.jar;lib/mockito-core-1.9.5.jar;lib/objenesis-1.0.jar;lib/openfin-desktop-java-adapter-8.0.8.jar;lib/openfin-desktop-java-example-7.1.1-tests.jar;lib/openfin-desktop-java-example-7.1.1.jar;lib/openfin-snap-dock-1.0.0.1.jar;lib/slf4j-api-1.7.21.jar;lib/slf4j-jdk14-1.6.1.jar;lib/slf4j-log4j12-1.7.18.jar;lib/TableLayout-20050920.jar;lib/websocket-api-9.4.18.v20190429.jar;lib/websocket-client-9.4.18.v20190429.jar;lib/websocket-common-9.4.18.v20190429.jar -Djava.util.logging.config.file=logging.properties org.junit.runner.JUnitCore com.openfin.desktop.WindowPositionTest diff --git a/release/watchlist.json b/release/watchlist.json new file mode 100644 index 0000000..7789c84 --- /dev/null +++ b/release/watchlist.json @@ -0,0 +1,33 @@ +{ + "devtools_port": 9090, + "startup_app": { + "name": "GiantMachinesWatchlist", + "url": "http://watchlist.giantmachines.com", + "uuid": "GiantMachinesWatchlist", + "applicationIcon": "http://watchlist.giantmachines.com/watchlist-icon.png", + "autoShow": true, + "frame": false, + "defaultHeight": 600, + "defaultWidth": 450, + "defaultTop": 50, + "defaultLeft": 50, + "resizable": false, + "maximizable": false + }, + "runtime": { + "arguments": "--v=1", + "version": "9.61.38.40", + "forceLatest": true + }, + "services": [{ + "manifestUrl": "https://cdn.openfin.co/services/openfin/layouts/1.0.0/app.json", + "name": "layouts", + "config": { + "features": { + "tab": false, + "dock": true + } + } + }], + "splashScreenImage": "http://watchlist.giantmachines.com/watchlist-splash.png" +} \ No newline at end of file diff --git a/release/websocket-api-9.3.12.v20160915.jar b/release/websocket-api-9.3.12.v20160915.jar deleted file mode 100644 index 2d0e662..0000000 Binary files a/release/websocket-api-9.3.12.v20160915.jar and /dev/null differ diff --git a/release/websocket-client-9.3.12.v20160915.jar b/release/websocket-client-9.3.12.v20160915.jar deleted file mode 100644 index db68054..0000000 Binary files a/release/websocket-client-9.3.12.v20160915.jar and /dev/null differ diff --git a/release/websocket-common-9.3.12.v20160915.jar b/release/websocket-common-9.3.12.v20160915.jar deleted file mode 100644 index 2e9e3cd..0000000 Binary files a/release/websocket-common-9.3.12.v20160915.jar and /dev/null differ diff --git a/src/main/java/com/openfin/desktop/demo/ChannelExample.java b/src/main/java/com/openfin/desktop/demo/ChannelExample.java new file mode 100644 index 0000000..0eba6b6 --- /dev/null +++ b/src/main/java/com/openfin/desktop/demo/ChannelExample.java @@ -0,0 +1,276 @@ +package com.openfin.desktop.demo; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; + +import com.openfin.desktop.channel.*; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.openfin.desktop.Ack; +import com.openfin.desktop.AckListener; +import com.openfin.desktop.AsyncCallback; +import com.openfin.desktop.DesktopConnection; +import com.openfin.desktop.DesktopException; +import com.openfin.desktop.DesktopStateListener; +import com.openfin.desktop.RuntimeConfiguration; + +public class ChannelExample implements DesktopStateListener { + + private static Logger logger = LoggerFactory.getLogger(ChannelExample.class.getName()); + private static CountDownLatch latch = new CountDownLatch(1); + private static String CHANNEL_NAME="ChannelExample"; + + private DesktopConnection desktopConnection; + + private static String channelType; // client or provider, if not set, both + + public ChannelExample() { + try { + StringBuilder sb = new StringBuilder("ChannelExample"); + if (channelType != null) { + sb.append(channelType); + } + desktopConnection = new DesktopConnection(sb.toString()); + String desktopVersion = java.lang.System.getProperty("com.openfin.demo.runtime.version", "stable"); + RuntimeConfiguration configuration = new RuntimeConfiguration(); + configuration.setRuntimeVersion(desktopVersion); + desktopConnection.connect(configuration, this, 60); + } + catch (Exception ex) { + logger.error("Error launching Runtime", ex); + } + } + + /** + * Create a provider that supports "getValue", "increment" and "incrementBy n" actions + */ + public void createChannelProvider() { + + // Create the channel provider. + desktopConnection.getChannel(CHANNEL_NAME).createAsync().thenAccept(provider -> { + provider.addProviderListener(new ChannelProviderListener() { + + // Create the onChannelConnect event handler. + @Override + public void onClientConnect(ChannelClientConnectEvent connectionEvent) throws Exception { + + // Add a line to the log file to identify the UUID of the caller. + logger.info(String.format("provider receives client connect event from %s ", connectionEvent.getUuid())); + + // Extract the JSON payload. + JSONObject payload = (JSONObject) connectionEvent.getPayload(); + + // If the "name" element of the payload says the client is invalid, reject the request. + if (payload != null) { + String name = payload.optString("name"); + if ("Invalid Client".equals(name)) { + throw new Exception("request rejected"); + } + } + } + + // Create the onChannelDisconnect event handler. + @Override + public void onClientDisconnect(ChannelClientConnectEvent connectionEvent) { + + // Add a line to the log file identifying the UUID of the caller. + logger.info(String.format("provider receives channel disconnect event from %s ", connectionEvent.getUuid())); + } + }); + + // The provider was created. Now to register the actions. + // ------------------------------------------------------ + + // This variable is used as the "value" element for the getValue, increment, and incrementBy actions. + AtomicInteger localInteger = new AtomicInteger(0); + + // Register the "getValue" action. + // This action will return the value of the localInteger variable. + provider.register("getValue", new ChannelAction() { + + // This is the logic for the "getValue" action. + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + + // Write a string to the logfile that shows the requested action and payload. + logger.info(String.format("provider processing action %s, payload=%s", action, payload.toString())); + + // Create a JSON object to return to the channel client. + JSONObject obj = new JSONObject(); + + // Set the "value" JSON element to the value of the localInteger variable. + obj.put("value", localInteger.get()); + + // Return the JSON object to the channel client. + return obj; + } + }); + + // Register the "increment" action. + // This action will increment the value of the localInteger variable by one. + provider.register("increment", new ChannelAction() { + + // This is the logic for the "increment" action. + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + + // Write a string to the logfile that identifies the action and payload. + logger.info(String.format("provider processing action %s, payload=%s", action, payload.toString())); + + // Create a JSON object to return to the channel client. + JSONObject obj = new JSONObject(); + + // Increment localInteger and set the "value" JSON element to the new value of localInteger. + obj.put("value", localInteger.incrementAndGet()); + provider.publish("event", obj, null); + + // Return the JSON object to the channel client. + return obj; + } + }); + + // Register the "incrementBy" action. + // This action will increment the value of the localInteger variable by a specified amount. + provider.register("incrementBy", new ChannelAction() { + + // This is the logic for the "incrementBy" action. + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + + // Write a string to the logfile that identifies the action and payload. + logger.info(String.format("provider processing action %s, payload=%s", action, payload.toString())); + + // Extract the increment amount (delta) from the payload JSON object. + int delta = ((JSONObject)payload).getInt("delta"); + + // Create a new JSON object to return to the channel client. + JSONObject obj = new JSONObject(); + + // Increase localInteger by the delta amount and set the "value" JSON element to the new value of localInteger. + obj.put("value", localInteger.addAndGet(delta)); + + // Return the new JSON object to the channel client. + return obj; + } + }); + }); + } + + /** + * Create a channel client that invokes "getValue", "increment" and "incrementBy n" actions + */ + public void createChannelClient() { + JSONObject payload = new JSONObject(); + payload.put("name", "java example"); + desktopConnection.getChannel(CHANNEL_NAME).connectAsync(false, payload).thenAccept(client -> { + client.addChannelListener(new ChannelListener() { + @Override + public void onChannelConnect(ConnectionEvent connectionEvent) { + } + @Override + public void onChannelDisconnect(ConnectionEvent connectionEvent) { + logger.info("channel disconnected {}", connectionEvent.getChannelId()); + } + }); + client.register("event", new ChannelAction() { + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + logger.info("channel event {}", action); + return null; + } + }); + + client.dispatch("getValue", null, new AckListener() { + @Override + public void onSuccess(Ack ack) { + logger.info("current value={}", ack.getJsonObject().getJSONObject("data").getJSONObject("result").getInt("value")); + + //got current value, do increment + client.dispatch("increment", null, new AckListener() { + @Override + public void onSuccess(Ack ack) { + logger.info("after invoking increment, value={}", ack.getJsonObject().getJSONObject("data").getJSONObject("result").getInt("value")); + + //let's do increatmentBy 10 + JSONObject payload = new JSONObject(); + payload.put("delta", 10); + client.dispatch("incrementBy", payload, new AckListener() { + @Override + public void onSuccess(Ack ack) { + logger.info("after invoking incrementBy, value={}", ack.getJsonObject().getJSONObject("data").getJSONObject("result").getInt("value")); + + try { + desktopConnection.disconnect(); + } catch (DesktopException e) { + e.printStackTrace(); + } + } + + @Override + public void onError(Ack ack) { + } + }); + } + + @Override + public void onError(Ack ack) { + } + }); + } + + @Override + public void onError(Ack ack) { + } + }); + }); + } + + @Override + public void onReady() { + if ("provider".equals(channelType) || channelType == null) { + createChannelProvider(); + } + if ("client".equals(channelType) || channelType == null) { + createChannelClient(); + } + } + + @Override + public void onClose(String error) { + logger.info("onClose, value={}", error); + latch.countDown(); + } + + @Override + public void onError(String reason) { + logger.info("onError, value={}", reason); + } + + @Override + public void onMessage(String message) { + + } + + @Override + public void onOutgoingMessage(String message) { + + } + + public static void main(String[] args) { + if (args.length > 0) { + channelType = args[0]; + } + try { + new ChannelExample(); + latch.await(); + } + catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + java.lang.System.exit(0); + } +} diff --git a/src/main/java/com/openfin/desktop/demo/DemoUtils.java b/src/main/java/com/openfin/desktop/demo/DemoUtils.java index 3fd5625..f6b1129 100644 --- a/src/main/java/com/openfin/desktop/demo/DemoUtils.java +++ b/src/main/java/com/openfin/desktop/demo/DemoUtils.java @@ -141,7 +141,7 @@ public static void ackError(AckListener ackListener, String reason) { if (ackListener != null) { JSONObject obj = new JSONObject(); obj.put("reason", reason); - ackListener.onError(new Ack(obj, null)); + ackListener.onError(new Ack(obj, ackListener)); } } diff --git a/src/main/java/com/openfin/desktop/demo/DockingDemo2.java b/src/main/java/com/openfin/desktop/demo/DockingDemo2.java deleted file mode 100644 index e28a951..0000000 --- a/src/main/java/com/openfin/desktop/demo/DockingDemo2.java +++ /dev/null @@ -1,289 +0,0 @@ -package com.openfin.desktop.demo; - -import com.openfin.desktop.*; -import com.openfin.desktop.win32.ExternalWindowObserver; -import info.clearthought.layout.TableLayout; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionListener; -import java.awt.event.WindowEvent; -import java.awt.event.WindowListener; - -/** - * This app works with OpenFinDockingDemo as another dockable Java window - * - * Created by wche on 3/9/2016. - */ -public class DockingDemo2 extends JPanel implements ActionListener, WindowListener { - private final static Logger logger = LoggerFactory.getLogger(DockingDemo2.class.getName()); - - protected String javaParentAppUuid = "Java Parent App"; // Its value must match OpenFinDockingDemo. Please see OpenFinDockingDemo for comments - - protected String appUuid = "AnotherJavaDocking"; // UUID for desktopConnection - protected String javaWindowName = "Another Java Dock Window"; - - protected DesktopConnection desktopConnection; - protected ExternalWindowObserver externalWindowObserver; - - private static JFrame jFrame; - protected JButton undockButton; - protected JTextField dockStatus; // show Ready to dock message - - public DockingDemo2() { - try { - this.desktopConnection = new DesktopConnection(appUuid); - startOpenFinRuntime(); - } catch (DesktopException desktopError) { - desktopError.printStackTrace(); - } - setLayout(new BorderLayout()); - add(layoutCenterPanel(), BorderLayout.CENTER); - add(layoutLeftPanel(), BorderLayout.WEST); - setBorder(BorderFactory.createEmptyBorder(20,20,20,20)); - } - - private JPanel layoutLeftPanel() { - JPanel panel = new JPanel(); - double size[][] = {{410}, {120, 30, TableLayout.FILL}}; - panel.setLayout(new TableLayout(size)); - panel.add(layoutActionButtonPanel(), "0,0,0,0"); - panel.add(layoutDockStatus(), "0,1,0,1"); - return panel; - } - - private JTextField layoutDockStatus() { - this.dockStatus = new JTextField(); - return this.dockStatus; - } - - private JPanel layoutActionButtonPanel() { - JPanel buttonPanel = new JPanel(); - JPanel topPanel = new JPanel(); - double size[][] = {{10, 190, 20, 190, 10}, {25, 10, 25, 10}}; - topPanel.setLayout(new TableLayout(size)); - topPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createBevelBorder(2), "Desktop")); - undockButton = new JButton("Undock"); - undockButton.setActionCommand("undock-window"); - undockButton.setEnabled(false); - topPanel.add(undockButton, "1,0,1,0"); - undockButton.addActionListener(this); - buttonPanel.add(topPanel, "0,0"); - return buttonPanel; - } - - private JPanel layoutCenterPanel() { - JPanel panel = new JPanel(); - double size[][] = {{TableLayout.FILL}, {150, 150, TableLayout.FILL}}; - panel.setLayout(new TableLayout(size)); - - return panel; - } - - private void undockFromOtherWindows() { - try { - // send message to Docking Manager to undock me - JSONObject msg = new JSONObject(); - msg.put("applicationUuid", javaParentAppUuid); - msg.put("windowName", javaWindowName); - desktopConnection.getInterApplicationBus().publish("undock-window", msg); - - } catch (Exception e) { - e.printStackTrace(); - } - undockButton.setEnabled(false); - } - - private void startOpenFinRuntime() { - try { - DesktopStateListener listener = new DesktopStateListener() { - @Override - public void onReady() { - onRuntimeReady(); - } - - @Override - public void onClose() { - } - @Override - public void onError(String reason) { - logger.error("Connection failed: " + reason); - java.lang.System.exit(0); - } - @Override - public void onMessage(String message) { - } - @Override - public void onOutgoingMessage(String message) { - } - }; - desktopConnection.setAdditionalRuntimeArguments(" --v=1"); // enable additional logging from Runtime - - String desktopVersion = java.lang.System.getProperty("com.openfin.demo.version"); - if (desktopVersion == null) { - desktopVersion = "stable"; - } - desktopConnection.connectToVersion(desktopVersion, listener, 60); // 5.44.10.26 has fix for cross-app docking, which is required for windowsInShameGroupMoveTogether - - } catch (Exception e) { - e.printStackTrace(); - } - } - private void onRuntimeReady() { - try { - this.desktopConnection.getInterApplicationBus().subscribe("*", "window-docked", (uuid, topic, data) -> { - JSONObject event = (JSONObject) data; - String appUuid = event.getString("applicationUuid"); - String windowName = event.getString("windowName"); - if (javaParentAppUuid.equals(appUuid) && javaWindowName.equals(windowName)) { - updateUndockButton(true); - } - }); - this.desktopConnection.getInterApplicationBus().subscribe("*", "window-undocked", (uuid, topic, data) -> { - JSONObject event = (JSONObject) data; - String appUuid = event.getString("applicationUuid"); - String windowName = event.getString("windowName"); - if (javaParentAppUuid.equals(appUuid) && javaWindowName.equals(windowName)) { - updateUndockButton(false); - } - }); - registerJavaWindow(); - Application javaParentApp = Application.wrap(javaParentAppUuid, desktopConnection); - javaParentApp.addEventListener("closed", actionEvent -> { shutdown(); }, null); - } catch (Exception e) { - logger.error("Error creating DockingManager", e); - } - } - - private void registerJavaWindow() { - try { - externalWindowObserver = new ExternalWindowObserver(desktopConnection.getPort(), javaParentAppUuid, javaWindowName, jFrame, - new AckListener() { - @Override - public void onSuccess(Ack ack) { - try { - if (ack.isSuccessful()) { - JSONObject request = new JSONObject(); - request.put("applicationUuid", javaParentAppUuid); - request.put("windowName", javaWindowName); - desktopConnection.getInterApplicationBus().publish("register-docking-window", request); - } - } catch (Exception ex) { - logger.error("Error registering window", ex); - } - } - @Override - public void onError(Ack ack) { - logger.error("Error registering java window ", ack.getReason()); - } - }); - } catch (Exception e) { - logger.error("Error registering external window", e); - } - } - - public void actionPerformed(java.awt.event.ActionEvent e) { - if ("undock-window".equals(e.getActionCommand())) { - undockFromOtherWindows(); - } - } - private void updateUndockButton(boolean enabled) { - this.undockButton.setEnabled(enabled); - if (enabled) { - this.dockStatus.setText("Docked. Click Unlock button to undock"); - } else { - this.dockStatus.setText(""); - } - } - - private static void createAndShowGUI() { - //Create and set up the window. - jFrame = new JFrame("Another Java Docking Demo"); - jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - //Create and set up the content pane. - DockingDemo2 newContentPane = new DockingDemo2(); - newContentPane.setOpaque(true); //content panes must be opaque - jFrame.setContentPane(newContentPane); - jFrame.addWindowListener(newContentPane); - - //Display the window. - jFrame.pack(); - jFrame.setSize(470, 300); - jFrame.setLocation(600, 400); -// jFrame.setLocationRelativeTo(null); - jFrame.setResizable(false); - jFrame.setVisible(true); - } - - private void shutdown() { - logger.debug("shutting down"); - if (externalWindowObserver != null) { - logger.debug("Closing"); - try { - JSONObject request = new JSONObject(); - request.put("applicationUuid", javaParentAppUuid); - request.put("windowName", javaWindowName); - desktopConnection.getInterApplicationBus().publish("unregister-docking-window", request); - Thread.sleep(2000); // give time to flush messages to Runtime - externalWindowObserver.dispose(); - desktopConnection.disconnect(); - Thread.sleep(1000); // give time to flush messages to Runtime - } catch (Exception ex) { - logger.error("Error existing", ex); - } - } - } - - /** - * - * @param args - */ - public static void main(String[] args) { - javax.swing.SwingUtilities.invokeLater(new Runnable() { - public void run() { - createAndShowGUI(); - } - }); - } - - @Override - public void windowOpened(WindowEvent e) { - - } - - @Override - public void windowClosing(WindowEvent e) { - shutdown(); - } - - @Override - public void windowClosed(WindowEvent e) { - - } - - @Override - public void windowIconified(WindowEvent e) { - - } - - @Override - public void windowDeiconified(WindowEvent e) { - - } - - @Override - public void windowActivated(WindowEvent e) { - - } - - @Override - public void windowDeactivated(WindowEvent e) { - - } -} - - diff --git a/src/main/java/com/openfin/desktop/demo/ExternalMessageDemo.java b/src/main/java/com/openfin/desktop/demo/ExternalMessageDemo.java deleted file mode 100644 index d113534..0000000 --- a/src/main/java/com/openfin/desktop/demo/ExternalMessageDemo.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.openfin.desktop.demo; - -import com.openfin.desktop.DesktopConnection; -import com.openfin.desktop.DesktopStateListener; -import com.openfin.desktop.ExternalMessageListener; -import com.openfin.desktop.ExternalMessageResultHandler; -import org.json.JSONObject; - -/** - * Created by richard on 2/28/15. - */ -public class ExternalMessageDemo { - DesktopConnection controller; - - ExternalMessageListener listener = new ExternalMessageListener() { - @Override - public void process(ExternalMessageResultHandler resultHandler, JSONObject payload) { - System.out.println("Receiving " + payload.toString()); - resultHandler.send(true, "Worked"); - } - }; - - public void test() throws Exception{ - controller = new DesktopConnection("ExternalWPFMainWindowConnectionExample2", "localhost", 9696); - controller.addExternalMessageHandler(listener, this); - - controller.connect(new DesktopStateListener() { - @Override - public void onReady() { - System.out.println("Desktop onReady"); - } - - @Override - public void onClose() { - System.out.println("Connection closed"); - } - - @Override - public void onError(String reason) { - System.out.println("Desktop onError " + reason); - } - - @Override - public void onMessage(String message) { - System.out.println("Desktop onMessage " + message); - } - - @Override - public void onOutgoingMessage(String message) { - System.out.println("Desktop onOutgoingMessage " + message); - } - }); - - synchronized (this) { - this.wait(300*1000); - } - } - - public static void main(String[] args) throws Exception{ - - ExternalMessageDemo demo = new ExternalMessageDemo(); - demo.test(); - - } - - - -} diff --git a/src/main/java/com/openfin/desktop/demo/FxDemo.java b/src/main/java/com/openfin/desktop/demo/FxDemo.java index 61cfdc4..df03ab4 100644 --- a/src/main/java/com/openfin/desktop/demo/FxDemo.java +++ b/src/main/java/com/openfin/desktop/demo/FxDemo.java @@ -1,252 +1,251 @@ -package com.openfin.desktop.demo; - -import com.openfin.desktop.*; -import com.openfin.desktop.Window; -import com.sun.javafx.tk.TKStage; -import javafx.application.Application; -import javafx.application.Platform; -import javafx.collections.ObservableList; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; -import javafx.scene.Group; -import javafx.scene.Scene; -import javafx.scene.control.Button; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.StackPane; -import javafx.stage.Stage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Method; - -/** - * Java example to embed HTML5 window in JavaFX window - * - * Created by wche on 3/13/15. - * - */ - -public class FxDemo extends Application implements DesktopStateListener { - private final static Logger logger = LoggerFactory.getLogger(FxDemo.class.getName()); - - private DesktopConnection desktopConnection; - private Button btnStart, btnStop; - private StackPane embedPane; - - protected String openfin_app_url = "https://cdn.openfin.co/examples/junit/SimpleDockingExample.html"; // source is in release/SimpleDockingExample.html - protected String startupUuid = "OpenFinHelloWorld"; - private long stageHWndId; - private com.openfin.desktop.Application startupHtml5app; - - @Override - public void start(Stage stage) { - btnStart = new Button(); - btnStart.setText("Launch OpenFin"); - btnStart.setLayoutX(10); - btnStart.setLayoutY(10); - btnStart.setOnAction(new EventHandler() { - @Override - public void handle(ActionEvent event) { - launchOpenFin(); - } - }); - btnStop = new Button(); - btnStop.setText("Shut down OpenFin"); - btnStop.setLayoutX(200); - btnStop.setLayoutY(10); - btnStop.setDisable(true); - btnStop.setOnAction(new EventHandler() { - @Override - public void handle(ActionEvent event) { - shutDown(); - } - }); - - AnchorPane anchorPane = new AnchorPane(); - anchorPane.getChildren().add(btnStart); - anchorPane.getChildren().add(btnStop); - - //Creating a Group object - Group root = new Group(); - - //Retrieving the observable list object - ObservableList list = root.getChildren(); - - - embedPane = new StackPane(); - embedPane.setLayoutX(10); - embedPane.setLayoutY(50); - AnchorPane.setTopAnchor(embedPane, 50.0); - AnchorPane.setBottomAnchor(embedPane, 0.0); - AnchorPane.setLeftAnchor(embedPane, 0.0); - AnchorPane.setRightAnchor(embedPane, 0.0); - anchorPane.getChildren().add(embedPane); - embedPane.widthProperty().addListener(observable -> { - onEmbedComponentSizeChange(); - }); - embedPane.heightProperty().addListener(observable -> { - onEmbedComponentSizeChange(); - }); - - //Creating a scene object - Scene scene = new Scene(anchorPane, 800, 800); - - //Setting title to the Stage - stage.setTitle("FX Demo"); - - //Adding scene to the stage - stage.setScene(scene); - - //Displaying the contents of the stage - stage.show(); - - this.stageHWndId = getWindowHandle(stage); - } - - private void launchOpenFin() { - RuntimeConfiguration cfg = new RuntimeConfiguration(); - cfg.setRuntimeVersion("stable"); - cfg.setAdditionalRuntimeArguments(" --v=1 "); - try { - desktopConnection = new DesktopConnection("JavaFxDemo"); - desktopConnection.connect(cfg, this, 60); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void launchHtmlApp() { - // launch 5 instances of same example app - int width = 500, height=500; - try { - String url = java.lang.System.getProperty("com.openfin.demo.embed.URL"); - if (url != null) { - openfin_app_url = url; - } - ApplicationOptions options = new ApplicationOptions(startupUuid, startupUuid, openfin_app_url); - options.setApplicationIcon("http://openfin.github.io/snap-and-dock/openfin.ico"); - WindowOptions mainWindowOptions = new WindowOptions(); - mainWindowOptions.setAutoShow(false); - mainWindowOptions.setDefaultHeight(height); - mainWindowOptions.setDefaultLeft(10); - mainWindowOptions.setDefaultTop(50); - mainWindowOptions.setDefaultWidth(width); - mainWindowOptions.setShowTaskbarIcon(true); - mainWindowOptions.setSaveWindowState(false); // set to false so all windows start at same initial positions for each run - mainWindowOptions.setFrame(false); - mainWindowOptions.setContextMenu(true); - mainWindowOptions.setResizeRegionSize(0); - options.setMainWindowOptions(mainWindowOptions); - DemoUtils.runApplication(options, this.desktopConnection, new AckListener() { - @Override - public void onSuccess(Ack ack) { - com.openfin.desktop.Application app = (com.openfin.desktop.Application) ack.getSource(); - try { - Thread.sleep(1000); - embedStartupApp(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - @Override - public void onError(Ack ack) { - logger.error(String.format("Error launching %s %s", options.getUUID(), ack.getReason())); - } - }); - } catch (Exception e) { - logger.error("Error launching app", e); - } - } - - private void embedStartupApp() { - try { - if (startupHtml5app == null) { - startupHtml5app = com.openfin.desktop.Application.wrap(this.startupUuid, this.desktopConnection); - } - - Window html5Wnd = startupHtml5app.getWindow(); - html5Wnd.embedInto(stageHWndId, (int)this.embedPane.getLayoutX(), (int)this.embedPane.getLayoutY(), - (int)this.embedPane.getWidth(), (int)this.embedPane.getHeight(), new AckListener() { - @Override - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - } else { - logger.error("embedding failed: " + ack.getJsonObject().toString()); - } - } - @Override - public void onError(Ack ack) { - } - }); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void onEmbedComponentSizeChange() { - logger.info(String.format("%f %f ", this.embedPane.getLayoutX(), this.embedPane.getLayoutY())); - if (startupHtml5app != null) { - startupHtml5app.getWindow().embedComponentSizeChange((int)this.embedPane.getLayoutX(), (int)this.embedPane.getLayoutY(), - (int)this.embedPane.getWidth(), (int)this.embedPane.getHeight()); - } - } - - private void shutDown() { - try { - this.desktopConnection.exit(); - Platform.exit(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private long getWindowHandle(Stage stage) { - long handle = -1; - try { - TKStage tkStage = stage.impl_getPeer(); - Method getPlatformWindow = tkStage.getClass().getDeclaredMethod("getPlatformWindow" ); - getPlatformWindow.setAccessible(true); - Object platformWindow = getPlatformWindow.invoke(tkStage); - Method getNativeHandle = platformWindow.getClass().getMethod( "getNativeHandle" ); - getNativeHandle.setAccessible(true); - Object nativeHandle = getNativeHandle.invoke(platformWindow); - handle = (Long) nativeHandle; - } catch (Throwable e) { - logger.error("Error getting Window Pointer", e); - } - logger.info(String.format("Stage hwnd %d", handle)); - return handle; - } - - @Override - public void onReady() { - logger.info("Connected to OpenFin Runtime"); - btnStart.setDisable(true); - btnStop.setDisable(false); - launchHtmlApp(); - } - - @Override - public void onClose() { - logger.info("Disconnected from OpenFin Runtime"); - btnStart.setDisable(false); - btnStop.setDisable(true); - } - - @Override - public void onError(String s) { - } - - @Override - public void onMessage(String s) { - } - - @Override - public void onOutgoingMessage(String s) { - } - - public static void main(String args[]) { - launch(args); - } - +package com.openfin.desktop.demo; + +import com.openfin.desktop.*; +import com.openfin.desktop.Window; +import com.sun.javafx.tk.TKStage; +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.User32; +import com.sun.jna.platform.win32.WinDef; + +import javafx.application.Application; +import javafx.application.Platform; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.StackPane; +import javafx.stage.Stage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Method; + +/** + * Java example to embed HTML5 window in JavaFX window + * + * Created by wche on 3/13/15. + * + */ + +public class FxDemo extends Application implements DesktopStateListener { + private final static Logger logger = LoggerFactory.getLogger(FxDemo.class.getName()); + private final static String WINDOW_TITLE = "FX Demo"; + + private DesktopConnection desktopConnection; + private Button btnStart, btnStop; + private StackPane embedPane; + + protected String openfin_app_url = "https://cdn.openfin.co/examples/junit/SimpleDockingExample.html"; // source is in release/SimpleDockingExample.html + protected String startupUuid = "OpenFinHelloWorld"; + private long stageHWndId; + private com.openfin.desktop.Application startupHtml5app; + + @Override + public void start(Stage stage) { + btnStart = new Button(); + btnStart.setText("Launch OpenFin"); + btnStart.setLayoutX(10); + btnStart.setLayoutY(10); + btnStart.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + launchOpenFin(); + } + }); + btnStop = new Button(); + btnStop.setText("Shut down OpenFin"); + btnStop.setLayoutX(200); + btnStop.setLayoutY(10); + btnStop.setDisable(true); + btnStop.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + shutDown(); + } + }); + + AnchorPane anchorPane = new AnchorPane(); + anchorPane.getChildren().add(btnStart); + anchorPane.getChildren().add(btnStop); + + //Creating a Group object + Group root = new Group(); + + //Retrieving the observable list object + ObservableList list = root.getChildren(); + + + embedPane = new StackPane(); + embedPane.setLayoutX(10); + embedPane.setLayoutY(50); + AnchorPane.setTopAnchor(embedPane, 50.0); + AnchorPane.setBottomAnchor(embedPane, 0.0); + AnchorPane.setLeftAnchor(embedPane, 0.0); + AnchorPane.setRightAnchor(embedPane, 0.0); + anchorPane.getChildren().add(embedPane); + embedPane.widthProperty().addListener(observable -> { + onEmbedComponentSizeChange(); + }); + embedPane.heightProperty().addListener(observable -> { + onEmbedComponentSizeChange(); + }); + + //Creating a scene object + Scene scene = new Scene(anchorPane, 800, 800); + + //Setting title to the Stage + stage.setTitle(WINDOW_TITLE); + + //Adding scene to the stage + stage.setScene(scene); + + //Displaying the contents of the stage + stage.show(); + + this.stageHWndId = getWindowHandle(stage); + } + + private void launchOpenFin() { + RuntimeConfiguration cfg = new RuntimeConfiguration(); + cfg.setRuntimeVersion("stable"); + cfg.setAdditionalRuntimeArguments(" --v=1 "); + try { + desktopConnection = new DesktopConnection("JavaFxDemo"); + desktopConnection.connect(cfg, this, 60); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void launchHtmlApp() { + // launch 5 instances of same example app + int width = 500, height=500; + try { + String url = java.lang.System.getProperty("com.openfin.demo.embed.URL"); + if (url != null) { + openfin_app_url = url; + } + ApplicationOptions options = new ApplicationOptions(startupUuid, startupUuid, openfin_app_url); + options.setApplicationIcon("http://openfin.github.io/snap-and-dock/openfin.ico"); + WindowOptions mainWindowOptions = new WindowOptions(); + mainWindowOptions.setAutoShow(false); + mainWindowOptions.setDefaultHeight(height); + mainWindowOptions.setDefaultLeft(10); + mainWindowOptions.setDefaultTop(50); + mainWindowOptions.setDefaultWidth(width); + mainWindowOptions.setShowTaskbarIcon(true); + mainWindowOptions.setSaveWindowState(false); // set to false so all windows start at same initial positions for each run + mainWindowOptions.setFrame(false); + mainWindowOptions.setContextMenu(true); + mainWindowOptions.setResizeRegionSize(0); + options.setMainWindowOptions(mainWindowOptions); + DemoUtils.runApplication(options, this.desktopConnection, new AckListener() { + @Override + public void onSuccess(Ack ack) { + com.openfin.desktop.Application app = (com.openfin.desktop.Application) ack.getSource(); + try { + Thread.sleep(1000); + embedStartupApp(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + @Override + public void onError(Ack ack) { + logger.error(String.format("Error launching %s %s", options.getUUID(), ack.getReason())); + } + }); + } catch (Exception e) { + logger.error("Error launching app", e); + } + } + + private void embedStartupApp() { + try { + if (startupHtml5app == null) { + startupHtml5app = com.openfin.desktop.Application.wrap(this.startupUuid, this.desktopConnection); + } + + Window html5Wnd = startupHtml5app.getWindow(); + html5Wnd.embedInto(stageHWndId, (int)this.embedPane.getLayoutX(), (int)this.embedPane.getLayoutY(), + (int)this.embedPane.getWidth(), (int)this.embedPane.getHeight(), new AckListener() { + @Override + public void onSuccess(Ack ack) { + if (ack.isSuccessful()) { + } else { + logger.error("embedding failed: " + ack.getJsonObject().toString()); + } + } + @Override + public void onError(Ack ack) { + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void onEmbedComponentSizeChange() { + logger.info(String.format("%f %f ", this.embedPane.getLayoutX(), this.embedPane.getLayoutY())); + if (startupHtml5app != null) { + startupHtml5app.getWindow().embedComponentSizeChange((int)this.embedPane.getLayoutX(), (int)this.embedPane.getLayoutY(), + (int)this.embedPane.getWidth(), (int)this.embedPane.getHeight()); + } + } + + private void shutDown() { + try { + this.desktopConnection.exit(); + Platform.exit(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private long getWindowHandle(Stage stage) { + long handle = -1; + try { + WinDef.HWND hWnd = User32.INSTANCE.FindWindow(null, WINDOW_TITLE); + handle = Pointer.nativeValue(hWnd.getPointer()); + } catch (Throwable e) { + logger.error("Error getting Window Pointer", e); + } + logger.info(String.format("Stage hwnd %d", handle)); + return handle; + } + + @Override + public void onReady() { + logger.info("Connected to OpenFin Runtime"); + btnStart.setDisable(true); + btnStop.setDisable(false); + launchHtmlApp(); + } + + @Override + public void onClose(String error) { + logger.info("Disconnected from OpenFin Runtime"); + btnStart.setDisable(false); + btnStop.setDisable(true); + } + + @Override + public void onError(String s) { + } + + @Override + public void onMessage(String s) { + } + + @Override + public void onOutgoingMessage(String s) { + } + + public static void main(String args[]) { + launch(args); + } + } \ No newline at end of file diff --git a/src/main/java/com/openfin/desktop/demo/FxLayoutFrame.java b/src/main/java/com/openfin/desktop/demo/FxLayoutFrame.java new file mode 100644 index 0000000..d2a67b6 --- /dev/null +++ b/src/main/java/com/openfin/desktop/demo/FxLayoutFrame.java @@ -0,0 +1,135 @@ +package com.openfin.desktop.demo; + +import com.openfin.desktop.*; +import com.openfin.desktop.channel.ChannelClient; +import com.openfin.desktop.win32.ExternalWindowObserver; +import javafx.embed.swing.JFXPanel; +import javafx.event.EventHandler; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.layout.StackPane; +import javafx.stage.Stage; +import javafx.stage.WindowEvent; +import org.json.JSONObject; + +import java.lang.System; +import java.util.List; + +public class FxLayoutFrame { + private static String LayoutServiceChannelName = "of-layouts-service-v1"; + private ExternalWindowObserver externalWindowObserver; + private String windowName; + private Stage stage; + private static JFXPanel jFXPanel; + + public FxLayoutFrame(DesktopConnection desktopConnection, String appUuid, String windowName) { + System.out.println(windowName + " being created "); + this.windowName = windowName; + if (jFXPanel == null) { + jFXPanel = new JFXPanel(); + javafx.application.Platform.setImplicitExit(false); + } + javafx.application.Platform.runLater(new Runnable() { + @Override + public void run() { + Button btnUndock = new Button("undock"); + btnUndock.setDisable(true); + + StackPane secondaryLayout = new StackPane(); + secondaryLayout.getChildren().add(btnUndock); + + Scene secondScene = new Scene(secondaryLayout, 640, 480); + + FxLayoutFrame.this.stage = new Stage(); + FxLayoutFrame.this.stage.setTitle(windowName); + FxLayoutFrame.this.stage.setScene(secondScene); + + // Set position of second window, related to primary window. + FxLayoutFrame.this.stage.setX(640); + FxLayoutFrame.this.stage.setY(480); + FxLayoutFrame.this.stage.show(); + +// FxLayoutFrame.this.stage.setOnCloseRequest(event -> FxLayoutFrame.this.cleanup()); + + try { + FxLayoutFrame.this.externalWindowObserver = + new ExternalWindowObserver(desktopConnection.getPort(), appUuid, windowName, FxLayoutFrame.this.stage, + new AckListener() { + @Override + public void onSuccess(Ack ack) { + ExternalWindowObserver observer = (ExternalWindowObserver) ack.getSource(); + observer.getDesktopConnection().getChannel(LayoutServiceChannelName).connect( + new AsyncCallback() { + @Override + public void onSuccess(ChannelClient client) { + btnUndock.setOnAction(new EventHandler() { + @Override + public void handle(javafx.event.ActionEvent e) { + JSONObject payload = new JSONObject(); + payload.put("uuid", appUuid); + payload.put("name", windowName); + client.dispatch("UNDOCK-WINDOW", payload, null); + } + }); + } + }); + } + + @Override + public void onError(Ack ack) { + } + }); + + Window w = Window.wrap(appUuid, windowName, desktopConnection); + w.addEventListener("group-changed", new EventListener() { + @Override + public void eventReceived(com.openfin.desktop.ActionEvent actionEvent) { + JSONObject eventObj = actionEvent.getEventObject(); + w.getGroup(new AsyncCallback>() { + @Override + public void onSuccess(java.util.List result) { + if (result.size() > 0) { + btnUndock.setDisable(false); + } else { + btnUndock.setDisable(true); + } + } + }, null); + } + }, null); + + try { + FxLayoutFrame.this.externalWindowObserver.start(); + } catch (Exception e) { + e.printStackTrace(); + } + + } catch (DesktopException e) { + e.printStackTrace(); + } + } + }); + } + + public String getWindowName() { + return windowName; + } + + public Stage getStage() { + return stage; + } + + public void cleanup() { + try { + System.out.println(windowName + " cleaning up "); + if (this.externalWindowObserver != null) { + this.externalWindowObserver.dispose(); + } + } + catch (Exception e) { + e.printStackTrace(); + } + this.externalWindowObserver = null; + } + +} diff --git a/src/main/java/com/openfin/desktop/demo/JNLPExample.java b/src/main/java/com/openfin/desktop/demo/JNLPExample.java index f58236e..646a244 100644 --- a/src/main/java/com/openfin/desktop/demo/JNLPExample.java +++ b/src/main/java/com/openfin/desktop/demo/JNLPExample.java @@ -31,7 +31,7 @@ public void onReady() { } @Override - public void onClose() { + public void onClose(String error) { java.lang.System.out.println("Connection closed"); } @@ -63,7 +63,9 @@ public JNLPExample() throws DesktopException { startButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { - desktopConnection.connectToVersion("stable", listener, 100000); + RuntimeConfiguration cfg = new RuntimeConfiguration(); + cfg.setRuntimeVersion("stable"); + desktopConnection.connect(cfg, listener, 30); } catch (Exception ex) { ex.printStackTrace(); } diff --git a/src/main/java/com/openfin/desktop/demo/JUnitDemo.java b/src/main/java/com/openfin/desktop/demo/JUnitDemo.java deleted file mode 100644 index 11e5b5c..0000000 --- a/src/main/java/com/openfin/desktop/demo/JUnitDemo.java +++ /dev/null @@ -1,609 +0,0 @@ -package com.openfin.desktop.demo; - -import com.openfin.desktop.*; -import com.openfin.desktop.System; -import com.openfin.desktop.animation.AnimationTransitions; -import com.openfin.desktop.animation.PositionTransition; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.StringTokenizer; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; -import static junit.framework.TestCase.fail; - -/** - * Exmaple testing code with JUNIT - * - * Created by wche on 1/4/16. - */ -public class JUnitDemo { - private static Logger logger = LoggerFactory.getLogger(JUnitDemo.class.getName()); - - private static DesktopConnection desktopConnection; - - private static final String DESKTOP_UUID = "DESKTOP_UUID"; - - private static int windowUuidCounter = 0; - - //set this to around 2000ms in order to see the chromium windows - private final long SLEEP_FOR_HUMAN_OBSERVATION = 1000L; - - @BeforeClass - public static void setup() throws Exception { - setupDesktopConnection(); - } - - @AfterClass - public static void teardown() throws Exception { - teardownDesktopConnection(); - } - - private static void setupDesktopConnection() throws Exception { - String desktopVersion = java.lang.System.getProperty("com.openfin.demo.version"); - if (desktopVersion == null) { - desktopVersion = "stable"; - } - - final CountDownLatch openFinConnectedLatch = new CountDownLatch(1); - - desktopConnection = null; - desktopConnection = new DesktopConnection(DESKTOP_UUID); - desktopConnection.setAdditionalRuntimeArguments(" --v=1"); // enable additional logging from Runtime - desktopConnection.connectToVersion(desktopVersion, new DesktopStateListener() { - @Override - public void onReady() { - printf("Connected to OpenFin runtime"); - openFinConnectedLatch.countDown(); - } - - @Override - public void onClose() { - printf("Connection to Runtime closed"); - } - - @Override - public void onError(String reason) { - printf("Connection failed: %s", reason); - } - - @Override - public void onMessage(String message) { - printf("openfin message: %s", message); - } - - @Override - public void onOutgoingMessage(String message) { - printf("openfin outgoing message: %s", message); - } - }, 60);//this timeout (in 4.40.2.9) is ignored - - printf("waiting for desktop to connect"); - // wait for 60 seconds here in case it takes time to download newer version of Runtime - openFinConnectedLatch.await(60, TimeUnit.SECONDS); - - if (desktopConnection.isConnected()) { - printf("desktop connected"); - } else { - throw new RuntimeException("failed to initialise desktop connection"); - } - } - - private static void teardownDesktopConnection() throws Exception { - new System(desktopConnection).exit(); - printf("desktop connection closed"); - } - - private Application openHelloOpenFin(String uuid, String url) throws Exception { - //default options for all test windows - int top = 50; - int left = 10; - int width = 395; - int height = 525; - boolean withFrame = false; - boolean resizable = false; - return openWindow(uuid, url, left, top, width, height, withFrame, resizable); - } - - private Application openWindow(String uuid, String url) throws Exception { - //default options for all test windows - int top = 10; - int left = 10; - int width = 200; - int height = 300; - boolean withFrame = true; - boolean resizable = true; - return openWindow(uuid, url, left, top, width, height, withFrame, resizable); - } - - /** - * Create an OpenFin Application - * @param uuid uuid of the app - * @param url url of the app - * @param left - * @param top - * @param width - * @param height - * @param withFrame - * @param resizable - * @return - * @throws Exception - */ - private Application openWindow(final String uuid, final String url, final int left, final int top, final int width, final int height, boolean withFrame, boolean resizable) throws Exception { - final WindowOptions windowOptions = new WindowOptions(); - windowOptions.setAutoShow(true); - windowOptions.setDefaultLeft(left); - windowOptions.setDefaultTop(top); - windowOptions.setDefaultHeight(height); - windowOptions.setDefaultWidth(width); - windowOptions.setFrame(withFrame); - windowOptions.setResizable(resizable); - - ApplicationOptions applicationOptions = new ApplicationOptions(uuid, uuid, url); - applicationOptions.setMainWindowOptions(windowOptions); - - //used to block JUnit thread until OpenFin has iniitialised - final CountDownLatch windowCreatedLatch = new CountDownLatch(1); - - //if this reference gets set, something went wrong creating the window - final AtomicReference failedReason = new AtomicReference(); - - printf("creating new chromium window (uuid: %s) (left: %s) (top: %s) (width: %s) (height: %s) (withFrame: %s) (resizable: %s)", - uuid, left, top, width, height, withFrame, resizable); - - Application application = new Application(applicationOptions, desktopConnection, new AckListener() { - @Override - public void onSuccess(Ack ack) { - try { - Application application = (Application) ack.getSource(); - // use app-connected event to wait for the app to be connected to OpenFin Runtime - application.getWindow().addEventListener("app-connected", new EventListener() { - public void eventReceived(ActionEvent actionEvent) { - printf("eventReceived: %s", actionEvent.getType()); - windowCreatedLatch.countDown(); - } - }, new AckListener() { - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - printf("app-connected listener added: %s", uuid); - } - } - public void onError(Ack ack) { - } - }); - - application.run(); - printf("window running: %s", ack); - } catch (Exception e) { - failedReason.set("failed to run window: " + ack.getReason()); - } - } - - @Override - public void onError(Ack ack) { - try { - failedReason.set("failed to open window: " + ack.getReason()); - } finally { - windowCreatedLatch.countDown(); - } - } - }); - - //wait for OpenFin callback - windowCreatedLatch.await(20, TimeUnit.SECONDS); - assertEquals("Open window timed out " + uuid, windowCreatedLatch.getCount(), 0); - - if (failedReason.get() != null) { - throw new RuntimeException(failedReason.get()); - } else { - - application.getWindow().setBounds(left, top, width, height, new AckListener() { - @Override - public void onSuccess(Ack ack) { - printf("successfully set bounds (uuid: %s) (left: %s) (top: %s) (width: %s) (height: %s)", uuid, left, top, width, height); - } - - @Override - public void onError(Ack ack) { - printf("failed to set window bounds (uuid: %s)", uuid); - } - }); - printf("explicity setting bounds (uuid: %s) (left: %s) (top: %s) (width: %s) (height: %s)", uuid, left, top, width, height); - - - return application; - } - } - - private static synchronized String nextTestUuid() { - return String.format("test_uuid_%s", windowUuidCounter++); - } - - @Test - public void canStopAndRestartOpenFinDesktopConnection() throws Exception { - //setupDesktopConnection() called from setup() - teardownDesktopConnection(); - setupDesktopConnection(); - //teardownDesktopConnection() will be caled from teardown() - } - - @Test - public void canOpenAndCloseMultipleWindowsWithDifferentUUIDS() throws Exception { - Application application1 = openWindow(nextTestUuid(), "http://www.google.com"); - Application application2 = openWindow(nextTestUuid(), "http://www.google.co.uk"); - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION);//allow the windows time to appear - application1.close(); - application2.close(); - } - - @Test - public void cannotOpenMultipleWindowsWithSameUUID() throws Exception { - Application application1 = null; - Application application2 = null; - try { - String uuid = nextTestUuid(); - application1 = openWindow(uuid, "http://www.google.com"); - application2 = openWindow(uuid, "http://www.google.co.uk"); - //above lines should throw an exception and not get past here - fail(); - } catch (Exception e) { - assertTrue(e.getMessage().contains("Application with specified UUID already exists")); - } finally { - if (application1 != null) application1.close(); - if (application2 != null) application2.close(); - } - } - - @Test - public void windowMoves() throws Exception { - Application application = openWindow(nextTestUuid(), "http://www.google.com"); - - //set the initial position of the window and check - application.getWindow().moveTo(10, 20); - WindowBounds initialBounds = getWindowBounds(application.getWindow()); - printf("initial bounds top:%s left:%s", initialBounds.getTop(), initialBounds.getLeft()); - assertEquals(10, initialBounds.getLeft().intValue()); - assertEquals(20, initialBounds.getTop().intValue()); - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - - //move the window and check again - application.getWindow().moveTo(100, 200); - WindowBounds movedBounds = getWindowBounds(application.getWindow()); - printf("moved bounds top:%s left:%s", movedBounds.getTop(), movedBounds.getLeft()); - - assertEquals(100, movedBounds.getLeft().intValue()); - assertEquals(200, movedBounds.getTop().intValue()); - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - } - - @Test - public void windowMovesWithAnimation() throws Exception { - Application application = openWindow(nextTestUuid(), "http://www.google.com"); - - //set the initial position of the window and check - application.getWindow().moveTo(10, 20); - WindowBounds initialBounds = getWindowBounds(application.getWindow()); - printf("initial bounds top:%s left:%s", initialBounds.getTop(), initialBounds.getLeft()); - assertEquals(10, initialBounds.getLeft().intValue()); - assertEquals(20, initialBounds.getTop().intValue()); - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - - //move the window and check again - final CountDownLatch transitionLatch = new CountDownLatch(1); - AnimationTransitions transitions = new AnimationTransitions(); - transitions.setPosition(new PositionTransition(100, 200, 2000));//duration in millisecods - application.getWindow().animate(transitions, null, new AckListener() { - @Override - public void onSuccess(Ack ack) { - transitionLatch.countDown(); - } - - @Override - public void onError(Ack ack) { - //noop - } - }); - transitionLatch.await(20, TimeUnit.SECONDS); - - WindowBounds movedBounds = getWindowBounds(application.getWindow()); - printf("moved bounds top:%s left:%s", movedBounds.getTop(), movedBounds.getLeft()); - - assertEquals(100, movedBounds.getLeft().intValue()); - assertEquals(200, movedBounds.getTop().intValue()); - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - } - - @Test - public void windowEventListenersWork() throws Exception { - Application application = openWindow(nextTestUuid(), "http://www.google.com"); - - //as per the javadoc (https://cdn.openfin.co/docs/java/4.40.2/com/openfin/desktop/Window.html), the event names: - String events = "blurred bounds-changed bounds-changing closed close-requested disabled-frame-bounds-changed disabled-frame-bounds-changing focused frame-disabled frame-enabled group-changed hidden maximized minimized restored shown"; - - final AtomicReference eventTypeRecieved = new AtomicReference(); - final CountDownLatch onMinimiseEventLatch = new CountDownLatch(1); - - //register even handlers for all event types - StringTokenizer tokenizer = new StringTokenizer(events); - while (tokenizer.hasMoreTokens()) { - final String event = tokenizer.nextToken().trim(); - application.getWindow().addEventListener(event, new EventListener() { - @Override - public void eventReceived(ActionEvent actionEvent) { - printf("eventReceived: %s", actionEvent.getType()); - String type = actionEvent.getType(); - eventTypeRecieved.set(type); - if ("minimized".equals(type)) { - onMinimiseEventLatch.countDown(); - } - } - }, new AckListener() { - @Override - public void onSuccess(Ack ack) { - printf("window '%s' onSuccess: %s", event, ack); - } - - @Override - public void onError(Ack ack) { - printf("window '%s' onError: %s", event, ack); - } - } - ); - printf("added listener for event: %s", event); - } - - //generate a minimized event to check that we get notification in the listener above - application.getWindow().minimize(); - onMinimiseEventLatch.await(20, TimeUnit.SECONDS); - assertEquals("minimized event not recieved", "minimized", eventTypeRecieved.get()); - } - - @Ignore("Cross app docking not supported") - @Test - public void windowsInSameGroupMoveTogether() throws Exception { - final int width = 600, height = 900; - - //place two application windows next to each other - Application applicationA = openWindow(nextTestUuid(), "http://www.google.com", 0, 0, width, height, true, true); - Application applicationB = openWindow(nextTestUuid(), "http://www.bbc.co.uk", width, 0, width, height, true, true); - - //bind the windows in the same group so that they move togther - applicationA.getWindow().joinGroup(applicationB.getWindow(), new AckListener() { - @Override - public void onSuccess(Ack ack) { - printf("window A joined group"); - } - - @Override - public void onError(Ack ack) { - printf("failed to join group"); - } - }); - - //move window A and check that B has followed it - final int moveLefPositiontBy = 100; - final int appBLeftStart = getWindowBounds(applicationB.getWindow()).getLeft(); - - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - applicationA.getWindow().moveBy(moveLefPositiontBy, 0, new AckListener() { - @Override - public void onSuccess(Ack ack) { - printf("moved window A"); - } - - @Override - public void onError(Ack ack) { - printf("failed to move window A"); - } - }); - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - final int appBLeftEnd = getWindowBounds(applicationB.getWindow()).getLeft(); - - assertEquals("the window for app B did not follow the move for app A", appBLeftStart + moveLefPositiontBy, appBLeftEnd); - } - - @Test - public void notificationEventListenersWork() throws Exception { - //record/wait for event - final CountDownLatch onCloseEventLatch = new CountDownLatch(1); - final AtomicReference eventTypeRecieved = new AtomicReference(); - - NotificationOptions options = new NotificationOptions("http://demoappdirectory.openf.in/desktop/config/apps/OpenFin/HelloOpenFin/views/notification.html"); - options.setTimeout(1000); - options.setMessageText("testing"); - new Notification(options, new NotificationListener() { - @Override - public void onClick(Ack ack) { - eventTypeRecieved.set("onClick"); - } - - @Override - public void onClose(Ack ack) { - eventTypeRecieved.set("onClose"); - onCloseEventLatch.countDown(); - } - - @Override - public void onDismiss(Ack ack) { - eventTypeRecieved.set("onDismiss"); - } - - @Override - public void onError(Ack ack) { - eventTypeRecieved.set("onError"); - } - - @Override - public void onMessage(Ack ack) { - eventTypeRecieved.set("onMessage"); - } - - @Override - public void onShow(Ack ack) { - eventTypeRecieved.set("onShow"); - } - }, this.desktopConnection, null); - - //wait for the onClose notification to arrive - onCloseEventLatch.await(20, TimeUnit.SECONDS); - assertEquals("onClose", eventTypeRecieved.get()); - } - - @Test - public void childWindow() throws Exception { - Application application = openHelloOpenFin(nextTestUuid(), "http://demoappdirectory.openf.in/desktop/config/apps/OpenFin/HelloOpenFin/index.html"); - Window childWindow = this.createChildWindow(application, "ChildWindow1", "http://test.openf.in/bus/simple.html", 300, 300, 150, 150); - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - WindowBounds bounds = getWindowBounds(childWindow); - assertEquals(300, bounds.getHeight().intValue()); - - application.close(); - } - - @Test - public void windowsOfSameAppInSameGroupMoveTogether() throws Exception { - //place two windows next to each other - Application application = openHelloOpenFin(nextTestUuid(), "http://demoappdirectory.openf.in/desktop/config/apps/OpenFin/HelloOpenFin/index.html"); - Window childWindowA = this.createChildWindow(application, "ChildWindowA", "http://test.openf.in/bus/simple.html", 300, 300, 150, 150); - Window childWindowB = this.createChildWindow(application, "ChildWindowB", "http://test.openf.in/bus/simple.html", 300, 300, 450, 150); - - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - - //bind the windows in the same group so that they move togther - childWindowA.joinGroup(childWindowB, new AckListener() { - @Override - public void onSuccess(Ack ack) { - printf("window A joined group"); - } - - @Override - public void onError(Ack ack) { - printf("failed to join group"); - } - }); - - //move window A and check that B has followed it - final int moveLefPositiontBy = 300; - final int appBLeftStart = getWindowBounds(childWindowB).getLeft(); - - childWindowA.moveBy(moveLefPositiontBy, 0, new AckListener() { - @Override - public void onSuccess(Ack ack) { - printf("moved window A"); - } - - @Override - public void onError(Ack ack) { - printf("failed to move window A"); - } - }); - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - final int appBLeftEnd = getWindowBounds(childWindowB).getLeft(); - - assertEquals("the window B did not follow the move for Window A", appBLeftStart + moveLefPositiontBy, appBLeftEnd); - - application.close(); - } - - - private WindowBounds getWindowBounds(Window window) throws Exception { - final AtomicReference atomicRef = new AtomicReference(); - final CountDownLatch latch = new CountDownLatch(1); - window.getBounds(new AsyncCallback() { - @Override - public void onSuccess(WindowBounds result) { - atomicRef.set(result); - latch.countDown(); - } - }, null); - latch.await(20, TimeUnit.SECONDS); - WindowBounds windowBounds = atomicRef.get(); - assertNotNull("failed to get bounds for window", windowBounds); - return windowBounds; - } - - /** - * Create a child window for an Application - * - * @param application owner application - * @param name name of the child window - * @param url url of the child window - * @param width - * @param height - * @param left - * @param top - * @return - * @throws Exception - */ - private Window createChildWindow(Application application, final String name, String url, int width, int height, int left, int top) throws Exception { - - WindowOptions options = new WindowOptions(name, url); - options.setAutoShow(false); - options.setSaveWindowState(false); // so windows will always open at position specified - options.setDefaultHeight(height); - options.setDefaultWidth(width); - options.setDefaultLeft(left); - options.setDefaultTop(top); - - final CountDownLatch onWindowCreatedLatch = new CountDownLatch(1); - // use window-end-load event to wait for the window to finish loading - application.addEventListener("window-end-load", new EventListener() { - public void eventReceived(ActionEvent actionEvent) { - printf("eventReceived: %s for window %s to listener %s", actionEvent.getType(), actionEvent.getEventObject().getString("name"), name); - if (actionEvent.getEventObject().has("name")) { - if (name.equals(actionEvent.getEventObject().getString("name"))) { - onWindowCreatedLatch.countDown(); - } - } - } - }, null); - application.createChildWindow(options, null); - onWindowCreatedLatch.await(20, TimeUnit.SECONDS); - assertEquals("child window " + name + " not being created", onWindowCreatedLatch.getCount(), 0); - - Window childWindow = Window.wrap(application.getOptions().getUUID(), name, desktopConnection); - final CountDownLatch addShownListenerLatch = new CountDownLatch(1); - final CountDownLatch onShownLatch = new CountDownLatch(1); - childWindow.addEventListener("shown", new EventListener() { - @Override - public void eventReceived(ActionEvent actionEvent) { - Window src = (Window) actionEvent.getSource(); - printf("eventReceived: %s for window %s", actionEvent.getType(), src.getName()); - onShownLatch.countDown(); - } - }, new AckListener() { - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - addShownListenerLatch.countDown(); - } - } - public void onError(Ack ack) { - - } - }); - addShownListenerLatch.await(20, TimeUnit.SECONDS); - assertEquals("child window " + name + " shown event listener was not added", addShownListenerLatch.getCount(), 0); - printf("Calling show() on %s", name); - childWindow.show(); - onShownLatch.await(20, TimeUnit.SECONDS); - assertEquals("child window " + name + " is not shown", onShownLatch.getCount(), 0); - return childWindow; - } - - private static void printf(String s, Object... args) { - logger.info(String.format(s, args)); - } - - - - -} diff --git a/src/main/java/com/openfin/desktop/demo/LaunchManifestDemo.java b/src/main/java/com/openfin/desktop/demo/LaunchManifestDemo.java new file mode 100644 index 0000000..32e7bee --- /dev/null +++ b/src/main/java/com/openfin/desktop/demo/LaunchManifestDemo.java @@ -0,0 +1,264 @@ +package com.openfin.desktop.demo; + +import com.openfin.desktop.*; +import com.openfin.desktop.channel.ChannelAction; +import com.openfin.desktop.channel.ChannelClient; +import com.openfin.desktop.win32.ExternalWindowObserver; +import javafx.application.Application; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.layout.AnchorPane; +import javafx.stage.Stage; +import org.json.JSONArray; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.System; + +public class LaunchManifestDemo extends Application implements DesktopStateListener { + + private final static Logger logger = LoggerFactory.getLogger(LaunchManifestDemo.class.getName()); + private final static String WINDOW_TITLE = "Launch Manifest Demo"; + + private static String LayoutServiceChannelName = "of-layouts-service-v1"; + private static String appUuid = "LaunchManifestDemo"; // App UUID for startup app in manifest + private final static String javaConnectUuid = "LaunchManifestDemo-Java"; // connection UUID for Java app + private DesktopConnection desktopConnection; + private ChannelClient channelClient; // for communicating with layout service + private Button btnGiantMachine, btnScottLogic; + private Button btnUndock; + private Stage stage; + + private ExternalWindowObserver externalWindowObserver; // required for Layout service + + @Override + public void start(Stage stage) { + btnGiantMachine = new Button(); + btnGiantMachine.setText("Launch Watchlist by Giant Machines"); + btnGiantMachine.setLayoutX(10); + btnGiantMachine.setLayoutY(10); + btnGiantMachine.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + launchGiantMachine(); + } + }); + btnGiantMachine.setDisable(true); + + btnScottLogic = new Button(); + btnScottLogic.setText("Launch StockFlux by Scott Logic"); + btnScottLogic.setLayoutX(10); + btnScottLogic.setLayoutY(50); + btnScottLogic.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + launchScottLogic(); + } + }); + btnScottLogic.setDisable(true); + + btnUndock = new Button(); + btnUndock.setText("Undock"); + btnUndock.setLayoutX(10); + btnUndock.setLayoutY(90); + btnUndock.setDisable(true); + + AnchorPane anchorPane = new AnchorPane(); + anchorPane.getChildren().add(btnGiantMachine); + anchorPane.getChildren().add(btnScottLogic); + anchorPane.getChildren().add(btnUndock); + + //Creating a Group object + Group root = new Group(); + + //Retrieving the observable list object + ObservableList list = root.getChildren(); + + //Creating a scene object + Scene scene = new Scene(anchorPane, 800, 800); + + //Setting title to the Stage + stage.setTitle(WINDOW_TITLE); + + //Adding scene to the stage + stage.setScene(scene); + + //Displaying the contents of the stage + stage.show(); + + this.stage = stage; + launchOpenFin(); + } + + private void launchOpenFin() { + RuntimeConfiguration config = new RuntimeConfiguration(); + config.setRuntimeVersion("stable"); +// config.setRuntimeVersion("9.61.38.40"); + config.setAdditionalRuntimeArguments("--v=1 --remote-debugging-port=9090 "); + JSONArray serviceConfig = new JSONArray(); + // add Layout service to app manifest + JSONObject layout = new JSONObject(); + layout.put("name", "layouts"); + JSONObject scfg = new JSONObject(); + JSONObject sfeatures = new JSONObject(); + sfeatures.put("dock", true); + sfeatures.put("tab", false); + scfg.put("features", sfeatures); + layout.put("config", scfg); + layout.put("manifestUrl", "https://cdn.openfin.co/services/openfin/layouts/1.0.0/app.json"); + serviceConfig.put(0, layout); + config.addConfigurationItem("services", serviceConfig); + + JSONObject startupApp = new JSONObject(); + startupApp.put("uuid", appUuid); + startupApp.put("name", appUuid); + startupApp.put("url", "about:blank"); + startupApp.put("autoShow", false); + config.setStartupApp(startupApp); + + try { + this.desktopConnection = new DesktopConnection(javaConnectUuid); + this.desktopConnection.connect(config, this, 60); + } catch (Exception ex){ + ex.printStackTrace(); + } + } + + private void launchGiantMachine() { + launchAppFromManifest("http://localhost:8000/watchlist.json"); + } + + private void launchScottLogic() { + launchAppFromManifest("http://localhost:8000/stockflux.json"); + } + + private void launchAppFromManifest(String manifest) { + try { + com.openfin.desktop.Application.createFromManifest(manifest, + new AsyncCallback() { + @Override + public void onSuccess(com.openfin.desktop.Application app) { + try { + app.run(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + }, new AckListener() { + @Override + public void onSuccess(Ack ack) { + } + + @Override + public void onError(Ack ack) { + logger.info("error creating app: {}", ack.getReason()); + } + }, desktopConnection); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + private void createExternalWindowObserver() { + if (this.externalWindowObserver != null) { + // only needs to happen once + return; + } + String windowName = appUuid + "-Java-Window"; + try { + this.externalWindowObserver = new ExternalWindowObserver(desktopConnection.getPort(), appUuid, windowName, this.stage, + new AckListener() { + @Override + public void onSuccess(Ack ack) { + ExternalWindowObserver observer = (ExternalWindowObserver) ack.getSource(); + observer.getDesktopConnection().getChannel(LayoutServiceChannelName).connect( + new AsyncCallback() { + @Override + public void onSuccess(ChannelClient client) { + LaunchManifestDemo.this.channelClient = client; + + client.register("event", new ChannelAction() { + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + System.out.printf("channel event " + action); + return null; + } + }); + } + }); + } + + @Override + public void onError(Ack ack) { + System.out.println(windowName + ": unable to register external window, " + ack.getReason()); + } + }); + } catch (Exception ex) { + ex.printStackTrace(); + } + + // when this Java window is docked or undocked by layout service, "group-changed" is fired. + // calling getGroup to determine if btnUndock should enabled. + Window w = Window.wrap(appUuid, windowName, desktopConnection); + w.addEventListener("group-changed", new EventListener() { + @Override + public void eventReceived(com.openfin.desktop.ActionEvent actionEvent) { + w.getGroup(new AsyncCallback>() { + @Override + public void onSuccess(java.util.List result) { + if (result.size() > 0) { + btnUndock.setDisable(false); + } else { + btnUndock.setDisable(true); + } + } + }, null); + } + }, null); + + try { + this.externalWindowObserver.start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void onReady() { + btnGiantMachine.setDisable(false); + btnScottLogic.setDisable(false); + this.createExternalWindowObserver(); + } + + @Override + public void onClose(String error) { + + } + + @Override + public void onError(String reason) { + + } + + @Override + public void onMessage(String message) { + + } + + @Override + public void onOutgoingMessage(String message) { + + } + + public static void main(String args[]) { + launch(args); + } + + + +} diff --git a/src/main/java/com/openfin/desktop/demo/LauncherBusDemo.java b/src/main/java/com/openfin/desktop/demo/LauncherBusDemo.java new file mode 100644 index 0000000..58d2cf3 --- /dev/null +++ b/src/main/java/com/openfin/desktop/demo/LauncherBusDemo.java @@ -0,0 +1,558 @@ +/** + * Demo for launching OpenFin app and send messages via Inter application bus + * + * javascript side is in release/busdemo.html, which needs to be hosted in localhost:8888 + */ + +package com.openfin.desktop.demo; + +import com.openfin.desktop.*; +import com.openfin.desktop.Window; +import com.openfin.desktop.channel.*; +import com.openfin.desktop.win32.ExternalWindowObserver; +import com.sun.jna.Native; +import info.clearthought.layout.TableLayout; +import org.json.JSONArray; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.lang.System; +import java.util.UUID; + +public class LauncherBusDemo extends JFrame { + private final static Logger logger = LoggerFactory.getLogger(LauncherBusDemo.class.getName()); + + private DesktopConnection desktopConnection; + private InterApplicationBus interApplicationBus; + private JButton btnOFApp1, btnOFApp2; + private JButton btnTabOFApp1; + private JButton btnUndock; // button to undock this Java window + private JButton btnOFSendApp1, btnOFSendApp2; // send messages to OpenFin app via Inter App Bus + private JButton btnGenerateWorkSpace, btnRestoreWorkSpace; + private static String appStartupUuid = "LaunchManifestDemo"; // App UUID for startup app in startup manifest + private static String javaWindowName = appStartupUuid + "-Java-Window"; // name of this Java window registered with Runtime + private final String app1Uuid = "Layout Client1"; // defined in layoutclient1.json + private final String app2Uuid = "Layout Client2"; // defined in layoutclient2.json + private final String appUrl = "http://localhost:8888/busdemo.html"; + com.openfin.desktop.Application app1, app2; // OpenFin apps + + private final String embedUuid = "Embed Client"; + Application embeddedApp; // OpenFin app to be embedded in Java canvas + + private LayoutClient layoutClient; // client for Layout service + private JSONObject lastSavedWorkspace; + private ExternalWindowObserver externalWindowObserver; // required for Layout service to control Java window + protected java.awt.Canvas embedCanvas; // required for embedding OpenFin window + + public LauncherBusDemo() { + btnOFApp1 = new JButton(); + btnOFApp1.setEnabled(false); + btnOFApp1.setText("Launch OpenFin app1"); + btnOFApp1.addActionListener(new ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + launchAppFromManifest("http://localhost:8888/layoutclient1.json"); + } + }); + + btnTabOFApp1 = new JButton(); + btnTabOFApp1.setEnabled(false); + btnTabOFApp1.setText("Tab to OpenFin app1"); + btnTabOFApp1.addActionListener(new ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + // uuid and name from http://localhost:8888/layoutclient1.json + tabToWindow("Layout Client1", "Layout Client1"); + } + }); + + btnOFApp2 = new JButton(); + btnOFApp2.setEnabled(false); + btnOFApp2.setText("Launch OpenFin App2"); + btnOFApp2.addActionListener(new ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + launchAppFromManifest("http://localhost:8888/layoutclient2.json"); + } + }); + + btnOFSendApp1 = new JButton(); + btnOFSendApp1.setEnabled(false); + btnOFSendApp1.setText("Send messages OpenFin app1"); + btnOFSendApp1.addActionListener(new ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + sendOFApp(app1Uuid); + } + }); + + btnOFSendApp2 = new JButton(); + btnOFSendApp2.setEnabled(false); + btnOFSendApp2.setText("Send messages OpenFin app2"); + btnOFSendApp1.addActionListener(new ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + sendOFApp(app2Uuid); + } + }); + + btnGenerateWorkSpace = new JButton(); + btnGenerateWorkSpace.setText("Generate WorkSpace"); + btnGenerateWorkSpace.setEnabled(false); + btnGenerateWorkSpace.addActionListener(new ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + generateWorkSpace(); + } + }); + + btnRestoreWorkSpace = new JButton(); + btnRestoreWorkSpace.setText("Restore WorkSpace"); + btnRestoreWorkSpace.setEnabled(false); + btnRestoreWorkSpace.addActionListener(new ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + restoreWorkSpace(); + } + }); + + btnUndock = new JButton(); + btnUndock.setText("Undock"); + btnUndock.setEnabled(false); + + JPanel topPanel = new JPanel(); + double size[][] = {{10, 190}, {25, 5, 25, 5, 25, 5, 25, 5, 25, 5, 25, 5, 25, 5, 25, 5, 25, 5, 25, 5}}; + topPanel.setLayout(new TableLayout(size)); + + topPanel.add(btnOFApp1, "1,0,1,0"); + topPanel.add(btnTabOFApp1, "1,2,1,2"); + topPanel.add(btnOFApp2, "1,4,1,4"); + topPanel.add(btnOFSendApp1, "1,6,1,6"); + topPanel.add(btnOFSendApp2, "1,8,1,8"); + topPanel.add(btnGenerateWorkSpace, "1,14,1,14"); + topPanel.add(btnRestoreWorkSpace, "1,16,1,16"); + topPanel.add(btnUndock, "1,18,1,18"); + + setLayout(new BorderLayout()); + add(topPanel, BorderLayout.NORTH); + add(layoutEmbedPanel(), BorderLayout.CENTER); + + launchRuntime(); + } + + protected JPanel layoutEmbedPanel() { + JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createBevelBorder(2), "HTML5 app")); + embedCanvas = new java.awt.Canvas(); + panel.add(embedCanvas, BorderLayout.CENTER); + embedCanvas.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent event) { + super.componentResized(event); + Dimension newSize = event.getComponent().getSize(); + try { +// if (startupHtml5app != null) { +// startupHtml5app.getWindow().embedComponentSizeChange((int)newSize.getWidth(), (int)newSize.getHeight()); +// } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + return panel; + } + + + private void launchRuntime() { + if (desktopConnection == null) { + RuntimeConfiguration cfg = new RuntimeConfiguration(); + cfg.setRuntimeVersion("stable"); + cfg.setSecurityRealm("java-test"); + cfg.setDevToolsPort(9099); + cfg.setAdditionalRuntimeArguments("--v=1 --enable-mesh "); // --v=1 => enable verbose logging by Runtime + // --enable-mesh => enable multi-Runtime for the security realm + // Add Layout Service to the manifest + JSONArray serviceConfig = new JSONArray(); + // add Layout service to app manifest + JSONObject layout = new JSONObject(); + layout.put("name", "layouts"); + JSONObject scfg = new JSONObject(); + JSONObject sfeatures = new JSONObject(); + sfeatures.put("dock", true); + sfeatures.put("tab", true); + scfg.put("features", sfeatures); + layout.put("config", scfg); +// layout.put("manifestUrl", "https://cdn.openfin.co/services/openfin/layouts/1.0.0/app.json"); + serviceConfig.put(0, layout); + + JSONObject notification = new JSONObject(); + notification.put("name", "notifications"); + serviceConfig.put(1, notification); + + cfg.addConfigurationItem("services", serviceConfig); + + JSONObject startupApp = new JSONObject(); + startupApp.put("uuid", appStartupUuid); + startupApp.put("name", appStartupUuid); + startupApp.put("url", "about:blank"); + startupApp.put("autoShow", false); + cfg.setStartupApp(startupApp); + + try { + desktopConnection = new DesktopConnection("Java app"); + desktopConnection.connect(cfg, new DesktopStateListener() { + @Override + public void onReady() { + logger.info("Connected to OpenFin Runtime"); + interApplicationBus = new InterApplicationBus(desktopConnection); + btnOFApp1.setEnabled(true); + btnTabOFApp1.setEnabled(true); + btnOFApp2.setEnabled(true); + configAppEventListener(); + createEmbddedApp(); + createLayoutClient(); + } + + @Override + public void onClose(String error) { + } + + @Override + public void onError(String reason) { + } + + @Override + public void onMessage(String message) { + } + + @Override + public void onOutgoingMessage(String message) { + } + }, 60); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void configAppEventListener() { + try { + // set up listener for "started" and "closed" event for layoutclient1.json + app1 = com.openfin.desktop.Application.wrap(app1Uuid, this.desktopConnection); + app1.addEventListener("started", new EventListener() { + @Override + public void eventReceived(com.openfin.desktop.ActionEvent actionEvent) { + btnOFApp1.setEnabled(false); + btnOFSendApp1.setEnabled(true); + } + }, null); + app1.addEventListener("closed", new EventListener() { + @Override + public void eventReceived(com.openfin.desktop.ActionEvent actionEvent) { + btnOFApp1.setEnabled(true); + btnOFSendApp1.setEnabled(false); + } + }, null); + + // set up listener for "started and "closed" event for layoutclient2.json + app2 = com.openfin.desktop.Application.wrap(app2Uuid, this.desktopConnection); + app2.addEventListener("started", new EventListener() { + @Override + public void eventReceived(com.openfin.desktop.ActionEvent actionEvent) { + btnOFApp2.setEnabled(false); + btnOFSendApp2.setEnabled(true); + } + }, null); + app2.addEventListener("closed", new EventListener() { + @Override + public void eventReceived(com.openfin.desktop.ActionEvent actionEvent) { + btnOFApp2.setEnabled(true); + btnOFSendApp2.setEnabled(false); + } + }, null); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + /** + * Create externalWindowObserver for this Java frame so Runtime & Layout Service can keep track of location & size + */ + private void createExternalWindowObserver() { + if (this.externalWindowObserver != null) { + // only needs to happen once + return; + } + try { + // ExternalWindowObserver forwards window events to Runtime & Layout Service. Currently ExternalWindowObserver requires UUID of an + // existing OpenFin app. So here we are using UUID of the startup app in manifest. + this.externalWindowObserver = new ExternalWindowObserver(desktopConnection.getPort(), appStartupUuid, javaWindowName, this, + new AckListener() { + @Override + public void onSuccess(Ack ack) { + btnUndock.addActionListener(new ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + LauncherBusDemo.this.layoutClient.undockWindow(appStartupUuid, javaWindowName, null); + } + }); + } + @Override + public void onError(Ack ack) { + System.out.println(javaWindowName + ": unable to register external window, " + ack.getReason()); + } + }); + } catch (Exception ex) { + ex.printStackTrace(); + } + + // when this Java window is docked or undocked by layout service, "group-changed" is fired. + // calling getGroup to determine if btnUndock should enabled. + Window w = Window.wrap(appStartupUuid, javaWindowName, desktopConnection); + w.addEventListener("group-changed", new EventListener() { + @Override + public void eventReceived(com.openfin.desktop.ActionEvent actionEvent) { + w.getGroup(new AsyncCallback>() { + @Override + public void onSuccess(java.util.List result) { + if (result.size() > 0) { + btnUndock.setEnabled(true); + } else { + btnUndock.setEnabled(false); + } + } + }, null); + } + }, null); + + try { + this.externalWindowObserver.start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void launchAppFromManifest(String manifest) { + try { + com.openfin.desktop.Application.createFromManifest(manifest, + new AsyncCallback() { + @Override + public void onSuccess(com.openfin.desktop.Application app) { + try { + app.run(); + createExternalWindowObserver(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + }, new AckListener() { + @Override + public void onSuccess(Ack ack) { + } + + @Override + public void onError(Ack ack) { + logger.info("error creating app: {}", ack.getReason()); + } + }, desktopConnection); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + private void sendOFApp(String desticationAppUuid) { + JSONObject msg = new JSONObject(); + msg.put("ticker", "AAPL"); + msg.put("price", Math.random() * 100); + try { + interApplicationBus.send(desticationAppUuid, "messageFromJavaTopic", msg); + } catch (DesktopException e) { + e.printStackTrace(); + } + } + + void createEmbddedApp() { + ApplicationOptions appOpt = new ApplicationOptions(embedUuid, embedUuid, "http://localhost:8888/busdemo.html"); + WindowOptions mainWindowOptions = new WindowOptions(); + mainWindowOptions.setAutoShow(true); + mainWindowOptions.setFrame(false); // remove frame for embedded app + mainWindowOptions.setResizable(true); + mainWindowOptions.setContextMenu(true); + appOpt.setMainWindowOptions(mainWindowOptions); + + this.embeddedApp = new Application(appOpt, this.desktopConnection, new AckListener() { + @Override + public void onSuccess(Ack ack) { + try { + embeddedApp.run(new AckListener() { + @Override + public void onSuccess(Ack ack) { + embedOpenFinApp(); + } + @Override + public void onError(Ack ack) { + } + }); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + @Override + public void onError(Ack ack) { + } + }); + } + private void embedOpenFinApp() { + try { + Window html5Wnd = embeddedApp.getWindow(); + long parentHWndId = Native.getComponentID(this.embedCanvas); + System.out.println("Canvas HWND " + Long.toHexString(parentHWndId)); + html5Wnd.embedInto(parentHWndId, this.embedCanvas.getWidth(), this.embedCanvas.getHeight(), new AckListener() { + @Override + public void onSuccess(Ack ack) { + if (ack.isSuccessful()) { + } else { + logger.error("embedding failed: " + ack.getJsonObject().toString()); + } + } + @Override + public void onError(Ack ack) { + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + private void createLayoutClient() { + this.layoutClient = new LayoutClient(this.desktopConnection, new AckListener() { + @Override + public void onSuccess(Ack ack) { + btnGenerateWorkSpace.setEnabled(true); + btnRestoreWorkSpace.setEnabled(true); + createExternalWindowObserver(); + } + @Override + public void onError(Ack ack) { + } + }); + } + + private void generateWorkSpace() { + this.layoutClient.generateWorkspace(new AsyncCallback() { + @Override + public void onSuccess(JSONObject result) { + LauncherBusDemo.this.lastSavedWorkspace = result; + logger.info(String.format("Current workspace %s", result.toString())); + } + }, + new AckListener() { + @Override + public void onSuccess(Ack ack) { + } + @Override + public void onError(Ack ack) { + logger.error(String.format("Error generating workspace %s", ack.getReason())); + } + }); + } + + private void restoreWorkSpace() { + if (this.lastSavedWorkspace != null) { + this.layoutClient.retoreWorkspace(this.lastSavedWorkspace, new AckListener() { + @Override + public void onSuccess(Ack ack) { + } + + @Override + public void onError(Ack ack) { + logger.error(String.format("Error restoring workspace %s", ack.getReason())); + } + }); + } + } + + /** + * Tab this Java window to an OpenFin windowq + * @param appUuid + * @param windowName + */ + public void tabToWindow(String appUuid, String windowName) { + WindowIdentity target = new WindowIdentity(); + target.setUuid(appUuid); + target.setName(windowName); + WindowIdentity me = new WindowIdentity(); + // this Java window is registered as appStartupUuid/javaWindowName, as in createExternalWindowObserver + me.setUuid(appStartupUuid); + me.setName(javaWindowName); + this.layoutClient.tabWindows(target, me, null); + } + + public void cleanup() { + try { + if (this.externalWindowObserver != null) { + this.externalWindowObserver.dispose(); + } + if (this.desktopConnection != null) { + // shut down startup app + Application app = Application.wrap(appStartupUuid, desktopConnection); + app.close(true, null); + + Application app2 = Application.wrap(embedUuid, desktopConnection); + app2.close(true, null); + + this.desktopConnection.disconnect(); + Thread.sleep(1000); + java.lang.System.exit(0); + } + } + catch (Exception e) { + e.printStackTrace(); + } + this.externalWindowObserver = null; + } + + private static void createAndShowGUI(final String startupUuid) { + //Create and set up the window. + LauncherBusDemo newContentPane = new LauncherBusDemo(); +// newContentPane.setOpaque(true); //content panes must be opaque +// jFrame.setContentPane(newContentPane); +// jFrame.addWindowListener(newContentPane); + //Display the window. + newContentPane.pack(); + newContentPane.setSize(700, 700); + newContentPane.setLocationRelativeTo(null); + newContentPane.setResizable(true); + newContentPane.setVisible(true); + + newContentPane.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent we) { + try { + newContentPane.cleanup(); + } + catch (Exception de) { + de.printStackTrace(); + } + } + }); + } + + + public static void main(String args[]) { + + System.out.println(String.format("Install info on your machine %s", OpenFinRuntime.getInstallInfo().toString())); + javax.swing.SwingUtilities.invokeLater(new Runnable() { + public void run() { + createAndShowGUI("OpenFin Embed Example"); + } + }); + } + + + +} diff --git a/src/main/java/com/openfin/desktop/demo/LayoutFrame.java b/src/main/java/com/openfin/desktop/demo/LayoutFrame.java new file mode 100644 index 0000000..93cc75f --- /dev/null +++ b/src/main/java/com/openfin/desktop/demo/LayoutFrame.java @@ -0,0 +1,306 @@ +package com.openfin.desktop.demo; + +/** + * Example of Java window that can be managed by OpenFin layout service for snap&dock + */ + +import com.openfin.desktop.*; +import com.openfin.desktop.Window; +import com.openfin.desktop.channel.ChannelAction; +import com.openfin.desktop.channel.ChannelClient; +import com.openfin.desktop.win32.ExternalWindowObserver; +import com.sun.jna.Native; +import com.sun.jna.platform.win32.WinDef; +import org.json.JSONArray; +import org.json.JSONObject; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.lang.System; + +public class LayoutFrame extends JFrame { + private static String LayoutServiceChannelName = "of-layouts-service-v1"; + private ExternalWindowObserver externalWindowObserver; + private JLabel labelName; + private JButton btnUndock; + private String windowName; + private ChannelClient channelClient; + private String appUuid; + private boolean frameless; + + public LayoutFrame(DesktopConnection desktopConnection, String appUuid, String windowName) throws DesktopException { + this(desktopConnection, appUuid, windowName, false); + } + + public LayoutFrame(DesktopConnection desktopConnection, String appUuid, String windowName, boolean frameless) throws DesktopException { + super(); + this.setTitle(windowName); + System.out.println(windowName + " being created "); + this.appUuid = appUuid; + this.windowName = windowName; + this.frameless = frameless; + this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + this.setPreferredSize(new Dimension(640, 480)); + JPanel pnl = new JPanel(); + pnl.setLayout(new BoxLayout(pnl, BoxLayout.Y_AXIS)); + this.labelName = new JLabel(windowName); + pnl.add(labelName); + this.btnUndock = new JButton("undock"); + this.btnUndock.setEnabled(false); + pnl.add(btnUndock); + this.getContentPane().add(pnl); + + if (frameless) { + this.setUndecorated(true); + JPanel titleBar = new JPanel(new BorderLayout()); + titleBar.setBackground(Color.DARK_GRAY); + MouseAdapter myListener = new MouseAdapter() { + int pressedAtX, pressedAtY; + @Override + public void mousePressed(MouseEvent e) { + pressedAtX = e.getX(); + pressedAtY = e.getY(); + System.out.println("mouse pressed at x=" + pressedAtX + ", y=" + pressedAtY); + LayoutFrame.this.externalWindowObserver.enterSizeMove(); + } + @Override + public void mouseDragged(MouseEvent e) { + int distanceX = e.getX() - pressedAtX; + int distanceY = e.getY() - pressedAtY; + System.out.println("dragged x=" + distanceX + ", y=" + distanceY); + Point frameLocation = LayoutFrame.this.getLocation(); + Dimension dimension = LayoutFrame.this.getSize(); + WindowBounds bounds = new WindowBounds(frameLocation.x + distanceX, frameLocation.y + distanceY, + dimension.width, dimension.height); + Point point = new Point(e.getX(), e.getY()); + if (!LayoutFrame.this.externalWindowObserver.onMoving(bounds, point)) { + LayoutFrame.this.setLocation(frameLocation.x + distanceX, frameLocation.y + distanceY); + } + } + @Override + public void mouseReleased(MouseEvent e) { + LayoutFrame.this.externalWindowObserver.exitSizeMove(); + } + }; + titleBar.addMouseListener(myListener); + titleBar.addMouseMotionListener(myListener); + + JButton btnClose = new JButton("X"); + btnClose.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + LayoutFrame.this.dispose(); + }}); + titleBar.add(btnClose, BorderLayout.EAST); + + this.getContentPane().add(titleBar, BorderLayout.NORTH); + + } + + this.pack(); + this.setLocationRelativeTo(null); + this.setVisible(true); + + this.externalWindowObserver = new ExternalWindowObserver(desktopConnection.getPort(), appUuid, windowName, this, + new AckListener() { + @Override + public void onSuccess(Ack ack) { + ExternalWindowObserver observer = (ExternalWindowObserver) ack.getSource(); + observer.getDesktopConnection().getChannel(LayoutServiceChannelName).connect( + new AsyncCallback() { + @Override + public void onSuccess(ChannelClient client) { + LayoutFrame.this.channelClient = client; + btnUndock.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JSONObject payload = new JSONObject(); + payload.put("uuid", appUuid); + payload.put("name", windowName); + client.dispatch("UNDOCK-WINDOW", payload, null); + } + }); + + client.register("event", new ChannelAction() { + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + System.out.printf("channel event " + action); + return null; + } + }); + } + }); + } + + @Override + public void onError(Ack ack) { + System.out.println(windowName + ": unable to register external window, " + ack.getReason()); + } + }); +// this.externalWindowObserver.setUserGesture(!this.frameless); + try { +// if (this.frameless) { +// WindowOptions options = new WindowOptions(); +// options.setFrame(false); +// this.externalWindowObserver.setWindowOptions(options); +// } + this.externalWindowObserver.start(); + } catch (Exception e) { + e.printStackTrace(); + } + + Window w = Window.wrap(appUuid, windowName, desktopConnection); + w.addEventListener("group-changed", new EventListener() { + @Override + public void eventReceived(com.openfin.desktop.ActionEvent actionEvent) { + JSONObject eventObj = actionEvent.getEventObject(); + w.getGroup(new AsyncCallback>() { + @Override + public void onSuccess(java.util.List result) { + if (result.size() > 0) { + checkTabbing(); + } else { + LayoutFrame.this.btnUndock.setEnabled(false); + setHasFrame(LayoutFrame.this, true); + } + } + }, null); + } + }, null); + + this.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + super.windowClosing(e); + try { + LayoutFrame.this.cleanup(); + LayoutFrame.this.dispose(); + } + catch (Exception e1) { + e1.printStackTrace(); + } + } + + public void windowClosed(WindowEvent e) { + super.windowClosed(e); + System.out.println(windowName + " closed "); + } + }); + } + + private void checkTabbing() { + JSONObject payload = new JSONObject(); + payload.put("uuid", appUuid); + payload.put("name", windowName); + channelClient.dispatch("GETTABS", payload, new AckListener() { + @Override + public void onSuccess(Ack ack) { + System.out.printf("channel GETTABS "); + JSONObject data = (JSONObject) ack.getData(); + Object result = data.get("result"); + if (result != null && result instanceof JSONArray) { + JSONArray tabs = (JSONArray) result; + boolean enabled = !(tabs != null && tabs.length() > 0); + LayoutFrame.this.btnUndock.setEnabled(enabled); + setHasFrame(LayoutFrame.this, false); + } else { + LayoutFrame.this.btnUndock.setEnabled(true); + setHasFrame(LayoutFrame.this, true); + } + } + + @Override + public void onError(Ack ack) { + System.out.printf("channel GETTABS error " + ack.getReason()); + } + }); + } + + private void setHasFrame(JFrame frame, boolean hasFrame) { + if (!this.frameless) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + System.out.println(windowName + " hasFrame=" + hasFrame); + WinDef.HWND hWnd = new WinDef.HWND(); + hWnd.setPointer(Native.getComponentPointer(frame)); + LayoutFrame.this.externalWindowObserver.setHasFrame(hWnd, hasFrame); + frame.setResizable(hasFrame); + frame.invalidate(); + frame.validate(); + frame.repaint(); + SwingUtilities.updateComponentTreeUI(frame); + } + }); + } + } + + public String getWindowName() { + return windowName; + } + + public void cleanup() { + try { + System.out.println(windowName + " cleaning up "); + this.externalWindowObserver.dispose(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + + public static void main(String[] args) { + final JFrame frame = new JFrame(); + frame.setPreferredSize(new Dimension(640, 480)); + JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER)); + + frame.setUndecorated(true); + JPanel titleBar = new JPanel(new BorderLayout()); + titleBar.setBackground(Color.DARK_GRAY); + MouseAdapter myListener = new MouseAdapter() { + int pressedAtX, pressedAtY; + @Override + public void mousePressed(MouseEvent e) { + pressedAtX = e.getX(); + pressedAtY = e.getY(); + System.out.println("mouse pressed at x=" + pressedAtX + ", y=" + pressedAtY); + } + @Override + public void mouseDragged(MouseEvent e) { + int distanceX = e.getX() - pressedAtX; + int distanceY = e.getY() - pressedAtY; + System.out.println("dragged x=" + distanceX + ", y=" + distanceY); + Point frameLocation = frame.getLocation(); + frame.setLocation(frameLocation.x + distanceX, frameLocation.y + distanceY); + } + @Override + public void mouseReleased(MouseEvent e) { + pressedAtX = e.getX(); + pressedAtY = e.getY(); + System.out.println("mouse released at x=" + pressedAtX + ", y=" + pressedAtY); + } + }; + titleBar.addMouseListener(myListener); + titleBar.addMouseMotionListener(myListener); + + JButton btnClose = new JButton("X"); + btnClose.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + frame.dispose(); + }}); + titleBar.add(btnClose, BorderLayout.EAST); + frame.getContentPane().add(titleBar, BorderLayout.NORTH); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + +} diff --git a/src/main/java/com/openfin/desktop/demo/LayoutServiceDemo.java b/src/main/java/com/openfin/desktop/demo/LayoutServiceDemo.java new file mode 100644 index 0000000..b22ac8a --- /dev/null +++ b/src/main/java/com/openfin/desktop/demo/LayoutServiceDemo.java @@ -0,0 +1,294 @@ +package com.openfin.desktop.demo; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.IOException; +import java.lang.System; +import java.util.*; +import java.util.concurrent.CountDownLatch; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import com.openfin.desktop.*; +import org.json.JSONArray; +import org.json.JSONObject; + +public class LayoutServiceDemo implements DesktopStateListener { + + private final static String appUuid = "layoutServiceDemo-" + UUID.randomUUID(); + private final static String javaConnectUuid = "layoutServiceDemoJava-" + UUID.randomUUID(); + + private DesktopConnection desktopConnection; + private CountDownLatch latch = new CountDownLatch(1); + private JFrame mainWindow; + private JButton btnCreateOpenfinWindow; + private JButton btnCreateJavaWindow; + private Application application; + + private JSONArray serviceConfig = new JSONArray(); + private Map childFrames = new HashMap(); + private Map childFxFrames = new HashMap(); + private WindowAdapter childFrameCleanListener; + private JButton btnCreateFramelessJavaWindow; + private JButton btnCreateJavaFxWindow; + + LayoutServiceDemo() { + try { + this.createMainWindow(); + this.launchOpenfin(); + + this.childFrameCleanListener = new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + super.windowClosed(e); + LayoutFrame frame = (LayoutFrame) e.getWindow(); + childFrames.remove(frame.getWindowName()); + } + }; + } + catch (Exception e) { + e.printStackTrace(); + } + } + + void createMainWindow() { + this.mainWindow = new JFrame("Layout Service Demo"); + this.mainWindow.setResizable(false); + this.mainWindow.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + this.mainWindow.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent we) { + try { + childFrames.values().forEach(frame -> { + frame.cleanup(); + }); + childFxFrames.values().forEach(frame -> { + frame.cleanup(); + }); + application.close(); + Thread.sleep(1000); + OpenFinRuntime runtime = new OpenFinRuntime(desktopConnection); + runtime.exit(); + Thread.sleep(1000); + java.lang.System.exit(0); + } + catch (Exception de) { + de.printStackTrace(); + } + } + }); + + this.btnCreateOpenfinWindow = new JButton("Create Openfin Window"); + this.btnCreateOpenfinWindow.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + createOpenfinWindow(); + } + }); + this.btnCreateJavaWindow = new JButton("Create Java Window"); + this.btnCreateJavaWindow.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + createJavaWindow(); + } + catch (DesktopException e1) { + e1.printStackTrace(); + } + } + }); + this.btnCreateFramelessJavaWindow = new JButton("Create Frameless Java Window"); + this.btnCreateFramelessJavaWindow.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + createFramelessJavaWindow(); + } + catch (DesktopException e1) { + e1.printStackTrace(); + } + } + }); + this.btnCreateJavaFxWindow = new JButton("Create JavaFX Window"); + this.btnCreateJavaFxWindow.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + createJavaFxWindow(); + } + }); + + this.btnCreateOpenfinWindow.setEnabled(false); + this.btnCreateJavaWindow.setEnabled(false); + this.btnCreateFramelessJavaWindow.setEnabled(false); + this.btnCreateJavaFxWindow.setEnabled(false); + JPanel contentPnl = new JPanel(new BorderLayout(10, 10)); + contentPnl.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER)); + pnl.add(btnCreateOpenfinWindow); + pnl.add(btnCreateJavaWindow); + if (System.getProperty("com.openfin.demo.layout.frameless") != null) { + // This example is experimental and not available yet + pnl.add(btnCreateFramelessJavaWindow); + } + pnl.add(btnCreateJavaFxWindow); + + contentPnl.add(new JLabel("Undock Openfin windows with global hotkey (CTRL+SHIFT+U or CMD+SHIFT+U)"), + BorderLayout.NORTH); + contentPnl.add(pnl, BorderLayout.CENTER); + + this.mainWindow.getContentPane().add(contentPnl); + + this.mainWindow.pack(); + this.mainWindow.setLocationRelativeTo(null); + this.mainWindow.setVisible(true); + } + + void launchOpenfin() throws DesktopException, DesktopIOException, IOException, InterruptedException { + RuntimeConfiguration config = new RuntimeConfiguration(); + String rvm = System.getProperty("com.openfin.demo.layout.rvm"); + if (rvm != null) { + config.setLaunchRVMPath(rvm); + } + config.setRuntimeVersion("alpha"); + config.setAdditionalRuntimeArguments("--v=1 "); + serviceConfig = new JSONArray(); + JSONObject layout = new JSONObject(); + layout.put("name", "layouts"); +// layout.put("manifestUrl", "http://localhost:8081/app3.json"); + JSONObject scfg = new JSONObject(); + JSONObject sfeatures = new JSONObject(); + sfeatures.put("dock", true); + sfeatures.put("tab", true); + scfg.put("features", sfeatures); + layout.put("config", scfg); + serviceConfig.put(0, layout); + config.addConfigurationItem("services", serviceConfig); + + JSONObject startupApp = new JSONObject(); + startupApp.put("uuid", appUuid); + startupApp.put("name", appUuid); + startupApp.put("url", "about:blank"); + startupApp.put("autoShow", false); + config.setStartupApp(startupApp); + + this.desktopConnection = new DesktopConnection(javaConnectUuid); + this.desktopConnection.connect(config, this, 60); + latch.await(); + } + + void createApplication(String name, String uuid, String url, AckListener listener) { + ApplicationOptions appOpt = new ApplicationOptions(name, uuid, url); + WindowOptions mainWindowOptions = new WindowOptions(); + mainWindowOptions.setAutoShow(false); + appOpt.setMainWindowOptions(mainWindowOptions); + appOpt.put("services", serviceConfig); + + this.application = new Application(appOpt, this.desktopConnection, new AckListener() { + @Override + public void onSuccess(Ack ack) { + application.run(listener); + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + btnCreateOpenfinWindow.setEnabled(true); + btnCreateJavaWindow.setEnabled(true); + btnCreateFramelessJavaWindow.setEnabled(true); + btnCreateJavaFxWindow.setEnabled(true); + } + }); + } + + @Override + public void onError(Ack ack) { + } + }); + } + + void createJavaWindow() throws DesktopException { + String windowName = "Java-" + UUID.randomUUID().toString(); + LayoutFrame frame = new LayoutFrame(this.desktopConnection, appUuid, windowName); + this.childFrames.put(windowName, frame); + frame.addWindowListener(this.childFrameCleanListener); + } + + void createFramelessJavaWindow() throws DesktopException { + String windowName = "Java-" + UUID.randomUUID().toString(); + LayoutFrame frame = new LayoutFrame(this.desktopConnection, appUuid, windowName, true); + this.childFrames.put(windowName, frame); + frame.addWindowListener(this.childFrameCleanListener); + } + + void createJavaFxWindow() { + String windowName = "JavaFX-" + UUID.randomUUID().toString(); + FxLayoutFrame frame = new FxLayoutFrame(this.desktopConnection, appUuid, windowName); + this.childFxFrames.put(windowName, frame); + } + + void createOpenfinWindow() { + try { + WindowOptions winOpts = new WindowOptions(); + winOpts.setAutoShow(true); + winOpts.setDefaultHeight(480); + winOpts.setDefaultWidth(640); + winOpts.setResizable(true); + winOpts.setFrame(true); + winOpts.setName(UUID.randomUUID().toString()); + String url = java.lang.System.getProperty("com.openfin.demo.layout.url"); + winOpts.setUrl(url == null ? "https://openfin.co" : url); + application.createChildWindow(winOpts, new AckListener() { + @Override + public void onSuccess(Ack ack) { + } + + @Override + public void onError(Ack ack) { + System.out.println("unable to create openfin window: " + ack.getReason()); + } + }); + } + catch (DesktopException e) { + e.printStackTrace(); + } + } + + @Override + public void onReady() { + this.application = Application.wrap(appUuid, this.desktopConnection); + btnCreateOpenfinWindow.setEnabled(true); + btnCreateJavaWindow.setEnabled(true); + btnCreateFramelessJavaWindow.setEnabled(true); + btnCreateJavaFxWindow.setEnabled(true); + } + + @Override + public void onClose(String error) { + latch.countDown(); + } + + @Override + public void onError(String reason) { + } + + @Override + public void onMessage(String message) { + } + + @Override + public void onOutgoingMessage(String message) { + } + + public static void main(String[] args) { + new LayoutServiceDemo(); + } +} diff --git a/src/main/java/com/openfin/desktop/demo/MemoryProfile.java b/src/main/java/com/openfin/desktop/demo/MemoryProfile.java new file mode 100644 index 0000000..0b22811 --- /dev/null +++ b/src/main/java/com/openfin/desktop/demo/MemoryProfile.java @@ -0,0 +1,96 @@ +package com.openfin.desktop.demo; + +import com.openfin.desktop.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + + +/** + * This class can be used to profile memory usage of Java Adapter for communicating with Runtime. The initial version + * just keeps calling getMachineId API. It can easily extended to test other APIs. + * + * VisualVM, available from https://visualvm.github.io/, can be used to monitor memory usgage while this code is running + */ + +public class MemoryProfile { + private final static Logger logger = LoggerFactory.getLogger(MemoryProfile.class.getName()); + + public static void main(String[] args) { + RuntimeConfiguration runtimeConfiguration = new RuntimeConfiguration(); + String connectionUuid = MemoryProfile.class.getName(); + String desktopVersion = java.lang.System.getProperty("com.openfin.demo.version"); + if (desktopVersion == null) { + desktopVersion = "stable"; + } + runtimeConfiguration.setRuntimeVersion(desktopVersion); + try { + final DesktopConnection desktopConnection = new DesktopConnection(connectionUuid); + DesktopStateListener listener = new DesktopStateListener() { + @Override + public void onReady() { + launchThread(desktopConnection); + } + @Override + public void onClose(String error) { + + } + @Override + public void onError(String reason) { + logger.error(String.format("onError %s", reason)); + } + + @Override + public void onMessage(String message) { + } + @Override + public void onOutgoingMessage(String message) { + } + }; + desktopConnection.connect(runtimeConfiguration, listener, 50); + } catch (Exception e) { + logger.error("", e); + } + } + + private static void launchThread(DesktopConnection desktopConnection) { + Thread t = new Thread() { + @Override + public void run() { + OpenFinRuntime openfinSystem = new OpenFinRuntime(desktopConnection); + AtomicInteger callCount = new AtomicInteger(); + AtomicBoolean shouldRun = new AtomicBoolean(true); + while (shouldRun.get()) { + try { + CountDownLatch latch = new CountDownLatch(1); + openfinSystem.getMachineId(new AckListener() { + @Override + public void onSuccess(Ack ack) { + if (ack.isSuccessful()) { + logger.info(String.format("API call count %d", callCount.incrementAndGet())); + latch.countDown(); + } else { + logger.error(String.format("API failed %s", ack.getReason())); + shouldRun.set(false); + } + } + @Override + public void onError(Ack ack) { + logger.error(String.format("API failed %s", ack.getReason())); + shouldRun.set(false); + } + }); + latch.await(1, TimeUnit.SECONDS); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + }; + t.start(); + } +} diff --git a/src/main/java/com/openfin/desktop/demo/NoGui.java b/src/main/java/com/openfin/desktop/demo/NoGui.java index f4421f0..3076fff 100644 --- a/src/main/java/com/openfin/desktop/demo/NoGui.java +++ b/src/main/java/com/openfin/desktop/demo/NoGui.java @@ -57,7 +57,7 @@ public void onError(Ack ack) { } @Override - public void onClose() { + public void onClose(String error) { System.out.println("Main.onClose"); } @@ -76,7 +76,9 @@ public void onOutgoingMessage(String message) { System.out.println("Main.onOutgoingMessage"); } }; - desktopConnection.connectToVersion("6.49.12.17", listener, 5000); + RuntimeConfiguration cfg = new RuntimeConfiguration(); + cfg.setRuntimeVersion("stable"); + desktopConnection.connect(cfg, listener, 50); try { // keep Runtime running for 10 seconds diff --git a/src/main/java/com/openfin/desktop/demo/NotificationServiceDemo.java b/src/main/java/com/openfin/desktop/demo/NotificationServiceDemo.java new file mode 100644 index 0000000..30d5c3f --- /dev/null +++ b/src/main/java/com/openfin/desktop/demo/NotificationServiceDemo.java @@ -0,0 +1,269 @@ +package com.openfin.desktop.demo; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.IOException; +import java.util.Date; +import java.util.UUID; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; + +import org.json.JSONObject; + +import com.openfin.desktop.DesktopConnection; +import com.openfin.desktop.DesktopException; +import com.openfin.desktop.DesktopIOException; +import com.openfin.desktop.DesktopStateListener; +import com.openfin.desktop.RuntimeConfiguration; +import com.openfin.desktop.notifications.ButtonOptions; +import com.openfin.desktop.notifications.NotificationActionResult; +import com.openfin.desktop.notifications.NotificationIndicator; +import com.openfin.desktop.notifications.NotificationOptions; +import com.openfin.desktop.notifications.Notifications; +import com.openfin.desktop.notifications.events.NotificationActionEvent; + +public class NotificationServiceDemo { + + private JFrame demoWindow; + private DesktopConnection desktopConnection; + private JPanel glassPane; + private Notifications notifications; + + public NotificationServiceDemo() { + this.demoWindow = new JFrame("OpenFin Notification Service Demo"); + this.demoWindow.setContentPane(this.createContentPanel()); + this.demoWindow.setGlassPane(this.createGlassPane()); + this.demoWindow.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + this.demoWindow.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + if (desktopConnection != null) { + try { + desktopConnection.disconnect(); + } + catch (DesktopException e1) { + e1.printStackTrace(); + } + } + } + }); + + this.demoWindow.pack(); + this.demoWindow.setLocationRelativeTo(null); + this.demoWindow.setVisible(true); + this.glassPane.setVisible(true); + this.initOpenFin(); + } + + private void initOpenFin() { + try { + this.desktopConnection = new DesktopConnection("OpenFin Notification Service Demo"); + RuntimeConfiguration config = new RuntimeConfiguration(); + config.setRuntimeVersion("stable"); + this.desktopConnection.connect(config, new DesktopStateListener() { + + @Override + public void onReady() { + notifications = new Notifications(desktopConnection); + + + notifications.addEventListener(Notifications.EVENT_TYPE_ACTION, ne ->{ + NotificationActionEvent actionEvent = (NotificationActionEvent) ne; + NotificationActionResult actionResult = actionEvent.getResult(); + System.out.println("actionResult: notificationId: " + actionEvent.getNotificationOptions().getId() + ", user clicked on btn: " + actionResult.getString("btn")); + }); + + SwingUtilities.invokeLater(()->{ + glassPane.setVisible(false); + }); + } + + @Override + public void onClose(String error) { + System.exit(0); + } + + @Override + public void onError(String reason) { + + } + + @Override + public void onMessage(String message) { + + } + + @Override + public void onOutgoingMessage(String message) { + + } + + }, 60); + + } + catch (DesktopException | DesktopIOException | IOException e) { + e.printStackTrace(); + } + finally { + + } + } + + private JPanel createGlassPane() { + this.glassPane = new JPanel(new BorderLayout()); + JLabel l = new JLabel("Loading, please wait......"); + l.setHorizontalAlignment(JLabel.CENTER); + this.glassPane.add(l, BorderLayout.CENTER); + this.glassPane.setBackground(Color.LIGHT_GRAY); + return this.glassPane; + } + + + private JPanel createToggleNotificationCenterPanel() { + JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER)); + pnl.setBorder(BorderFactory.createTitledBorder("Notification Center")); + JButton btnToggleNotificationCenter = new JButton("Toggle Notification Center"); + btnToggleNotificationCenter.addActionListener(e->{ + this.notifications.toggleNotificationCenter(); + }); + JButton btnClearAll = new JButton("Clear All"); + btnClearAll.addActionListener(e->{ + this.notifications.clearAll(); + }); + pnl.add(btnToggleNotificationCenter); + pnl.add(btnClearAll); + return pnl; + } + + private JPanel createCreateNotificationPanel() { + JPanel pnl = new JPanel(new BorderLayout()); + pnl.setBorder(BorderFactory.createTitledBorder("Notification")); + + JTextField tfTitle = new JTextField("Title"); + JTextField tfBody = new JTextField("Body"); + JTextField tfCategory = new JTextField("Category"); + JTextField tfIcon = new JTextField("https://openfin.co/favicon-32x32.png"); + JTextField tfIndicatorText = new JTextField("Hello From Java"); + JTextField tfExpiresInSecs = new JTextField("60"); + + JComboBox cbSticky = new JComboBox<>(); + cbSticky.addItem(NotificationOptions.STICKY_STICKY); + cbSticky.addItem(NotificationOptions.STICKY_TRANSIENT); + + JComboBox cbIndicator = new JComboBox<>(); + cbIndicator.addItem(NotificationIndicator.TYPE_FAILURE); + cbIndicator.addItem(NotificationIndicator.TYPE_WARNING); + cbIndicator.addItem(NotificationIndicator.TYPE_SUCCESS); + cbIndicator.setSelectedIndex(2); + + JPanel pnlCenter = new JPanel(new GridBagLayout()); + GridBagConstraints gbConst = new GridBagConstraints(); + gbConst.gridx = 0; + gbConst.gridy = 0; + gbConst.weightx = 0; + gbConst.insets = new Insets(5, 5, 5, 5); + gbConst.anchor = GridBagConstraints.EAST; + pnlCenter.add(new JLabel("Title"), gbConst); + gbConst.gridy++; + pnlCenter.add(new JLabel("Body"), gbConst); + gbConst.gridy++; + pnlCenter.add(new JLabel("Category"), gbConst); + gbConst.gridy++; + pnlCenter.add(new JLabel("Icon"), gbConst); + gbConst.gridy++; + pnlCenter.add(new JLabel("Sticky"), gbConst); + gbConst.gridy++; + pnlCenter.add(new JLabel("Indicator"), gbConst); + gbConst.gridy++; + pnlCenter.add(new JLabel("Indicator Text"), gbConst); + gbConst.gridy++; + pnlCenter.add(new JLabel("Expires (in seconds)"), gbConst); + gbConst.gridx = 1; + gbConst.gridy = 0; + gbConst.weightx = 0.5; + gbConst.insets = new Insets(5, 0, 5, 5); + gbConst.fill = GridBagConstraints.BOTH; + pnlCenter.add(tfTitle, gbConst); + gbConst.gridy++; + pnlCenter.add(tfBody, gbConst); + gbConst.gridy++; + pnlCenter.add(tfCategory, gbConst); + gbConst.gridy++; + pnlCenter.add(tfIcon, gbConst); + gbConst.gridy++; + pnlCenter.add(cbSticky, gbConst); + gbConst.gridy++; + pnlCenter.add(cbIndicator, gbConst); + gbConst.gridy++; + pnlCenter.add(tfIndicatorText, gbConst); + gbConst.gridy++; + pnlCenter.add(tfExpiresInSecs, gbConst); + gbConst.weighty = 0.5; + gbConst.gridy++; + pnlCenter.add(new JLabel(), gbConst); + + + JButton btnCreate = new JButton("Create Notification"); + btnCreate.addActionListener(e->{ + NotificationOptions opt = new NotificationOptions(tfTitle.getText(), tfBody.getText(), tfCategory.getText()); + String icon = tfIcon.getText().trim(); + if (!icon.isEmpty()) { + opt.setIcon(icon); + } + opt.setSticky((String) cbSticky.getSelectedItem()); + NotificationIndicator indicatorOpts = new NotificationIndicator((String) cbIndicator.getSelectedItem()); + String indicatorText = tfIndicatorText.getText().trim(); + if (!indicatorText.isEmpty()) { + indicatorOpts.setText(indicatorText); + } + opt.setIndicator(indicatorOpts); + + String expires = tfExpiresInSecs.getText().trim(); + if (!expires.isEmpty()) { + opt.setExpires(new Date(System.currentTimeMillis() + (1000 * (Integer.parseInt(expires))))); + } + + ButtonOptions bo1 = new ButtonOptions("Button 1"); + bo1.setOnClick(new NotificationActionResult(new JSONObject().put("btn", "btn1"))); + ButtonOptions bo2 = new ButtonOptions("Button 2"); + bo2.setOnClick(new NotificationActionResult(new JSONObject().put("btn", "btn2"))); + bo2.setCta(true); + opt.setButtons(bo1, bo2); + + this.notifications.create(opt); + }); + JPanel pnlBottom = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + pnlBottom.add(btnCreate); + pnl.add(pnlCenter, BorderLayout.CENTER); + pnl.add(pnlBottom, BorderLayout.SOUTH); + return pnl; + } + + private JPanel createContentPanel() { + JPanel p = new JPanel(new BorderLayout()); + p.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + p.setPreferredSize(new Dimension(550, 400)); + p.add(this.createToggleNotificationCenterPanel(), BorderLayout.NORTH); + p.add(this.createCreateNotificationPanel(), BorderLayout.CENTER); + return p; + } + + public static void main(String[] args) { + new NotificationServiceDemo(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/openfin/desktop/demo/OpenFinDesktopDemo.java b/src/main/java/com/openfin/desktop/demo/OpenFinDesktopDemo.java index d18ecc6..d849a82 100644 --- a/src/main/java/com/openfin/desktop/demo/OpenFinDesktopDemo.java +++ b/src/main/java/com/openfin/desktop/demo/OpenFinDesktopDemo.java @@ -6,6 +6,9 @@ import com.openfin.desktop.animation.AnimationTransitions; import com.openfin.desktop.animation.OpacityTransition; import com.openfin.desktop.animation.PositionTransition; +import com.openfin.desktop.notifications.*; +import com.openfin.desktop.notifications.NotificationOptions; +import com.openfin.desktop.notifications.events.NotificationActionEvent; import info.clearthought.layout.TableLayout; import javax.swing.*; @@ -19,6 +22,8 @@ import java.util.ArrayList; import java.util.HashMap; +import jdk.nashorn.internal.scripts.JO; +import org.json.JSONArray; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -61,7 +66,8 @@ public class OpenFinDesktopDemo extends JPanel implements ActionListener, Window protected JButton largerButton, smallerButton, upButton, downButton, rightButton, leftButton; protected JButton createApplication; - protected JButton createRfq; + protected JButton createNotification; + private Notifications notifications; protected JList activeApplications; protected java.util.List appOptionsList; @@ -116,13 +122,13 @@ private void initDesktopConnection() throws DesktopException { securityRealm = java.lang.System.getProperty("com.openfin.demo.security.realm"); } if (securityRealm != null) { - this.desktopConnection.setRuntimeSecurityRealm(securityRealm); this.runtimeConfiguration.setSecurityRealm(securityRealm); } String desktopVersion = java.lang.System.getProperty("com.openfin.demo.version"); if (desktopVersion == null) { desktopVersion = "stable"; } + this.runtimeConfiguration.setLocalManifestFileName("OpenFinJavaDemo"); this.runtimeConfiguration.setRuntimeVersion(desktopVersion); String fallBackVersion = java.lang.System.getProperty("com.openfin.demo.fallBackVersion"); @@ -134,17 +140,52 @@ private void initDesktopConnection() throws DesktopException { updateMessagePanel("Additional RVM arguments: " + rvmArgs); this.runtimeConfiguration.setAdditionalRvmArguments(rvmArgs); } - this.runtimeConfiguration.setRdmURL(java.lang.System.getProperty("com.openfin.demo.rdmURL")); - this.runtimeConfiguration.setRuntimeAssetURL(java.lang.System.getProperty("com.openfin.demo.assetsURL")); - this.runtimeConfiguration.setAdditionalRuntimeArguments("--v=1 --no-sandbox "); // enable additional logging + this.runtimeConfiguration.setAdditionalRuntimeArguments("--v=1 "); // enable additional logging this.runtimeConfiguration.setDevToolsPort(9090); - this.runtimeConfiguration.setLicenseKey("my-license-key"); + + JSONObject startupApp = new JSONObject(); + startupApp.put("uuid", "DEMO-JAVA"); + startupApp.put("name", "DEMO-JAVA"); + startupApp.put("url", "https://cdn.openfin.co/process-manager/index.html"); + startupApp.put("autoShow", true); + + String licenseKey = java.lang.System.getProperty("com.openfin.demo.licenseKey"); + if (licenseKey != null) { + this.runtimeConfiguration.setLicenseKey(licenseKey); + } JSONObject myconfig = new JSONObject(); - myconfig.put("key1", "value1"); - myconfig.put("PI", 3.14); +// this.runtimeConfiguration.setManifestLocation("https://cdn.openfin.co/process-manager/app.json"); +// myconfig.put("key1", "value1"); +// myconfig.put("PI", 3.14); this.runtimeConfiguration.addConfigurationItem("myconfig", myconfig); } + private void addCustomConfig(JSONObject startupApp) { + JSONObject defaultDomainSettings = new JSONObject(); + JSONArray rules = new JSONArray(); + JSONObject rule1 = new JSONObject(); + JSONArray matchList = new JSONArray(); + matchList.put("*/*.example.com"); + rule1.put("match", matchList); + JSONObject options = new JSONObject(); + JSONObject downloadSettings = new JSONObject(); + JSONArray downloadSettingsRules = new JSONArray(); + JSONObject downloadSettingsRule1 = new JSONObject(); + JSONArray matchList1 = new JSONArray(); + matchList1.put("*://*/*.png"); + matchList1.put("*://*/*.jpg"); + downloadSettingsRule1.put("match", matchList1); + downloadSettingsRule1.put("behavior", "no-prompt"); + downloadSettingsRules.put(downloadSettingsRule1); + downloadSettings.put("rules", downloadSettingsRules); + options.put("downloadSettings", downloadSettings); + rule1.put("options", options); + rules.put(rule1); + defaultDomainSettings.put("rules", rules); + startupApp.put("defaultDomainSettings", defaultDomainSettings); + this.runtimeConfiguration.setStartupApp(startupApp); + } + private JPanel layoutLeftPanel() { JPanel panel = new JPanel(); double size[][] = {{TableLayout.FILL}, {160, 30, TableLayout.FILL}}; @@ -195,17 +236,17 @@ private JPanel layoutActionButtonPanel() { createApplication = new JButton("Create Application"); createApplication.setActionCommand("create-application"); - createRfq = new JButton("Create RFQ"); - createRfq.setActionCommand("create-rfq"); + createNotification = new JButton("Create Notification"); + createNotification.setActionCommand("create-notification"); close.addActionListener(this); launch.addActionListener(this); createApplication.addActionListener(this); - createRfq.addActionListener(this); + createNotification.addActionListener(this); buttonPanel.add(topPanel, "0,0"); buttonPanel.add(createApplication, "0,1"); -// buttonPanel.add(createRfq, "0,2"); + buttonPanel.add(createNotification, "0,2"); return buttonPanel; } @@ -363,6 +404,12 @@ public void windowOpened(WindowEvent e) { @Override public void windowClosing(WindowEvent e) { closeDesktop(); + try { + Thread.sleep(1000); + java.lang.System.exit(0); + } catch (Exception ex) { + ex.printStackTrace(); + } } @Override @@ -447,6 +494,14 @@ private void createAdminApplication() throws DesktopException { updateMessagePanel("Creating InterAppBus"); bus = desktopConnection.getInterApplicationBus(); openfinSystem = new System(desktopConnection); + + this.notifications = new Notifications(desktopConnection); + this.notifications.addEventListener(Notifications.EVENT_TYPE_ACTION, ne ->{ + NotificationActionEvent actionEvent = (NotificationActionEvent) ne; + NotificationActionResult actionResult = actionEvent.getResult(); + java.lang.System.out.println("actionResult: notificationId: " + actionEvent.getNotificationOptions().getId() + ", user clicked on btn: " + actionResult.getString("btn")); + }); + updateMessagePanel("Connected to Desktop"); setMainButtonsEnabled(true); @@ -500,8 +555,8 @@ public void onReady() { } @Override - public void onClose() { - updateMessagePanel("Connection closed"); + public void onClose(String error) { + updateMessagePanel(String.format("Connection closed %s", error)); resetUI(); } @@ -516,24 +571,24 @@ public void onError(String reason) { @Override public void onMessage(String message) { - updateMessagePanel("-->FROM DESKTOP-" + message); +// updateMessagePanel("-->FROM DESKTOP-" + message); } @Override public void onOutgoingMessage(String message) { - updateMessagePanel("<--TO DESKTOP-" + message); +// updateMessagePanel("<--TO DESKTOP-" + message); } }; try { if (this.desktopPort > 0) { - this.runtimeConfiguration.setRuntimePort(9696); + this.runtimeConfiguration.setRuntimePort(this.desktopPort); updateMessagePanel("Connecting to Runtime already running at port " + this.desktopPort); this.runtimeConfiguration.setMaxMessageSize(1024*1024); - desktopConnection.connect(this.runtimeConfiguration, listener, 10); + desktopConnection.connect(this.runtimeConfiguration, listener, 20); } else { updateMessagePanel("Connecting to version " + this.runtimeConfiguration.getRuntimeVersion()); - desktopConnection.connect(this.runtimeConfiguration, listener, 10); + desktopConnection.connect(this.runtimeConfiguration, listener, 20); } } catch (Exception ex) { ex.printStackTrace(); @@ -552,6 +607,9 @@ public void actionPerformed(ActionEvent e) { if (options != null) { createApplication(options); } + } else if ("create-notification".equals(e.getActionCommand())) { + createNotification(); + bus.send("*", "test", "Hello from Java"); } else if ("minimize".equals(e.getActionCommand())) { if (this.selectedApplication != null) { this.selectedApplication.getWindow().minimize(); @@ -608,11 +666,25 @@ public void onError(Ack ack) { } } + private void createNotification() throws Exception { + NotificationOptions opt = new NotificationOptions("Notification from Java", "Write once, run everywhere", "Category"); + opt.setSticky(NotificationOptions.STICKY_STICKY); + opt.setIndicator(new NotificationIndicator(NotificationIndicator.TYPE_SUCCESS)); + ButtonOptions bo1 = new ButtonOptions("Button 1"); + bo1.setOnClick(new NotificationActionResult(new JSONObject().put("btn", "btn1"))); + ButtonOptions bo2 = new ButtonOptions("Button 2"); + bo2.setOnClick(new NotificationActionResult(new JSONObject().put("btn", "btn2"))); + bo2.setCta(true); + opt.setButtons(bo1, bo2); + + this.notifications.create(opt); + } + private void testOpacity() { this.selectedApplication.getWindow().getOptions(new AsyncCallback() { @Override public void onSuccess(WindowOptions result) { - java.lang.System.out.println("getOptions: " + result.toJsonObject().toString()); + java.lang.System.out.println("getOptions: " + result.getJson().toString()); double opacity = result.getOpacity() > 0.5 ? 0.5 : 1; WindowOptions options = new WindowOptions(); options.setOpacity(opacity); @@ -637,18 +709,6 @@ private void testRoundedCorners() { e.printStackTrace(); } } - private void testRoundedCorners2() { - this.selectedApplication.getWindow().getOptions(new AsyncCallback() { - @Override - public void onSuccess(WindowOptions result) { - java.lang.System.out.println("getOptions: " + result.toJsonObject().toString()); - int width = result.getCornerRoundingWidth() > 0 ? 0 : 10; - WindowOptions options = new WindowOptions(); - options.setCornerRounding(width, width); - selectedApplication.getWindow().updateOptions(options, null); - } - }, null); - } private void testOpacityAnimation() { this.selectedApplication.getWindow().getOptions(new AsyncCallback() { @@ -686,7 +746,7 @@ private void setMainButtonsEnabled(boolean enabled) { close.setEnabled(enabled); createApplication.setEnabled(enabled); - createRfq.setEnabled(enabled); + createNotification.setEnabled(enabled); } @@ -701,7 +761,7 @@ private void setAppButtonsEnabled(boolean enabled) { } private void createApplication(final ApplicationOptions options) { - options.getMainWindowOptions().setContextMenu(false); + options.getMainWindowOptions().setContextMenu(true); Application app = new Application(options, desktopConnection, new AckListener() { @Override public void onSuccess(Ack ack) { diff --git a/src/main/java/com/openfin/desktop/demo/OpenFinDockingDemo.java b/src/main/java/com/openfin/desktop/demo/OpenFinDockingDemo.java deleted file mode 100644 index a33aa47..0000000 --- a/src/main/java/com/openfin/desktop/demo/OpenFinDockingDemo.java +++ /dev/null @@ -1,516 +0,0 @@ -package com.openfin.desktop.demo; - -import com.openfin.desktop.DockingManager; -import com.openfin.desktop.*; -import info.clearthought.layout.TableLayout; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; -import java.io.*; -import java.lang.System; -import java.util.Arrays; - -/** - * Example of snap&dock Java window with OpenFin html5 window - * - * Move windows close to each other so they snap, and release mouse to dock 2 windows. - * - * This example use snap and dock library at https://github.com/openfin/java-snap-and-dock. - * - * Steps to implement snap&dock in this example - * - * 1. Launch OpenFin Runtime, as in startOpenFinRuntime - * 2. Create an instance of DockingManager - * 2. Launch a HTML5 app and register with DockingManager as in launchHTMLApps - * 3. Register Java window as in DockingManager registerJavaWindow - * - * All windows can receive notification when it is docked by subscribing to 'window-docked' topic. It can also request to be undocked - * by sending a message to Docking Manager. Please refer to document of Snap&Dock library for more into - * - * Created by wche on 2/28/15. - * - */ -public class OpenFinDockingDemo extends JPanel implements ActionListener, WindowListener { - private final static Logger logger = LoggerFactory.getLogger(OpenFinDockingDemo.class.getName()); - - private static JFrame jFrame; - protected JButton launch; - protected JButton close; - - protected JButton undockButton; - - // For a Java window to be dockable, it must be registered with Runtime as a child window of a HTML5 app. We are going to create - // a hidden HTML5 app, with javaParentAppUuid as UUID, as the parent app of all Java windows - protected String javaParentAppUuid = "Java Parent App"; - - protected String appUuid = "JavaDocking"; // UUID for desktopConnection - protected String javaWindowName = "Java Dock Window"; - protected String openfin_app_url = "https://cdn.openfin.co/examples/junit/SimpleDockingExample.html"; // source is in release/SimpleDockingExample.html - - protected DesktopConnection desktopConnection; - protected DockingManager dockingManager; - protected JTextField dockStatus; // show Ready to dock message - protected JTextArea status; - - public OpenFinDockingDemo() { - try { - this.desktopConnection = new DesktopConnection(appUuid); - } catch (DesktopException desktopError) { - desktopError.printStackTrace(); - } - setLayout(new BorderLayout()); - add(layoutCenterPanel(), BorderLayout.CENTER); - add(layoutLeftPanel(), BorderLayout.WEST); - setBorder(BorderFactory.createEmptyBorder(20,20,20,20)); - setMainButtonsEnabled(false); - setAppButtonsEnabled(false); - } - - private JPanel layoutLeftPanel() { - JPanel panel = new JPanel(); - double size[][] = {{410}, {120, 30, TableLayout.FILL}}; - panel.setLayout(new TableLayout(size)); - panel.add(layoutActionButtonPanel(), "0,0,0,0"); - panel.add(layoutDockStatus(), "0,1,0,1"); - panel.add(layoutStatusPanel(), "0, 2, 0, 2"); - return panel; - } - - private JTextField layoutDockStatus() { - this.dockStatus = new JTextField(); - this.dockStatus.setForeground(Color.RED); - return this.dockStatus; - } - - private JPanel layoutActionButtonPanel() { - JPanel buttonPanel = new JPanel(); - - JPanel topPanel = new JPanel(); - double size[][] = {{10, 190, 20, 190, 10}, {25, 10, 25, 10}}; - topPanel.setLayout(new TableLayout(size)); - topPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createBevelBorder(2), "Desktop")); - - launch = new JButton("Launch OpenFin"); - launch.setActionCommand("start"); - close = new JButton("Shutdown OpenFin"); - close.setActionCommand("close"); - topPanel.add(launch, "1,0,1,0"); - topPanel.add(close, "3,0,3,0"); - - undockButton = new JButton("Undock"); - undockButton.setActionCommand("undock-window"); - undockButton.setEnabled(false); - topPanel.add(undockButton, "1,2,1,2"); - - close.addActionListener(this); - launch.addActionListener(this); - undockButton.addActionListener(this); - - buttonPanel.add(topPanel, "0,0"); - return buttonPanel; - } - - private JPanel layoutCenterPanel() { - JPanel panel = new JPanel(); - double size[][] = {{TableLayout.FILL}, {150, 150, TableLayout.FILL}}; - panel.setLayout(new TableLayout(size)); - - return panel; - } - - protected JPanel layoutStatusPanel() { - //Simple status console - status = new JTextArea(); - status.setEditable(false); - status.setAutoscrolls(true); - status.setLineWrap(true); - JScrollPane statusPane = new JScrollPane(status); - statusPane.setVerticalScrollBarPolicy( - JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); - statusPane.getViewport().setOpaque(false); - statusPane.setOpaque(false); - statusPane.setBorder(BorderFactory.createEmptyBorder(5,15,15,15)); - - - - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout()); - panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createBevelBorder(2), "Status")); - panel.add(statusPane, BorderLayout.CENTER); - - return panel; - } - - @Override - public void windowOpened(WindowEvent e) { - } - - @Override - public void windowClosing(WindowEvent e) { - closeDesktop(); - } - - @Override - public void windowClosed(WindowEvent e) { - } - - @Override - public void windowIconified(WindowEvent e) { - } - - @Override - public void windowDeiconified(WindowEvent e) { - } - - @Override - public void windowActivated(WindowEvent e) { - } - - @Override - public void windowDeactivated(WindowEvent e) { - } - - private void updateMessagePanel(final String msg) { - if (SwingUtilities.isEventDispatchThread()) { - String t = ""; - if (status.getText().length() > 0) { - t = status.getText(); - } - StringBuilder b = new StringBuilder(); - b.append(msg).append("\n").append(t); - status.setText(b.toString()); - status.setCaretPosition(0); - } else { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - updateMessagePanel(msg); - } - }); - } - } - - - private void closeDesktop() { - if (desktopConnection != null && desktopConnection.isConnected()) { - try { - Application javaParentApp = Application.wrap(javaParentAppUuid, desktopConnection); - javaParentApp.close(); - dockingManager.dispose(); - Thread.sleep(2000); - desktopConnection.exit(); - desktopConnection = null; - } catch (Exception e) { - e.printStackTrace(); - } - } - - try { - Thread.sleep(2000); - System.exit(0); - } catch (InterruptedException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - - private void undockFromOtherWindows() { - try { - // send message to Docking Manager to undock me - JSONObject msg = new JSONObject(); - msg.put("applicationUuid", javaParentAppUuid); - msg.put("windowName", javaWindowName); - desktopConnection.getInterApplicationBus().publish("undock-window", msg); - - } catch (Exception e) { - e.printStackTrace(); - } - undockButton.setEnabled(false); - } - - /** - * - * Start OpenFin Runtime - * - */ - private void startOpenFinRuntime() { - try { - DesktopStateListener listener = new DesktopStateListener() { - @Override - public void onReady() { - onRuntimeReady(); - } - - @Override - public void onClose() { - updateMessagePanel("Connection closed"); - } - @Override - public void onError(String reason) { - updateMessagePanel("Connection failed: " + reason); - } - @Override - public void onMessage(String message) { - } - @Override - public void onOutgoingMessage(String message) { - } - }; - RuntimeConfiguration configuration = new RuntimeConfiguration(); - configuration.setDevToolsPort(9090); - configuration.setAdditionalRuntimeArguments(" --v=1 "); // enable additional logging from Runtime - String desktopVersion = java.lang.System.getProperty("com.openfin.demo.version"); - if (desktopVersion == null) { - desktopVersion = "stable"; - } - configuration.setRuntimeVersion(desktopVersion); - desktopConnection.connect(configuration, listener, 60); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void onRuntimeReady() { - try { - updateMessagePanel("Connection authorized."); - setMainButtonsEnabled(true); - this.dockingManager = new DockingManager(this.desktopConnection, this.javaParentAppUuid); - this.desktopConnection.getInterApplicationBus().subscribe("*", "window-docked", (uuid, topic, data) -> { - JSONObject event = (JSONObject) data; - String appUuid = event.getString("applicationUuid"); - String windowName = event.getString("windowName"); - updateMessagePanel(String.format("Window docked %s %s", appUuid, windowName)); - if (javaParentAppUuid.equals(appUuid) && javaWindowName.equals(windowName)) { - updateUndockButton(true); - } - }); - this.desktopConnection.getInterApplicationBus().subscribe("*", "window-undocked", (uuid, topic, data) -> { - JSONObject event = (JSONObject) data; - String appUuid = event.getString("applicationUuid"); - String windowName = event.getString("windowName"); - updateMessagePanel(String.format("Window undocked %s %s", appUuid, windowName)); - if (javaParentAppUuid.equals(appUuid) && javaWindowName.equals(windowName)) { - updateUndockButton(false); - } - }); - registerJavaWindow(); - launchHTMLApps(); - launchAnotherJavaApp(); - } catch (Exception e) { - logger.error("Error creating DockingManager", e); - } - } - - public void actionPerformed(java.awt.event.ActionEvent e) { - if ("start".equals(e.getActionCommand())) { - startOpenFinRuntime(); - } else if ("close".equals(e.getActionCommand())) { - closeDesktop(); - } else if ("undock-window".equals(e.getActionCommand())) { - undockFromOtherWindows(); - } - } - - - private void setMainButtonsEnabled(boolean enabled) { - launch.setEnabled(!enabled); - close.setEnabled(enabled); - } - - private void setAppButtonsEnabled(boolean enabled) { - } - - /** - * Register Java window with OpenFin Runtime - * - */ - private void registerJavaWindow() { - try { - // Java window needs to be assigned a HTML5 app as parent app in order for Runtime to control it. - // now we are creating a HTML5 app aith autoShow = false so it is hidden. - ApplicationOptions options = new ApplicationOptions(javaParentAppUuid, javaParentAppUuid, openfin_app_url); - options.setApplicationIcon("http://openfin.github.io/snap-and-dock/openfin.ico"); - WindowOptions mainWindowOptions = new WindowOptions(); - mainWindowOptions.setAutoShow(false); - mainWindowOptions.setDefaultHeight(50); - mainWindowOptions.setDefaultLeft(50); - mainWindowOptions.setDefaultTop(50); - mainWindowOptions.setDefaultWidth(50); - mainWindowOptions.setShowTaskbarIcon(false); - mainWindowOptions.setSaveWindowState(false); // set to false so all windows start at same initial positions for each run - options.setMainWindowOptions(mainWindowOptions); - launchHTMLApp(options, new AckListener() { - @Override - public void onSuccess(Ack ack) { - Application app = (Application) ack.getSource(); - logger.debug("Registering java window"); - dockingManager.registerJavaWindow(javaWindowName, jFrame, - new AckListener() { - @Override - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - undockButton.setEnabled(false); - } - } - @Override - public void onError(Ack ack) { - logger.error("Error registering Java window " + ack.getReason()); - } - }); - } - @Override - public void onError(Ack ack) { - logger.error("Error launching " + javaParentAppUuid); - } - }); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * - * Launching HTML5 apps and register docking manager - * - */ - private void launchHTMLApps() { - // launch 5 instances of same example app - int width = 300, height=200; - int gap = 50; // gap between windows at initial positions - for (int i = 0; i < 2; i++) { - try { - String uuid = String.format("docking-html-%d", i); - ApplicationOptions options = new ApplicationOptions(uuid, uuid, openfin_app_url); - options.setApplicationIcon("http://openfin.github.io/snap-and-dock/openfin.ico"); - WindowOptions mainWindowOptions = new WindowOptions(); - mainWindowOptions.setAutoShow(true); - mainWindowOptions.setDefaultHeight(height); - mainWindowOptions.setDefaultLeft(10 + i * (width + gap)); - mainWindowOptions.setDefaultTop(50); - mainWindowOptions.setDefaultWidth(width); - mainWindowOptions.setShowTaskbarIcon(true); - mainWindowOptions.setSaveWindowState(false); // set to false so all windows start at same initial positions for each run - options.setMainWindowOptions(mainWindowOptions); - launchHTMLApp(options, new AckListener() { - @Override - public void onSuccess(Ack ack) { - logger.debug(String.format("Successful launching %s", options.getUUID())); - Application app = (Application) ack.getSource(); - dockingManager.registerWindow(app.getWindow()); - } - @Override - public void onError(Ack ack) { - logger.error(String.format("Error launching %s %s", options.getUUID(), ack.getReason())); - } - }); - } catch (Exception e) { - logger.error("Error launching app", e); - } - } - } - - private void launchHTMLApp(ApplicationOptions options, AckListener ackListener) throws Exception { - logger.debug(String.format("Launching %s", options.getUUID())); - DemoUtils.runApplication(options, this.desktopConnection, ackListener); - } - - - private void launchAnotherJavaApp() { - Thread launchThread = new Thread() { - public void run() { - logger.debug(String.format("Launching docking.bat %s", DockingDemo2.class.getName())); - String[] command = {"docking.bat", DockingDemo2.class.getName()}; - ProcessBuilder probuilder = new ProcessBuilder( command ); - //You can set up your work directory - probuilder.directory(new File(".")); - try { -// Process process = probuilder.start(); -// //Read out dir output -// InputStream is = process.getInputStream(); -// InputStreamReader isr = new InputStreamReader(is); -// BufferedReader br = new BufferedReader(isr); -// String line; -// while ((line = br.readLine()) != null) { -// logger.debug(String.format("Java App output: %s", line)); -// } -// int exitValue = process.waitFor(); -// logger.debug(String.format("Java app exit code %d", exitValue)); - - Process process = Runtime.getRuntime().exec("cmd"); - OutputStream stdin = process.getOutputStream(); - InputStream stderr = process.getErrorStream(); - InputStream stdout = process.getInputStream(); - String line = "start docking.bat " + DockingDemo2.class.getName() + "\n"; - stdin.write(line.getBytes()); - stdin.flush(); - stdin.close(); - // clean up if any output in stdout - BufferedReader brCleanUp = - new BufferedReader(new InputStreamReader(stdout)); - while ((line = brCleanUp.readLine()) != null) { - logger.debug("[Stdout] " + line); - } - brCleanUp.close(); - // clean up if any output in stderr - brCleanUp = - new BufferedReader(new InputStreamReader(stderr)); - while ((line = brCleanUp.readLine()) != null) { - logger.info("[Stderr] " + line); - } - brCleanUp.close(); - } catch (Exception ex) { - logger.error("Error launch java app", ex); - } - } - }; - launchThread.start(); - } - - private void updateUndockButton(boolean enabled) { - this.undockButton.setEnabled(enabled); - if (enabled) { - this.dockStatus.setText("Docked. Click Unlock button to undock"); - } else { - this.dockStatus.setText(""); - } - } - - - private static void createAndShowGUI() { - //Create and set up the window. - jFrame = new JFrame("Java Docking Demo"); - jFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); - - //Create and set up the content pane. - OpenFinDockingDemo newContentPane = new OpenFinDockingDemo(); - newContentPane.setOpaque(true); //content panes must be opaque - jFrame.setContentPane(newContentPane); - jFrame.addWindowListener(newContentPane); - - //Display the window. - jFrame.pack(); - jFrame.setSize(470, 300); - jFrame.setLocation(100, 400); -// jFrame.setLocationRelativeTo(null); - jFrame.setResizable(false); - jFrame.setVisible(true); - } - - - /** - * - * @param args - */ - public static void main(String[] args) { - javax.swing.SwingUtilities.invokeLater(new Runnable() { - public void run() { - createAndShowGUI(); - } - }); - } - -} diff --git a/src/main/java/com/openfin/desktop/demo/OpenFinWindowTest.java b/src/main/java/com/openfin/desktop/demo/OpenFinWindowTest.java deleted file mode 100644 index f9bf642..0000000 --- a/src/main/java/com/openfin/desktop/demo/OpenFinWindowTest.java +++ /dev/null @@ -1,522 +0,0 @@ -package com.openfin.desktop.demo; - -import com.openfin.desktop.*; -import com.openfin.desktop.System; -import com.openfin.desktop.animation.AnimationTransitions; -import com.openfin.desktop.animation.PositionTransition; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.StringTokenizer; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import static junit.framework.Assert.*; -import static junit.framework.TestCase.fail; - -/** - * Created by wche on 1/20/16. - * - */ -public class OpenFinWindowTest { - private static Logger logger = LoggerFactory.getLogger(JUnitDemo.class.getName()); - - private static DesktopConnection desktopConnection; - - private static final String DESKTOP_UUID = "DESKTOP_UUID"; - - private static int windowUuidCounter = 0; - - //set this to around 2000ms in order to see the chromium windows - private final long SLEEP_FOR_HUMAN_OBSERVATION = 3000L; - - private static CountDownLatch openFinDisconnectedLatch = new CountDownLatch(1); - - @BeforeClass - public static void setup() throws Exception { - setupDesktopConnection(); - } - - @AfterClass - public static void teardown() throws Exception { - printf("teardown"); - if (desktopConnection.isConnected()) { - teardownDesktopConnection(); - } else { - printf("Not connected, no need to teardown"); - } - } - - private static void setupDesktopConnection() throws Exception { - CountDownLatch openFinConnectedLatch = new CountDownLatch(1); - // if RVM needs to download the version of Runtime specified, waitTime may need to be increased for slow download - int waitTime = 60; - String swaiTime = java.lang.System.getProperty("com.openfin.demo.runtime.connect.wait.time"); - if (swaiTime != null) { - waitTime = Integer.parseInt(swaiTime); - } - - desktopConnection = null; - desktopConnection = new DesktopConnection(DESKTOP_UUID); - desktopConnection.setAdditionalRuntimeArguments(" --v=1 "); // turn on Chromium debug log - String desktopVersion = java.lang.System.getProperty("com.openfin.demo.runtime.version"); - if (desktopVersion == null) { - desktopVersion = "5.44.10.26"; // 5.44.10.26 has fix for cross-app docking, which is required for windowsInShameGroupMoveTogether - } - desktopConnection.connectToVersion(desktopVersion, new DesktopStateListener() { - @Override - public void onReady() { - printf("Connected to OpenFin runtime"); - openFinConnectedLatch.countDown(); - openFinDisconnectedLatch = new CountDownLatch(1); - } - - @Override - public void onClose() { - printf("Connection to Runtime is closed"); - } - - @Override - public void onError(String reason) { - printf("Connection failed: %s", reason); - openFinDisconnectedLatch.countDown(); - } - - @Override - public void onMessage(String message) { - printf("openfin message: %s", message); - } - - @Override - public void onOutgoingMessage(String message) { - printf("openfin outgoing message: %s", message); - } - }, waitTime);//this timeout (in 4.40.2.9) is ignored. Not anymore in 5.44.2.2 - - printf("waiting for desktop to connect"); - openFinConnectedLatch.await(waitTime, TimeUnit.SECONDS); - - if (desktopConnection.isConnected()) { - printf("desktop connected"); - } else { - throw new RuntimeException("failed to initialise desktop connection"); - } - } - - private static void teardownDesktopConnection() throws Exception { - printf("teardownDesktopConnection"); - new System(desktopConnection).exit(); - // OpenFin update: wait for websocket to be disconnected so re-launch of OpenFin Runtime will work - openFinDisconnectedLatch.await(20, TimeUnit.SECONDS); - assertFalse(desktopConnection.isConnected()); - printf("desktop connection closed"); - } - - private Application openWindow(String uuid, String url) throws Exception { - //default options for all test windows - int top = 10; - int left = 10; - int width = 200; - int height = 300; - boolean withFrame = true; - boolean resizable = true; - return openWindow(uuid, url, left, top, width, height, withFrame, resizable); - } - - private Application openWindow(String uuid, String url, int left, int top, int width, int height, boolean withFrame, boolean resizable) throws Exception { - final WindowOptions windowOptions = new WindowOptions(); - windowOptions.setAutoShow(true); - windowOptions.setDefaultLeft(left); - windowOptions.setDefaultTop(top); - windowOptions.setDefaultHeight(height); - windowOptions.setDefaultWidth(width); - windowOptions.setFrame(withFrame); - windowOptions.setResizable(resizable); - - ApplicationOptions applicationOptions = new ApplicationOptions(uuid, uuid, url); - applicationOptions.setMainWindowOptions(windowOptions); - - //used to block JUnit thread until OpenFin has iniitialised - CountDownLatch windowCreatedLatch = new CountDownLatch(1); - - //if this reference gets set, something went wrong creating the window - final AtomicReference failedReason = new AtomicReference(); - - printf("creating new chromium window (uuid: %s) (left: %s) (top: %s) (width: %s) (height: %s) (withFrame: %s) (resizable: %s)", - uuid, left, top, width, height, withFrame, resizable); - - Application application = new Application(applicationOptions, desktopConnection, new AckListener() { - @Override - public void onSuccess(Ack ack) { - try { - Application application = (Application) ack.getSource(); - application.run(); - printf("window running: %s", application.getOptions().getUUID()); - application.getWindow().setBounds(left, top, width, height, new AckListener() { - @Override - public void onSuccess(Ack ack) { - printf("successfully set bounds (uuid: %s) (left: %s) (top: %s) (width: %s) (height: %s)", uuid, left, top, width, height); - } - - @Override - public void onError(Ack ack) { - printf("failed to set window bounds (uuid: %s)", uuid); - } - }); - printf("explicity setting bounds (uuid: %s) (left: %s) (top: %s) (width: %s) (height: %s)", uuid, left, top, width, height); - } catch (Exception e) { - failedReason.set("failed to run window: " + ack.getReason()); - } finally { - windowCreatedLatch.countDown(); - } - } - - @Override - public void onError(Ack ack) { - try { - failedReason.set("failed to open window: " + ack.getReason()); - } finally { - windowCreatedLatch.countDown(); - } - } - }); - - //wait for OpenFin callback - windowCreatedLatch.await(20, TimeUnit.SECONDS); - - if (failedReason.get() != null) { - throw new RuntimeException(failedReason.get()); - } else { - return application; - } - } - - private static synchronized String nextTestUuid() { - return String.format("test_uuid_%s", windowUuidCounter++); - } - - @Test - public void canStopAndRestartOpenFinDesktopConnection() throws Exception { - //setupDesktopConnection() called from setup() - teardownDesktopConnection(); - setupDesktopConnection(); - //teardownDesktopConnection() will be caled from teardown() - } - - @Test - public void throwingExceptionFromOpenFinThreadRecoversCleanly() throws Exception { - - Application application = openWindow(nextTestUuid(), "http://www.google.com"); - WindowBounds bounds1 = getWindowBounds(application.getWindow()); - - //throw an exception from the OpenFin event thread - final int delta = 10; - application.getWindow().moveBy(delta, delta, new AckListener() { - @Override - public void onSuccess(Ack ack) { - throw new RuntimeException("thrown intentionally - OpenFin should recover from this"); - } - @Override - public void onError(Ack ack) { - fail("could not open a window to run test: " + ack.getReason()); - } - }); - - try { - WindowBounds bounds2 = getWindowBounds(application.getWindow()); - assertEquals("window was not moved", new Integer(bounds1.getLeft() + delta), bounds2.getLeft()); - } catch (Throwable t) { - fail("OpenFin did not respond after an exception was thrown, caused by: " + t.getMessage()); - t.printStackTrace(); - } - application.close(); - } - - - - @Test - public void canOpenAndCloseMultipleWindowsWithDifferentUUIDS() throws Exception { - Application application1 = openWindow(nextTestUuid(), "http://www.google.com"); - Application application2 = openWindow(nextTestUuid(), "http://www.google.co.uk"); - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION);//allow the windows time to appear - application1.close(); - application2.close(); - } - - @Test - public void cannotOpenMultipleWindowsWithSameUUID() throws Exception { - Application application1 = null; - Application application2 = null; - try { - String uuid = nextTestUuid(); - application1 = openWindow(uuid, "http://www.google.com"); - application2 = openWindow(uuid, "http://www.google.co.uk"); - //above lines should throw an exception and not get past here - fail(); - } catch (Exception e) { - assertTrue(e.getMessage().contains("Application with specified UUID already exists")); - } finally { - if (application1 != null) application1.close(); - if (application2 != null) application2.close(); - } - } - - @Test - public void windowMoves() throws Exception { - Application application = openWindow(nextTestUuid(), "http://www.google.com"); - - //set the initial position of the window and check - CountDownLatch moveLatch = new CountDownLatch(1); - // OpenFin update: need to pass AckListener to make sure moveTo operations is completed before checking bounds - application.getWindow().moveTo(10, 20, new AckListener() { - @Override - public void onSuccess(Ack ack) { - moveLatch.countDown(); - } - @Override - public void onError(Ack ack) { - } - }); - moveLatch.await(5, TimeUnit.SECONDS); - WindowBounds initialBounds = getWindowBounds(application.getWindow()); - printf("initial bounds top:%s left:%s", initialBounds.getTop(), initialBounds.getLeft()); - assertEquals(10, initialBounds.getLeft().intValue()); - assertEquals(20, initialBounds.getTop().intValue()); - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - - //move the window and check again - // OpenFin update: need to pass AckListener to make sure moveTo operations is completed before checking bounds - CountDownLatch moveLatch2 = new CountDownLatch(1); - application.getWindow().moveTo(100, 200, new AckListener() { - @Override - public void onSuccess(Ack ack) { - moveLatch2.countDown(); - } - @Override - public void onError(Ack ack) { - } - }); - moveLatch2.await(5, TimeUnit.SECONDS); - WindowBounds movedBounds = getWindowBounds(application.getWindow()); - printf("moved bounds top:%s left:%s", movedBounds.getTop(), movedBounds.getLeft()); - - assertEquals(100, movedBounds.getLeft().intValue()); - assertEquals(200, movedBounds.getTop().intValue()); - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - } - - @Test - public void windowMovesWithAnimation() throws Exception { - Application application = openWindow(nextTestUuid(), "http://www.google.com"); - - //set the initial position of the window and check - CountDownLatch moveLatch = new CountDownLatch(1); - application.getWindow().moveTo(10, 20, new AckListener() { - @Override - public void onSuccess(Ack ack) { - moveLatch.countDown(); - } - @Override - public void onError(Ack ack) { - } - }); - moveLatch.await(5, TimeUnit.SECONDS); - WindowBounds initialBounds = getWindowBounds(application.getWindow()); - printf("initial bounds top:%s left:%s", initialBounds.getTop(), initialBounds.getLeft()); - assertEquals(10, initialBounds.getLeft().intValue()); - assertEquals(20, initialBounds.getTop().intValue()); - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - - //move the window and check again - CountDownLatch transitionLatch = new CountDownLatch(1); - AnimationTransitions transitions = new AnimationTransitions(); - transitions.setPosition(new PositionTransition(100, 200, 2000));//duration in millisecods - application.getWindow().animate(transitions, null, new AckListener() { - @Override - public void onSuccess(Ack ack) { - transitionLatch.countDown(); - } - - @Override - public void onError(Ack ack) { - //noop - } - }); - transitionLatch.await(20, TimeUnit.SECONDS); - - WindowBounds movedBounds = getWindowBounds(application.getWindow()); - printf("moved bounds top:%s left:%s", movedBounds.getTop(), movedBounds.getLeft()); - - assertEquals(100, movedBounds.getLeft().intValue()); - assertEquals(200, movedBounds.getTop().intValue()); - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - } - - @Test - public void windowEventListenersWork() throws Exception { - Application application = openWindow(nextTestUuid(), "http://www.google.com"); - - //as per the javadoc (https://cdn.openfin.co/docs/java/4.40.2/com/openfin/desktop/Window.html), the event names: - String events = "blurred bounds-changed bounds-changing closed close-requested disabled-frame-bounds-changed disabled-frame-bounds-changing focused frame-disabled frame-enabled group-changed hidden maximized minimized restored shown"; - - AtomicReference eventTypeRecieved = new AtomicReference(); - CountDownLatch onMinimiseEventLatch = new CountDownLatch(1); - - //register even handlers for all event types - StringTokenizer tokenizer = new StringTokenizer(events); - while (tokenizer.hasMoreTokens()) { - String event = tokenizer.nextToken().trim(); - application.getWindow().addEventListener( - event, - actionEvent -> { - printf("eventReceived: %s", actionEvent.getType()); - String type = actionEvent.getType(); - eventTypeRecieved.set(type); - if ("minimized".equals(type)) { - onMinimiseEventLatch.countDown(); - } - }, new AckListener() { - @Override - public void onSuccess(Ack ack) { - printf("window '%s' onSuccess: %s", event, ack); - } - - @Override - public void onError(Ack ack) { - printf("window '%s' onError: %s", event, ack); - } - } - ); - printf("added listener for event: %s", event); - } - - //generate a minimized event to check that we get notification in the listener above - application.getWindow().minimize(); - onMinimiseEventLatch.await(20, TimeUnit.SECONDS); - assertEquals("minimized event not recieved", "minimized", eventTypeRecieved.get()); - } - - @Test - public void windowsInShameGroupMoveTogether() throws Exception { - final int width = 600, height = 900; - - //place two application windows next to each other - Application applicationA = openWindow(nextTestUuid(), "http://www.google.com", 0, 0, width, height, true, true); - Application applicationB = openWindow(nextTestUuid(), "http://www.bbc.co.uk", width, 0, width, height, true, true); - - //bind the windows in the same group so that they move togther - applicationA.getWindow().joinGroup(applicationB.getWindow(), new AckListener() { - @Override - public void onSuccess(Ack ack) { - printf("window A joined group"); - } - - @Override - public void onError(Ack ack) { - printf("failed to join group"); - } - }); - - //move window A and check that B has followed it - final int moveLefPositiontBy = 100; - final int appBLeftStart = getWindowBounds(applicationB.getWindow()).getLeft(); - - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - applicationA.getWindow().moveBy(moveLefPositiontBy, 0, new AckListener() { - @Override - public void onSuccess(Ack ack) { - printf("moved window A"); - } - - @Override - public void onError(Ack ack) { - printf("failed to move window A"); - } - }); - Thread.sleep(SLEEP_FOR_HUMAN_OBSERVATION); - final int appBLeftEnd = getWindowBounds(applicationB.getWindow()).getLeft(); - - assertEquals("the window for app B did not follow the move for app A", appBLeftStart + moveLefPositiontBy, appBLeftEnd); - } - - @Test - public void notificationEventListenersWork() throws Exception { - // wait for Notification service to start up - Window notificationService = Window.wrap("service:notifications", "queueCounter", desktopConnection); - CountDownLatch notificationLatch = new CountDownLatch(1); - notificationService.addEventListener("app-connected", actionEvent -> { - if (actionEvent.getType().equals("app-connected")) { - logger.info("notification center ready"); - notificationLatch.countDown(); - } - }, null); - notificationLatch.await(10, TimeUnit.SECONDS); - - //record/wait for event - CountDownLatch onCloseEventLatch = new CountDownLatch(1); - AtomicReference eventTypeRecieved = new AtomicReference<>(); - - NotificationOptions options = new NotificationOptions("http://demoappdirectory.openf.in/desktop/config/apps/OpenFin/HelloOpenFin/views/notification.html"); - options.setTimeout(1000); - options.setMessageText("testing"); - new Notification(options, new NotificationListener() { - @Override - public void onClick(Ack ack) { - eventTypeRecieved.set("onClick"); - } - - @Override - public void onClose(Ack ack) { - eventTypeRecieved.set("onClose"); - onCloseEventLatch.countDown(); - } - - @Override - public void onDismiss(Ack ack) { - eventTypeRecieved.set("onDismiss"); - } - - @Override - public void onError(Ack ack) { - eventTypeRecieved.set("onError"); - } - - @Override - public void onMessage(Ack ack) { - eventTypeRecieved.set("onMessage"); - } - - @Override - public void onShow(Ack ack) { - eventTypeRecieved.set("onShow"); - } - }, this.desktopConnection, null); - - //wait for the onClose notification to arrive - onCloseEventLatch.await(20000, TimeUnit.SECONDS); - assertEquals("onClose", eventTypeRecieved.get()); - } - - private WindowBounds getWindowBounds(Window window) throws Exception { - final AtomicReference atomicRef = new AtomicReference<>(); - final CountDownLatch latch = new CountDownLatch(1); - window.getBounds(windowBounds -> { - atomicRef.set(windowBounds); - latch.countDown(); - }, null); - latch.await(20, TimeUnit.SECONDS); - WindowBounds windowBounds = atomicRef.get(); - assertNotNull("failed to get bounds for window", windowBounds); - return windowBounds; - } - - private static void printf(String s, Object... args) { - logger.info(String.format(s, args)); - } - -} diff --git a/src/main/java/com/openfin/desktop/demo/PubSubTest.java b/src/main/java/com/openfin/desktop/demo/PubSubTest.java index 626cf3d..ff72859 100644 --- a/src/main/java/com/openfin/desktop/demo/PubSubTest.java +++ b/src/main/java/com/openfin/desktop/demo/PubSubTest.java @@ -164,7 +164,7 @@ public void run() { } @Override - public void onClose() { + public void onClose(String error) { logger.info("onClose"); } @@ -246,7 +246,7 @@ void launch() { } @Override - public void onClose() { + public void onClose(String error) { } diff --git a/src/main/java/com/openfin/desktop/demo/Signer.java b/src/main/java/com/openfin/desktop/demo/Signer.java new file mode 100644 index 0000000..4c3bd42 --- /dev/null +++ b/src/main/java/com/openfin/desktop/demo/Signer.java @@ -0,0 +1,98 @@ +package com.openfin.desktop.demo; + +import java.io.InputStream; +import java.security.CodeSigner; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.Manifest; + +public class Signer { + private final String filename; + + public Signer(String filename) { + this.filename = filename; + } + + public void verify() throws Exception { + JarFile jar = new JarFile(this.filename, true); + + Enumeration entries = jar.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + byte[] buffer = new byte[8192]; + InputStream is = jar.getInputStream(entry); + while ((is.read(buffer, 0, buffer.length)) != -1) { + // We just read. This will throw a SecurityException + // if a signature/digest check fails. + } + is.close(); + } + + if (!checkSign(jar)) { + throw new SecurityException("not signed"); + } + + } + + private boolean checkSign(JarFile jar) throws Exception { + InputStream jis = jar.getInputStream(jar.getEntry("META-INF/MANIFEST.MF")); + Manifest man = new Manifest(jis); + jis.close(); + + HashSet signed = new HashSet<>(); + for(Map.Entry entry: man.getEntries().entrySet()) { + for(Object attrkey: entry.getValue().keySet()) { + if (attrkey instanceof Attributes.Name && attrkey.toString().contains("-Digest")) { + signed.add(entry.getKey()); + } + } + } + System.out.printf("Number of Digest from manifest %d \n", signed.size()); + + Set entries = new HashSet<>(); + for(Enumeration entry = jar.entries(); entry.hasMoreElements(); ) { + JarEntry je = entry.nextElement(); + String fileName = je.getName().toUpperCase(); + if (!je.isDirectory() + && !fileName.endsWith(".MF") + && !fileName.endsWith(".SF") + && !fileName.endsWith(".DSA") + && !fileName.endsWith(".EC") + && !fileName.endsWith(".RSA") + ) { + CodeSigner[] signers = je.getCodeSigners(); + if (signers != null && signers.length == 1) { + CodeSigner signer = signers[0]; + if (signer.getSignerCertPath().getCertificates().size() != 4) { + throw new SecurityException(String.format("invalid cert chain %s", je.getName())); + } + X509Certificate cert = (X509Certificate) signer.getSignerCertPath().getCertificates().get(0); + if (!cert.getSubjectDN().toString().contains("OpenFin Inc.")) { + throw new SecurityException(String.format("invalid signed %s", je.getName())); + } + entries.add(je.getName()); + } else { + throw new SecurityException(String.format("missing cert %s", je.getName())); + } + } + } + System.out.printf("Number of signed entries %d \n", entries.size()); + + Set unsigned = new HashSet<>(entries); + unsigned.removeAll(signed); + return unsigned.size() == 0; + } + + public static void main(String[] args) throws Exception { + Signer signer = new Signer(args[0]); + signer.verify(); + } + +} diff --git a/src/main/java/com/openfin/desktop/demo/TVBEmbedDemo.java b/src/main/java/com/openfin/desktop/demo/TVBEmbedDemo.java deleted file mode 100644 index 1b53c74..0000000 --- a/src/main/java/com/openfin/desktop/demo/TVBEmbedDemo.java +++ /dev/null @@ -1,366 +0,0 @@ -package com.openfin.desktop.demo; - -import com.openfin.desktop.*; -import com.openfin.desktop.win32.WinMessageHelper; -import com.sun.jna.Native; -import info.clearthought.layout.TableLayout; -import org.json.JSONArray; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionListener; -import java.awt.event.WindowEvent; -import java.awt.event.WindowListener; -import java.lang.System; -import java.util.*; - -/** - * Created by wche on 3/26/2016. - */ -public class TVBEmbedDemo extends JPanel implements ActionListener, WindowListener { - - private final static Logger logger = LoggerFactory.getLogger(TVBEmbedDemo.class.getName()); - - private static JFrame jFrame; - private String appUuid = "JavaEmbedding"; - private String startupUuid = "TVBWebLocal-yeotwn3hvf6wh142"; - protected DesktopConnection desktopConnection; - private JButton launch, close; - private java.awt.Canvas embedCanvas; - private Long previousPrarentHwndId; - private java.util.Timer timer = new java.util.Timer(); - - // bounds of HTML5 app - private static int appHeigth = 1080; - private static int appWidth = 1920; - - public TVBEmbedDemo() { - try { - this.desktopConnection = new DesktopConnection(appUuid); - } catch (DesktopException desktopError) { - desktopError.printStackTrace(); - } - setLayout(new BorderLayout()); - add(layoutCenterPanel(), BorderLayout.CENTER); - setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); - setMainButtonsEnabled(false); - } - - private JPanel layoutCenterPanel() { - JPanel panel = new JPanel(); - double size[][] = {{TableLayout.FILL}, {40, TableLayout.FILL}}; - panel.setLayout(new TableLayout(size)); - panel.add(layoutActionButtonPanel(), "0,0,0,0"); - panel.add(layoutEmbedPanel(), "0, 1, 0, 1"); - return panel; - } - - private JPanel layoutActionButtonPanel() { - JPanel buttonPanel = new JPanel(); - - JPanel topPanel = new JPanel(); - double size[][] = {{10, 190, 20, 190, 10}, {25}}; - topPanel.setLayout(new TableLayout(size)); - - launch = new JButton("Launch OpenFin"); - launch.setActionCommand("start"); - close = new JButton("Shutdown OpenFin"); - close.setActionCommand("close"); - topPanel.add(launch, "1,0,1,0"); - topPanel.add(close, "3,0,3,0"); - - close.addActionListener(this); - launch.addActionListener(this); - - buttonPanel.add(topPanel, "0,0"); - return buttonPanel; - } - - protected JPanel layoutEmbedPanel() { - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout()); - panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createBevelBorder(2), "HTML5 app")); - - embedCanvas = new java.awt.Canvas(); - panel.add(embedCanvas, BorderLayout.CENTER); - - - return panel; - } - - private void setMainButtonsEnabled(boolean enabled) { - launch.setEnabled(!enabled); - close.setEnabled(enabled); - - if (enabled) { - this.desktopConnection.getInterApplicationBus().addSubscribeListener(new SubscriptionListener() { - public void subscribed(String uuid, String topic) { - System.out.println("subscribed " + uuid + " on topic " + topic); - } - - public void unsubscribed(String uuid, String topic) { - System.out.println("unsubscribed " + uuid + " on topic " + topic); - - } - }); - } - } - - private static void createAndShowGUI() { - //Create and set up the window. - jFrame = new JFrame("Java Embedding Demo"); - jFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); - //Create and set up the content pane. - TVBEmbedDemo newContentPane = new TVBEmbedDemo(); - newContentPane.setOpaque(true); //content panes must be opaque - jFrame.setContentPane(newContentPane); - jFrame.addWindowListener(newContentPane); - //Display the window. - jFrame.pack(); - jFrame.setSize(appWidth+80, appHeigth+160); - jFrame.setLocationRelativeTo(null); - jFrame.setResizable(true); - jFrame.setVisible(true); - } - - private void closeDesktop() { - if (desktopConnection != null && desktopConnection.isConnected()) { - try { - if (startupHtml5app != null) { - startupHtml5app.close(); - } - desktopConnection.disconnect(); -// OpenFinRuntime runtime = new OpenFinRuntime(desktopConnection); -// runtime.exit(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - //closeWebSocket(); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - jFrame.dispose(); - } - }); - try { - Thread.sleep(1000); - java.lang.System.exit(0); - } catch (InterruptedException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - - @Override - public void windowOpened(WindowEvent e) { - } - - @Override - public void windowClosing(WindowEvent e) { - closeDesktop(); - } - - @Override - public void windowClosed(WindowEvent e) { - } - - @Override - public void windowIconified(WindowEvent e) { - } - - @Override - public void windowDeiconified(WindowEvent e) { - } - - @Override - public void windowActivated(WindowEvent e) { - } - - @Override - public void windowDeactivated(WindowEvent e) { - } - - public void actionPerformed(java.awt.event.ActionEvent e) { - if ("start".equals(e.getActionCommand())) { - runStartAction(); - } else if ("close".equals(e.getActionCommand())) { - closeDesktop(); - } else if ("embed-window".equals(e.getActionCommand())) { - embedStartupApp(); - } - } - - private void runStartAction() { - try { - DesktopStateListener listener = new DesktopStateListener() { - @Override - public void onReady() { - setMainButtonsEnabled(true); - - long embedWaitTime = 3000L; - String s = java.lang.System.getProperty("com.openfin.demo.embedWaitTime"); - if (s != null) { - embedWaitTime = Long.parseLong(s); - } - System.out.println(String.format("Embed wait time %d", embedWaitTime)); - timer.schedule(new TimerTask() { - @Override - public void run() { - embedStartupApp(); - } - }, embedWaitTime); - } - - @Override - public void onClose() { - } - - @Override - public void onError(String reason) { - - } - @Override - public void onMessage(String message) { - } - @Override - public void onOutgoingMessage(String message) { - } - }; - - RuntimeConfiguration configuration = new RuntimeConfiguration(); -// configuration.setRuntimeVersion("6.49.8.14"); - - String runtimeVersion = java.lang.System.getProperty("com.openfin.demo.version"); - if (runtimeVersion == null) { - runtimeVersion = "stable"; - } - configuration.setRuntimeVersion(runtimeVersion); - configuration.setDevToolsPort(9090); - configuration.setAdditionalRuntimeArguments("--v=1 --noerrdialogs --disable-web-security --enable-aggressive-domstorage-flushing --load-extension=%LOCALAPPDATA%/OpenFin/apps/1578057152/assets/gktvbext-8266cea06bade1e88033/1.0.0"); - - JSONObject asset = new JSONObject(); - asset.put("src", "https://test.web.tradervoicebox.com/openfin/gkt-vb-chrome-extension-8266cea06bade1e88033.zip"); - asset.put("alias", "gktvbext-8266cea06bade1e88033"); - asset.put("version", "1.0.0"); - configuration.addAppAsset(asset); - - JSONObject startupApp = new JSONObject(); - startupApp.put("name", "TVBWebTest"); - startupApp.put("uuid", startupUuid); - startupApp.put("url", "https://test.web.tradervoicebox.com"); - startupApp.put("applicationIcon", "https://test.web.tradervoicebox.com/img/logo-large.jpg"); - startupApp.put("autoShow", false); - startupApp.put("defaultWidth", appWidth); - startupApp.put("defaultHeight", appHeigth); - - JSONArray permissions = new JSONArray(); - permissions.put("audioCapture"); - permissions.put("videoCapture"); - permissions.put("midi"); - startupApp.put("permissions",permissions); - - startupApp.put("delay_connection", true); - startupApp.put("frame", false); - startupApp.put("saveWindowState", false); - configuration.setStartupApp(startupApp); - -// ApplicationOptions options = new ApplicationOptions("TVBWebTest", startupUuid, "https://test.web.tradervoicebox.com"); -// options.setApplicationIcon("https://test.web.tradervoicebox.com/img/logo-large.jpg"); -// WindowOptions mainWindowOptions = new WindowOptions(); -// mainWindowOptions.setAutoShow(true); -// mainWindowOptions.setDefaultHeight(appHeigth); -// mainWindowOptions.setDefaultWidth(appWidth); -// mainWindowOptions.setSaveWindowState(false); // set to false so all windows start at same initial positions for each run -// mainWindowOptions.setFrame(false); -// mainWindowOptions.toJsonObject().put("permissions","[audioCapture,videoCapture,midi]"); -// mainWindowOptions.toJsonObject().put("delay_connection", true); -// options.setMainWindowOptions(mainWindowOptions); - - - desktopConnection.connect(configuration, listener, 60); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void launchHtmlApp() { - try { - ApplicationOptions options = new ApplicationOptions("TVBWebTest", startupUuid, "https://test.web.tradervoicebox.com"); - options.setApplicationIcon("https://test.web.tradervoicebox.com/img/logo-large.jpg"); - WindowOptions mainWindowOptions = new WindowOptions(); - mainWindowOptions.setAutoShow(false); - mainWindowOptions.setDefaultHeight(appHeigth); - mainWindowOptions.setDefaultWidth(appWidth); - mainWindowOptions.setSaveWindowState(false); // set to false so all windows start at same initial positions for each run - mainWindowOptions.setFrame(false); - mainWindowOptions.toJsonObject().put("permissions","[audioCapture,videoCapture,midi]"); - mainWindowOptions.toJsonObject().put("delay_connection", true); - options.setMainWindowOptions(mainWindowOptions); - - DemoUtils.runApplication(options, this.desktopConnection, new AckListener() { - @Override - public void onSuccess(Ack ack) { - startupHtml5app = (Application) ack.getSource(); -// embedStartupApp(); - } - @Override - public void onError(Ack ack) { - logger.error(String.format("Error launching %s %s", options.getUUID(), ack.getReason())); - } - }); - } catch (Exception e) { - logger.error("Error launching app", e); - } - } - - private boolean trayIconAdded = false; - private Application startupHtml5app; - - private void embedStartupApp() { - try { - if (startupHtml5app == null) { - startupHtml5app = Application.wrap(this.startupUuid, this.desktopConnection); - } - - com.openfin.desktop.Window html5Wnd = startupHtml5app.getWindow(); - long parentHWndId = Native.getComponentID(this.embedCanvas); - System.out.println("Canvas HWND " + Long.toHexString(parentHWndId)); - html5Wnd.embedInto(parentHWndId, appWidth, appHeigth, new AckListener() { - @Override - public void onSuccess(Ack ack) { - if (!ack.isSuccessful()) { - java.lang.System.out.println("embedding failed: " + ack.getJsonObject().toString()); - } - } - @Override - public void onError(Ack ack) { - } - }); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * To start OpenFin Desktop and Connect, pass full path of OpenFin with* - * -DOpenFinOption=--config=\"RemoteConfigUrl\" - * - * Set UUID of startup HTML5 app to dock to - * -DStartupUUID="550e8400-e29b-41d4-a716-4466333333000" - * - * @param args - */ - public static void main(String[] args) { - javax.swing.SwingUtilities.invokeLater(new Runnable() { - public void run() { - createAndShowGUI(); - } - }); - } - -} diff --git a/src/main/java/com/openfin/desktop/demo/WindowEmbedDemo.java b/src/main/java/com/openfin/desktop/demo/WindowEmbedDemo.java index 1725198..5288cd6 100644 --- a/src/main/java/com/openfin/desktop/demo/WindowEmbedDemo.java +++ b/src/main/java/com/openfin/desktop/demo/WindowEmbedDemo.java @@ -86,8 +86,7 @@ protected JPanel layoutEmbedPanel() { embedCanvas = new java.awt.Canvas(); panel.add(embedCanvas, BorderLayout.CENTER); - panel.add(embedCanvas, BorderLayout.CENTER); - panel.addComponentListener(new ComponentAdapter() { + embedCanvas.addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent event) { super.componentResized(event); @@ -141,7 +140,20 @@ private static void createAndShowGUI(final String startupUuid) { jFrame.setVisible(true); } + private void closeEmbeddedApp() { + if (this.startupHtml5app != null) { + try { + this.startupHtml5app.close(); + this.startupHtml5app = null; + } catch (DesktopException e) { + e.printStackTrace(); + } + } + } + private void closeDesktop() { + this.closeEmbeddedApp(); + if (desktopConnection != null && desktopConnection.isConnected()) { try { // new com.openfin.desktop.System(desktopConnection).exit(); @@ -216,7 +228,7 @@ public void onReady() { } @Override - public void onClose() { + public void onClose(String error) { } @Override diff --git a/src/test/java/com/openfin/desktop/AllTests.java b/src/test/java/com/openfin/desktop/AllTests.java index bb3cb33..cc84773 100644 --- a/src/test/java/com/openfin/desktop/AllTests.java +++ b/src/test/java/com/openfin/desktop/AllTests.java @@ -10,6 +10,6 @@ */ @RunWith(Suite.class) -@Suite.SuiteClasses({ ApplicationTest.class, OpenFinRuntimeTest.class, WindowTest.class, SystemTest.class, InterApplicationBusTest.class, RuntimeConfigTest.class}) +@Suite.SuiteClasses({ ApplicationTest.class, OpenFinRuntimeTest.class, WindowTest.class, SystemTest.class, InterApplicationBusTest.class, ChannelTest.class, RuntimeConfigTest.class, InteropTest.class, SnapshotTest.class}) public class AllTests { } diff --git a/src/test/java/com/openfin/desktop/ApplicationTest.java b/src/test/java/com/openfin/desktop/ApplicationTest.java index e3425c3..4eedf85 100644 --- a/src/test/java/com/openfin/desktop/ApplicationTest.java +++ b/src/test/java/com/openfin/desktop/ApplicationTest.java @@ -155,110 +155,6 @@ public void createChildWindow() throws Exception { TestUtils.closeApplication(application); } - @Test - public void crossAppDockAndUndock() throws Exception { - Application application1 = TestUtils.runApplication(TestUtils.getAppOptions(null), desktopConnection); - Application application2 = TestUtils.runApplication(TestUtils.getAppOptions(null), desktopConnection); - - WindowBounds beforeMoveBounds = TestUtils.getBounds(application2.getWindow()); - CountDownLatch joinLatch = new CountDownLatch(1); - application2.getWindow().joinGroup(application1.getWindow(), new AckListener() { - @Override - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - joinLatch.countDown(); - } - } - @Override - public void onError(Ack ack) { - logger.error(String.format("onError %s", ack.getReason())); - } - }); - joinLatch.await(3, TimeUnit.SECONDS); - assertEquals(joinLatch.getCount(), 0); - - // get group info for a window - CountDownLatch groupInfoLatch = new CountDownLatch(2); - application1.getWindow().getGroup(result -> { - for (Window window : result) { - if (window.getUuid().equals(application1.getWindow().getUuid()) && window.getName().equals(application1.getWindow().getName())) { - groupInfoLatch.countDown(); - } else if (window.getUuid().equals(application2.getWindow().getUuid()) && window.getName().equals(application2.getWindow().getName())) { - groupInfoLatch.countDown(); - } - } - }, new AckListener() { - @Override - public void onSuccess(Ack ack) { - } - @Override - public void onError(Ack ack) { - logger.error(String.format("onError %s", ack.getReason())); - } - }); - groupInfoLatch.await(3, TimeUnit.SECONDS); - assertEquals(groupInfoLatch.getCount(), 0); - - // get group info for an application - CountDownLatch appGroupInfoLatch = new CountDownLatch(2); - application1.getGroups(result -> { - for (List list: result) { - for (Window window : list) { - if (window.getUuid().equals(application1.getWindow().getUuid()) && window.getName().equals(application1.getWindow().getName())) { - appGroupInfoLatch.countDown(); - } else if (window.getUuid().equals(application2.getWindow().getUuid()) && window.getName().equals(application2.getWindow().getName())) { - appGroupInfoLatch.countDown(); - } - } - } - }, new AckListener() { - @Override - public void onSuccess(Ack ack) { - } - @Override - public void onError(Ack ack) { - logger.error(String.format("onError %s", ack.getReason())); - } - } - ); - appGroupInfoLatch.await(3, TimeUnit.SECONDS); - assertEquals(appGroupInfoLatch.getCount(), 0); - - int leftBy = 20, topBy = 30; - TestUtils.moveWindowBy(application1.getWindow(), leftBy, topBy); - // child window sohuld move with main window since they are docked - WindowBounds afterMoveBounds = TestUtils.getBounds(application2.getWindow()); - int topAfterDockMove = afterMoveBounds.getTop(), leftAfterDockMove = afterMoveBounds.getLeft(); - assertEquals(afterMoveBounds.getTop() - beforeMoveBounds.getTop(), topBy); - assertEquals(afterMoveBounds.getLeft() - beforeMoveBounds.getLeft(), leftBy); - - // undock by leaving the group - CountDownLatch undockLatch = new CountDownLatch(1); - application2.getWindow().leaveGroup(new AckListener() { - @Override - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - undockLatch.countDown(); - } - } - - @Override - public void onError(Ack ack) { - logger.error(String.format("onError %s", ack.getReason())); - } - }); - undockLatch.await(5, TimeUnit.SECONDS); - assertEquals(undockLatch.getCount(), 0); - TestUtils.moveWindowBy(application1.getWindow(), leftBy, topBy); - // child window should not move afer leaving group - afterMoveBounds = TestUtils.getBounds(application2.getWindow()); - assertEquals(afterMoveBounds.getLeft().intValue(), leftAfterDockMove); - assertEquals(afterMoveBounds.getTop().intValue(), topAfterDockMove); - - TestUtils.closeApplication(application1); - TestUtils.closeApplication(application2); - } - @Test public void addEventListener() throws Exception { ApplicationOptions options = TestUtils.getAppOptions(null); @@ -553,4 +449,43 @@ public void onError(Ack ack) { assertEquals(0, latch.getCount()); } + + @Test + public void errorStack() throws Exception { + Application application = TestUtils.runApplication(TestUtils.getAppOptions(null), desktopConnection); + final CountDownLatch latch = new CountDownLatch(1); + + application.close(true, new AckListener() { + + @Override + public void onSuccess(Ack ack) { + application.getChildWindows(new AsyncCallback>() { + + @Override + public void onSuccess(List result) { + } + }, new AckListener() { + + @Override + public void onSuccess(Ack ack) { + } + + @Override + public void onError(Ack ack) { + if (ack.getErrorStack() != null) { + latch.countDown(); + } + } + }); + } + + @Override + public void onError(Ack ack) { + } + }); + + latch.await(5, TimeUnit.SECONDS); + + assertEquals(0, latch.getCount()); + } } diff --git a/src/test/java/com/openfin/desktop/ChannelTest.java b/src/test/java/com/openfin/desktop/ChannelTest.java new file mode 100644 index 0000000..e8009de --- /dev/null +++ b/src/test/java/com/openfin/desktop/ChannelTest.java @@ -0,0 +1,429 @@ +package com.openfin.desktop; + +import static org.junit.Assert.assertEquals; + +import java.util.Objects; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import com.openfin.desktop.channel.*; +import org.json.JSONObject; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * JUnit tests for OpenFin Channel API + * + * Created by wche on 1/27/16. + * + */ +public class ChannelTest { + private static Logger logger = LoggerFactory.getLogger(ChannelTest.class.getName()); + + private static final String DESKTOP_UUID = ChannelTest.class.getName(); + private static DesktopConnection desktopConnection; + + @BeforeClass + public static void setup() throws Exception { + logger.debug("starting"); + desktopConnection = TestUtils.setupConnection(DESKTOP_UUID); + } + + @AfterClass + public static void teardown() throws Exception { + TestUtils.teardownDesktopConnection(desktopConnection); + } + + @Test + public void createChannelProvider() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + desktopConnection.getChannel("createChannelProvider").create(new AsyncCallback() { + @Override + public void onSuccess(ChannelProvider provider) { + latch.countDown(); + } + }); + latch.await(10, TimeUnit.SECONDS); + assertEquals(0, latch.getCount()); + } + + @Test + public void createChannelProviderAsync() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + desktopConnection.getChannel("createChannelProviderAsync").createAsync().thenAccept(provider -> { + if (Objects.nonNull(provider)) { + latch.countDown(); + } + }); + latch.await(10, TimeUnit.SECONDS); + assertEquals(0, latch.getCount()); + } + + @Test + public void createChannelClient() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + final String channelName = "createChannelClientTest"; + desktopConnection.getChannel(channelName).create(new AsyncCallback() { + @Override + public void onSuccess(ChannelProvider provider) { + desktopConnection.getChannel(channelName).connect(new AsyncCallback() { + @Override + public void onSuccess(ChannelClient result) { + latch.countDown(); + } + }); + } + }); + latch.await(10, TimeUnit.SECONDS); + assertEquals(0, latch.getCount()); + } + @Test + public void createChannelClientAsync() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + final String channelName = "createChannelClientAsync"; + desktopConnection.getChannel(channelName).createAsync().thenAccept(provider -> { + desktopConnection.getChannel(channelName).connectAsync().thenAccept(client -> { + if (Objects.nonNull(client)) { + latch.countDown(); + } + }); + }); + latch.await(10, TimeUnit.SECONDS); + assertEquals(0, latch.getCount()); + } + + @Test + public void multipleChannelClients() throws Exception { + CountDownLatch latch1 = new CountDownLatch(1); + CountDownLatch latch2 = new CountDownLatch(1); + final String channelName = "createMultipleChannelClientTest"; + final String clientActionName = "clientAction"; + final String providerActionName = "providerAction"; + desktopConnection.getChannel(channelName).create(new AsyncCallback() { + @Override + public void onSuccess(ChannelProvider provider) { + provider.register(providerActionName, new ChannelAction() { + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + return null; + } + }); + + //first channel client + desktopConnection.getChannel(channelName).connect(new AsyncCallback() { + @Override + public void onSuccess(ChannelClient client) { + client.dispatch(providerActionName, new JSONObject(), null); + client.register(clientActionName, new ChannelAction() { + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + latch1.countDown(); + return null; + } + }); + } + }); + //second channel client + desktopConnection.getChannel(channelName).connect(new AsyncCallback() { + @Override + public void onSuccess(ChannelClient client) { + client.register(clientActionName, new ChannelAction() { + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + latch2.countDown(); + return null; + } + }); + provider.publish(clientActionName, new JSONObject(), null); + } + }); + } + }); + + latch1.await(10, TimeUnit.SECONDS); + latch2.await(10, TimeUnit.SECONDS); + + assertEquals(0, latch1.getCount()); + assertEquals(0, latch2.getCount()); + } + + @Test + public void registerAction() throws Exception { + final String channelName = "registerActionTest"; + CountDownLatch latch = new CountDownLatch(1); + desktopConnection.getChannel(channelName).create(new AsyncCallback() { + @Override + public void onSuccess(ChannelProvider provider) { + provider.register("currentTime", new ChannelAction() { + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + return ((JSONObject)payload).put("currentTime", java.lang.System.currentTimeMillis()); + } + }); + latch.countDown(); + } + }); + + latch.await(10, TimeUnit.SECONDS); + + assertEquals(0, latch.getCount()); + } + + @Test + public void invokeProviderAction() throws Exception { + final String channelName = "invokeProviderActionTest"; + final String actionName = "increment"; + final int initValue = 10; + final AtomicInteger resultValue = new AtomicInteger(-1); + + CountDownLatch latch = new CountDownLatch(1); + desktopConnection.getChannel(channelName).create(new AsyncCallback() { + @Override + public void onSuccess(ChannelProvider provider) { + provider.register(actionName, new ChannelAction() { + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + int currentValue = ((JSONObject)payload).getInt("value"); + return ((JSONObject)payload).put("value", currentValue + 1); + } + }); + + desktopConnection.getChannel(channelName).connect(new AsyncCallback() { + + @Override + public void onSuccess(ChannelClient client) { + JSONObject payload = new JSONObject(); + payload.put("value", initValue); + client.dispatch(actionName, payload, new AckListener() { + @Override + public void onSuccess(Ack ack) { + resultValue.set(ack.getJsonObject().getJSONObject("data").getJSONObject("result") + .getInt("value")); + latch.countDown(); + } + + @Override + public void onError(Ack ack) { + } + }); + } + + }); + } + }); + + latch.await(10, TimeUnit.SECONDS); + + assertEquals(0, latch.getCount()); + assertEquals(initValue + 1, resultValue.get()); + } + + @Test + public void invokeClientAction() throws Exception { + final String channelName = "invokeClientActionTest"; + final String providerActionName = "invokeClientAction"; + final String clientActionName = "clientAction"; + + CountDownLatch latch = new CountDownLatch(1); + desktopConnection.getChannel(channelName).create(new AsyncCallback() { + @Override + public void onSuccess(ChannelProvider provider) { + provider.register(providerActionName, new ChannelAction() { + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + provider.dispatch(senderIdentity, clientActionName, new JSONObject(), null); + return null; + } + }); + + desktopConnection.getChannel(channelName).connect(new AsyncCallback() { + @Override + public void onSuccess(ChannelClient client) { + client.register(clientActionName, new ChannelAction() { + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + latch.countDown(); + return null; + } + }); + + client.dispatch(providerActionName, new JSONObject(), null); + } + }); + } + }); + + latch.await(10, TimeUnit.SECONDS); + + assertEquals(0, latch.getCount()); + } + + @Test + public void publishToClient() throws Exception { + final String channelName = "publishToClientTest"; + final String actionName = "message"; + final String actionMessage = "actionMessage"; + + CountDownLatch latch = new CountDownLatch(1); + desktopConnection.getChannel(channelName).create(new AsyncCallback() { + @Override + public void onSuccess(ChannelProvider provider) { + desktopConnection.getChannel(channelName).connect(new AsyncCallback() { + @Override + public void onSuccess(ChannelClient client) { + + client.register(actionName, new ChannelAction() { + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + if (actionName.equals(action) && actionMessage.equals(((JSONObject)payload).getString("message"))) { + latch.countDown(); + } + return null; + } + }); + + JSONObject payload = new JSONObject(); + payload.put("message", actionMessage); + provider.publish(actionName, payload, null); + } + }); + } + }); + + latch.await(10, TimeUnit.SECONDS); + + assertEquals(0, latch.getCount()); + } + + @Test + public void connectionListener() throws Exception { + final String channelName = "connectionListenerTest"; + CountDownLatch latch = new CountDownLatch(3); + desktopConnection.getChannel(channelName).createAsync().thenAccept(provider -> { + provider.addProviderListener(new ChannelProviderListener() { + @Override + public void onClientConnect(ChannelClientConnectEvent connectionEvent) throws Exception { + latch.countDown(); + } + @Override + public void onClientDisconnect(ChannelClientConnectEvent connectionEvent) { + latch.countDown(); + } + }); + + desktopConnection.getChannel(channelName).connectAsync().thenAccept(client -> { + client.disconnect(new AckListener() { + @Override + public void onSuccess(Ack ack) { + latch.countDown(); + } + @Override + public void onError(Ack ack) { + } + }); + }); + }); + latch.await(10, TimeUnit.SECONDS); + assertEquals(0, latch.getCount()); + } + + @Test + public void middlewareAction() throws Exception { + final String channelName = "middlewateActionTest"; + final String actionName = "increment"; + final int initValue = 10; + final int middlewareIncrement = 2; + final AtomicInteger resultValue = new AtomicInteger(-1); + + CountDownLatch latch = new CountDownLatch(1); + desktopConnection.getChannel(channelName).create(new AsyncCallback() { + @Override + public void onSuccess(ChannelProvider provider) { + provider.setBeforeAction(new Middleware() { + + @Override + public Object invoke(String action, Object payload, JSONObject senderId) { + if (actionName.equals(action)) { + int value = ((JSONObject)payload).getInt("value"); + ((JSONObject)payload).put("value", value + middlewareIncrement); + } + return payload; + }}); + + provider.register(actionName, new ChannelAction() { + @Override + public JSONObject invoke(String action, Object payload, JSONObject senderIdentity) { + int currentValue = ((JSONObject)payload).getInt("value"); + return ((JSONObject) payload).put("value", currentValue + 1); + } + }); + + desktopConnection.getChannel(channelName).connect(new AsyncCallback() { + + @Override + public void onSuccess(ChannelClient client) { + JSONObject payload = new JSONObject(); + payload.put("value", initValue); + client.dispatch(actionName, payload, new AckListener() { + @Override + public void onSuccess(Ack ack) { + resultValue.set(ack.getJsonObject().getJSONObject("data").getJSONObject("result") + .getInt("value")); + latch.countDown(); + } + + @Override + public void onError(Ack ack) { + } + }); + } + + }); + } + }); + + latch.await(10, TimeUnit.SECONDS); + + assertEquals(0, latch.getCount()); + assertEquals(initValue + 3, resultValue.get()); + } + + @Test + public void rejectConnection() throws Exception { + final String channelName = "rejectConnectionTest"; + final String payloadValue = "reject me"; + final String rejectReason = "not allowed"; + + CountDownLatch latch = new CountDownLatch(1); + + desktopConnection.getChannel(channelName).createAsync().thenAccept(provider -> { + provider.addProviderListener(new ChannelProviderListener() { + @Override + public void onClientConnect(ChannelClientConnectEvent connectionEvent) throws Exception { + String payload = (String) connectionEvent.getPayload(); + if (payloadValue.equals(payload)) { + throw new Exception(rejectReason); + } + } + @Override + public void onClientDisconnect(ChannelClientConnectEvent connectionEvent) { + } + }); + + desktopConnection.getChannel(channelName).connectAsync(payloadValue).thenAccept(client -> { + }).exceptionally(ex -> { + if (ex.getMessage().contains(rejectReason)) { + latch.countDown(); + } + return null; + }); + }); + + latch.await(10, TimeUnit.SECONDS); + assertEquals(0, latch.getCount()); + } +} diff --git a/src/test/java/com/openfin/desktop/DesktopConnectionTest.java b/src/test/java/com/openfin/desktop/DesktopConnectionTest.java new file mode 100644 index 0000000..ee39c4a --- /dev/null +++ b/src/test/java/com/openfin/desktop/DesktopConnectionTest.java @@ -0,0 +1,183 @@ +package com.openfin.desktop; + +import static org.junit.Assert.assertEquals; + +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DesktopConnectionTest { + private static Logger logger = LoggerFactory.getLogger(DesktopConnectionTest.class.getName()); + + private static final String DESKTOP_UUID = DesktopConnectionTest.class.getName(); + + @BeforeClass + public static void setup() throws Exception { + } + + @AfterClass + public static void teardown() throws Exception { + } + + @Test + public void reconnect() throws Exception { + // IAB subscription shouldn't survive reconnection + + final AtomicInteger invokeCnt = new AtomicInteger(0); + String topic1 = "myTopic1"; + String topic2 = "myTopic2"; + String message1 = "myMessage1"; + String message2 = "myMessage2"; + final CyclicBarrier connectLatch = new CyclicBarrier(2); + final CountDownLatch disconnectLatch = new CountDownLatch(1); + DesktopConnection conn = new DesktopConnection(DESKTOP_UUID); + RuntimeConfiguration conf = new RuntimeConfiguration(); + conf.setRuntimeVersion(TestUtils.getRuntimeVersion()); + + DesktopStateListener listener = new DesktopStateListener() { + + @Override + public void onReady() { + try { + connectLatch.await(); + logger.debug("onReady"); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + catch (BrokenBarrierException e) { + e.printStackTrace(); + } + } + + @Override + public void onClose(String error) { + disconnectLatch.countDown(); + logger.debug("onClose: " + error); + } + + @Override + public void onError(String reason) { + } + + @Override + public void onMessage(String message) { + } + + @Override + public void onOutgoingMessage(String message) { + } + + }; + + conn.connect(conf, listener, 10); + connectLatch.await(10, TimeUnit.SECONDS); + + assertEquals(0, connectLatch.getNumberWaiting()); + + // create an app and let it sit through the reconnection. + ApplicationOptions options = TestUtils.getAppOptions(null); + Application application = TestUtils.runApplication(options, conn); + + CountDownLatch listener1Latch = new CountDownLatch(1); + // subscribe to a topic + conn.getInterApplicationBus().subscribe("*", topic1, new BusListener() { + + @Override + public void onMessageReceived(String sourceUuid, String topic, Object payload) { + logger.info("listener1 received: " + payload.toString()); + invokeCnt.incrementAndGet(); + if (message1.equals(payload.toString())) { + listener1Latch.countDown(); + } + } + }, new AckListener() { + @Override + public void onSuccess(Ack ack) { + if (ack.isSuccessful()) { + try { + conn.getInterApplicationBus().publish(topic1, message1); + } + catch (DesktopException e) { + e.printStackTrace(); + } + } + } + + @Override + public void onError(Ack ack) { + logger.error(ack.getReason()); + } + }); + + listener1Latch.await(5, TimeUnit.SECONDS); + assertEquals(0, listener1Latch.getCount()); + + try { + conn.disconnect("junit test"); + } + catch (DesktopException e) { + e.printStackTrace(); + } + + disconnectLatch.await(5, TimeUnit.SECONDS); + + assertEquals(0, disconnectLatch.getCount()); + + // connect it again. + connectLatch.reset(); + conn.connect(conf, listener, 10); + connectLatch.await(10, TimeUnit.SECONDS); + assertEquals(0, connectLatch.getNumberWaiting()); + + CountDownLatch listener2Latch = new CountDownLatch(1); + + conn.getInterApplicationBus().subscribe("*", topic2, new BusListener() { + + @Override + public void onMessageReceived(String sourceUuid, String topic, Object payload) { + listener2Latch.countDown(); + logger.info("listener2 received: " + payload.toString()); + } + }, new AckListener() { + @Override + public void onSuccess(Ack ack) { + if (ack.isSuccessful()) { + try { + conn.getInterApplicationBus().publish(topic1, message2); + conn.getInterApplicationBus().publish(topic2, message2); + } + catch (DesktopException e) { + e.printStackTrace(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Override + public void onError(Ack ack) { + logger.error(ack.getReason()); + } + }); + + //can kill the app now. + Application app = Application.wrap(application.uuid, conn); + app.close(); + + listener2Latch.await(5, TimeUnit.SECONDS); + + assertEquals(0, listener2Latch.getCount()); + assertEquals(1, invokeCnt.get()); + } + +} diff --git a/src/test/java/com/openfin/desktop/InterApplicationBusTest.java b/src/test/java/com/openfin/desktop/InterApplicationBusTest.java index 26f7807..38f4bf1 100644 --- a/src/test/java/com/openfin/desktop/InterApplicationBusTest.java +++ b/src/test/java/com/openfin/desktop/InterApplicationBusTest.java @@ -275,50 +275,6 @@ public void unsubscribed(String uuid, String topic) { TestUtils.closeApplication(application); } - @Ignore - @Test - public void wildCardTopic() throws Exception { - - CountDownLatch latch = new CountDownLatch(1); - BusListener busListener = (sourceUuid, receivingTopic, payload) -> { - logger.debug(String.format("Receiving %s", payload.toString())); - // PubSubExample.html sends the following - // fin.desktop.InterApplicationBus.publish('check-in', {name: 'Pub/Sub example app'}); - if (receivingTopic.equals("check-in")) { - latch.countDown(); - } - }; - subscribeToTopic("*", "*", busListener); - - ApplicationOptions options = TestUtils.getAppOptions(openfin_app_url); - Application application = TestUtils.createApplication(options, desktopConnection); - TestUtils.runApplication(application, true); - - latch.await(5, TimeUnit.SECONDS); - assertEquals(latch.getCount(), 0); - } - - @Ignore - @Test - public void wildCardTopicSelf() throws Exception { - - CountDownLatch latch = new CountDownLatch(1); - BusListener busListener = (sourceUuid, receivingTopic, payload) -> { - logger.debug(String.format("Receiving %s", payload.toString())); - if (receivingTopic.equals("wildcard-self")) { - latch.countDown(); - } - }; - subscribeToTopic("*", "*", busListener); - - JSONObject msg = new JSONObject(); - msg.put("name", "wildCardTopicSelf"); - desktopConnection.getInterApplicationBus().publish("wildcard-self", msg); - - latch.await(5, TimeUnit.SECONDS); - assertEquals(latch.getCount(), 0); - } - @Ignore @Test public void topicWithSpecialCharacters() throws Exception { diff --git a/src/test/java/com/openfin/desktop/InteropTest.java b/src/test/java/com/openfin/desktop/InteropTest.java new file mode 100644 index 0000000..7b412c3 --- /dev/null +++ b/src/test/java/com/openfin/desktop/InteropTest.java @@ -0,0 +1,203 @@ +package com.openfin.desktop; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import com.openfin.desktop.interop.Intent; +import com.openfin.desktop.interop.InteropClient; +import org.json.JSONObject; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.openfin.desktop.interop.Context; +import com.openfin.desktop.interop.ContextGroupInfo; + +public class InteropTest { + private static Logger logger = LoggerFactory.getLogger(InteropTest.class.getName()); + + private static final String DESKTOP_UUID = InteropTest.class.getName(); + private static final String BROKER_NANE = "AdapterInteropTest"; // created by javascript side + private static DesktopConnection desktopConnection; + + @BeforeClass + public static void setup() throws Exception { + logger.debug("starting"); + RuntimeConfiguration cfg = new RuntimeConfiguration(); + cfg.setManifestLocation("https://testing-assets.openfin.co/adapters/interop/app.json"); +// cfg.setManifestLocation("http://localhost:5555/app.json"); + desktopConnection = TestUtils.setupConnection(DESKTOP_UUID, cfg); + Thread.sleep(3000); // give time for the js app to start up and configure everything properly + } + + @AfterClass + public static void teardown() throws Exception { + TestUtils.teardownDesktopConnection(desktopConnection); + } + + @Test + public void clientGetContextGroupInfo() throws Exception { + CompletionStage getContextFuture = desktopConnection.getInterop().connect(BROKER_NANE).thenCompose(client->{ + return client.getContextGroups(); + }); + + ContextGroupInfo[] contextGroupInfo = getContextFuture.toCompletableFuture().get(10, TimeUnit.SECONDS); + assertNotNull(contextGroupInfo); + assertTrue(contextGroupInfo.length > 0); + assertNotNull(contextGroupInfo[0].getDisplayMetadata().getColor()); + } + + @Test + public void clientGetInfoForContextGroup() throws Exception { + CompletionStage getContextFuture = desktopConnection.getInterop().connect(BROKER_NANE).thenCompose(client->{ + return client.getInfoForContextGroup("red"); + }); + + ContextGroupInfo contextGroupInfo = getContextFuture.toCompletableFuture().get(10, TimeUnit.SECONDS); + assertNotNull(contextGroupInfo); + assertNotNull(contextGroupInfo.getDisplayMetadata().getColor()); + } + + @Test + public void clientGetAllClientsInContextGroup() throws Exception { + CompletionStage getContextFuture = desktopConnection.getInterop().connect(BROKER_NANE).thenCompose(client->{ + return client.joinContextGroup("red").thenCompose(v->{ + return client.getAllClientsInContextGroup("red"); + }); + }); + + ClientIdentity[] clientIdentity = getContextFuture.toCompletableFuture().get(10, TimeUnit.SECONDS); + assertNotNull(clientIdentity); + assertTrue(clientIdentity.length > 0); + assertNotNull(clientIdentity[0].getEndpointId()); + } + + @Test + public void clientJoinThenRemoveFromContextGroup() throws Exception { + AtomicInteger clientCntAfterJoin = new AtomicInteger(0); + AtomicInteger clientCntAfterRemove = new AtomicInteger(0); + CompletionStage testFuture = desktopConnection.getInterop().connect(BROKER_NANE).thenCompose(client->{ + return client.joinContextGroup("green").thenCompose(v->{ + return client.getAllClientsInContextGroup("green"); + }).thenAccept(clients->{ + logger.info(String.format("clientJoinThenRemoveFromContextGroup after join %d", clients.length)); + clientCntAfterJoin.set(clients.length); + }).thenCompose(v->{ + return client.removeFromContextGroup(); + }).thenCompose(v->{ + return client.getAllClientsInContextGroup("green"); + }).thenAccept(clients->{ + logger.info(String.format("clientJoinThenRemoveFromContextGroup after remove %d", clients.length)); + clientCntAfterRemove.set(clients.length); + }); + }); + + testFuture.toCompletableFuture().get(10, TimeUnit.SECONDS); + assertEquals(clientCntAfterJoin.get(), clientCntAfterRemove.incrementAndGet()); + } + + @Test + public void clientSetContext() throws Exception { + final Context context = getRandomContext(); + CompletionStage setContextFuture = desktopConnection.getInterop().connect(BROKER_NANE).thenCompose(client->{ + return client.getContextGroups().thenCompose(groups->{ + return client.joinContextGroup("red").thenCompose(v->{ + return client.setContext(context); + }); + }); + }); + + setContextFuture.toCompletableFuture().get(10, TimeUnit.SECONDS); + } + + @Test + public void clientAddContextListener() throws Exception { + final Context context = getRandomContext(); + + CompletableFuture listenerInvokedFuture = new CompletableFuture<>(); + + desktopConnection.getInterop().connect(BROKER_NANE).thenCompose(client->{ + return client.addContextListener(ctx->{ + String ticker = ctx.getId().optString("ticker", ""); + StringBuilder sb = new StringBuilder(context.getId().getString("ticker")); + if (ticker.equals(sb.append("1").toString())) { + listenerInvokedFuture.complete(ctx); + } + }).thenApply(v->{ + return client; + }); + }).thenCompose(client->{ + return client.joinContextGroup("red").thenCompose(v->{ + return client.setContext(context); + }); + }); + + Context ctx = listenerInvokedFuture.toCompletableFuture().get(10, TimeUnit.SECONDS); + assertNotNull(ctx); + } + + @Test + public void clientFireIntent() throws Exception { + final Context context = getRandomContext(); + Intent intent = new Intent(); + intent.setName("JavaIntent"); + intent.setContext(context); + CompletionStage fireIntentFuture = desktopConnection.getInterop().connect(BROKER_NANE).thenCompose(client->{ + return client.fireIntent(intent); + }); + desktopConnection.getInterop().connect(BROKER_NANE).thenCompose(client->{ + return client.registerIntentListener("JavaIntent", intentReceived->{ + String ticker = intentReceived.getContext().getId().optString("ticker", ""); + StringBuilder sb = new StringBuilder(context.getId().getString("ticker")); + }).thenCompose(v -> { + return client.fireIntent(intent); + }); + }); + + + fireIntentFuture.toCompletableFuture().get(10, TimeUnit.SECONDS); + } + + @Test + public void clientFireAndRegisterIntentListener() throws Exception { + final Context context = getRandomContext(); + + CompletableFuture listenerInvokedFuture = new CompletableFuture<>(); + desktopConnection.getInterop().connect(BROKER_NANE).thenCompose(client->{ + return client.registerIntentListener("JavaIntent", intentReceived->{ + String ticker = intentReceived.getContext().getId().optString("ticker", ""); + StringBuilder sb = new StringBuilder(context.getId().getString("ticker")); + if (ticker.equals(sb.append("1").toString())) { + listenerInvokedFuture.complete(intentReceived); + } + }).thenCompose(v -> { + Intent intent = new Intent(); + intent.setName("JsTestIntent"); + intent.setContext(context); + return client.fireIntent(intent); + }); + }); + + Intent intent = listenerInvokedFuture.toCompletableFuture().get(60, TimeUnit.SECONDS); + assertNotNull(intent); + } + + private Context getRandomContext() { + Long randomTicker = Math.round(Math.random() * 100); + final Context context = new Context(); + JSONObject id = new JSONObject(); + id.put("ticker", String.format("%d", randomTicker)); + context.setId(id); + context.setType("java"); + context.setName("java"); + return context; + } +} diff --git a/src/test/java/com/openfin/desktop/NotificationTest.java b/src/test/java/com/openfin/desktop/NotificationTest.java index 44f5765..eeb0fbf 100644 --- a/src/test/java/com/openfin/desktop/NotificationTest.java +++ b/src/test/java/com/openfin/desktop/NotificationTest.java @@ -47,128 +47,4 @@ public static void teardown() throws Exception { TestUtils.teardownDesktopConnection(desktopConnection); } - @Test - public void notificationEventListenersWork() throws Exception { - CountDownLatch onShowLatch = new CountDownLatch(1); - CountDownLatch onCloseLatch = new CountDownLatch(1); - - NotificationOptions options = new NotificationOptions(notification_url); - options.setTimeout(1000); - options.setMessageText("Unit test for notification"); - new Notification(options, new NotificationListener() { - @Override - public void onClick(Ack ack) { - logger.debug("onClick for notification"); - } - - @Override - public void onClose(Ack ack) { - logger.debug("onClose for notification"); - onCloseLatch.countDown(); - } - - @Override - public void onDismiss(Ack ack) { - logger.debug("onDismiss for notification"); - onCloseLatch.countDown(); - } - - @Override - public void onError(Ack ack) { - logger.error("onError for notification"); - } - - @Override - public void onMessage(Ack ack) { - logger.debug("onMessage for notification"); - } - - @Override - public void onShow(Ack ack) { - logger.debug("onShow for notification"); - onShowLatch.countDown(); - } - }, desktopConnection, new AckListener() { - @Override - public void onSuccess(Ack ack) { - } - @Override - public void onError(Ack ack) { - logger.error(ack.getReason()); - fail("onError"); - } - }); - - onShowLatch.await(5, TimeUnit.SECONDS); - onCloseLatch.await(5, TimeUnit.SECONDS); - assertEquals(onShowLatch.getCount(), 0); - assertEquals(onCloseLatch.getCount(), 0); - } - - @Test - public void sendMessage() throws Exception { - CountDownLatch latch = new CountDownLatch(1); - NotificationOptions options = new NotificationOptions(notification_url); - options.setMessage(new JSONObject("{message: \"JSONMessage\"}")); - //options.setMessageText("Notification Text"); - options.setTimeout(1000); - - NotificationListener nListener = new NotificationListener() { - - @Override - public void onClick(Ack ack) { - } - - @Override - public void onClose(Ack ack) { - } - - @Override - public void onDismiss(Ack ack) { - } - - @Override - public void onError(Ack ack) { - logger.error("onError for notification"); - } - - @Override - public void onMessage(Ack ack) { - logger.info("onMessage"); - latch.countDown(); - } - - @Override - public void onShow(Ack ack) { - } - }; - - AckListener ackListener = new AckListener() { - @Override - public void onSuccess(Ack ack) { - } - - @Override - public void onError(Ack ack) { - logger.error(ack.getReason()); - } - }; - - Notification n = new Notification(options, nListener, desktopConnection, ackListener); - n.sendMessage(new JSONObject("{message: \"JSONMessage2\"}"), new AckListener() { - - @Override - public void onSuccess(Ack ack) { - latch.countDown(); - } - - @Override - public void onError(Ack ack) { - logger.error("onError for sendMessage"); - } - }); - latch.await(10, TimeUnit.SECONDS); - assertEquals(0, latch.getCount()); - - } } diff --git a/src/test/java/com/openfin/desktop/OpenFinRuntimeTest.java b/src/test/java/com/openfin/desktop/OpenFinRuntimeTest.java index 4bc7c75..a741f7a 100644 --- a/src/test/java/com/openfin/desktop/OpenFinRuntimeTest.java +++ b/src/test/java/com/openfin/desktop/OpenFinRuntimeTest.java @@ -12,6 +12,7 @@ import org.json.JSONObject; import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,7 +49,7 @@ public static void teardown() throws Exception { public void getDeviceId() throws Exception { logger.debug("start getDeviceId"); CountDownLatch latch = new CountDownLatch(1); - runtime.getDeviceId(new AckListener() { + runtime.getMachineId(new AckListener() { @Override public void onSuccess(Ack ack) { if (ack.isSuccessful()) { @@ -398,6 +399,8 @@ public void onError(Ack ack) { } } + // this test does not work anymore with Secure By Default in place + @Ignore @Test public void startAndTerminateExternalProcess() throws Exception { CountDownLatch startLatch = new CountDownLatch(1); @@ -534,4 +537,27 @@ public void duplicateConnectionUuid() throws Exception { Thread.sleep(5000); assertEquals("Duplicate connection UUID should not be allowed", setupFailed, true); } + + @Test + public void getEntityInfo() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + runtime.getEntityInfo(DESKTOP_UUID, DESKTOP_UUID, new AckListener() { + + @Override + public void onSuccess(Ack ack) { + JSONObject jsonData = (JSONObject) ack.getData(); + String uuid = jsonData.getString("uuid"); + String entityType = jsonData.getString("entityType"); + if (DESKTOP_UUID.equals(uuid) && "external connection".equals(entityType)) { + latch.countDown(); + } + } + + @Override + public void onError(Ack ack) { + } + }); + latch.await(5, TimeUnit.SECONDS); + assertEquals("getEntityInfo timeout", latch.getCount(), 0); + } } diff --git a/src/test/java/com/openfin/desktop/RuntimeConfigTest.java b/src/test/java/com/openfin/desktop/RuntimeConfigTest.java index 143abd3..58f8570 100644 --- a/src/test/java/com/openfin/desktop/RuntimeConfigTest.java +++ b/src/test/java/com/openfin/desktop/RuntimeConfigTest.java @@ -63,6 +63,15 @@ public void launchFromConfig() throws Exception { TestUtils.teardownDesktopConnection(conn); } + @Test + public void launchFromRemoteConfig() throws Exception { + RuntimeConfiguration configuration = new RuntimeConfiguration(); + configuration.setManifestLocation(TestUtils.hello_app_manifest_url); + DesktopConnection conn = TestUtils.setupConnection(DESKTOP_UUID, configuration); + assertTrue(isWindowCreated("OpenFinHelloWorld", conn)); + TestUtils.teardownDesktopConnection(conn); + } + private boolean isWindowCreated(String uuid, DesktopConnection conn) throws Exception { CountDownLatch latch = new CountDownLatch(1); AtomicReference atomicReference = new AtomicReference<>(); diff --git a/src/test/java/com/openfin/desktop/SnapshotTest.java b/src/test/java/com/openfin/desktop/SnapshotTest.java new file mode 100644 index 0000000..d3513e1 --- /dev/null +++ b/src/test/java/com/openfin/desktop/SnapshotTest.java @@ -0,0 +1,120 @@ +package com.openfin.desktop; + +import com.openfin.desktop.snapshot.SnapshotSourceProvider; +import org.json.JSONObject; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.assertEquals; + +public class SnapshotTest implements SnapshotSourceProvider { + + private static Logger logger = LoggerFactory.getLogger(SnapshotTest.class.getName()); + + private static final String DESKTOP_UUID = SnapshotTest.class.getName(); + private static DesktopConnection desktopConnection; + private static OpenFinRuntime runtime; + private static final JSONObject SNAPSHOT_CONTENT = new JSONObject("{width: 123}"); + + private JSONObject randomSnapshot; + + @BeforeClass + public static void setup() throws Exception { + logger.debug("starting"); + desktopConnection = TestUtils.setupConnection(DESKTOP_UUID); + if (desktopConnection != null) { + runtime = new OpenFinRuntime(desktopConnection); + } + } + + @AfterClass + public static void teardown() throws Exception { + TestUtils.teardownDesktopConnection(desktopConnection); + } + + @Test + public void initProviderThenCreateClient() throws Exception { + CountDownLatch latch = new CountDownLatch(2); + final String appUuid = "initProviderThenCreateClient"; + desktopConnection.getSnapshotSource().initSnapshotSourceProviderAsync(appUuid, this).thenAccept(provider -> { + logger.debug("Snapshot provider created"); + latch.countDown(); + }); + desktopConnection.getSnapshotSource().createSnapshotSourceClientAsync(appUuid).thenAccept(client -> { + logger.debug("Snapshot client created"); + latch.countDown(); + }); + + latch.await(5, TimeUnit.SECONDS); + + assertEquals("initProviderThenCreateClient timeout", latch.getCount(), 0); + } + + @Test + public void initProviderThenCreateClientThenGetSnapshot() throws Exception { + CountDownLatch latch = new CountDownLatch(2); + final String appUuid = "initProviderThenCreateClientThenGetSnapshot"; + desktopConnection.getSnapshotSource().initSnapshotSourceProviderAsync(appUuid, this).thenAccept(provider -> { + logger.debug("Snapshot provider created"); + latch.countDown(); + }); + + desktopConnection.getSnapshotSource().createSnapshotSourceClientAsync(appUuid).thenAccept(client -> { + client.getSnapshotAsync().thenAccept(snapshot -> { + if (SNAPSHOT_CONTENT.toString().equals(snapshot.toString())) { + latch.countDown(); + } + }); + }); + + latch.await(5, TimeUnit.SECONDS); + + assertEquals("initProviderThenCreateClientThenGetSnapshot timeout", latch.getCount(), 0); + } + + @Test + public void initProviderThenCreateClientThenApplySnapshot() throws Exception { + CountDownLatch latch = new CountDownLatch(2); + final JSONObject random = new JSONObject(String.format("{value: %f}", Math.random())); + final String appUuid = "initProviderThenCreateClientThenApplySnapshot"; + desktopConnection.getSnapshotSource().initSnapshotSourceProviderAsync(appUuid, this).thenAccept(provider -> { + latch.countDown(); + }); + + desktopConnection.getSnapshotSource().createSnapshotSourceClientAsync(appUuid).thenAccept(client -> { + client.applySnapshotAsync(random).thenAccept(ack -> { + client.getSnapshotAsync().thenAccept(snapshot -> { + if (random.toString().equals(snapshot.toString())) { + latch.countDown(); + } + }); + + }); + }); + + latch.await(5, TimeUnit.SECONDS); + + assertEquals("initProviderThenCreateClientThenGetSnapshot timeout", latch.getCount(), 0); + } + + @Override + public JSONObject getSnapshot() { + if (this.randomSnapshot != null) { + return this.randomSnapshot; + } else { + return SNAPSHOT_CONTENT; + } + } + + @Override + public void applySnapshot(JSONObject snapshot) { + this.randomSnapshot = snapshot; + } +} diff --git a/src/test/java/com/openfin/desktop/SystemTest.java b/src/test/java/com/openfin/desktop/SystemTest.java index 9acd8a1..135e02d 100644 --- a/src/test/java/com/openfin/desktop/SystemTest.java +++ b/src/test/java/com/openfin/desktop/SystemTest.java @@ -50,7 +50,7 @@ public static void teardown() throws Exception { @Test public void getDeviceId() throws Exception { CountDownLatch latch = new CountDownLatch(1); - runtime.getDeviceId(new AckListener() { + runtime.getMachineId(new AckListener() { @Override public void onSuccess(Ack ack) { if (ack.isSuccessful()) { @@ -393,6 +393,8 @@ public void onError(Ack ack) { } } + // this test does not work anymore with Secure By Default in place + @Ignore @Test public void startAndTerminateExternalProcess() throws Exception { CountDownLatch startLatch = new CountDownLatch(1); @@ -463,7 +465,6 @@ public void onError(Ack ack) { assertEquals("getEnvironmentVariables timeout", latch.getCount(), 0); } - @Ignore @Test public void deleteCacheOnRestart() throws Exception { CountDownLatch latch = new CountDownLatch(1); @@ -514,31 +515,49 @@ public void restartRuntime() throws Exception { } @Test - public void customRdmAssetUrls() throws Exception { - TestUtils.teardownDesktopConnection(desktopConnection); - String rdmUrl = "https://rdm.openfin.co/services"; - String assetsUrl = "https://cdn.openfin.co/release"; - desktopConnection = TestUtils.setupConnection(DESKTOP_UUID, rdmUrl, assetsUrl); - runtime = new OpenFinRuntime(desktopConnection); + public void getRuntimeInfo() throws Exception { CountDownLatch latch = new CountDownLatch(1); - runtime.getConfig(null, new AckListener() { + runtime.getRuntimeInfo(new AckListener() { @Override public void onSuccess(Ack ack) { if (ack.isSuccessful()) { + // { "manifestUrl":"http://localhost:5090/getManifest","port":9696,"version":"8.56.30.37","architecture":"x64"} JSONObject data = (JSONObject) ack.getData(); - if (rdmUrl.equals(data.getString("rdmUrl")) && assetsUrl.equals(data.getString("assetsUrl"))) { + if (data.has("manifestUrl") && data.has("port") && data.has("version")) { latch.countDown(); } } } + @Override public void onError(Ack ack) { - logger.error(ack.getReason()); } }); latch.await(5, TimeUnit.SECONDS); - assertEquals("getConfig timeout", latch.getCount(), 0); + assertEquals("getRuntimeInfo timeout", latch.getCount(), 0); + } + + @Test + public void getRvmInfo() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + runtime.getRvmInfo(new AckListener() { + @Override + public void onSuccess(Ack ack) { + if (ack.isSuccessful()) { + // { "action":"get-rvm-info","path":"C:\\Users\\abc\\AppData\\Local\\OpenFin\\OpenFinRVM.exe","start-time":"2018-04-12 14:01:41","version":"4.0.1.1","working-dir":"C:\\Users\\abc\\AppData\\Local\\OpenFin"} + JSONObject data = (JSONObject) ack.getData(); + if (data.has("action") && data.has("path") && data.has("start-time")) { + latch.countDown(); + } + } + } + @Override + public void onError(Ack ack) { + } + }); + latch.await(5, TimeUnit.SECONDS); + assertEquals("getRvmInfo timeout", latch.getCount(), 0); } diff --git a/src/test/java/com/openfin/desktop/TestExample.java b/src/test/java/com/openfin/desktop/TestExample.java index 444c2c5..85f1226 100644 --- a/src/test/java/com/openfin/desktop/TestExample.java +++ b/src/test/java/com/openfin/desktop/TestExample.java @@ -33,7 +33,7 @@ public void onReady() { publishMessages(); } @Override - public void onClose() { + public void onClose(String error) { } @Override diff --git a/src/test/java/com/openfin/desktop/TestUtils.java b/src/test/java/com/openfin/desktop/TestUtils.java index c024750..a60b4c8 100644 --- a/src/test/java/com/openfin/desktop/TestUtils.java +++ b/src/test/java/com/openfin/desktop/TestUtils.java @@ -27,7 +27,8 @@ public class TestUtils { private static String runtimeVersion; private static CountDownLatch disconnectedLatch; public static final String openfin_app_url = "https://cdn.openfin.co/examples/junit/SimpleOpenFinApp.html"; // source is in release/SimpleOpenFinApp.html - public static final String icon_url = "http://demoappdirectory.openf.in/desktop/config/apps/OpenFin/HelloOpenFin/img/openfin.ico"; + public static final String icon_url = "https://cdn.openfin.co/demos/hello/img/openfin.ico"; + public static final String hello_app_manifest_url = "https://cdn.openfin.co/demos/hello/app.json"; static { runtimeVersion = java.lang.System.getProperty("com.openfin.test.runtime.version"); @@ -37,9 +38,6 @@ public class TestUtils { logger.debug(String.format("Runtime version %s", runtimeVersion)); } - public static DesktopConnection setupConnection(String connectionUuid) throws Exception { - return setupConnection(connectionUuid, null, null); - } public static DesktopConnection setupConnection(String connectionUuid, RuntimeConfiguration configuration) throws Exception { logger.debug("starting from Runtime configuration"); CountDownLatch connectedLatch = new CountDownLatch(1); @@ -50,9 +48,11 @@ public static DesktopConnection setupConnection(String connectionUuid, RuntimeCo if (swaiTime != null) { waitTime = Integer.parseInt(swaiTime); } - DesktopConnection desktopConnection = new DesktopConnection(connectionUuid); - desktopConnection.setAdditionalRuntimeArguments(" --v=1 --no-sandbox "); // turn on Chromium debug log + String args = java.lang.System.getProperty("com.openfin.test.runtime.additionalRuntimeArguments"); + if (args != null) { + configuration.setAdditionalRuntimeArguments(args); + } desktopConnection.connect(configuration, new DesktopStateListener() { @Override public void onReady() { @@ -61,7 +61,7 @@ public void onReady() { connectedLatch.countDown(); } @Override - public void onClose() { + public void onClose(String error) { logger.debug("Connection closed"); disconnectedLatch.countDown(); } @@ -96,7 +96,7 @@ public void onOutgoingMessage(String message) { return desktopConnection; } - public static DesktopConnection setupConnection(String connectionUuid, String rdmUrl, String assetsUrl) throws Exception { + public static DesktopConnection setupConnection(String connectionUuid) throws Exception { logger.debug("starting"); CountDownLatch connectedLatch = new CountDownLatch(1); disconnectedLatch = new CountDownLatch(1); @@ -110,10 +110,12 @@ public static DesktopConnection setupConnection(String connectionUuid, String rd DesktopConnection desktopConnection = new DesktopConnection(connectionUuid); RuntimeConfiguration configuration = new RuntimeConfiguration(); configuration.setRuntimeVersion(runtimeVersion); - configuration.setAdditionalRuntimeArguments(" --v=1 --no-sandbox --enable-crash-reporting "); // turn on Chromium debug log + configuration.setMaxMessageSize(738320); + String args = java.lang.System.getProperty("com.openfin.test.runtime.additionalRuntimeArguments"); + if (args != null) { + configuration.setAdditionalRuntimeArguments(args); + } configuration.setDevToolsPort(9090); - configuration.setRdmURL(rdmUrl); - configuration.setRuntimeAssetURL(assetsUrl); configuration.setLicenseKey("JavaAdapterJUnitTests"); desktopConnection.connect(configuration, new DesktopStateListener() { @Override @@ -123,7 +125,7 @@ public void onReady() { connectedLatch.countDown(); } @Override - public void onClose() { + public void onClose(String error) { logger.debug("Connection closed"); disconnectedLatch.countDown(); connectedLatch.countDown(); // interrupt connectedLatch.await @@ -297,15 +299,7 @@ public void eventReceived(ActionEvent actionEvent) { }; addEventListener(application, "closed", listener); - application.close(new AckListener() { - @Override - public void onSuccess(Ack ack) { - } - @Override - public void onError(Ack ack) { - logger.error(ack.getReason()); - } - }); + application.close(); stoppedLatch.await(5, TimeUnit.SECONDS); assertEquals("Close application timeout " + application.getUuid(), stoppedLatch.getCount(), 0); } @@ -444,4 +438,12 @@ public void onError(Ack ack) { assertEquals("getMonitorInfo timeout", latch.getCount(), 0); return windowBoundsAtomicReference.get(); } + + public static void pause(int milliSeconds) { + try { + Thread.sleep(milliSeconds); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } diff --git a/src/test/java/com/openfin/desktop/WindowPositionTest.java b/src/test/java/com/openfin/desktop/WindowPositionTest.java index 4bfcee0..f26143e 100644 --- a/src/test/java/com/openfin/desktop/WindowPositionTest.java +++ b/src/test/java/com/openfin/desktop/WindowPositionTest.java @@ -59,10 +59,9 @@ public static void teardown() throws Exception { TestUtils.teardownDesktopConnection(desktopConnection); } - @Ignore("for now") @Test public void saveWindowStateWithRuntimeRestart() throws Exception { - int repeat = 30; + int repeat = 3; String value = java.lang.System.getProperty("com.openfin.desktop.WindowPositionTest.repeat"); if (value != null) { repeat = Integer.parseInt(value); diff --git a/src/test/java/com/openfin/desktop/WindowTest.java b/src/test/java/com/openfin/desktop/WindowTest.java index 75c085d..6e65f60 100644 --- a/src/test/java/com/openfin/desktop/WindowTest.java +++ b/src/test/java/com/openfin/desktop/WindowTest.java @@ -31,7 +31,7 @@ public class WindowTest { private static final String DESKTOP_UUID = WindowTest.class.getName(); private static DesktopConnection desktopConnection; - private static final String child_window_url = "http://test.openf.in/test.html"; // simple test app + private static final String guest_url = "https://example.com/"; @BeforeClass public static void setup() throws Exception { @@ -213,85 +213,6 @@ public void onError(Ack ack) { TestUtils.closeApplication(application); } - @Test - public void dockAndUndock() throws Exception { - String childName = "docking test"; - Application application = TestUtils.runApplication(TestUtils.getAppOptions(null), desktopConnection); - Window mainWindow = application.getWindow(); - WindowOptions childOptions = TestUtils.getWindowOptions(childName, child_window_url); - Window childWindow = TestUtils.createChildWindow(application, childOptions, desktopConnection); - WindowBounds beforeMoveBounds = TestUtils.getBounds(childWindow); - CountDownLatch joinLatch = new CountDownLatch(1); - childWindow.joinGroup(mainWindow, new AckListener() { - @Override - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - joinLatch.countDown(); - } - } - @Override - public void onError(Ack ack) { - logger.error(String.format("onError %s", ack.getReason())); - } - }); - joinLatch.await(3, TimeUnit.SECONDS); - assertEquals(joinLatch.getCount(), 0); - - CountDownLatch groupInfoLatch = new CountDownLatch(2); - mainWindow.getGroup(result -> { - for (Window window : result) { - if (window.getUuid().equals(mainWindow.getUuid()) && window.getName().equals(mainWindow.getName())) { - groupInfoLatch.countDown(); - } - else if (window.getUuid().equals(childWindow.getUuid()) && window.getName().equals(childWindow.getName())) { - groupInfoLatch.countDown(); - } - } - }, new AckListener() { - @Override - public void onSuccess(Ack ack) { - } - @Override - public void onError(Ack ack) { - } - }); - groupInfoLatch.await(3, TimeUnit.SECONDS); - assertEquals(groupInfoLatch.getCount(), 0); - - int leftBy = 20, topBy = 30; - TestUtils.moveWindowBy(mainWindow, leftBy, topBy); - // child window sohuld move with main window since they are docked - WindowBounds afterMoveBounds = TestUtils.getBounds(childWindow); - int topAfterDockMove = afterMoveBounds.getTop(), leftAfterDockMove = afterMoveBounds.getLeft(); - assertEquals(afterMoveBounds.getTop() - beforeMoveBounds.getTop(), topBy); - assertEquals(afterMoveBounds.getLeft() - beforeMoveBounds.getLeft(), leftBy); - - // undock by leaving the group - CountDownLatch undockLatch = new CountDownLatch(1); - childWindow.leaveGroup(new AckListener() { - @Override - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - undockLatch.countDown(); - } - } - @Override - public void onError(Ack ack) { - logger.error(String.format("onError %s", ack.getReason())); - } - }); - undockLatch.await(5, TimeUnit.SECONDS); - assertEquals(undockLatch.getCount(), 0); - TestUtils.moveWindowBy(mainWindow, leftBy, topBy); - // child window should not move afer leaving group - afterMoveBounds = TestUtils.getBounds(childWindow); - assertEquals(afterMoveBounds.getLeft().intValue(), leftAfterDockMove); - assertEquals(afterMoveBounds.getTop().intValue(), topAfterDockMove); - - TestUtils.closeApplication(application); - } - - @Test public void animateMove() throws Exception { ApplicationOptions options = TestUtils.getAppOptions(null); @@ -452,7 +373,7 @@ public void navigate() throws Exception { Application application = TestUtils.runApplication(options, desktopConnection); Window window = application.getWindow(); CountDownLatch latch = new CountDownLatch(1); - window.navigate("https://openfin.co", new AckListener() { + window.navigate(guest_url, new AckListener() { @Override public void onSuccess(Ack ack) { if (ack.isSuccessful()) { @@ -466,9 +387,9 @@ public void onError(Ack ack) { latch.await(5, TimeUnit.SECONDS); assertEquals("Window.navigate timeout", latch.getCount(), 0); - Thread.sleep(1000); // give time for https://openfin.co to load + Thread.sleep(1000); // give time for guest_url to load window.executeJavaScript("location.href", result -> { - if (result != null && result.toString().equals("https://openfin.co")) { + if (result != null && result.toString().equals(guest_url)) { latch.countDown(); } }, null); @@ -483,46 +404,13 @@ public void navigateBack() throws Exception { ApplicationOptions options = TestUtils.getAppOptions(null); Application application = TestUtils.runApplication(options, desktopConnection); Window window = application.getWindow(); - CountDownLatch latch = new CountDownLatch(1); - window.navigate("https://openfin.co", new AckListener() { - @Override - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - window.navigate("https://www.google.com", new AckListener() { - @Override - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - window.navigateBack(new AckListener() { - @Override - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - if (ack.isSuccessful()) { - latch.countDown(); - } - } - } - @Override - public void onError(Ack ack) { - } - }); - } - } - @Override - public void onError(Ack ack) { - } - }); - } - } - @Override - public void onError(Ack ack) { - } - }); + CountDownLatch latch = new CountDownLatch(2); + navigateAndWaitForContent(window, guest_url); + navigateAndWaitForContent(window, "https://google.com"); + navigateHistoryAndWaitForContent(window, -1, latch); - latch.await(5, TimeUnit.SECONDS); - assertEquals("Window.navigate timeout", latch.getCount(), 0); - Thread.sleep(1000); // give time for https://openfin.co to load window.executeJavaScript("location.href", result -> { - if (result != null && result.toString().equals("https://openfin.co")) { + if (result != null && result.toString().equals(guest_url)) { latch.countDown(); } }, null); @@ -537,54 +425,15 @@ public void navigateForward() throws Exception { ApplicationOptions options = TestUtils.getAppOptions(null); Application application = TestUtils.runApplication(options, desktopConnection); Window window = application.getWindow(); - CountDownLatch latch = new CountDownLatch(1); - window.navigate("https://www.google.com", new AckListener() { - @Override - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - window.navigate("https://openfin.co", new AckListener() { - @Override - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - window.navigateBack(new AckListener() { - @Override - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - window.navigateForward(new AckListener() { - @Override - public void onSuccess(Ack ack) { - if (ack.isSuccessful()) { - latch.countDown(); - } - } - @Override - public void onError(Ack ack) { - } - }); - } - } - @Override - public void onError(Ack ack) { - } - }); - } - } - @Override - public void onError(Ack ack) { - } - }); - } - } - @Override - public void onError(Ack ack) { - } - }); + CountDownLatch latch = new CountDownLatch(3); + navigateAndWaitForContent(window, "https://google.com"); + navigateAndWaitForContent(window, guest_url); + navigateHistoryAndWaitForContent(window, -1, latch); + navigateHistoryAndWaitForContent(window, 1, latch); - latch.await(5, TimeUnit.SECONDS); - assertEquals("Window.navigate timeout", latch.getCount(), 0); - Thread.sleep(1000); // give time for https://openfin.co to load window.executeJavaScript("location.href", result -> { - if (result != null && result.toString().equals("https://openfin.co")) { + logger.info(String.format("location.ref %s ", result.toString())); + if (result != null && result.toString().equals(guest_url)) { latch.countDown(); } }, null); @@ -594,13 +443,51 @@ public void onError(Ack ack) { TestUtils.closeApplication(application); } + private void navigateAndWaitForContent(Window window, String url) throws Exception { + String eventType = "dom-content-loaded"; + CountDownLatch latch = new CountDownLatch(1); + EventListener listener = new EventListener() { + @Override + public void eventReceived(ActionEvent actionEvent) { + if (eventType.equals(actionEvent.getType())) { + latch.countDown(); + } + } + }; + TestUtils.addEventListener(window, eventType, listener); + window.navigate(url, null); + latch.await(5, TimeUnit.SECONDS); + window.removeEventListener(eventType, listener, null); + assertEquals("waitForWindowEvent timeout", latch.getCount(), 0); + } + + private void navigateHistoryAndWaitForContent(Window window, int direction, CountDownLatch latch) throws Exception { + String eventType = "dom-content-loaded"; + EventListener listener = new EventListener() { + @Override + public void eventReceived(ActionEvent actionEvent) { + if (eventType.equals(actionEvent.getType())) { + latch.countDown(); + } + } + }; + TestUtils.addEventListener(window, "dom-content-loaded", listener); + if (direction < 0) { + window.navigateBack(null); + } else { + window.navigateForward(null); + } + latch.await(5, TimeUnit.SECONDS); + window.removeEventListener(eventType, listener, null); + } + @Test public void stopNavigate() throws Exception { ApplicationOptions options = TestUtils.getAppOptions(null); Application application = TestUtils.runApplication(options, desktopConnection); Window window = application.getWindow(); CountDownLatch latch = new CountDownLatch(1); - window.navigate("https://openfin.co", new AckListener() { + window.navigate(guest_url, new AckListener() { @Override public void onSuccess(Ack ack) { if (ack.isSuccessful()) { @@ -628,7 +515,7 @@ public void onError(Ack ack) { assertEquals("Window.navigate timeout", latch.getCount(), 0); Thread.sleep(1000); window.executeJavaScript("location.href", result -> { - if (result != null && result.toString().equals("https://openfin.co")) { + if (result != null && result.toString().equals(guest_url)) { latch.countDown(); } }, null); @@ -698,6 +585,10 @@ public void onError(Ack ack) { @Override public void onError(Ack ack) { + // starting 13.76.43.x, Runtime rejects setBounds with numbers > max height/width + if (ack.getReason().contains("Proposed window bounds violate size constraints")) { + latch.countDown(); + } } }); @@ -751,7 +642,6 @@ public void onError(Ack ack) { TestUtils.closeApplication(application); } - @Ignore @Test public void getSetZoomLevel() throws Exception { double level = -1.5;