You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hop.apache.org by hi...@apache.org on 2021/01/01 22:09:14 UTC

[incubator-hop] branch master updated: HOP-2370: Add RCP fragments to the master branch

This is an automated email from the ASF dual-hosted git repository.

hiromu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-hop.git


The following commit(s) were added to refs/heads/master by this push:
     new df3560c  HOP-2370: Add RCP fragments to the master branch
     new 8057a39  Merge pull request #519 from HiromuHota/HOP-2370
df3560c is described below

commit df3560c08c9b8a3e7a59674be304545ed21fd236
Author: Hiromu Hota <hi...@gmail.com>
AuthorDate: Wed Dec 30 22:38:29 2020 -0800

    HOP-2370: Add RCP fragments to the master branch
    
    - Copy rcp/ from my web branch
    - Add rcp module to the base profile
    - Modify pom.xml and assembly.xml
    - Add default constructors for HopGui and GuiResource
    - Move PrintSpool.java to RCP fragments
---
 assemblies/client/pom.xml                          |  7 +++
 assemblies/client/src/assembly/assembly.xml        |  8 ++++
 pom.xml                                            |  1 +
 rcp/pom.xml                                        | 52 ++++++++++++++++++++++
 .../java/org/apache/hop/ui/core/PrintSpool.java    |  0
 .../apache/hop/ui/core/gui/GuiResourceImpl.java    | 30 +++++++++++++
 .../org/apache/hop/ui/hopgui/CanvasFacadeImpl.java | 30 +++++++++++++
 .../apache/hop/ui/hopgui/CanvasListenerImpl.java   | 36 +++++++++++++++
 .../java/org/apache/hop/ui/hopgui/HopGuiImpl.java  | 28 ++++++++++++
 .../hop/ui/hopgui/ServerPushSessionFacadeImpl.java | 31 +++++++++++++
 .../hop/ui/hopgui/TextSizeUtilFacadeImpl.java      | 39 ++++++++++++++++
 .../hop/ui/hopgui/context/GuiContextUtilImpl.java  | 30 +++++++++++++
 .../org/apache/hop/ui/core/gui/GuiResource.java    | 18 +++++---
 .../org/apache/hop/ui/hopgui/CanvasFacade.java     | 32 +++++++++++++
 .../org/apache/hop/ui/hopgui/CanvasListener.java   | 35 +++++++++++++++
 .../main/java/org/apache/hop/ui/hopgui/HopGui.java | 21 ++++++---
 .../apache/hop/ui/hopgui/ISingletonProvider.java   | 22 +++++++++
 .../apache/hop/ui/hopgui/ImplementationLoader.java | 37 +++++++++++++++
 .../hop/ui/hopgui/ServerPushSessionFacade.java     | 35 +++++++++++++++
 .../apache/hop/ui/hopgui/TextSizeUtilFacade.java   | 33 ++++++++++++++
 .../hop/ui/hopgui/context/GuiContextUtil.java      | 12 ++---
 21 files changed, 518 insertions(+), 19 deletions(-)

diff --git a/assemblies/client/pom.xml b/assemblies/client/pom.xml
index 47df256..8e3ce8e 100644
--- a/assemblies/client/pom.xml
+++ b/assemblies/client/pom.xml
@@ -90,6 +90,13 @@
       </exclusions>
     </dependency>
 
+    <!-- RCP fragment -->
+    <dependency>
+      <groupId>org.apache.hop</groupId>
+      <artifactId>hop-ui-rcp</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
     <!-- swt -->
     <dependency>
       <groupId>org.eclipse.platform</groupId>
diff --git a/assemblies/client/src/assembly/assembly.xml b/assemblies/client/src/assembly/assembly.xml
index ec6ef84..1d4ce2f 100644
--- a/assemblies/client/src/assembly/assembly.xml
+++ b/assemblies/client/src/assembly/assembly.xml
@@ -73,6 +73,14 @@
       <useTransitiveDependencies>false</useTransitiveDependencies>
       <useProjectArtifact>false</useProjectArtifact>
     </dependencySet>
+    <dependencySet>
+      <includes>
+        <include>org.apache.hop:hop-ui-rcp:jar</include>
+      </includes>
+      <outputDirectory>lib</outputDirectory>
+      <useTransitiveDependencies>false</useTransitiveDependencies>
+      <useProjectArtifact>false</useProjectArtifact>
+    </dependencySet>
 
   </dependencySets>
 </assembly>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index db18ca8..f42e0fa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -887,6 +887,7 @@
                 <module>core</module>
                 <module>engine</module>
                 <module>ui</module>
+                <module>rcp</module>
                 <module>plugins</module>
             </modules>
         </profile>
diff --git a/rcp/pom.xml b/rcp/pom.xml
new file mode 100644
index 0000000..60aa862
--- /dev/null
+++ b/rcp/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.hop</groupId>
+  <artifactId>hop-ui-rcp</artifactId>
+  <packaging>jar</packaging>
+  <version>0.60-SNAPSHOT</version>
+
+  <name>Hop GUI (RCP fragment)</name>
+
+  <parent>
+    <groupId>org.apache.hop</groupId>
+    <artifactId>hop</artifactId>
+    <version>0.60-SNAPSHOT</version>
+  </parent>
+
+  <dependencies>
+    <!-- Hop dependencies -->
+    <dependency>
+      <groupId>org.apache.hop</groupId>
+      <artifactId>hop-ui-swt</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <!-- Third-party dependencies -->
+    <dependency>
+      <groupId>org.eclipse.platform</groupId>
+      <artifactId>org.eclipse.swt.gtk.linux.x86_64</artifactId>
+      <version>${org.eclipse.platform.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>*</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.eclipse.platform</groupId>
+      <artifactId>org.eclipse.jface</artifactId>
+      <version>${org.eclipse.jface.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>*</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/ui/src/main/java/org/apache/hop/ui/core/PrintSpool.java b/rcp/src/main/java/org/apache/hop/ui/core/PrintSpool.java
similarity index 100%
rename from ui/src/main/java/org/apache/hop/ui/core/PrintSpool.java
rename to rcp/src/main/java/org/apache/hop/ui/core/PrintSpool.java
diff --git a/rcp/src/main/java/org/apache/hop/ui/core/gui/GuiResourceImpl.java b/rcp/src/main/java/org/apache/hop/ui/core/gui/GuiResourceImpl.java
new file mode 100644
index 0000000..11afa61
--- /dev/null
+++ b/rcp/src/main/java/org/apache/hop/ui/core/gui/GuiResourceImpl.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.core.gui;
+
+import org.apache.hop.ui.hopgui.ISingletonProvider;
+
+public class GuiResourceImpl implements ISingletonProvider {
+  private static GuiResource instance;
+  public Object getInstanceInternal() {
+    if ( instance == null ) {
+      instance = new GuiResource();
+    }
+    return instance;
+  }
+}
diff --git a/rcp/src/main/java/org/apache/hop/ui/hopgui/CanvasFacadeImpl.java b/rcp/src/main/java/org/apache/hop/ui/hopgui/CanvasFacadeImpl.java
new file mode 100644
index 0000000..4088e55
--- /dev/null
+++ b/rcp/src/main/java/org/apache/hop/ui/hopgui/CanvasFacadeImpl.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+import org.apache.hop.base.AbstractMeta;
+import org.eclipse.swt.widgets.Canvas;
+
+public class CanvasFacadeImpl extends CanvasFacade {
+
+  @Override
+  void setDataInternal( Canvas canvas, float magnification, AbstractMeta meta, Class type ) {
+    // do nothing
+  }
+
+}
diff --git a/rcp/src/main/java/org/apache/hop/ui/hopgui/CanvasListenerImpl.java b/rcp/src/main/java/org/apache/hop/ui/hopgui/CanvasListenerImpl.java
new file mode 100644
index 0000000..7cd503c
--- /dev/null
+++ b/rcp/src/main/java/org/apache/hop/ui/hopgui/CanvasListenerImpl.java
@@ -0,0 +1,36 @@
+/*! ******************************************************************************
+ *
+ * Hop : The Hop Orchestration Platform
+ *
+ * http://www.project-hop.org
+ *
+ *******************************************************************************
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+package org.apache.hop.ui.hopgui;
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+public class CanvasListenerImpl implements ISingletonProvider, Listener {
+  public Object getInstanceInternal() {
+    return this;
+  }
+  @Override
+  public void handleEvent( Event event ) {
+    // do nothing
+  }
+}
diff --git a/rcp/src/main/java/org/apache/hop/ui/hopgui/HopGuiImpl.java b/rcp/src/main/java/org/apache/hop/ui/hopgui/HopGuiImpl.java
new file mode 100644
index 0000000..ef2c9b9
--- /dev/null
+++ b/rcp/src/main/java/org/apache/hop/ui/hopgui/HopGuiImpl.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+public class HopGuiImpl implements ISingletonProvider {
+  private static HopGui instance;
+  public Object getInstanceInternal() {
+    if ( instance == null ) {
+      instance = new HopGui();
+    }
+    return instance;
+  }
+}
diff --git a/rcp/src/main/java/org/apache/hop/ui/hopgui/ServerPushSessionFacadeImpl.java b/rcp/src/main/java/org/apache/hop/ui/hopgui/ServerPushSessionFacadeImpl.java
new file mode 100644
index 0000000..30daea6
--- /dev/null
+++ b/rcp/src/main/java/org/apache/hop/ui/hopgui/ServerPushSessionFacadeImpl.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+public class ServerPushSessionFacadeImpl extends ServerPushSessionFacade {
+
+  @Override
+  void startInternal() {
+    // do nothing
+  }
+
+  @Override
+  void stopInternal() {
+    // do nothing
+  }
+}
diff --git a/rcp/src/main/java/org/apache/hop/ui/hopgui/TextSizeUtilFacadeImpl.java b/rcp/src/main/java/org/apache/hop/ui/hopgui/TextSizeUtilFacadeImpl.java
new file mode 100644
index 0000000..cf011e7
--- /dev/null
+++ b/rcp/src/main/java/org/apache/hop/ui/hopgui/TextSizeUtilFacadeImpl.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Display;
+
+public class TextSizeUtilFacadeImpl extends TextSizeUtilFacade {
+
+  @Override
+  Point textExtentInternal( Font font, String text, int wrapWidth ) {
+    Image dummyImage = new Image( Display.getCurrent(), 50, 10 );
+    GC dummyGC = new GC( dummyImage );
+    Point point = dummyGC.textExtent( text, SWT.DRAW_TAB | SWT.DRAW_DELIMITER );
+    dummyImage.dispose();
+    dummyGC.dispose();
+    return point;
+  }
+
+}
diff --git a/rcp/src/main/java/org/apache/hop/ui/hopgui/context/GuiContextUtilImpl.java b/rcp/src/main/java/org/apache/hop/ui/hopgui/context/GuiContextUtilImpl.java
new file mode 100644
index 0000000..27e80a3
--- /dev/null
+++ b/rcp/src/main/java/org/apache/hop/ui/hopgui/context/GuiContextUtilImpl.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui.context;
+
+import org.apache.hop.ui.hopgui.ISingletonProvider;
+
+public class GuiContextUtilImpl implements ISingletonProvider {
+  private static GuiContextUtil instance;
+  public Object getInstanceInternal() {
+    if ( instance == null ) {
+      instance = new GuiContextUtil();
+    }
+    return instance;
+  }
+}
diff --git a/ui/src/main/java/org/apache/hop/ui/core/gui/GuiResource.java b/ui/src/main/java/org/apache/hop/ui/core/gui/GuiResource.java
index 9f64cba..f166431 100644
--- a/ui/src/main/java/org/apache/hop/ui/core/gui/GuiResource.java
+++ b/ui/src/main/java/org/apache/hop/ui/core/gui/GuiResource.java
@@ -31,6 +31,8 @@ import org.apache.hop.core.row.IValueMeta;
 import org.apache.hop.core.row.value.ValueMetaPluginType;
 import org.apache.hop.ui.core.ConstUi;
 import org.apache.hop.ui.core.PropsUi;
+import org.apache.hop.ui.hopgui.ISingletonProvider;
+import org.apache.hop.ui.hopgui.ImplementationLoader;
 import org.apache.hop.ui.util.SwtSvgImageUtil;
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.jface.dialogs.MessageDialogWithToggle;
@@ -67,8 +69,6 @@ public class GuiResource {
 
   private static ILogChannel log = LogChannel.UI;
 
-  private static GuiResource guiResource;
-
   private Display display;
 
   private double zoomFactor;
@@ -265,6 +265,10 @@ public class GuiResource {
    */
   private static Clipboard clipboard;
 
+  protected GuiResource() {
+    this(Display.getCurrent());
+  }
+
   private GuiResource( Display display ) {
     this.display = display;
 
@@ -309,12 +313,12 @@ public class GuiResource {
 
   }
 
+  private static final ISingletonProvider PROVIDER;
+  static {
+    PROVIDER = (ISingletonProvider) ImplementationLoader.newInstance( GuiResource.class );
+  }
   public static final GuiResource getInstance() {
-    if ( guiResource != null ) {
-      return guiResource;
-    }
-    guiResource = new GuiResource( Display.getCurrent() );
-    return guiResource;
+    return (GuiResource) PROVIDER.getInstanceInternal();
   }
 
   /**
diff --git a/ui/src/main/java/org/apache/hop/ui/hopgui/CanvasFacade.java b/ui/src/main/java/org/apache/hop/ui/hopgui/CanvasFacade.java
new file mode 100644
index 0000000..559fd41
--- /dev/null
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/CanvasFacade.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+import org.apache.hop.base.AbstractMeta;
+import org.eclipse.swt.widgets.Canvas;
+
+public abstract class CanvasFacade {
+  private final static CanvasFacade IMPL;
+  static {
+    IMPL = (CanvasFacade) ImplementationLoader.newInstance( CanvasFacade.class );
+  }
+  public static void setData( Canvas canvas, float magnification, AbstractMeta meta, Class type ) {
+    IMPL.setDataInternal( canvas, magnification, meta, type );
+  }
+  abstract void setDataInternal( Canvas canvas, float magnification, AbstractMeta meta, Class type );
+}
diff --git a/ui/src/main/java/org/apache/hop/ui/hopgui/CanvasListener.java b/ui/src/main/java/org/apache/hop/ui/hopgui/CanvasListener.java
new file mode 100644
index 0000000..f2ac266
--- /dev/null
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/CanvasListener.java
@@ -0,0 +1,35 @@
+/*! ******************************************************************************
+ *
+ * Hop : The Hop Orchestration Platform
+ *
+ * http://www.project-hop.org
+ *
+ *******************************************************************************
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+package org.apache.hop.ui.hopgui;
+
+import org.eclipse.swt.widgets.Listener;
+
+public class CanvasListener {
+  private static final ISingletonProvider PROVIDER;
+  static {
+    PROVIDER = (ISingletonProvider) ImplementationLoader.newInstance( CanvasListener.class );
+  }
+  public static final Listener getInstance() {
+    return (Listener) PROVIDER.getInstanceInternal();
+  }
+}
diff --git a/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java b/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java
index e580491..8dcf9eb 100644
--- a/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java
@@ -188,7 +188,6 @@ public class HopGui
 
   public static final String APP_NAME = "Hop";
 
-  private static HopGui hopGui;
   private String id;
 
   private IHopMetadataProvider metadataProvider;
@@ -230,6 +229,10 @@ public class HopGui
 
   private boolean openingLastFiles;
 
+  protected HopGui() {
+    this(Display.getCurrent());
+  }
+
   private HopGui(Display display) {
     this.display = display;
     this.id = UUID.randomUUID().toString();
@@ -264,8 +267,12 @@ public class HopGui
     partitionManager = new MetadataManager<>(variables, metadataProvider, PartitionSchema.class);
   }
 
+  private static final ISingletonProvider PROVIDER;
+  static {
+    PROVIDER = (ISingletonProvider) ImplementationLoader.newInstance( HopGui.class );
+  }
   public static final HopGui getInstance() {
-    return hopGui;
+    return (HopGui) PROVIDER.getInstanceInternal();
   }
 
   public static void main(String[] arguments) {
@@ -284,7 +291,7 @@ public class HopGui
       HopLogStore.init();
       Locale.setDefault(LanguageChoice.getInstance().getDefaultLocale());
 
-      hopGui = new HopGui(display);
+      HopGui hopGui = HopGui.getInstance();
       hopGui.getCommandLineArguments().addAll(Arrays.asList(arguments));
       hopGui.setProps(PropsUi.getInstance());
 
@@ -860,12 +867,12 @@ public class HopGui
       label = "Options...",
       parentId = ID_MAIN_MENU_TOOLS_PARENT_ID)
   public void menuToolsOptions() {
-    if (new EnterOptionsDialog(hopGui.getShell()).open() != null) {
+    if (new EnterOptionsDialog(getShell()).open() != null) {
       try {
         HopConfig.getInstance().saveToFile();
       } catch (Exception e) {
         new ErrorDialog(
-            hopGui.getShell(),
+            getShell(),
             "Error",
             "Error saving the configuration file '"
                 + HopConfig.getInstance().getConfigFilename()
@@ -891,7 +898,7 @@ public class HopGui
         HopConfig.getInstance().saveToFile();
       } catch (Exception e) {
         new ErrorDialog(
-            hopGui.getShell(),
+            getShell(),
             "Error",
             "Error saving config variables to configuration file '"
                 + HopConfig.getInstance().getConfigFilename()
@@ -917,7 +924,7 @@ public class HopGui
       label = "About...",
       parentId = ID_MAIN_MENU_HELP_PARENT_ID)
   public void menuHelpAbout() {
-    AboutDialog dialog = new AboutDialog(hopGui.getShell());
+    AboutDialog dialog = new AboutDialog(getShell());
     dialog.open();
   }
   
diff --git a/ui/src/main/java/org/apache/hop/ui/hopgui/ISingletonProvider.java b/ui/src/main/java/org/apache/hop/ui/hopgui/ISingletonProvider.java
new file mode 100644
index 0000000..6d9c9d8
--- /dev/null
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/ISingletonProvider.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+public interface ISingletonProvider {
+  Object getInstanceInternal();
+}
diff --git a/ui/src/main/java/org/apache/hop/ui/hopgui/ImplementationLoader.java b/ui/src/main/java/org/apache/hop/ui/hopgui/ImplementationLoader.java
new file mode 100644
index 0000000..f0b74fc
--- /dev/null
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/ImplementationLoader.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+import java.text.MessageFormat;
+
+public class ImplementationLoader {
+  public static Object newInstance(final Class type) {
+    String name = type.getName();
+    Object result = null;
+    try {
+      // TODO: https://stackoverflow.com/questions/234600/can-i-use-class-newinstance-with-constructor-arguments
+      // TODO: https://stackoverflow.com/questions/195321/why-is-class-newinstance-evil
+      result = type.getClassLoader().loadClass( name + "Impl" ).newInstance();
+    } catch (Throwable throwable) {
+      String txt = "Could not load implementation for {0}";
+      String msg = MessageFormat.format(txt, new Object[] {name});
+      throw new RuntimeException(msg, throwable);
+    }
+    return result;
+  }
+}
diff --git a/ui/src/main/java/org/apache/hop/ui/hopgui/ServerPushSessionFacade.java b/ui/src/main/java/org/apache/hop/ui/hopgui/ServerPushSessionFacade.java
new file mode 100644
index 0000000..c46b320
--- /dev/null
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/ServerPushSessionFacade.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+public abstract class ServerPushSessionFacade {
+  private final static ServerPushSessionFacade IMPL;
+  static {
+    IMPL = (ServerPushSessionFacade) ImplementationLoader.newInstance( ServerPushSessionFacade.class );
+  }
+
+  public static void start() {
+    IMPL.startInternal();
+  }
+  abstract void startInternal();
+
+  public static void stop() {
+    IMPL.stopInternal();
+  }
+  abstract void stopInternal();
+}
diff --git a/ui/src/main/java/org/apache/hop/ui/hopgui/TextSizeUtilFacade.java b/ui/src/main/java/org/apache/hop/ui/hopgui/TextSizeUtilFacade.java
new file mode 100644
index 0000000..0c71027
--- /dev/null
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/TextSizeUtilFacade.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Point;
+
+public abstract class TextSizeUtilFacade {
+  private final static TextSizeUtilFacade IMPL;
+  static {
+    IMPL = (TextSizeUtilFacade) ImplementationLoader.newInstance( TextSizeUtilFacade.class );
+  }
+
+  public static Point textExtent( Font font, String text, int wrapWidth ) {
+    return IMPL.textExtentInternal( font, text, wrapWidth );
+  }
+  abstract Point textExtentInternal( Font font, String text, int wrapWidth );
+}
diff --git a/ui/src/main/java/org/apache/hop/ui/hopgui/context/GuiContextUtil.java b/ui/src/main/java/org/apache/hop/ui/hopgui/context/GuiContextUtil.java
index 1df589f..123dd5a 100644
--- a/ui/src/main/java/org/apache/hop/ui/hopgui/context/GuiContextUtil.java
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/context/GuiContextUtil.java
@@ -28,6 +28,8 @@ import org.apache.hop.core.gui.plugin.action.GuiAction;
 import org.apache.hop.core.gui.plugin.action.GuiActionType;
 import org.apache.hop.ui.core.dialog.ContextDialog;
 import org.apache.hop.ui.core.dialog.ErrorDialog;
+import org.apache.hop.ui.hopgui.ISingletonProvider;
+import org.apache.hop.ui.hopgui.ImplementationLoader;
 import org.eclipse.swt.widgets.Shell;
 
 import java.util.ArrayList;
@@ -41,12 +43,12 @@ public class GuiContextUtil {
 
   private final Map<String, ContextDialog> shellDialogMap = new HashMap<>();
 
-  private static GuiContextUtil guiContextUtil;
+  private static final ISingletonProvider PROVIDER;
+  static {
+    PROVIDER = (ISingletonProvider) ImplementationLoader.newInstance( GuiContextUtil.class );
+  }
   public static final GuiContextUtil getInstance() {
-    if (guiContextUtil == null) {
-      guiContextUtil = new GuiContextUtil();
-    }
-    return guiContextUtil;
+    return (GuiContextUtil) PROVIDER.getInstanceInternal();
   }
 
   public final List<GuiAction> getContextActions( IActionContextHandlersProvider provider, GuiActionType actionType, String contextId ) {