changeset 2516:5507e0168b50

Platform as Plugin review-thread: http://icedtea.classpath.org/pipermail/thermostat/2016-November/021508.html reviewed-by: aazores PR3226
author Mario Torre <neugens.limasoftware@gmail.com>
date Wed, 09 Nov 2016 11:56:27 +0100
parents 6227b428daa7
children 0be4e0290bca
files client/core/pom.xml client/core/src/main/java/com/redhat/thermostat/client/core/InformationService.java client/core/src/main/java/com/redhat/thermostat/client/core/controllers/InformationServiceController.java client/core/src/main/java/com/redhat/thermostat/client/core/internal/platform/DynamicHostPluginProvider.java client/core/src/main/java/com/redhat/thermostat/client/core/internal/platform/DynamicVMPluginProvider.java client/core/src/main/java/com/redhat/thermostat/client/core/internal/platform/EmbeddedPlatformService.java client/core/src/main/java/com/redhat/thermostat/client/core/internal/platform/UIPluginAction.java client/core/src/main/java/com/redhat/thermostat/client/core/views/UIPluginInfo.java client/core/src/main/java/com/redhat/thermostat/client/core/views/VmInformationView.java client/core/src/main/java/com/redhat/thermostat/client/ui/HostInformationController.java client/core/src/main/java/com/redhat/thermostat/client/ui/VmInformationController.java client/core/src/test/java/com/redhat/thermostat/client/ui/HostInformationControllerTest.java client/core/src/test/java/com/redhat/thermostat/client/ui/VmInformationControllerTest.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/DymamicHostPluginTracker.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/DymamicVMPluginTracker.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/InformationServiceTracker.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindow.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImpl.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/views/VmInformationPanel.java client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowTest.java client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/views/VmInformationPanelTest.java platform/core/pom.xml platform/core/src/main/java/com/redhat/thermostat/platform/EmbeddedPlatform.java platform/core/src/main/java/com/redhat/thermostat/platform/annotations/Extension.java platform/core/src/main/java/com/redhat/thermostat/platform/annotations/ExtensionPoint.java platform/core/src/main/java/com/redhat/thermostat/platform/internal/command/PlatformCommand.java platform/core/src/main/java/com/redhat/thermostat/platform/internal/command/PlatformCommandDelegate.java platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/MVCLifeCycleManager.java platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/handlers/MVCExtensionLinker.java platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/Context.java platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/Init.java platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/PlatformServiceRegistrar.java platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/StateMachine.java platform/core/src/main/java/com/redhat/thermostat/platform/mvc/MVCProvider.java platform/core/src/test/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/handlers/MVCExtensionLinkerTest.java platform/core/src/test/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/InitTest.java platform/core/src/test/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/StateMachineTest.java platform/distribution/thermostat-plugin.xml platform/swing/compat/pom.xml platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/DynamicHostPlugin.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/DynamicVMPlugin.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/EmbeddedPlatformController.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/EmbeddedPlatformPlugin.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/EmbeddedPlatformSwingView.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/DynamicHostPluginProviderImpl.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/DynamicHostPluginRegistry.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/DynamicVMPluginProviderImpl.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/DynamicVMPluginRegistry.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/HostPlugin1.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/HostPluginInterface1.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/HostProvider1.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/VMPlugin1.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/VMPlugin2.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/VMPluginInterface1.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/VMProvider1.java platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/VMProvider2.java platform/swing/core/src/main/java/com/redhat/thermostat/platform/application/swing/internal/ComponentVisibilityDispatcher.java platform/swing/core/src/main/java/com/redhat/thermostat/platform/application/swing/internal/EmbeddedSwingPlatformService.java platform/swing/core/src/main/java/com/redhat/thermostat/platform/swing/ContentProvider.java platform/swing/core/src/main/java/com/redhat/thermostat/platform/swing/SwingView.java platform/swing/core/src/main/java/com/redhat/thermostat/platform/swing/SwingWorkbench.java platform/swing/core/src/main/java/com/redhat/thermostat/platform/swing/ViewContainer.java platform/swing/core/src/main/java/com/redhat/thermostat/platform/swing/WorkbenchSwingView.java platform/swing/core/src/main/java/com/redhat/thermostat/platform/swing/WorkbenchView.java platform/swing/distribution/pom.xml platform/swing/distribution/thermostat-plugin.xml platform/swing/pom.xml thermostat-gui/core/src/main/java/com/redhat/thermostat/application/gui/internal/ThermostatWorkbenchController.java thermostat-gui/core/src/main/java/com/redhat/thermostat/application/gui/internal/ThermostatWorkbenchProvider.java thermostat-gui/core/src/main/java/com/redhat/thermostat/application/gui/internal/ThermostatWorkbenchSwingView.java thermostat-gui/core/src/main/java/com/redhat/thermostat/application/gui/internal/ThermostatWorkbenchView.java thermostat-gui/core/src/test/java/com/redhat/thermostat/application/gui/internal/ThermostatWorkbenchControllerTest.java
diffstat 72 files changed, 3232 insertions(+), 515 deletions(-) [+]
line wrap: on
line diff
--- a/client/core/pom.xml	Tue Nov 08 15:09:04 2016 -0500
+++ b/client/core/pom.xml	Wed Nov 09 11:56:27 2016 +0100
@@ -127,6 +127,7 @@
               com.redhat.thermostat.client.core.progress,
               com.redhat.thermostat.client.core.controllers,
               com.redhat.thermostat.client.core.views,
+              com.redhat.thermostat.client.core.internal.platform,
             </Export-Package>
             <Private-Package/>
             <!-- Do not autogenerate uses clauses in Manifests -->
--- a/client/core/src/main/java/com/redhat/thermostat/client/core/InformationService.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/client/core/src/main/java/com/redhat/thermostat/client/core/InformationService.java	Wed Nov 09 11:56:27 2016 +0100
@@ -54,7 +54,10 @@
  * {@link Constants#GENERIC_SERVICE_CLASSNAME} set to the name of the Class that
  * this {@link InformationService} provides information for, and the property
  * {@link #KEY_SERVICE_ID} set to a unique identifier for your implementation.
+ *
+ * @deprecated The preferred method is to use Platform plugins
  */
+@Deprecated
 @ExtensionPoint
 public interface InformationService<T extends Ref> extends Ordered {
     
--- a/client/core/src/main/java/com/redhat/thermostat/client/core/controllers/InformationServiceController.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/client/core/src/main/java/com/redhat/thermostat/client/core/controllers/InformationServiceController.java	Wed Nov 09 11:56:27 2016 +0100
@@ -42,7 +42,9 @@
 
 /**
  * The UI controller for a view that provides some information about a Host or a VM.
+ * @deprecated use UIPluginInfo instead
  */
+@Deprecated
 public interface InformationServiceController<T extends Ref> {
 
     UIComponent getView();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/core/src/main/java/com/redhat/thermostat/client/core/internal/platform/DynamicHostPluginProvider.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.core.internal.platform;
+
+import com.redhat.thermostat.annotations.Service;
+import com.redhat.thermostat.storage.core.HostRef;
+
+import java.util.List;
+
+/**
+ */
+@Service
+public interface DynamicHostPluginProvider {
+    void forEach(HostRef host, UIPluginAction action);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/core/src/main/java/com/redhat/thermostat/client/core/internal/platform/DynamicVMPluginProvider.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.core.internal.platform;
+
+import com.redhat.thermostat.annotations.Service;
+import com.redhat.thermostat.storage.core.VmRef;
+
+/**
+ */
+@Service
+public interface DynamicVMPluginProvider {
+    void forEach(VmRef host, UIPluginAction action);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/core/src/main/java/com/redhat/thermostat/client/core/internal/platform/EmbeddedPlatformService.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.core.internal.platform;
+
+import com.redhat.thermostat.annotations.Service;
+import com.redhat.thermostat.client.core.views.UIComponent;
+
+/**
+ */
+@Service
+public class EmbeddedPlatformService {
+    private final UIComponent topLevelContainer;
+    public EmbeddedPlatformService(UIComponent topLevelContainer) {
+        this.topLevelContainer = topLevelContainer;
+    }
+
+    public UIComponent getTopLevelContainer() {
+        return topLevelContainer;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/core/src/main/java/com/redhat/thermostat/client/core/internal/platform/UIPluginAction.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.core.internal.platform;
+
+import com.redhat.thermostat.client.core.views.UIPluginInfo;
+
+/**
+ */
+public interface UIPluginAction {
+    void execute(UIPluginInfo info);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/core/src/main/java/com/redhat/thermostat/client/core/views/UIPluginInfo.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.core.views;
+
+import com.redhat.thermostat.client.core.views.UIComponent;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+
+/**
+ * A visual component plugin.
+ */
+public interface UIPluginInfo {
+    UIComponent getView();
+    LocalizedString getLocalizedName();
+}
--- a/client/core/src/main/java/com/redhat/thermostat/client/core/views/VmInformationView.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/client/core/src/main/java/com/redhat/thermostat/client/core/views/VmInformationView.java	Wed Nov 09 11:56:27 2016 +0100
@@ -38,6 +38,8 @@
 
 import com.redhat.thermostat.shared.locale.LocalizedString;
 
+import java.util.List;
+
 
 public abstract class VmInformationView extends BasicView implements UIComponent {
 
@@ -50,6 +52,11 @@
     public abstract boolean selectChildID(int id);
     public abstract int getSelectedChildID();
 
-    public abstract void clear();
+    public void addChildViews(List<UIPluginInfo> plugins) {
+        for (UIPluginInfo plugin : plugins) {
+            addChildView(plugin.getLocalizedName(), plugin.getView());
+        }
+    }
+
+    public void clear() {}
 }
-
--- a/client/core/src/main/java/com/redhat/thermostat/client/ui/HostInformationController.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/client/core/src/main/java/com/redhat/thermostat/client/ui/HostInformationController.java	Wed Nov 09 11:56:27 2016 +0100
@@ -41,9 +41,12 @@
 
 import com.redhat.thermostat.client.core.InformationService;
 import com.redhat.thermostat.client.core.controllers.InformationServiceController;
+import com.redhat.thermostat.client.core.internal.platform.DynamicHostPluginProvider;
+import com.redhat.thermostat.client.core.internal.platform.UIPluginAction;
 import com.redhat.thermostat.client.core.views.BasicView;
 import com.redhat.thermostat.client.core.views.HostInformationView;
 import com.redhat.thermostat.client.core.views.HostInformationViewProvider;
+import com.redhat.thermostat.client.core.views.UIPluginInfo;
 import com.redhat.thermostat.common.OrderedComparator;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.storage.core.HostRef;
@@ -53,15 +56,31 @@
     private final List<InformationService<HostRef>> hostInfoServices;
     private final HostRef ref;
     private final HostInformationView view;
+    private List<DynamicHostPluginProvider> dynamicProviders;
+
+    private static class PluginAction implements UIPluginAction {
+
+        private HostInformationView view;
+        PluginAction(HostInformationView view) {
+            this.view = view;
+        }
+
+        @Override
+        public void execute(UIPluginInfo info) {
+            LocalizedString name = info.getLocalizedName();
+            view.addChildView(name, info.getView());
+        }
+    }
 
     public HostInformationController(List<InformationService<HostRef>> hostInfoServices,
                                      HostRef ref,
-                                     HostInformationViewProvider provider)
+                                     HostInformationViewProvider provider,
+                                     List<DynamicHostPluginProvider> dynamicProviders)
     {
         this.hostInfoServices = hostInfoServices;
         this.ref = ref;
+        this.dynamicProviders = dynamicProviders;
         view = provider.createView();
-        rebuild();
     }
 
     public void rebuild() {
@@ -73,6 +92,12 @@
                 view.addChildView(name, ctrl.getView());
             }
         }
+
+        PluginAction action = new PluginAction(view);
+
+        for (DynamicHostPluginProvider dynamicProvider : dynamicProviders) {
+            dynamicProvider.forEach(ref, action);
+        }
     }
 
     public BasicView getView() {
--- a/client/core/src/main/java/com/redhat/thermostat/client/ui/VmInformationController.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/client/core/src/main/java/com/redhat/thermostat/client/ui/VmInformationController.java	Wed Nov 09 11:56:27 2016 +0100
@@ -36,12 +36,17 @@
 
 package com.redhat.thermostat.client.ui;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 import com.redhat.thermostat.client.core.InformationService;
 import com.redhat.thermostat.client.core.controllers.InformationServiceController;
+import com.redhat.thermostat.client.core.internal.platform.DynamicVMPluginProvider;
+import com.redhat.thermostat.client.core.internal.platform.UIPluginAction;
 import com.redhat.thermostat.client.core.views.BasicView;
+import com.redhat.thermostat.client.core.views.UIComponent;
+import com.redhat.thermostat.client.core.views.UIPluginInfo;
 import com.redhat.thermostat.client.core.views.VmInformationView;
 import com.redhat.thermostat.client.core.views.VmInformationViewProvider;
 import com.redhat.thermostat.common.OrderedComparator;
@@ -56,19 +61,56 @@
 
     private int selectedID;
 
+    private List<DynamicVMPluginProvider> dynamicProviders;
+
+    private static class PluginAction implements UIPluginAction {
+
+        private List<UIPluginInfo> plugins;
+        PluginAction(List<UIPluginInfo> plugins) {
+            this.plugins = plugins;
+        }
+
+        @Override
+        public void execute(UIPluginInfo info) {
+            plugins.add(info);
+        }
+    }
+
+    private class PluginInfo implements UIPluginInfo {
+        UIComponent view;
+        LocalizedString name;
+
+        public PluginInfo(LocalizedString name, UIComponent view) {
+            this.view = view;
+            this.name = name;
+        }
+
+        @Override
+        public UIComponent getView() {
+            return view;
+        }
+
+        @Override
+        public LocalizedString getLocalizedName() {
+            return name;
+        }
+    }
+
     public VmInformationController(List<InformationService<VmRef>> vmInfoServices,
                                    VmRef vmRef,
-                                   VmInformationViewProvider provider)
+                                   VmInformationViewProvider provider,
+                                   List<DynamicVMPluginProvider> dynamicProviders)
     {
         this.vmInfoServices = vmInfoServices;
         this.vmRef = vmRef;
         this.selectedID = 0;
+        this.dynamicProviders = dynamicProviders;
 
         view = provider.createView();
-        rebuild();
     }
 
     void rebuild() {
+        List<UIPluginInfo> plugins = new ArrayList<>();
 
         view.clear();
 
@@ -76,11 +118,17 @@
         for (InformationService<VmRef> vmInfoService : vmInfoServices) {
             if (vmInfoService.getFilter().matches(vmRef)) {
                 InformationServiceController<VmRef> ctrl = vmInfoService.getInformationServiceController(vmRef);
-                LocalizedString name = ctrl.getLocalizedName();
-                view.addChildView(name, ctrl.getView());
+                plugins.add(new PluginInfo(ctrl.getLocalizedName(), ctrl.getView()));
             }
         }
 
+        PluginAction action = new PluginAction(plugins);
+        for (DynamicVMPluginProvider dynamicProvider : dynamicProviders) {
+            dynamicProvider.forEach(vmRef, action);
+        }
+
+        view.addChildViews(plugins);
+
         view.selectChildID(selectedID);
     }
 
--- a/client/core/src/test/java/com/redhat/thermostat/client/ui/HostInformationControllerTest.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/client/core/src/test/java/com/redhat/thermostat/client/ui/HostInformationControllerTest.java	Wed Nov 09 11:56:27 2016 +0100
@@ -43,6 +43,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import com.redhat.thermostat.client.core.internal.platform.DynamicHostPluginProvider;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.InOrder;
@@ -62,12 +63,14 @@
     private HostRef ref;
     private HostInformationViewProvider provider;
     private HostInformationView view;
+    private List<DynamicHostPluginProvider> dynamicProviders;
 
     @Before
     public void setup() {
         ref = mock(HostRef.class);
         provider = mock(HostInformationViewProvider.class);
         view = mock(HostInformationView.class);
+        dynamicProviders = new ArrayList<>();
         when(provider.createView()).thenReturn(view);
     }
 
@@ -78,7 +81,11 @@
         // Mock services
         List<InformationService<HostRef>> services = mockServices(orderValues);
 
-        new HostInformationController(new ArrayList<>(services), ref, provider);
+        HostInformationController controller =
+                new HostInformationController(new ArrayList<>(services), ref,
+                                              provider,
+                                              dynamicProviders);
+        controller.rebuild();
 
         InOrder order = inOrder(services.get(0), services.get(1),
                 services.get(2), services.get(3), services.get(4));
--- a/client/core/src/test/java/com/redhat/thermostat/client/ui/VmInformationControllerTest.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/client/core/src/test/java/com/redhat/thermostat/client/ui/VmInformationControllerTest.java	Wed Nov 09 11:56:27 2016 +0100
@@ -43,6 +43,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import com.redhat.thermostat.client.core.internal.platform.DynamicVMPluginProvider;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.InOrder;
@@ -62,6 +63,7 @@
     private VmRef ref;
     private VmInformationViewProvider provider;
     private VmInformationView view;
+    private List<DynamicVMPluginProvider> dynamicProviders;
 
     @Before
     public void setup() {
@@ -69,6 +71,8 @@
         provider = mock(VmInformationViewProvider.class);
         view = mock(VmInformationView.class);
         when(provider.createView()).thenReturn(view);
+
+        dynamicProviders = new ArrayList<>();
     }
 
     @Test
@@ -78,7 +82,11 @@
         // Mock services
         List<InformationService<VmRef>> services = mockServices(orderValues);
 
-        new VmInformationController(new ArrayList<>(services), ref, provider);
+        VmInformationController controller =
+                new VmInformationController(new ArrayList<>(services), ref, provider,
+                                    dynamicProviders);
+
+        controller.rebuild();
 
         InOrder order = inOrder(services.get(0), services.get(1),
                 services.get(2), services.get(3), services.get(4));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/DymamicHostPluginTracker.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.swing.internal;
+
+import com.redhat.thermostat.client.core.internal.platform.DynamicHostPluginProvider;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ */
+public class DymamicHostPluginTracker extends ServiceTracker {
+
+    private List<DynamicHostPluginProvider> dynamicHostPluginProviders;
+
+    public DymamicHostPluginTracker(BundleContext context) {
+        super(context, DynamicHostPluginProvider.class.getName(), null);
+        dynamicHostPluginProviders = new CopyOnWriteArrayList<>();
+    }
+
+    @Override
+    public Object addingService(ServiceReference reference) {
+        Object service = super.addingService(reference);
+        dynamicHostPluginProviders.add((DynamicHostPluginProvider) service);
+        return service;
+    }
+
+    @Override
+    public void removedService(ServiceReference reference, Object service) {
+        dynamicHostPluginProviders.remove(service);
+        super.removedService(reference, service);
+    }
+
+    public List<DynamicHostPluginProvider> getPluginProviders() {
+        return new ArrayList<>(dynamicHostPluginProviders);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/DymamicVMPluginTracker.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.swing.internal;
+
+import com.redhat.thermostat.client.core.internal.platform.DynamicVMPluginProvider;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ */
+public class DymamicVMPluginTracker extends ServiceTracker {
+
+    private List<DynamicVMPluginProvider> dynamicHostPluginProviders;
+
+    public DymamicVMPluginTracker(BundleContext context) {
+        super(context, DynamicVMPluginProvider.class.getName(), null);
+        dynamicHostPluginProviders = new CopyOnWriteArrayList<>();
+    }
+
+    @Override
+    public Object addingService(ServiceReference reference) {
+        Object service = super.addingService(reference);
+        dynamicHostPluginProviders.add((DynamicVMPluginProvider) service);
+        return service;
+    }
+
+    @Override
+    public void removedService(ServiceReference reference, Object service) {
+        dynamicHostPluginProviders.remove(service);
+        super.removedService(reference, service);
+    }
+
+    public List<DynamicVMPluginProvider> getPluginProviders() {
+        return new ArrayList<>(dynamicHostPluginProviders);
+    }
+}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/InformationServiceTracker.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/InformationServiceTracker.java	Wed Nov 09 11:56:27 2016 +0100
@@ -38,8 +38,10 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.logging.Logger;
 
+import com.redhat.thermostat.client.core.internal.platform.DynamicHostPluginProvider;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.util.tracker.ServiceTracker;
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindow.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindow.java	Wed Nov 09 11:56:27 2016 +0100
@@ -36,6 +36,7 @@
 
 package com.redhat.thermostat.client.swing.internal;
 
+import com.redhat.thermostat.client.core.internal.platform.EmbeddedPlatformService;
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Component;
@@ -103,9 +104,11 @@
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.VmRef;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
 
 @SuppressWarnings({ "restriction", "serial" })
-public class MainWindow extends JFrame implements MainView {
+public class MainWindow extends JFrame implements MainView, SwingComponent {
     
     public static final String MAIN_WINDOW_NAME = "Thermostat_mainWindo_JFrame_parent#1";
 
@@ -178,6 +181,24 @@
                 fireViewAction(Action.HIDDEN);
             }
         });
+        
+        registerServiceForPlatform(getContext());
+    }
+
+    @Override
+    public Component getUiComponent() {
+        return this;
+    }
+
+    BundleContext getContext() {
+        BundleContext context =
+                FrameworkUtil.getBundle(MainWindow.class).getBundleContext();
+        return context;
+    }
+
+    void registerServiceForPlatform(BundleContext context) {
+        EmbeddedPlatformService embeddedPlatformService = new EmbeddedPlatformService(this);
+        context.registerService(EmbeddedPlatformService.class, embeddedPlatformService, null);
     }
 
     private void setupNotificationPane(StatusBar statusBar, final ThermostatGlassPane glassPane) {
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImpl.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImpl.java	Wed Nov 09 11:56:27 2016 +0100
@@ -140,6 +140,8 @@
     private AgentInformationViewProvider agentInfoViewProvider;
     private ClientConfigViewProvider clientConfigViewProvider;
 
+    private DymamicHostPluginTracker dymamicHostPluginTracker;
+    private DymamicVMPluginTracker dymamicVMPluginTracker;
     private InformationServiceTracker infoServiceTracker;
     private ContextActionServiceTracker contextActionTracker;
     private MultipleServiceTracker depTracker;
@@ -217,7 +219,13 @@
                 
         this.infoServiceTracker = new InformationServiceTracker(context);
         this.infoServiceTracker.open();
-        
+
+        dymamicHostPluginTracker = new DymamicHostPluginTracker(context);
+        dymamicHostPluginTracker.open();
+
+        dymamicVMPluginTracker = new DymamicVMPluginTracker(context);
+        dymamicVMPluginTracker.open();
+
         this.contextActionTracker = new ContextActionServiceTracker(context);
         this.contextActionTracker.open();
         
@@ -416,6 +424,8 @@
         depTracker.close();
         infoServiceTracker.close();
         contextActionTracker.close();
+        dymamicHostPluginTracker.close();
+        dymamicVMPluginTracker.close();
     }
 
     private void installListenersAndStartRegistries() {
@@ -564,12 +574,14 @@
 
     private HostInformationController createHostInformationController(HostRef ref) {
         List<InformationService<HostRef>> hostInfoServices = infoServiceTracker.getHostInformationServices();
-        return new HostInformationController(hostInfoServices, ref, hostInfoViewProvider);
+        return new HostInformationController(hostInfoServices, ref, hostInfoViewProvider,
+                                             dymamicHostPluginTracker.getPluginProviders());
     }
 
     private VmInformationController createVmController(VmRef ref) {
         List<InformationService<VmRef>> vmInfoServices = infoServiceTracker.getVmInformationServices();
-        return new VmInformationController(vmInfoServices, ref, vmInfoViewProvider);
+        return new VmInformationController(vmInfoServices, ref, vmInfoViewProvider,
+                                           dymamicVMPluginTracker.getPluginProviders());
     }
 
     static class UriOpener {
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/views/VmInformationPanel.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/views/VmInformationPanel.java	Wed Nov 09 11:56:27 2016 +0100
@@ -39,12 +39,14 @@
 import java.awt.BorderLayout;
 import java.awt.Component;
 import java.lang.reflect.InvocationTargetException;
+import java.util.List;
 import java.util.logging.Logger;
 
 import javax.swing.JPanel;
 import javax.swing.JTabbedPane;
 
 import com.redhat.thermostat.client.core.views.UIComponent;
+import com.redhat.thermostat.client.core.views.UIPluginInfo;
 import com.redhat.thermostat.client.core.views.VmInformationView;
 import com.redhat.thermostat.client.swing.EdtHelper;
 import com.redhat.thermostat.client.swing.OverlayContainer;
@@ -53,6 +55,14 @@
 import com.redhat.thermostat.shared.locale.LocalizedString;
 
 public class VmInformationPanel extends VmInformationView implements SwingComponent {
+    private static final String VIEW_NAME = "%VIEW_NAME%";
+    private static final String TEMPLATE =
+            "There's a non-swing view registered: '" + VIEW_NAME + "'. " +
+            "The swing client can not use these views. This is "         +
+            "most likely a developer mistake. If this is meant to "      +
+            "be a swing-based view, it must implement the "              +
+            "'SwingComponent' interface. If it's not meant to be a "     +
+            "swing-based view, it should not have been registered.";
 
     private static final Logger logger = LoggingUtils.getLogger(VmInformationPanel.class);
     private static final EdtHelper edtHelper = new EdtHelper();
@@ -84,31 +94,53 @@
     }
 
     @Override
+    public void addChildViews(final List<UIPluginInfo> plugins) {
+        try {
+            edtHelper.callAndWait(new Runnable() {
+                @Override
+                public void run() {
+                    for (UIPluginInfo plugin : plugins) {
+                        UIComponent view = plugin.getView();
+                        if (view instanceof SwingComponent) {
+                            addViewImpl(plugin.getLocalizedName(), (SwingComponent) view);
+                        } else {
+                            logger.severe(getLoggerMessage(view));
+                        }
+                    }
+                }
+            });
+        } catch (InvocationTargetException | InterruptedException e) {
+            logger.severe(e.getLocalizedMessage());
+        }
+    }
+
+    String getLoggerMessage(UIComponent view) {
+        return TEMPLATE.replace(VIEW_NAME, view.toString());
+    }
+
+    private void addViewImpl(final LocalizedString title, final SwingComponent view) {
+        tabPane.addTab(title.getContents(), null, view.getUiComponent(), null);
+        if (view instanceof OverlayContainer) {
+            OverlayContainer overlayContainer = (OverlayContainer) view;
+            tabPane.addMouseListener(overlayContainer.getOverlay().getClickOutCloseListener(tabPane));
+        }
+    }
+
+    @Override
     public void addChildView(final LocalizedString title, final UIComponent view) {
         if (view instanceof SwingComponent) {
             try {
                 edtHelper.callAndWait(new Runnable() {
                     @Override
                     public void run() {
-                        SwingComponent panel = (SwingComponent) view;
-                        tabPane.addTab(title.getContents(), null, panel.getUiComponent(), null);
-                        if (view instanceof OverlayContainer) {
-                            OverlayContainer overlayContainer = (OverlayContainer) view;
-                            tabPane.addMouseListener(overlayContainer.getOverlay().getClickOutCloseListener(tabPane));
-                        }
+                        addViewImpl(title, (SwingComponent) view);
                     }
                 });
             } catch (InvocationTargetException | InterruptedException e) {
                 logger.severe(e.getLocalizedMessage());
             }
         } else {
-            String message = ""
-                    + "There's a non-swing view registered: '" + view.toString()
-                    + "'. The swing client can not use these views. This is "
-                    + "most likely a developer mistake. If this is meant to "
-                    + "be a swing-based view, it must implement the "
-                    + "'SwingComponent' interface. If it's not meant to be a "
-                    + "swing-based view, it should not have been registered.";
+            String message = getLoggerMessage(view);
             logger.severe(message);
             throw new AssertionError(message);
         }
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowTest.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowTest.java	Wed Nov 09 11:56:27 2016 +0100
@@ -38,7 +38,9 @@
 
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -46,8 +48,8 @@
 import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JRadioButtonMenuItem;
 
+import com.redhat.thermostat.client.core.internal.platform.EmbeddedPlatformService;
 import com.redhat.thermostat.client.ui.ContentProvider;
-import com.redhat.thermostat.common.config.ClientPreferences;
 import com.redhat.thermostat.shared.config.CommonPaths;
 import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
 
@@ -71,10 +73,12 @@
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.shared.locale.LocalizedString;
+import org.osgi.framework.BundleContext;
 
 import java.awt.AWTException;
 import java.awt.Robot;
 import java.io.File;
+import java.util.Dictionary;
 import java.util.logging.Logger;
 
 @Category(CacioTest.class)
@@ -84,6 +88,7 @@
     private FrameFixture frameFixture;
     private MainWindow window;
     private ActionListener<MainView.Action> l;
+    private BundleContext context;
 
     @BeforeClass
     public static void setUpOnce() {
@@ -94,11 +99,18 @@
     @Before
     public void setUp() {
 
+        context = mock(BundleContext.class);
+
         GuiActionRunner.execute(new GuiTask() {
             
             @Override
             protected void executeInEDT() throws Throwable {
-                window = new MainWindow();
+                window = new MainWindow() {
+                    @Override
+                    BundleContext getContext() {
+                        return context;
+                    }
+                };
                 l = mock(ActionListener.class);
                 window.addActionListener(l);
                 CommonPaths commonPaths = mock(CommonPaths.class);
@@ -110,6 +122,14 @@
 
         frameFixture = new FrameFixture(window);
     }
+    
+    @Category(GUITest.class)
+    @Test
+    public void assertPlatformServiceRegistered() {
+        verify(context).registerService(eq(EmbeddedPlatformService.class),
+                                        any(EmbeddedPlatformService.class),
+                                        eq((Dictionary<String, ?>) null));
+    }
 
     @After
     public void tearDown() {
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/views/VmInformationPanelTest.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/views/VmInformationPanelTest.java	Wed Nov 09 11:56:27 2016 +0100
@@ -37,9 +37,12 @@
 package com.redhat.thermostat.client.swing.internal.views;
 
 import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+import com.redhat.thermostat.client.core.views.UIPluginInfo;
 import com.redhat.thermostat.client.swing.TabbedPaneMatcher;
 import com.redhat.thermostat.common.internal.test.Bug;
 import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
@@ -58,7 +61,11 @@
 import com.redhat.thermostat.shared.locale.LocalizedString;
 
 import javax.swing.JTabbedPane;
+import java.awt.AWTException;
+import java.awt.Robot;
 import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
 
 @Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
@@ -98,6 +105,20 @@
         panel.addChildView(new LocalizedString("test. please ignore"), view);
     }
 
+    @Test
+    public void testLoggerMessage() throws AWTException {
+        UIComponent view = mock(UIComponent.class);
+        when(view.toString()).thenReturn("TEST");
+        String text =
+                "There's a non-swing view registered: 'TEST'. " +
+                "The swing client can not use these views. This is "        +
+                "most likely a developer mistake. If this is meant to "     +
+                "be a swing-based view, it must implement the "             +
+                "'SwingComponent' interface. If it's not meant to be a "    +
+                "swing-based view, it should not have been registered.";
+        assertEquals(text, panel.getLoggerMessage(view));
+    }
+
     @GUITest
     @Test
     @Bug(id = "2996",
@@ -115,5 +136,4 @@
             }
         });
     }
-
 }
--- a/platform/core/pom.xml	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/core/pom.xml	Wed Nov 09 11:56:27 2016 +0100
@@ -147,6 +147,7 @@
                             com.redhat.thermostat.platform.internal.mvc,
                             com.redhat.thermostat.platform.internal.mvc.lifecycle,
                             com.redhat.thermostat.platform.internal.mvc.lifecycle.state,
+                            com.redhat.thermostat.platform.internal.mvc.lifecycle.handlers,
                             com.redhat.thermostat.platform.internal.locale,
                         </Private-Package>
                         <!--Do not autogenerate uses clauses in Manifests -->
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/EmbeddedPlatform.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.platform;
+
+import com.redhat.thermostat.platform.internal.command.PlatformCommand;
+import com.redhat.thermostat.platform.internal.mvc.lifecycle.MVCLifeCycleManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+
+/**
+ * A special class that allows existing clients to start Platform services from
+ * within an already running command that does not implement the Platform
+ * Application protocol, effectively embedding the Platform inside.
+ * The embedded platform does not follow the Application life cycle and is not
+ * managed, users  needs to manually controlled and invoke the methods.
+ */
+public class EmbeddedPlatform {
+    
+    private MVCLifeCycleManager mvcLifeCycleManager;
+
+    public EmbeddedPlatform(Platform platform) {
+        mvcLifeCycleManager = new MVCLifeCycleManager();
+        mvcLifeCycleManager.setPlatform(platform);
+    }
+   
+    public MDIService start() {
+        // this is not really a solid check, but will do for now
+        if (PlatformCommand.IS_PLATFORM) {
+            return null;
+        }
+
+        mvcLifeCycleManager.start();
+        
+        BundleContext context =
+            FrameworkUtil.getBundle(MDIService.class).getBundleContext();
+        context.registerService(MDIService.class, mvcLifeCycleManager, null);
+
+        return mvcLifeCycleManager;
+    }
+    
+    public void shutdown() {
+        if (PlatformCommand.IS_PLATFORM) {
+            return;
+        }
+        mvcLifeCycleManager.stop();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/annotations/Extension.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.platform.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Extension {
+    Class<?> value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/annotations/ExtensionPoint.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.platform.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface ExtensionPoint {
+    Class<?> value();
+}
--- a/platform/core/src/main/java/com/redhat/thermostat/platform/internal/command/PlatformCommand.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/internal/command/PlatformCommand.java	Wed Nov 09 11:56:27 2016 +0100
@@ -61,6 +61,8 @@
 @Property(name = Command.NAME, value = PlatformCommand.NAME)
 public class PlatformCommand extends AbstractCommand {
     
+    public volatile static boolean IS_PLATFORM = false;
+    
     static final String NAME = "platform";
 
     @Reference
--- a/platform/core/src/main/java/com/redhat/thermostat/platform/internal/command/PlatformCommandDelegate.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/internal/command/PlatformCommandDelegate.java	Wed Nov 09 11:56:27 2016 +0100
@@ -80,6 +80,8 @@
             return;
         }
 
+        PlatformCommand.IS_PLATFORM = true;
+        
         lifeCycleManager.setTarget(info);
         lifeCycleManager.registerShutdownService();
         lifeCycleManager.registerMDIService();
--- a/platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/MVCLifeCycleManager.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/MVCLifeCycleManager.java	Wed Nov 09 11:56:27 2016 +0100
@@ -44,6 +44,7 @@
 import com.redhat.thermostat.platform.MDIService;
 import com.redhat.thermostat.platform.Platform;
 import com.redhat.thermostat.platform.event.EventQueue;
+import com.redhat.thermostat.platform.internal.mvc.lifecycle.handlers.MVCExtensionLinker;
 import com.redhat.thermostat.platform.internal.mvc.lifecycle.state.PlatformServiceRegistrar;
 import com.redhat.thermostat.platform.internal.mvc.lifecycle.state.StateMachine;
 import com.redhat.thermostat.platform.mvc.MVCProvider;
@@ -60,6 +61,7 @@
     private EventQueue eventQueue;
     private Deque<StateMachine> providers;
 
+    private MVCExtensionLinker linker;
     private Platform platform;
     private PlatformServiceRegistrar serviceRegistrar;
 
@@ -80,6 +82,7 @@
         registry.addMVCRegistryListener(listener);
 
         eventQueue = createEventQueue();
+        linker = new MVCExtensionLinker();
     }
 
     // Testing hook
@@ -120,13 +123,14 @@
 
         StateMachine stateMachine = new StateMachine(provider, platform,
                                                      serviceRegistrar,
-                                                     eventQueue);
+                                                     eventQueue, linker);
         providers.add(stateMachine);
         stateMachine.start();
     }
 
     public void setPlatform(Platform platform) {
         this.platform = platform;
+        linker.setPlatform(platform);
     }
 
     public Platform getPlatform() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/handlers/MVCExtensionLinker.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.platform.internal.mvc.lifecycle.handlers;
+
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.platform.Platform;
+import com.redhat.thermostat.platform.annotations.Extension;
+import com.redhat.thermostat.platform.annotations.ExtensionPoint;
+import com.redhat.thermostat.platform.mvc.MVCComponent;
+import com.redhat.thermostat.platform.mvc.MVCProvider;
+import com.redhat.thermostat.platform.mvc.View;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ */
+public class MVCExtensionLinker {
+
+    private static final Logger logger = LoggingUtils.getLogger(MVCExtensionLinker.class);
+
+    private HashMap<Class<?>, List<MethodInfo>> extensions;
+    private HashMap<Class<?>, List<MVCComponent>> extensionConsumers;
+
+    private Platform platform;
+
+    private static class MethodInfo {
+        Method method;
+        Class<?> extension;
+        MVCComponent provider;
+    }
+
+    public MVCExtensionLinker() {
+        extensions = new HashMap<>();
+        extensionConsumers = new HashMap<>();
+    }
+
+    public void setPlatform(Platform platform) {
+        this.platform = platform;
+    }
+
+    public void link(MVCProvider provider) {
+
+        checkExtensions(provider.getController());
+        checkExtensions(provider.getModel());
+        checkExtensions(provider.getView());
+    }
+
+    void link(final MVCComponent consumer, final MethodInfo info) {
+
+        Runnable action = new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    info.method.setAccessible(true);
+                    info.method.invoke(info.provider, consumer);
+
+                } catch (Exception e) {
+                    logger.log(Level.SEVERE,
+                               "Cannot link provider " + info.provider +
+                               " with consumer " + consumer, e);
+                }
+            }
+        };
+        if (info.provider instanceof View) {
+            platform.queueOnViewThread(action);
+        } else {
+            platform.queueOnApplicationThread(action);
+        }
+    }
+
+    void checkExtensions(MVCComponent component) {
+        Class<? extends MVCComponent> componentClass = component.getClass();
+        if (componentClass.isAnnotationPresent(Extension.class)) {
+            // before adding, let's first see if we have any component exporting
+            // this extension
+
+            Class<?> extension = componentClass.getAnnotation(Extension.class).value();
+
+            if (extensions.containsKey(extension)) {
+                for (MethodInfo info : extensions.get(extension)) {
+                    link(component, info);
+                }
+            }
+
+            List<MVCComponent> consumers = extensionConsumers.get(extension);
+            if (consumers == null) {
+                consumers = new ArrayList<>();
+                extensionConsumers.put(extension, consumers);
+            }
+            consumers.add(component);
+        }
+
+        // check what extension this component exports
+        for (Method method : component.getClass().getDeclaredMethods()) {
+            ExtensionPoint extension = method.getAnnotation(ExtensionPoint.class);
+            if (extension != null) {
+                MethodInfo info = new MethodInfo();
+                info.method = method;
+                info.extension = extension.value();
+                info.provider = component;
+
+                List<MethodInfo> infos = extensions.get(info.extension);
+                if (infos == null) {
+                    infos = new ArrayList<>();
+                    extensions.put(info.extension, infos);
+                }
+                infos.add(info);
+
+                // check if this component is exporting something that another
+                // components wants to use
+                List<MVCComponent> consumers = extensionConsumers.get(info.extension);
+                if (consumers != null) {
+                    for (MVCComponent consumer : consumers) {
+                        link(consumer, info);
+                    }
+                }
+            }
+        }
+    }
+}
--- a/platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/Context.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/Context.java	Wed Nov 09 11:56:27 2016 +0100
@@ -37,6 +37,7 @@
 package com.redhat.thermostat.platform.internal.mvc.lifecycle.state;
 
 import com.redhat.thermostat.platform.Platform;
+import com.redhat.thermostat.platform.internal.mvc.lifecycle.handlers.MVCExtensionLinker;
 import com.redhat.thermostat.platform.mvc.MVCProvider;
 
 /**
@@ -46,4 +47,5 @@
     MVCProvider provider;
     StateMachineTransitionDispatcher dispatcher;
     PlatformServiceRegistrar registrar;
+    MVCExtensionLinker linker;
 }
--- a/platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/Init.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/Init.java	Wed Nov 09 11:56:27 2016 +0100
@@ -59,6 +59,7 @@
                                                               context.provider.getModel(),
                                                               context.provider.getView());
                         context.registrar.checkAndRegister(context.provider);
+                        context.linker.link(context.provider);
                         if (context.provider instanceof Workbench) {
                             context.dispatcher.dispatch(State.START);
                         }
--- a/platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/PlatformServiceRegistrar.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/PlatformServiceRegistrar.java	Wed Nov 09 11:56:27 2016 +0100
@@ -68,6 +68,8 @@
         checkAndRegisterImpl(provider.getModel());
         checkAndRegisterImpl(provider.getController());
         checkAndRegisterImpl(provider.getView());
+
+        checkAndRegisterImpl(provider);
     }
 
     // Testing hook
--- a/platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/StateMachine.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/StateMachine.java	Wed Nov 09 11:56:27 2016 +0100
@@ -39,6 +39,7 @@
 import com.redhat.thermostat.beans.property.ObjectProperty;
 import com.redhat.thermostat.platform.Platform;
 import com.redhat.thermostat.platform.event.EventQueue;
+import com.redhat.thermostat.platform.internal.mvc.lifecycle.handlers.MVCExtensionLinker;
 import com.redhat.thermostat.platform.mvc.MVCProvider;
 
 /**
@@ -50,13 +51,15 @@
 
     public StateMachine(MVCProvider provider, Platform platform,
                         PlatformServiceRegistrar registrar,
-                        EventQueue eventQueue) {
+                        EventQueue eventQueue,
+                        MVCExtensionLinker linker) {
 
         context = new Context();
         context.platform = platform;
         context.provider = provider;
         context.dispatcher = new StateMachineTransitionDispatcher(eventQueue, this);
         context.registrar = registrar;
+        context.linker = linker;
         stateProperty = new ObjectProperty<>(State.INVALID);
     }
 
--- a/platform/core/src/main/java/com/redhat/thermostat/platform/mvc/MVCProvider.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/mvc/MVCProvider.java	Wed Nov 09 11:56:27 2016 +0100
@@ -42,7 +42,7 @@
  * at each invocation of the getters, in other words, they are expected
  * to be singletons.
  */
-public interface MVCProvider {
+public interface MVCProvider extends MVCComponent {
     public Controller getController();
     public View getView();
     public Model getModel();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/core/src/test/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/handlers/MVCExtensionLinkerTest.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.platform.internal.mvc.lifecycle.handlers;
+
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.platform.Platform;
+import com.redhat.thermostat.platform.annotations.Extension;
+import com.redhat.thermostat.platform.annotations.ExtensionPoint;
+import com.redhat.thermostat.platform.mvc.Controller;
+import com.redhat.thermostat.platform.mvc.MVCProvider;
+import com.redhat.thermostat.platform.mvc.Model;
+import com.redhat.thermostat.platform.mvc.View;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+
+/**
+ */
+public class MVCExtensionLinkerTest {
+
+    private interface TestExtension {
+        String saySomething();
+    }
+
+    private class TestMVC implements MVCProvider {
+        String saidSomething = "";
+        Controller controller = new Controller() {
+
+            @ExtensionPoint(TestExtension.class)
+            private void addTest(TestExtension extension) {
+                saidSomething = extension.saySomething();
+            }
+        };
+        View view = new View();
+        Model model = new Model();
+
+        @Override
+        public Controller getController() {
+            return controller;
+        }
+
+        @Override
+        public View getView() {
+            return view;
+        }
+
+        @Override
+        public Model getModel() {
+            return model;
+        }
+    }
+
+    @Extension(TestExtension.class)
+    private class ExtendedController extends Controller implements TestExtension {
+        @Override
+        public String saySomething() {
+            return "Huzza!";
+        }
+    }
+
+    private class ExtensionForTest implements MVCProvider {
+        Controller controller = new ExtendedController();
+        View view = new View();
+        Model model = new Model();
+
+        @Override
+        public Controller getController() {
+            return controller;
+        }
+
+        @Override
+        public View getView() {
+            return view;
+        }
+
+        @Override
+        public Model getModel() {
+            return model;
+        }
+    }
+
+    @Test
+    public void link() throws Exception {
+        TestPlatform platform = new TestPlatform();
+        MVCExtensionLinker linker = new MVCExtensionLinker();
+        linker.setPlatform(platform);
+
+        TestMVC testMVC = new TestMVC();
+        linker.link(testMVC);
+
+        assertEquals("", testMVC.saidSomething);
+        assertNull(platform.applicationRunnable);
+        assertNull(platform.viewRunnable);
+
+        ExtensionForTest extensionForTest = new ExtensionForTest();
+        linker.link(extensionForTest);
+
+        assertNotNull(platform.applicationRunnable);
+        assertNull(platform.viewRunnable);
+        platform.applicationRunnable.run();
+        platform.applicationRunnable = null;
+
+        assertEquals("Huzza!", testMVC.saidSomething);
+    }
+
+    @Test
+    public void linkProviderRegisteredAfterUser() throws Exception {
+        TestPlatform platform = new TestPlatform();
+        MVCExtensionLinker linker = new MVCExtensionLinker();
+        linker.setPlatform(platform);
+
+        ExtensionForTest extensionForTest = new ExtensionForTest();
+        linker.link(extensionForTest);
+
+        assertNull(platform.applicationRunnable);
+        assertNull(platform.viewRunnable);
+
+        TestMVC testMVC = new TestMVC();
+        linker.link(testMVC);
+
+        assertNotNull(platform.applicationRunnable);
+        assertNull(platform.viewRunnable);
+        platform.applicationRunnable.run();
+        platform.applicationRunnable = null;
+
+        assertEquals("Huzza!", testMVC.saidSomething);
+    }
+
+    private class TestPlatform implements Platform {
+
+        Runnable applicationRunnable;
+        Runnable viewRunnable;
+
+        @Override
+        public void queueOnApplicationThread(Runnable runnable) {
+            applicationRunnable = runnable;
+        }
+
+        @Override
+        public void queueOnViewThread(Runnable runnable) {
+            viewRunnable = runnable;
+        }
+
+        @Override
+        public boolean isViewThread() {
+            return true;
+        }
+
+        @Override
+        public boolean isApplicationThread() {
+            return true;
+        }
+
+        @Override
+        public ApplicationService getAppService() {
+            return null;
+        }
+    }
+}
\ No newline at end of file
--- a/platform/core/src/test/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/InitTest.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/core/src/test/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/InitTest.java	Wed Nov 09 11:56:27 2016 +0100
@@ -39,6 +39,7 @@
 import com.redhat.thermostat.beans.property.BooleanProperty;
 import com.redhat.thermostat.beans.property.ChangeListener;
 import com.redhat.thermostat.platform.Platform;
+import com.redhat.thermostat.platform.internal.mvc.lifecycle.handlers.MVCExtensionLinker;
 import com.redhat.thermostat.platform.mvc.Controller;
 import com.redhat.thermostat.platform.mvc.MVCProvider;
 import com.redhat.thermostat.platform.mvc.Model;
@@ -66,6 +67,7 @@
     private Model model;
     private PlatformServiceRegistrar registrar;
     private BooleanProperty visible;
+    private MVCExtensionLinker linker;
 
     @Before
     public void setUp() {
@@ -74,6 +76,7 @@
         dispatcher = mock(StateMachineTransitionDispatcher.class);
         visible = mock(BooleanProperty.class);
         registrar = mock(PlatformServiceRegistrar.class);
+        linker = mock(MVCExtensionLinker.class);
 
         view = mock(View.class);
         when(view.showingProperty()).thenReturn(visible);
@@ -90,6 +93,7 @@
         context.provider = provider;
         context.platform = platform;
         context.registrar = registrar;
+        context.linker = linker;
     }
 
     @Test
@@ -113,6 +117,7 @@
         verify(model).init(platform);
         verify(controller).init(platform, model, view);
         verify(context.registrar).checkAndRegister(context.provider);
+        verify(context.linker).link(context.provider);
     }
 
     @Test
@@ -135,4 +140,4 @@
         captor2.getValue().changed(visible, false, true);
         verify(context.dispatcher).dispatch(State.START);
     }
-}
\ No newline at end of file
+}
--- a/platform/core/src/test/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/StateMachineTest.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/core/src/test/java/com/redhat/thermostat/platform/internal/mvc/lifecycle/state/StateMachineTest.java	Wed Nov 09 11:56:27 2016 +0100
@@ -38,6 +38,7 @@
 
 import com.redhat.thermostat.platform.Platform;
 import com.redhat.thermostat.platform.event.EventQueue;
+import com.redhat.thermostat.platform.internal.mvc.lifecycle.handlers.MVCExtensionLinker;
 import com.redhat.thermostat.platform.mvc.MVCProvider;
 import org.junit.Test;
 
@@ -56,9 +57,10 @@
         Platform platform = mock(Platform.class);
         EventQueue eventQueue = mock(EventQueue.class);
         PlatformServiceRegistrar registrar = mock(PlatformServiceRegistrar.class);
+        MVCExtensionLinker linker = mock(MVCExtensionLinker.class);
 
         StateMachine stateMachine =
-                new StateMachine(provider, platform, registrar, eventQueue);
+                new StateMachine(provider, platform, registrar, eventQueue, linker);
 
         assertTrue(stateMachine.canGoToState(State.CREATE));
 
--- a/platform/distribution/thermostat-plugin.xml	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/distribution/thermostat-plugin.xml	Wed Nov 09 11:56:27 2016 +0100
@@ -73,4 +73,13 @@
             </bundles>
         </command>
     </commands>
+  <extensions>
+    <extension>
+      <name>gui</name>
+      <bundles>
+        <bundle><symbolic-name>com.redhat.thermostat.compat.platform</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.core</symbolic-name><version>${project.version}</version></bundle>
+      </bundles>
+    </extension>
+  </extensions>
 </plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/pom.xml	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2012-2016 Red Hat, Inc.
+
+ This file is part of Thermostat.
+
+ Thermostat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ Thermostat is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Thermostat; see the file COPYING.  If not see
+ <http://www.gnu.org/licenses/>.
+
+ Linking this code with other modules is making a combined work
+ based on this code.  Thus, the terms and conditions of the GNU
+ General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this code give
+ you permission to link this code with independent modules to
+ produce an executable, regardless of the license terms of these
+ independent modules, and to copy and distribute the resulting
+ executable under terms of your choice, provided that you also
+ meet, for each linked independent module, the terms and conditions
+ of the license of that module.  An independent module is a module
+ which is not derived from or based on this code.  If you modify
+ this code, you may extend this exception to your version of the
+ library, but you are not obligated to do so.  If you do not wish
+ to do so, delete this exception statement from your version.
+
+-->
+<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>
+
+    <parent>
+        <groupId>com.redhat.thermostat</groupId>
+        <artifactId>thermostat-platform-swing</artifactId>
+        <version>1.99.12-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>thermostat-platform-swing-compat</artifactId>
+    <packaging>bundle</packaging>
+
+    <name>Thermostat Swing Platform Compatibility Bridge</name>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>${gson.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- declarative services -->
+
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- thermostat specific dependencies -->
+
+        <dependency>
+            <groupId>com.redhat.thermostat</groupId>
+            <artifactId>thermostat-common-core</artifactId>
+            <version>${project.version}</version>
+            <type>jar</type>
+        </dependency>
+
+        <dependency>
+            <groupId>com.redhat.thermostat</groupId>
+            <artifactId>thermostat-platform-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.redhat.thermostat</groupId>
+            <artifactId>thermostat-client-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.redhat.thermostat</groupId>
+            <artifactId>thermostat-annotations</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        
+        <dependency>
+            <groupId>com.redhat.thermostat</groupId>
+            <artifactId>thermostat-platform-swing-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>false</filtering>
+            </resource>
+        </resources>
+        <plugins>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <compilerArgument>-proc:none</compilerArgument>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+                        <Bundle-SymbolicName>com.redhat.thermostat.compat.platform
+                        </Bundle-SymbolicName>
+                        <Export-Package>
+                            com.redhat.thermostat.compat.platform,
+                        </Export-Package>
+                        <Private-Package>
+                            com.redhat.thermostat.compat.platform.internal,
+                            com.redhat.thermostat.compat.platform.internal.test,
+                        </Private-Package>
+                        <!--Do not autogenerate uses clauses in Manifests -->
+                        <_nouses>true</_nouses>
+                    </instructions>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>generate-scr-scrdescriptor</id>
+                        <goals>
+                            <goal>scr</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+        </plugins>
+    </build>
+
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/DynamicHostPlugin.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform;
+
+import com.redhat.thermostat.annotations.ExtensionPoint;
+import com.redhat.thermostat.common.AllPassFilter;
+import com.redhat.thermostat.common.Filter;
+import com.redhat.thermostat.common.Ordered;
+import com.redhat.thermostat.platform.annotations.PlatformService;
+import com.redhat.thermostat.storage.core.HostRef;
+
+/**
+ *
+ */
+@ExtensionPoint
+public class DynamicHostPlugin extends EmbeddedPlatformPlugin implements Ordered {
+    public Filter<HostRef> getFilter() {
+        return new AllPassFilter<>();
+    }
+
+    @Override
+    public int getOrderValue() {
+        return ORDER_DEFAULT_GROUP;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/DynamicVMPlugin.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform;
+
+import com.redhat.thermostat.common.AllPassFilter;
+import com.redhat.thermostat.common.Filter;
+import com.redhat.thermostat.common.Ordered;
+import com.redhat.thermostat.storage.core.VmRef;
+
+/**
+ */
+public class DynamicVMPlugin extends EmbeddedPlatformPlugin implements Ordered {
+    public Filter<VmRef> getFilter() {
+        return new AllPassFilter<>();
+    }
+
+    @Override
+    public int getOrderValue() {
+        return ORDER_DEFAULT_GROUP;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/EmbeddedPlatformController.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform;
+
+import com.redhat.thermostat.platform.mvc.Controller;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+
+/**
+ *
+ */
+public class EmbeddedPlatformController extends Controller {
+   public LocalizedString getName() {
+       return LocalizedString.EMPTY_STRING;
+   }
+   
+   public LocalizedString getDescription() {
+       return LocalizedString.EMPTY_STRING;
+   }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/EmbeddedPlatformPlugin.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.redhat.thermostat.compat.platform;
+
+import com.redhat.thermostat.platform.mvc.MVCProvider;
+import com.redhat.thermostat.platform.mvc.Model;
+
+/**
+
+ */
+public class EmbeddedPlatformPlugin implements MVCProvider {
+
+    private Model model;
+    private EmbeddedPlatformSwingView view;
+    private EmbeddedPlatformController controller;
+    
+    protected EmbeddedPlatformController createController() {
+        return new EmbeddedPlatformController();
+    }
+    
+    protected Model createModel() {
+        return new Model();
+    }
+    
+    protected EmbeddedPlatformSwingView createView() {
+        return new EmbeddedPlatformSwingView();
+    }
+    
+    @Override
+    public final EmbeddedPlatformController getController() {
+        if (controller == null) {
+            controller = createController();
+        }
+        return controller;
+    }
+
+    @Override
+    public final EmbeddedPlatformSwingView getView() {
+        if (view == null) {
+            view = createView();
+        }
+        return view;
+    }
+
+    @Override
+    public final Model getModel() {
+        if (model == null) {
+            model = createModel();
+        }
+        return model;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/EmbeddedPlatformSwingView.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.redhat.thermostat.compat.platform;
+
+import com.redhat.thermostat.client.swing.SwingComponent;
+import com.redhat.thermostat.platform.Platform;
+import com.redhat.thermostat.platform.swing.SwingView;
+import com.redhat.thermostat.platform.swing.components.ContentPane;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+
+/**
+ *
+ */
+public class EmbeddedPlatformSwingView extends SwingView implements SwingComponent {
+
+    @Override
+    public final ContentPane getUiComponent() {
+        return contentPane;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/DynamicHostPluginProviderImpl.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform.internal;
+
+import com.redhat.thermostat.client.core.internal.platform.DynamicHostPluginProvider;
+import com.redhat.thermostat.client.core.internal.platform.UIPluginAction;
+import com.redhat.thermostat.client.core.views.UIPluginInfo;
+import com.redhat.thermostat.client.core.views.UIComponent;
+import com.redhat.thermostat.common.OrderedComparator;
+import com.redhat.thermostat.compat.platform.DynamicHostPlugin;
+import com.redhat.thermostat.platform.MDIService;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+import com.redhat.thermostat.storage.core.HostRef;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+
+import java.util.Collections;
+import java.util.List;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+
+/**
+ */
+@Component
+@Service(DynamicHostPluginProvider.class)
+public class DynamicHostPluginProviderImpl implements DynamicHostPluginProvider {
+
+    private class UIPluginInfoImpl implements UIPluginInfo {
+        private DynamicHostPlugin plugin;
+        private UIPluginInfoImpl(DynamicHostPlugin plugin) {
+            this.plugin = plugin;
+        }
+
+        @Override
+        public UIComponent getView() {
+            return plugin.getView();
+        }
+
+        @Override
+        public LocalizedString getLocalizedName() {
+            return plugin.getController().getName();
+        }
+        
+    }
+    
+    private DynamicHostPluginRegistry registry;
+    
+    @Activate
+    private void activate() {
+        BundleContext context =
+            FrameworkUtil.getBundle(MDIService.class).getBundleContext();
+        registry = new DynamicHostPluginRegistry(context);
+        registry.open();
+    }
+
+    @Deactivate
+    private void deactivate() {
+        registry.close();
+    }
+
+    @Override
+    public void forEach(HostRef host, UIPluginAction action) {
+        List<DynamicHostPlugin> plugins = registry.getPlugins();
+        Collections.sort(plugins, new OrderedComparator<DynamicHostPlugin>());
+        for (DynamicHostPlugin plugin : plugins) {
+            if (plugin.getFilter().matches(host)) {
+                UIPluginInfo info = new UIPluginInfoImpl(plugin);
+                action.execute(info);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/DynamicHostPluginRegistry.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform.internal;
+
+import com.redhat.thermostat.compat.platform.DynamicHostPlugin;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ */
+public class DynamicHostPluginRegistry extends ServiceTracker {
+    
+    private List<DynamicHostPlugin> dynamicHostPlugins;
+
+    public DynamicHostPluginRegistry(BundleContext context) {
+        super(context, DynamicHostPlugin.class.getName(), null);
+        dynamicHostPlugins = new CopyOnWriteArrayList<>();
+    }
+
+    @Override
+    public Object addingService(ServiceReference reference) {
+        Object service = super.addingService(reference);
+        dynamicHostPlugins.add((DynamicHostPlugin) service);
+        return service;
+    }
+
+    @Override
+    public void removedService(ServiceReference reference, Object service) {
+        dynamicHostPlugins.remove(service);
+        super.removedService(reference, service);
+    }
+
+    public List<DynamicHostPlugin> getPlugins() {
+        return new ArrayList<>(dynamicHostPlugins);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/DynamicVMPluginProviderImpl.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform.internal;
+
+import com.redhat.thermostat.client.core.internal.platform.DynamicVMPluginProvider;
+import com.redhat.thermostat.client.core.internal.platform.UIPluginAction;
+import com.redhat.thermostat.client.core.views.UIPluginInfo;
+import com.redhat.thermostat.client.core.views.UIComponent;
+import com.redhat.thermostat.common.OrderedComparator;
+import com.redhat.thermostat.compat.platform.DynamicVMPlugin;
+import com.redhat.thermostat.platform.MDIService;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+import com.redhat.thermostat.storage.core.VmRef;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ */
+@Component
+@Service(DynamicVMPluginProvider.class)
+public class DynamicVMPluginProviderImpl implements DynamicVMPluginProvider {
+
+    private class UIPluginInfoImpl implements UIPluginInfo {
+        private DynamicVMPlugin plugin;
+        private UIPluginInfoImpl(DynamicVMPlugin plugin) {
+            this.plugin = plugin;
+        }
+
+        @Override
+        public UIComponent getView() {
+            return plugin.getView();
+        }
+
+        @Override
+        public LocalizedString getLocalizedName() {
+            return plugin.getController().getName();
+        }
+
+    }
+
+    private DynamicVMPluginRegistry registry;
+
+    @Activate
+    private void activate() {
+        BundleContext context =
+                FrameworkUtil.getBundle(MDIService.class).getBundleContext();
+        registry = new DynamicVMPluginRegistry(context);
+        registry.open();
+    }
+
+    @Deactivate
+    private void deactivate() {
+        registry.close();
+    }
+
+    @Override
+    public void forEach(VmRef vm, UIPluginAction action) {
+        List<DynamicVMPlugin> plugins = registry.getPlugins();
+        Collections.sort(plugins, new OrderedComparator<DynamicVMPlugin>());
+        for (DynamicVMPlugin plugin : plugins) {
+            if (plugin.getFilter().matches(vm)) {
+                UIPluginInfo info = new UIPluginInfoImpl(plugin);
+                action.execute(info);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/DynamicVMPluginRegistry.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform.internal;
+
+import com.redhat.thermostat.compat.platform.DynamicVMPlugin;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ */
+public class DynamicVMPluginRegistry extends ServiceTracker {
+    private List<DynamicVMPlugin> dynamicVMPlugins;
+
+    public DynamicVMPluginRegistry(BundleContext context) {
+        super(context, DynamicVMPlugin.class.getName(), null);
+        dynamicVMPlugins = new CopyOnWriteArrayList<>();
+    }
+
+    @Override
+    public Object addingService(ServiceReference reference) {
+        Object service = super.addingService(reference);
+        dynamicVMPlugins.add((DynamicVMPlugin) service);
+        return service;
+    }
+
+    @Override
+    public void removedService(ServiceReference reference, Object service) {
+        dynamicVMPlugins.remove(service);
+        super.removedService(reference, service);
+    }
+
+    public List<DynamicVMPlugin> getPlugins() {
+        return new ArrayList<>(dynamicVMPlugins);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/HostPlugin1.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform.internal.test;
+
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformPlugin;
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformSwingView;
+import com.redhat.thermostat.platform.annotations.Extension;
+import com.redhat.thermostat.platform.mvc.MVCProvider;
+import com.redhat.thermostat.platform.swing.components.ContentPane;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+
+import javax.swing.JLabel;
+
+/**
+ */
+@Component
+@Service(MVCProvider.class)
+public class HostPlugin1 extends EmbeddedPlatformPlugin {
+    @Override
+    protected EmbeddedPlatformSwingView createView() {
+        return new TheSwingView();
+    }
+
+    @Extension(HostPluginInterface1.class)
+    private class TheSwingView extends EmbeddedPlatformSwingView implements HostPluginInterface1 {
+
+        @Override
+        protected void postCreate(ContentPane contentPane) {
+            super.postCreate(contentPane);
+            contentPane.add(new JLabel("HostPlugin1"));
+        }
+
+        @Override
+        public EmbeddedPlatformSwingView getContent() {
+            return this;
+        }
+
+        @Override
+        public void start() {
+            System.err.println("------------------ HostPlugin1 Started -------------");
+        }
+
+        @Override
+        public void stop() {
+            System.err.println("------------------ HostPlugin1 Stopped -------------");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/HostPluginInterface1.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform.internal.test;
+
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformSwingView;
+
+/**
+ */
+public interface HostPluginInterface1 {
+    EmbeddedPlatformSwingView getContent();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/HostProvider1.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform.internal.test;
+
+import com.redhat.thermostat.compat.platform.DynamicHostPlugin;
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformController;
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformSwingView;
+import com.redhat.thermostat.platform.annotations.ExtensionPoint;
+import com.redhat.thermostat.platform.annotations.PlatformService;
+import com.redhat.thermostat.platform.mvc.MVCProvider;
+
+import com.redhat.thermostat.shared.locale.LocalizedString;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+
+/**
+ *
+ */
+@Component
+@Service(MVCProvider.class)
+@PlatformService(service = DynamicHostPlugin.class)
+public class HostProvider1 extends DynamicHostPlugin {
+
+    @Override
+    protected EmbeddedPlatformController createController() {
+        return new EmbeddedPlatformController() {
+            @Override
+            public LocalizedString getName() {
+                return new LocalizedString("Test Plugin");
+            }
+        };
+    }
+
+    @Override
+    protected EmbeddedPlatformSwingView createView() {
+        return new EmbeddedPlatformSwingView() {
+            @ExtensionPoint(HostPluginInterface1.class)
+            public void hook(HostPluginInterface1 extension) {
+                add(extension.getContent());
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/VMPlugin1.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform.internal.test;
+
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformController;
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformPlugin;
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformSwingView;
+import com.redhat.thermostat.platform.annotations.Extension;
+import com.redhat.thermostat.platform.mvc.MVCProvider;
+import com.redhat.thermostat.platform.swing.components.ContentPane;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+
+import javax.swing.JLabel;
+
+/**
+ */
+@Component
+@Service(MVCProvider.class)
+public class VMPlugin1 extends EmbeddedPlatformPlugin {
+    @Override
+    protected EmbeddedPlatformSwingView createView() {
+        return new TheSwingView();
+    }
+
+    @Override
+    protected EmbeddedPlatformController createController() {
+        return new EmbeddedPlatformController() {
+            @Override
+            public void stop() {
+                System.err.println("/////////////////// VMPlugin1.Controller stop");
+            }
+
+            @Override
+            public void start() {
+                System.err.println("/////////////////// VMPlugin1.Controller start");
+            }
+        };
+    }
+
+    @Extension(VMPluginInterface1.class)
+    private class TheSwingView extends EmbeddedPlatformSwingView implements VMPluginInterface1 {
+
+        @Override
+        protected void postCreate(ContentPane contentPane) {
+            super.postCreate(contentPane);
+            contentPane.setName("VMPlugin1");
+            contentPane.add(new JLabel("VMPlugin1"));
+        }
+
+        @Override
+        public EmbeddedPlatformSwingView getContent() {
+            return this;
+        }
+
+        @Override
+        protected void init() {
+            super.init();
+
+            System.err.println("------------------ VMPlugin1 init -------------");
+        }
+
+        @Override
+        public void start() {
+            System.err.println("------------------ VMPlugin1 start -------------");
+        }
+
+        @Override
+        public void stop() {
+            System.err.println("------------------ VMPlugin1 stop -------------");
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/VMPlugin2.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform.internal.test;
+
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformController;
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformPlugin;
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformSwingView;
+import com.redhat.thermostat.platform.Platform;
+import com.redhat.thermostat.platform.annotations.Extension;
+import com.redhat.thermostat.platform.mvc.MVCProvider;
+import com.redhat.thermostat.platform.swing.components.ContentPane;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+
+import javax.swing.JLabel;
+
+@Component
+@Service(MVCProvider.class)
+public class VMPlugin2 extends EmbeddedPlatformPlugin {
+    @Override
+    protected EmbeddedPlatformSwingView createView() {
+        return new TheSwingView();
+    }
+
+    @Override
+    protected EmbeddedPlatformController createController() {
+        return new EmbeddedPlatformController() {
+            @Override
+            public void stop() {
+                System.err.println("/////////////////// VMPlugin2.Controller stop");
+            }
+
+            @Override
+            public void start() {
+                System.err.println("/////////////////// VMPlugin2.Controller start");
+            }
+        };
+    }
+
+    @Extension(VMPluginInterface1.class)
+    private class TheSwingView extends EmbeddedPlatformSwingView implements VMPluginInterface1 {
+
+        @Override
+        protected void postCreate(ContentPane contentPane) {
+            super.postCreate(contentPane);
+            contentPane.setName("VMPlugin2");
+            contentPane.add(new JLabel("VMPlugin2"));
+        }
+
+        @Override
+        public EmbeddedPlatformSwingView getContent() {
+            return this;
+        }
+
+        @Override
+        protected void init() {
+            super.init();
+
+            System.err.println("------------------ VMPlugin2          init -------------");
+        }
+
+        @Override
+        public void start() {
+            System.err.println("------------------ VMPlugin2          start -------------");
+        }
+
+        @Override
+        public void stop() {
+            System.err.println("------------------ VMPlugin2          stop -------------");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/VMPluginInterface1.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform.internal.test;
+
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformSwingView;
+
+/**
+ */
+public interface VMPluginInterface1 {
+    EmbeddedPlatformSwingView getContent();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/VMProvider1.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform.internal.test;
+
+import com.redhat.thermostat.compat.platform.DynamicHostPlugin;
+import com.redhat.thermostat.compat.platform.DynamicVMPlugin;
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformController;
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformSwingView;
+import com.redhat.thermostat.platform.annotations.ExtensionPoint;
+import com.redhat.thermostat.platform.annotations.PlatformService;
+import com.redhat.thermostat.platform.mvc.MVCProvider;
+import com.redhat.thermostat.platform.swing.components.ContentPane;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+
+import javax.swing.JTabbedPane;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ */
+@Component
+@Service(MVCProvider.class)
+@PlatformService(service = DynamicVMPlugin.class)
+public class VMProvider1 extends DynamicVMPlugin {
+    @Override
+    protected EmbeddedPlatformController createController() {
+        return new EmbeddedPlatformController() {
+            @Override
+            public LocalizedString getName() {
+                return new LocalizedString("VMProvider1");
+            }
+
+            @Override
+            public void stop() {
+                System.err.println("/////////////////// VMProvider1.Controller stop");
+            }
+
+            @Override
+            public void start() {
+                System.err.println("/////////////////// VMProvider1.Controller start");
+            }
+        };
+    }
+
+    @Override
+    protected EmbeddedPlatformSwingView createView() {
+        return new EmbeddedPlatformSwingView() {
+            private List<VMPluginInterface1> extensions;
+
+            JTabbedPane pane;
+
+            @Override
+            protected void init() {
+                extensions = new ArrayList<>();
+                pane = new JTabbedPane();
+                contentPane.add(pane);
+                contentPane.setName("VMProvider1");
+            }
+
+            @ExtensionPoint(VMPluginInterface1.class)
+            public void hook(VMPluginInterface1 extension) {
+                System.err.println("/////////////////// VMProvider1 adding: " + extension.getClass());
+                extensions.add(extension);
+            }
+
+            @Override
+            protected void addImpl(ContentPane contentPane, Object constraints, int index) {
+                pane.addTab(contentPane.getName(), contentPane);
+            }
+
+            @Override
+            public void start() {
+                super.start();
+
+                System.err.println("/////////////////// VMProvider1 start");
+
+                for (VMPluginInterface1 extension : extensions) {
+                    add(extension.getContent());
+                }
+            }
+
+            @Override
+            public void stop() {
+                super.stop();
+
+                System.err.println("/////////////////// VMProvider1 stop");
+
+                for (VMPluginInterface1 extension : extensions) {
+                    remove(extension.getContent());
+                }
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/compat/src/main/java/com/redhat/thermostat/compat/platform/internal/test/VMProvider2.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.compat.platform.internal.test;
+
+import com.redhat.thermostat.compat.platform.DynamicVMPlugin;
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformController;
+import com.redhat.thermostat.compat.platform.EmbeddedPlatformSwingView;
+import com.redhat.thermostat.platform.annotations.ExtensionPoint;
+import com.redhat.thermostat.platform.annotations.PlatformService;
+import com.redhat.thermostat.platform.mvc.MVCProvider;
+import com.redhat.thermostat.platform.swing.components.ContentPane;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+
+import javax.swing.JLabel;
+import javax.swing.JTabbedPane;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ */
+@Component
+@Service(MVCProvider.class)
+@PlatformService(service = DynamicVMPlugin.class)
+public class VMProvider2 extends DynamicVMPlugin {
+    @Override
+    protected EmbeddedPlatformController createController() {
+        return new EmbeddedPlatformController() {
+            @Override
+            public LocalizedString getName() {
+                return new LocalizedString("VMProvider2");
+            }
+
+            @Override
+            public void stop() {
+                System.err.println(">>>>>>>>>>>>>>>>>>>>> VMProvider2.Controller stop");
+            }
+
+            @Override
+            public void start() {
+                System.err.println(">>>>>>>>>>>>>>>>>>>>> VMProvider2.Controller start");
+            }
+        };
+    }
+
+    @Override
+    protected EmbeddedPlatformSwingView createView() {
+        return new EmbeddedPlatformSwingView() {
+
+            private List<VMPluginInterface1> extensions;
+
+            JTabbedPane pane;
+
+            @Override
+            protected void init() {
+                extensions = new ArrayList<>();
+                pane = new JTabbedPane();
+                contentPane.add(pane);
+            }
+
+            @ExtensionPoint(VMPluginInterface1.class)
+            public void hook(VMPluginInterface1 extension) {
+                System.err.println(">>>>>>>>>>>>>>>>>>>>> VMProvider2 adding: " + extension.getClass());
+                extensions.add(extension);
+            }
+
+            @Override
+            protected void addImpl(ContentPane contentPane, Object constraints, int index) {
+                pane.addTab(contentPane.getName(), contentPane);
+            }
+
+            @Override
+            public void start() {
+                super.start();
+                System.err.println(">>>>>>>>>>>>>>>>>>>>> VMProvider2 start");
+
+                for (VMPluginInterface1 extension : extensions) {
+                    add(extension.getContent());
+                }
+            }
+
+            @Override
+            public void stop() {
+                super.stop();
+                System.err.println(">>>>>>>>>>>>>>>>>>>>> VMProvider2 stop");
+
+                for (VMPluginInterface1 extension : extensions) {
+                    remove(extension.getContent());
+                }
+            }
+        };
+
+    }
+}
--- a/platform/swing/core/src/main/java/com/redhat/thermostat/platform/application/swing/internal/ComponentVisibilityDispatcher.java	Tue Nov 08 15:09:04 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright 2012-2016 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.platform.application.swing.internal;
-
-import com.redhat.thermostat.platform.swing.ContentProvider;
-
-import java.awt.event.HierarchyEvent;
-import java.awt.event.HierarchyListener;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- */
-public class ComponentVisibilityDispatcher {
-
-    private Map<ContentProvider, ComponentVisibilityListener> dispatchers;
-
-    public ComponentVisibilityDispatcher() {
-        dispatchers = new ConcurrentHashMap<>();
-    }
-
-    public void register(ContentProvider contentProvider) {
-
-        ComponentVisibilityListener listener =
-                new ComponentVisibilityListener(contentProvider);
-
-        dispatchers.put(contentProvider, listener);
-        contentProvider.getContent().addHierarchyListener(listener);
-    }
-
-    public void deregister(ContentProvider contentProvider) {
-        if (dispatchers.containsKey(contentProvider)) {
-            ComponentVisibilityListener listener = dispatchers.get(contentProvider);
-            contentProvider.getContent().removeHierarchyListener(listener);
-            dispatchers.remove(contentProvider);
-        }
-    }
-
-    private class ComponentVisibilityListener implements HierarchyListener {
-
-        private ContentProvider contentProvider;
-
-        public ComponentVisibilityListener(ContentProvider contentProvider) {
-            this.contentProvider = contentProvider;
-        }
-
-        @Override
-        public void hierarchyChanged(HierarchyEvent e) {
-            if (contentProvider == null) {
-                return;
-            }
-
-            if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0)  {
-                contentProvider.getView().showingProperty().set(e.getComponent().isShowing());
-            }
-
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/core/src/main/java/com/redhat/thermostat/platform/application/swing/internal/EmbeddedSwingPlatformService.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.platform.application.swing.internal;
+
+import com.redhat.thermostat.client.core.internal.platform.EmbeddedPlatformService;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.platform.EmbeddedPlatform;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+
+/**
+ */
+@Component
+public class EmbeddedSwingPlatformService {
+    private EmbeddedPlatform embeddedPlatform;
+    
+    @Reference
+    private ApplicationService applicationService;
+
+    @Reference
+    private EmbeddedPlatformService embeddedPlatformService;
+
+    public void bindEmbeddedPlatformService(EmbeddedPlatformService embeddedPlatformService) {
+        this.embeddedPlatformService = embeddedPlatformService;
+    }
+    
+    public void unbindEmbeddedPlatformService(EmbeddedPlatformService embeddedPlatformService) {
+        this.embeddedPlatformService = embeddedPlatformService;
+    }
+    
+    public void bindApplicationService(ApplicationService applicationService) {
+        this.applicationService = applicationService;
+    }
+    
+    public void unbindApplicationService(ApplicationService applicationService) {
+        this.applicationService = applicationService;
+    }
+    
+    @Activate
+    private void activate() {
+        SwingPlatform platform = new SwingPlatform(applicationService);
+        platform.start();
+        embeddedPlatform = new EmbeddedPlatform(platform);
+        embeddedPlatform.start();
+    }
+
+    @Deactivate
+    private void deactivate() {
+        //embeddedPlatform.shutdown();
+    }
+}
--- a/platform/swing/core/src/main/java/com/redhat/thermostat/platform/swing/ContentProvider.java	Tue Nov 08 15:09:04 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012-2016 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.platform.swing;
-
-import com.redhat.thermostat.platform.mvc.View;
-import com.redhat.thermostat.platform.swing.components.ThermostatComponent;
-
-/**
- */
-public interface ContentProvider {
-    ThermostatComponent getContent();
-    View getView();
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/core/src/main/java/com/redhat/thermostat/platform/swing/SwingView.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.platform.swing;
+import com.redhat.thermostat.platform.mvc.View;
+import com.redhat.thermostat.platform.swing.components.ContentPane;
+
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ */
+public class SwingView extends View  {
+
+    protected ContentPane contentPane;
+    private ComponentVisibilityListener listener;
+
+    @Override
+    public final void create() {
+
+        preCreate();
+
+        super.create();
+
+        contentPane = createContentPane();
+        listener = new ComponentVisibilityListener(contentPane, this);
+        contentPane.addHierarchyListener(listener);
+
+        postCreate(contentPane);
+    }
+
+    protected ContentPane createContentPane() {
+        return new ContentPane();
+    }
+
+    @Override
+    public final void destroy() {
+        preDestroy();
+
+        super.destroy();
+
+        contentPane.removeHierarchyListener(listener);
+        postDestroy();
+    }
+
+    protected void preDestroy() {}
+    protected void postDestroy() {}
+    protected void preCreate() {}
+    protected void postCreate(ContentPane contentPane) {}
+
+    public final void add(SwingView content) {
+        add(content, null, -1);
+    }
+
+    public final void remove(final SwingView content) {
+        clean(content);
+    }
+
+    private void clean(SwingView content) {
+        removeImpl(content.contentPane);
+    }
+
+    public final void add(SwingView content, Object constraints, int index) {
+        addImpl(content.contentPane, constraints, index);
+    }
+
+    protected void addImpl(ContentPane content, Object constraints, int index) {
+        contentPane.add(content, constraints, index);
+    }
+
+    protected void removeImpl(ContentPane content) {
+        contentPane.remove(content);
+    }
+
+    private class ComponentVisibilityListener implements HierarchyListener {
+
+        private ContentPane contentPane;
+        private SwingView view;
+
+        public ComponentVisibilityListener(ContentPane contentPane, SwingView view) {
+            this.contentPane = contentPane;
+            this.view = view;
+        }
+
+        @Override
+        public void hierarchyChanged(HierarchyEvent e) {
+            if (contentPane == null) {
+                return;
+            }
+
+            if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0)  {
+                view.showingProperty().set(e.getComponent().isShowing());
+            }
+        }
+    }
+}
--- a/platform/swing/core/src/main/java/com/redhat/thermostat/platform/swing/SwingWorkbench.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/swing/core/src/main/java/com/redhat/thermostat/platform/swing/SwingWorkbench.java	Wed Nov 09 11:56:27 2016 +0100
@@ -54,7 +54,7 @@
 public class SwingWorkbench implements Workbench {
 
     private WorkbenchModel model;
-    private WorkbenchView view;
+    private WorkbenchSwingView view;
     private WorkbenchController controller;
 
     @Reference()
@@ -64,7 +64,7 @@
     @Activate
     private void activate() {
         model = new WorkbenchModel();
-        view = new WorkbenchView();
+        view = new WorkbenchSwingView();
         controller = new WorkbenchController();
         controller.setPlatformShutdown(shutdown);
     }
--- a/platform/swing/core/src/main/java/com/redhat/thermostat/platform/swing/ViewContainer.java	Tue Nov 08 15:09:04 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright 2012-2016 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.platform.swing;
-
-import com.redhat.thermostat.beans.property.ChangeListener;
-import com.redhat.thermostat.beans.property.ObservableValue;
-import com.redhat.thermostat.platform.application.swing.internal.ComponentVisibilityDispatcher;
-import com.redhat.thermostat.platform.mvc.View;
-import com.redhat.thermostat.animation.Animation;
-import com.redhat.thermostat.platform.swing.components.ContentPane;
-
-/**
- */
-public class ViewContainer extends View  {
-
-    protected ContentPane contentPane;
-    private ComponentVisibilityDispatcher visibilityDispatcher;
-
-    @Override
-    public final void create() {
-        super.create();
-        visibilityDispatcher = new ComponentVisibilityDispatcher();
-        contentPane = createContentPane();
-        postCreate(contentPane);
-    }
-
-    protected ContentPane createContentPane() {
-        return new ContentPane();
-    }
-
-    protected void postCreate(ContentPane contentPane) {}
-
-    public final void add(ContentProvider content) {
-        add(content, null);
-    }
-
-    public final void add(ContentProvider content, Animation animation) {
-        add(content, null, -1, animation);
-    }
-
-    public final void remove(ContentProvider content) {
-        remove(content, null);
-    }
-
-    public final void remove(final ContentProvider content, final Animation animation) {
-
-        if (animation != null) {
-            animation.statusProperty().addListener(new ChangeListener<Animation.Status>() {
-                @Override
-                public void changed(ObservableValue<? extends Animation.Status> status,
-                                    Animation.Status oldValue,
-                                    Animation.Status newValue)
-                {
-                    if (newValue.equals(Animation.Status.STOPPED)) {
-                        clean(content);
-                        animation.statusProperty().removeListener(this);
-                    }
-                }
-            });
-            animation.play();
-
-        } else {
-            clean(content);
-        }
-    }
-
-    private void clean(ContentProvider content) {
-        visibilityDispatcher.deregister(content);
-        contentPane.remove(content.getContent());
-    }
-
-    public final void add(ContentProvider content, Object constraints, int index, Animation animation) {
-        visibilityDispatcher.register(content);
-        addImpl(content, constraints, index, animation);
-    }
-
-    protected void addImpl(ContentProvider content, Object constraints, int index, Animation animation) {
-        contentPane.add(content.getContent(), constraints, index);
-        if (animation != null) {
-            animation.play();
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/swing/core/src/main/java/com/redhat/thermostat/platform/swing/WorkbenchSwingView.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.platform.swing;
+
+import com.redhat.thermostat.platform.annotations.PlatformService;
+import com.redhat.thermostat.platform.mvc.View;
+import com.redhat.thermostat.platform.swing.components.ContentPane;
+
+import javax.swing.JFrame;
+import javax.swing.WindowConstants;
+import java.awt.Dimension;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+@PlatformService(service = {
+        WorkbenchSwingView.class,
+        View.class,
+})
+public class WorkbenchSwingView extends SwingView {
+
+    private JFrame frame;
+    private WindowAdapter adapter;
+
+    @Override
+    protected void postCreate(ContentPane contentPane) {
+        frame = createFrame();
+        adapter = new WindowAdapter() {
+
+            @Override
+            public void windowClosing(WindowEvent e) {
+                showingProperty().setValue(false);
+            }
+
+            @Override
+            public void windowOpened(WindowEvent e) {
+                showingProperty().setValue(true);
+            }
+        };
+
+        contentPane.setName("Thermostat Platform Swing Workbench");
+    }
+
+    public JFrame getFrame() {
+        return frame;
+    }
+
+    /**
+     * Returns the frame used as main frame for the whole application.
+     */
+    protected JFrame createFrame() {
+        return new JFrame();
+    }
+
+    /**
+     * Called before window listeners and content pane are attached to
+     * this frame. The frame passed to this method is the same instance
+     * returned by {@link #createFrame}.
+     *
+     * <br /><br />
+     *
+     * The default implementation sets a minimum size of the frame.
+     */
+    protected void preInitFrame(JFrame frame) {
+        frame.setMinimumSize(new Dimension(800, 800));
+    }
+
+    @Override
+    protected void postDestroy() {
+        frame.dispose();
+    }
+
+    @Override
+    public void stop() {
+        frame.setVisible(false);
+    }
+
+    @Override
+    protected void init() {
+
+        preInitFrame(frame);
+
+        frame.addWindowListener(adapter);
+        frame.setContentPane(contentPane);
+
+        frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+    }
+
+    @Override
+    public void start() {
+        frame.setVisible(true);
+    }
+}
--- a/platform/swing/core/src/main/java/com/redhat/thermostat/platform/swing/WorkbenchView.java	Tue Nov 08 15:09:04 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright 2012-2016 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.platform.swing;
-
-import com.redhat.thermostat.platform.annotations.PlatformService;
-import com.redhat.thermostat.platform.mvc.View;
-import com.redhat.thermostat.platform.swing.components.ContentPane;
-
-import javax.swing.JFrame;
-import javax.swing.WindowConstants;
-import java.awt.Dimension;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-
-@PlatformService(service = {
-        WorkbenchView.class,
-        View.class,
-})
-public class WorkbenchView extends ViewContainer {
-
-    private JFrame frame;
-    private WindowAdapter adapter;
-
-    @Override
-    protected void postCreate(ContentPane contentPane) {
-        frame = createFrame();
-        adapter = new WindowAdapter() {
-
-            @Override
-            public void windowClosing(WindowEvent e) {
-                showingProperty().setValue(false);
-            }
-
-            @Override
-            public void windowOpened(WindowEvent e) {
-                showingProperty().setValue(true);
-            }
-        };
-
-        contentPane.setName("Thermostat Platform Swing Workbench");
-    }
-
-    public JFrame getFrame() {
-        return frame;
-    }
-
-    /**
-     * Returns the frame used as main frame for the whole application.
-     */
-    protected JFrame createFrame() {
-        return new JFrame();
-    }
-
-    /**
-     * Called before window listeners and content pane are attached to
-     * this frame. The frame passed to this method is the same instance
-     * returned by {@link #createFrame}.
-     *
-     * <br /><br />
-     *
-     * The default implementation sets a minimum size of the frame.
-     */
-    protected void preInitFrame(JFrame frame) {
-        frame.setMinimumSize(new Dimension(800, 800));
-    }
-
-    @Override
-    public void destroy() {
-        frame.dispose();
-    }
-
-    @Override
-    public void stop() {
-        frame.setVisible(false);
-    }
-
-    @Override
-    protected void init() {
-
-        preInitFrame(frame);
-
-        frame.addWindowListener(adapter);
-        frame.setContentPane(contentPane);
-
-        frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
-    }
-
-    @Override
-    public void start() {
-        frame.setVisible(true);
-    }
-}
--- a/platform/swing/distribution/pom.xml	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/swing/distribution/pom.xml	Wed Nov 09 11:56:27 2016 +0100
@@ -95,6 +95,11 @@
       <artifactId>thermostat-platform-swing-widgets</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-platform-swing-compat</artifactId>
+      <version>${project.version}</version>
+    </dependency>
   </dependencies>
 
 </project>
--- a/platform/swing/distribution/thermostat-plugin.xml	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/swing/distribution/thermostat-plugin.xml	Wed Nov 09 11:56:27 2016 +0100
@@ -54,5 +54,13 @@
                 </bundle>
             </bundles>
         </extension>
-    </extensions>
+        <extension>
+          <name>gui</name>
+          <bundles>
+            <bundle><symbolic-name>com.redhat.thermostat.compat.platform</symbolic-name><version>${project.version}</version></bundle>
+            <bundle><symbolic-name>com.redhat.thermostat.platform.swing.core</symbolic-name><version>${project.version}</version></bundle>
+            <bundle><symbolic-name>com.redhat.thermostat.client.core</symbolic-name><version>${project.version}</version></bundle>
+          </bundles>
+        </extension>
+  </extensions>
 </plugin>
--- a/platform/swing/pom.xml	Tue Nov 08 15:09:04 2016 -0500
+++ b/platform/swing/pom.xml	Wed Nov 09 11:56:27 2016 +0100
@@ -54,6 +54,7 @@
   <modules>
       <module>core</module>
       <module>widgets</module>
+      <module>compat</module>
       <module>distribution</module>
   </modules>
 
--- a/thermostat-gui/core/src/main/java/com/redhat/thermostat/application/gui/internal/ThermostatWorkbenchController.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/thermostat-gui/core/src/main/java/com/redhat/thermostat/application/gui/internal/ThermostatWorkbenchController.java	Wed Nov 09 11:56:27 2016 +0100
@@ -50,14 +50,14 @@
     private final ApplicationInfo appInfo = new ApplicationInfo();
     private CommonPaths commonPaths;
 
-    private ThermostatWorkbenchView workbenchView;
+    private ThermostatWorkbenchSwingView workbenchView;
     private MenuHandler handler;
 
     @Override
     public void init(final Platform platform, Model model, View view) {
         super.init(platform, model, view);
 
-        workbenchView = (ThermostatWorkbenchView) view;
+        workbenchView = (ThermostatWorkbenchSwingView) view;
         handler = createMenuHandler();
 
         platform.queueOnViewThread(new Runnable() {
--- a/thermostat-gui/core/src/main/java/com/redhat/thermostat/application/gui/internal/ThermostatWorkbenchProvider.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/thermostat-gui/core/src/main/java/com/redhat/thermostat/application/gui/internal/ThermostatWorkbenchProvider.java	Wed Nov 09 11:56:27 2016 +0100
@@ -42,7 +42,7 @@
 import com.redhat.thermostat.platform.mvc.Model;
 import com.redhat.thermostat.platform.mvc.View;
 import com.redhat.thermostat.platform.swing.SwingWorkbench;
-import com.redhat.thermostat.platform.swing.WorkbenchView;
+import com.redhat.thermostat.platform.swing.WorkbenchSwingView;
 import com.redhat.thermostat.shared.config.CommonPaths;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -65,7 +65,7 @@
     private ThermostatGUI thermostatGUI;
 
     private Model model;
-    private ThermostatWorkbenchView view;
+    private ThermostatWorkbenchSwingView view;
     private ThermostatWorkbenchController controller;
 
     @Override
@@ -90,6 +90,6 @@
         controller = new ThermostatWorkbenchController();
         controller.setCommonPaths(paths);
 
-        view = new ThermostatWorkbenchView((WorkbenchView) workbench.getView());
+        view = new ThermostatWorkbenchSwingView((WorkbenchSwingView) workbench.getView());
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermostat-gui/core/src/main/java/com/redhat/thermostat/application/gui/internal/ThermostatWorkbenchSwingView.java	Wed Nov 09 11:56:27 2016 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.application.gui.internal;
+
+import com.redhat.thermostat.platform.Platform;
+import com.redhat.thermostat.platform.swing.SwingView;
+import com.redhat.thermostat.platform.swing.WorkbenchSwingView;
+import com.redhat.thermostat.platform.swing.components.ContentPane;
+
+/**
+ */
+public class ThermostatWorkbenchSwingView extends SwingView {
+
+    private MenuHandler handler;
+    private WorkbenchSwingView parent;
+
+    public ThermostatWorkbenchSwingView(WorkbenchSwingView parent) {
+        this.parent = parent;
+    }
+
+    @Override
+    public void init(Platform platform) {
+        super.init(platform);
+        parent.add(this);
+    }
+
+    public void setMenuHandler(MenuHandler handler) {
+        this.handler = handler;
+        parent.getFrame().setJMenuBar(handler.getMenuBar());
+    }
+
+    void setApplicationTitle(String title) {
+        parent.getFrame().setTitle(title);
+    }
+}
--- a/thermostat-gui/core/src/main/java/com/redhat/thermostat/application/gui/internal/ThermostatWorkbenchView.java	Tue Nov 08 15:09:04 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright 2012-2016 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.application.gui.internal;
-
-import com.redhat.thermostat.platform.Platform;
-import com.redhat.thermostat.platform.mvc.View;
-import com.redhat.thermostat.platform.swing.ContentProvider;
-import com.redhat.thermostat.platform.swing.ViewContainer;
-import com.redhat.thermostat.platform.swing.WorkbenchView;
-import com.redhat.thermostat.platform.swing.components.ContentPane;
-import com.redhat.thermostat.platform.swing.components.ThermostatComponent;
-
-/**
- */
-public class ThermostatWorkbenchView extends ViewContainer implements ContentProvider {
-
-    private MenuHandler handler;
-    private WorkbenchView parent;
-
-    public ThermostatWorkbenchView(WorkbenchView parent) {
-        this.parent = parent;
-    }
-
-    @Override
-    protected void postCreate(ContentPane contentPane) {
-        super.postCreate(contentPane);
-    }
-
-    @Override
-    public void init(Platform platform) {
-        super.init(platform);
-        parent.add(this);
-    }
-
-    public void setMenuHandler(MenuHandler handler) {
-        this.handler = handler;
-        parent.getFrame().setJMenuBar(handler.getMenuBar());
-    }
-
-    void setApplicationTitle(String title) {
-        parent.getFrame().setTitle(title);
-    }
-
-    @Override
-    public ThermostatComponent getContent() {
-        return contentPane;
-    }
-
-    @Override
-    public View getView() {
-        return this;
-    }
-}
--- a/thermostat-gui/core/src/test/java/com/redhat/thermostat/application/gui/internal/ThermostatWorkbenchControllerTest.java	Tue Nov 08 15:09:04 2016 -0500
+++ b/thermostat-gui/core/src/test/java/com/redhat/thermostat/application/gui/internal/ThermostatWorkbenchControllerTest.java	Wed Nov 09 11:56:27 2016 +0100
@@ -78,7 +78,7 @@
         }
     }
 
-    private ThermostatWorkbenchView view;
+    private ThermostatWorkbenchSwingView view;
     private Model model;
     private TestPlatform platform;
     private CommonPaths paths;
@@ -100,7 +100,7 @@
     @Before
     public void setUp() {
         platform = new TestPlatform();
-        view = Mockito.mock(ThermostatWorkbenchView.class);
+        view = Mockito.mock(ThermostatWorkbenchSwingView.class);
         model = Mockito.mock(Model.class);
         menuHandler = Mockito.mock(MenuHandler.class);
         paths = Mockito.mock(CommonPaths.class);