The JMX console gui



git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@424263 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.mosgi.console.gui/pom.xml b/org.apache.felix.mosgi.console.gui/pom.xml
new file mode 100644
index 0000000..637286b
--- /dev/null
+++ b/org.apache.felix.mosgi.console.gui/pom.xml
@@ -0,0 +1,67 @@
+<project>
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>0.8.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <packaging>osgi-bundle</packaging>
+  <name>MOSGi JMX Console Main GUI</name>
+  <artifactId>org.apache.felix.mosgi.console.gui</artifactId>
+  <dependencies>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <version>${pom.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <version>${pom.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.apache.felix.framework</artifactId>
+      <version>${pom.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.apache.felix.mosgi.console.ifc</artifactId>
+      <version>${pom.version}</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix.plugins</groupId>
+        <artifactId>maven-osgi-plugin</artifactId>
+        <version>${pom.version}</version>
+        <extensions>true</extensions>
+        <configuration>
+          <osgiManifest>
+            <bundleName>MOSGi JMX Console main GUI</bundleName>
+            <bundleDescription>MOSGi JMX Console main GUI</bundleDescription>
+						<bundleActivator>auto-detect</bundleActivator>
+            <bundleDocUrl>http://oscar-osgi.sf.net/obr2/${pom.artifactId}/</bundleDocUrl>
+            <bundleUrl>http://oscar-osgi.sf.net/obr2/${pom.artifactId}/${pom.artifactId}-${pom.version}.jar</bundleUrl>
+            <bundleSource>http://oscar-osgi.sf.net/obr2/${pom.artifactId}/${pom.artifactId}-${pom.version}-src.jar</bundleSource>
+            <bundleSymbolicName>${pom.artifactId}</bundleSymbolicName>
+						<importPackage>
+						  org.osgi.framework;specification-version="1.0.0",
+						  javax.swing;specification-version="1.0.0",
+						  javax.swing.event;specification-version="1.0.0",
+						  javax.swing.tree;specification-version="1.0.0",
+						  javax.management;specification-version="1.0.0",
+						  javax.management.remote;specification-version="1.0.0",
+						  org.apache.felix.mosgi.console.ifc;specification-version="1.0.0"
+						</importPackage>
+          </osgiManifest>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/Activator.java b/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/Activator.java
new file mode 100644
index 0000000..0abd057
--- /dev/null
+++ b/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/Activator.java
@@ -0,0 +1,219 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.felix.mosgi.console.gui;
+
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.ArrayList;
+import javax.swing.JFrame;
+import javax.swing.JRootPane;
+import javax.swing.JSplitPane;
+import javax.swing.event.EventListenerList;
+
+import org.apache.felix.mosgi.console.ifc.Plugin;
+import org.apache.felix.mosgi.console.ifc.CommonPlugin;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.InvalidSyntaxException;
+
+public class Activator implements BundleActivator {
+  protected BundleContext m_context = null;
+  protected ArrayList m_pluginList = null;
+  protected ArrayList m_commonpluginList = null; //TODO To I need this table ?
+  private EventListenerList m_listenerList = null;
+  private JFrame m_frame = null;
+  private NodesTree nodesTree=null;
+
+  public Activator() {
+    m_pluginList = new ArrayList();
+    m_commonpluginList = new ArrayList();
+    m_listenerList = new EventListenerList();
+  }
+
+  public void start(BundleContext context) {
+    m_context = context;
+
+    // Listen for factory service events.
+    ServiceListener sl = new ServiceListener() {
+      public void serviceChanged(ServiceEvent event) {
+        ServiceReference ref = event.getServiceReference();
+        Object svcObj = m_context.getService(ref);
+        if (event.getType() == ServiceEvent.REGISTERED) {
+           synchronized (Activator.this) {
+              // !!!!!!!!!! ORDER MATTERS (Inheritance pb)
+              if (!m_pluginList.contains(svcObj)) {
+                 if(svcObj instanceof CommonPlugin){
+                   m_commonpluginList.add(svcObj);
+                   firePropertyChangedEvent(CommonPlugin.COMMON_PLUGIN_ADDED, null, svcObj);
+                 }else if (svcObj instanceof Plugin){
+                   m_pluginList.add(svcObj);
+                   firePropertyChangedEvent(Plugin.PLUGIN_ADDED, null, svcObj);
+                 }
+               }
+             }
+           } else if (event.getType() == ServiceEvent.UNREGISTERING) {
+             synchronized (Activator.this) {
+               removePropertyChangeListener((PropertyChangeListener)svcObj);
+               if(svcObj instanceof CommonPlugin){
+                 m_commonpluginList.remove(svcObj);
+                 firePropertyChangedEvent(CommonPlugin.COMMON_PLUGIN_REMOVED, null, svcObj);
+               }else if (svcObj instanceof Plugin){
+                 m_pluginList.remove(svcObj);
+                 firePropertyChangedEvent(Plugin.PLUGIN_REMOVED, null, svcObj);
+               }
+             }
+           } else {
+             m_context.ungetService(ref);
+           }
+         }
+        };
+        try
+        {
+            m_context.addServiceListener(sl,
+                "(|(objectClass="
+                + Plugin.class.getName()
+                + ")(objectClass="
+                + CommonPlugin.class.getName()+"))");
+        }
+        catch (InvalidSyntaxException ex)
+        {
+            System.err.println("ShellGuiActivator: Cannot add service listener.");
+            System.err.println("ShellGuiActivator: " + ex);
+        }
+
+
+        // Create and display the frame.
+        if (m_frame == null)
+        {
+            m_frame=new JFrame("OSGi GUI Remote Manager");
+            m_frame.setUndecorated(true);
+            m_frame.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
+            Dimension wndSize = m_frame.getToolkit().getScreenSize();
+            m_frame.setBounds(wndSize.width / 8, wndSize.height / 8, 1000, 700);
+            m_frame.setIconImage(Toolkit.getDefaultToolkit().getImage(m_context.getBundle().getResource("images/logo.gif")));
+           
+            //Right panel
+            JSplitPane rightSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new NodePanel(this, context) , new CommonPanel(this));
+            rightSplitPane.setOneTouchExpandable(true);
+            rightSplitPane.setDividerLocation(500);
+
+            //General Panel
+            this.nodesTree = new NodesTree(this, context);
+            JSplitPane gSplitPane=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, this.nodesTree , rightSplitPane);
+            gSplitPane.setOneTouchExpandable(true);
+            gSplitPane.setDividerLocation(200);
+
+
+            m_frame.getContentPane().add(gSplitPane);
+            //m_frame.setResizable(false);
+            m_frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+        }
+
+        // Now try to manually initialize the plugin list
+        // since some might already be available.
+        //initializePlugins();
+        this.nodesTree.runDiscovery();
+
+        m_frame.setVisible(true);
+    }
+
+    private synchronized void initializePlugins() {
+      try {
+        // Get all model services.
+        Object svcObj=null;
+        ServiceReference refs[] = m_context.getServiceReferences(Plugin.class.getName(), null);
+        if (refs != null) {
+          // Add model services to list, ignore duplicates.
+          for (int i = 0; i < refs.length; i++) {
+            svcObj = m_context.getService(refs[i]);
+            if (!m_pluginList.contains(svcObj)) {
+              m_pluginList.add(svcObj);
+              firePropertyChangedEvent(Plugin.PLUGIN_ADDED, null, (Plugin)svcObj);
+            }
+          }
+        }
+        // Get all common plugins
+        refs = m_context.getServiceReferences(CommonPlugin.class.getName(), null);
+        if (refs != null) {
+          for (int i = 0; i < refs.length; i++) {
+            svcObj = m_context.getService(refs[i]);
+            if (!m_commonpluginList.contains(svcObj)) {
+              m_commonpluginList.add(svcObj);
+              firePropertyChangedEvent(CommonPlugin.COMMON_PLUGIN_ADDED, null, (CommonPlugin)svcObj);
+            }
+          }
+        }
+      } catch (Exception ex) {
+        System.err.println("ShellGuiActivator: Error initializing model list.");
+        System.err.println("ShellGuiActivator: " + ex);
+        ex.printStackTrace();
+      }
+    }
+
+    public void stop(BundleContext context)
+    {
+        if (m_frame != null)
+        {   this.nodesTree.stop();
+            m_frame.setVisible(false);
+            m_frame.dispose();
+            m_frame = null;
+        }
+    }
+
+    //
+    // Event methods.
+    //
+
+    public void addPropertyChangeListener(PropertyChangeListener l)
+    {
+        m_listenerList.add(PropertyChangeListener.class, l);
+    }
+
+    public void removePropertyChangeListener(PropertyChangeListener l)
+    {
+        m_listenerList.remove(PropertyChangeListener.class, l);
+    }
+
+    public void firePropertyChangedEvent(String name, Object oldValue, Object newValue)
+    {
+        PropertyChangeEvent event = null;
+
+        // Guaranteed to return a non-null array
+        Object[] listeners = m_listenerList.getListenerList();
+
+        // Process the listeners last to first, notifying
+        // those that are interested in this event
+        for (int i = listeners.length - 2; i >= 0; i -= 2)
+        {
+            if (listeners[i] == PropertyChangeListener.class)
+            {
+                // Lazily create the event:
+                if (event == null)
+                {
+                    event = new PropertyChangeEvent(this, name, oldValue, newValue);
+                }
+                ((PropertyChangeListener) listeners[i + 1]).propertyChange(event);
+            }
+        }
+    }
+}
diff --git a/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/CommonPanel.java b/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/CommonPanel.java
new file mode 100644
index 0000000..bad4c8b
--- /dev/null
+++ b/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/CommonPanel.java
@@ -0,0 +1,45 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.felix.mosgi.console.gui;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import javax.swing.JTabbedPane;
+
+import org.apache.felix.mosgi.console.ifc.CommonPlugin;
+
+public class CommonPanel extends JTabbedPane implements PropertyChangeListener {
+  Activator beanEventBroadcaster;
+
+  public CommonPanel(Activator activator){
+    this.beanEventBroadcaster=activator;
+    this.beanEventBroadcaster.addPropertyChangeListener(this);
+  }
+
+  public void propertyChange(PropertyChangeEvent event) {
+    if (event.getPropertyName().equals(CommonPlugin.COMMON_PLUGIN_ADDED)) {
+      CommonPlugin cp=(CommonPlugin)event.getNewValue();
+      this.add(cp.getName(), cp.getGUI());
+      this.beanEventBroadcaster.addPropertyChangeListener(cp);
+    }
+    if (event.getPropertyName().equals(CommonPlugin.COMMON_PLUGIN_REMOVED)){
+      CommonPlugin cp=(CommonPlugin)event.getNewValue();
+      this.remove(cp.getGUI());
+      this.beanEventBroadcaster.removePropertyChangeListener(cp);
+    }
+  }
+}
diff --git a/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodeCellRenderer.java b/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodeCellRenderer.java
new file mode 100644
index 0000000..c6f2015
--- /dev/null
+++ b/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodeCellRenderer.java
@@ -0,0 +1,56 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.felix.mosgi.console.gui;
+
+import java.awt.Component;
+import java.awt.Toolkit;
+
+import javax.swing.ImageIcon;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+import org.osgi.framework.BundleContext;
+
+public class NodeCellRenderer extends DefaultTreeCellRenderer {
+  private ImageIcon iconConnected;
+  private ImageIcon iconStopped;
+  private NodesTree nodesTree;
+
+  public NodeCellRenderer(BundleContext m_context, NodesTree nt){
+    this.iconConnected=new ImageIcon(Toolkit.getDefaultToolkit().getImage(m_context.getBundle().getResource("images/ServerRunning.gif")));
+    this.iconStopped=new ImageIcon(Toolkit.getDefaultToolkit().getImage(m_context.getBundle().getResource("images/ServerBlocked.gif")));
+    this.nodesTree=nt;
+  }
+
+	public Component getTreeCellRendererComponent(JTree tree, Object value,
+			boolean sel, boolean expanded, boolean leaf, int row,
+			boolean hasFocus) {
+
+		super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf,
+				row, hasFocus);
+    String val=value.toString();
+    if (!val.equals(NodesTree.TOP_NAME)){ 
+      if (nodesTree.isNodeConnected(val)){
+        setIcon(iconConnected);
+      }else{
+        setIcon(iconStopped);
+      }
+    }
+    return this;
+  }
+}
+
diff --git a/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodePanel.java b/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodePanel.java
new file mode 100644
index 0000000..281fdae
--- /dev/null
+++ b/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodePanel.java
@@ -0,0 +1,193 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.felix.mosgi.console.gui;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.IOException;
+import java.net.URLClassLoader;
+import java.rmi.server.RMIClassLoader;
+import java.rmi.server.RMIClassLoaderSpi;
+import java.security.SecureClassLoader;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Set;
+import javax.swing.JTabbedPane;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+//import javax.management.MalformedObjectNameException;
+import javax.management.MBeanException;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import org.apache.felix.mosgi.console.ifc.Plugin;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ChangeEvent;
+
+public class NodePanel extends JTabbedPane implements PropertyChangeListener, ChangeListener {
+  //private String repo;
+  private Activator m_activator = null;
+  private BundleContext m_context = null;
+  
+  private Hashtable pluginList = null;
+
+  public NodePanel(Activator activator, BundleContext context){
+    m_context = context;
+    m_activator = activator;
+    m_activator.addPropertyChangeListener(this);
+    this.pluginList = new Hashtable();
+    //repo = m_context.getProperty("insa.jmxconsole.repository");
+    this.addChangeListener(this);
+  }
+
+  //////////////////////////////////////
+  // ChangeListener Implementation
+  //////////////////////////////////////
+  public void stateChanged(ChangeEvent e){
+//   System.out.println("coucou => "+((JTabbedPane)e.getSource()).getSelectedIndex()+":"+((JTabbedPane)e.getSource()).getSelectedComponent().getName());
+   if (this.getSelectedComponent()!=null){
+     m_activator.firePropertyChangedEvent(Plugin.PLUGIN_ACTIVATED, null, this.getSelectedComponent().getName());
+   }
+  }
+
+
+  public void propertyChange(PropertyChangeEvent event) {
+    if (event.getPropertyName().equals(Plugin.PLUGIN_ADDED)) {
+      Plugin cp = (Plugin) event.getNewValue();
+      this.add(cp.getName(), cp.getGUI());
+System.out.println("add gui "+cp.getName()+" :: "+cp.getGUI());      
+      this.m_activator.addPropertyChangeListener(cp);
+      this.pluginList.put(cp.pluginLocation(), cp);
+      
+    }else if(event.getPropertyName().equals(Plugin.PLUGIN_REMOVED)) {
+      Plugin cp = (Plugin) event.getNewValue();
+      this.remove(cp.getGUI());
+      this.m_activator.removePropertyChangeListener(cp);
+//			this.pluginList.remove(cp.pluginLocation());
+      
+    }else if(event.getPropertyName().equals(Plugin.EMPTY_NODE)) {
+System.out.println("******* Debug No node selected");
+      this.clean();
+    }else if (event.getPropertyName().equals(Plugin.NEW_NODE_SELECTED)) {
+//System.out.println("Event NEW_NODE_SELECTED");
+    /* Update the tabs (Plugin) in the JTabbedPane (NodePanel) */
+      MBeanServerConnection mbsc = (MBeanServerConnection)event.getNewValue();
+      try {
+	this.clean();
+
+        Set ons = mbsc.queryNames( null, null );
+        for( Iterator i=ons.iterator(); i.hasNext(); ) {
+          ObjectName name = ( ObjectName )i.next();
+System.out.println("Queried name: "+name.toString());
+          if ( "TabUI".equals(name.getDomain()) ) {
+System.out.println("New tab: "+name.toString());
+	    /* Get the plugin implementation via a bundle */
+	    String tabBundle = (String) mbsc.getAttribute(name, "BundleName");
+System.out.println("Bundle name for current Plugin: "+tabBundle);
+	    if (tabBundle!=null){
+              Plugin p = (Plugin) this.pluginList.get(tabBundle);
+              if (p == null){
+  	          Bundle b = m_context.installBundle(tabBundle);
+		  b.start();
+System.out.println("Bundle started");
+//Thread.sleep(5000);
+               }else{
+System.out.println("register service plugin: " + p);
+                 p.registerServicePlugin();
+               }
+
+//             ServiceReference[] sr = b.getRegisteredServices();
+//             System.out.println(sr);
+//             Plugin p;
+//             for (int j=0 ; j < sr.length ; j++) {
+//               p=(Plugin)m_context.getService(sr[j]);
+//               this.add(p.getName(), p.getGUI());
+//               this.m_activator.addPropertyChangeListener(p);
+//             }
+
+//               System.out.println("Delegation for this");
+//               printcl = this.getClass().getClassLoader();
+//               while (printcl != null) {
+//                 System.out.println(printcl);
+//                 printcl = printcl.getParent();
+//               }
+//               System.out.println("{bootstrap loader}");
+//               System.out.println("");
+
+					/* Get the tab object */
+//             Object tabObj = mbsc.getAttribute(name, "Tab");
+// 
+//               System.out.println("Delegation for tabObj: " + tabObj);
+//               printcl = tabObj.getClass().getClassLoader();
+//               while (printcl != null) {
+//                 System.out.println(printcl);
+//                 printcl = printcl.getParent();
+//               }
+//               System.out.println("{bootstrap loader}");
+//               System.out.println("");
+  
+//          System.out.println("tabObj.getName(): " + ((fr.inria.ares.managedelements.testprobe.tab.TestProbeTabUI) tabObj).getName());
+              
+          /* Cast the tab */  
+//            Plugin tab = (Plugin)tabObj;
+          /* register the tab on the JTabbedPane */
+//            this.add(tab.getName(), tab.getGUI());
+            }else{
+	      System.out.println("No "+tabBundle+" property defined. I cannot install "+tabBundle+" tab");
+            }
+          }
+        }
+        m_activator.firePropertyChangedEvent(Plugin.NEW_NODE_READY, null, mbsc);
+        m_activator.firePropertyChangedEvent(Plugin.PLUGIN_ACTIVATED, null, this.getComponentAt(0).getName());
+
+
+      } catch (MBeanException e) {
+          System.err.println(e);
+//        } catch (MalformedObjectNameException e) {
+//          System.err.println(e);
+      } catch (AttributeNotFoundException e) {
+        System.err.println(e);
+      } catch (InstanceNotFoundException e) {
+        System.err.println(e);
+      } catch (ReflectionException e) {
+        System.err.println(e);
+      } catch (IOException e) {
+        System.err.println(e);
+      } catch (BundleException e) {
+        System.err.println(e);
+      }
+      
+//       catch (java.lang.InterruptedException e) {
+// 	      System.err.println(e);
+//       }
+    }
+  }
+
+  private void clean(){
+    this.removeAll();
+    for ( Iterator i=pluginList.keySet().iterator(); i.hasNext();) {
+      ((Plugin) pluginList.get(i.next())).unregisterServicePlugin();
+    }
+  }
+
+}
diff --git a/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodesTree.java b/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodesTree.java
new file mode 100644
index 0000000..f98c636
--- /dev/null
+++ b/org.apache.felix.mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodesTree.java
@@ -0,0 +1,260 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.felix.mosgi.console.gui;
+
+import java.awt.GridLayout;
+import java.util.Hashtable;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeSelectionModel;
+
+import org.osgi.framework.BundleContext;
+
+import org.apache.felix.mosgi.console.ifc.Plugin;
+
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.NotificationListener;
+import javax.management.Notification;
+import javax.management.MalformedObjectNameException;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.JMXConnectionNotification;
+
+import org.apache.felix.framework.cache.BundleCache;
+
+
+public class NodesTree extends JPanel implements TreeSelectionListener, NotificationListener {
+  static String TOP_NAME="Servers";
+  static int POOLING_TIME=10000;
+
+	protected JTree tree;
+  private DefaultTreeModel dtm;
+	private Hashtable connectedNodes = new Hashtable();
+	private Hashtable jmxConnectors = new Hashtable();
+	private DefaultMutableTreeNode top = null;
+  protected boolean cont=true;
+  
+	private static boolean useSystemLookAndFeel = false;
+
+  private Activator a;
+  private BundleContext bc;
+  private PoolingThread pt;
+  protected Thread poolThread;
+  private NodeCellRenderer ncr;
+  private Hashtable nodes=new Hashtable();
+
+
+	public NodesTree(Activator a,BundleContext bc) {
+		super(new GridLayout(1, 0));
+    this.a=a;
+    this.bc=bc;
+    this.pt=new PoolingThread();
+    
+		System.setProperty("java.security.policy", "client.policy");
+		top = new DefaultMutableTreeNode(NodesTree.TOP_NAME);
+    dtm=new DefaultTreeModel(top);
+		tree = new JTree(dtm);
+    tree.setCellRenderer(ncr=new NodeCellRenderer(bc,this));
+		tree.addTreeSelectionListener(this);
+		tree.getSelectionModel().setSelectionMode(
+				TreeSelectionModel.SINGLE_TREE_SELECTION);
+
+		JScrollPane treeView = new JScrollPane(tree);
+		add(treeView);
+	}
+
+  public void runDiscovery(){
+	this.createDefaultNodes(true);
+    poolThread=new Thread(this.pt);
+    poolThread.start();
+  }
+
+  //////////////////////////////////////////////////////
+  //               TreeSelectionListener //
+  //////////////////////////////////////////////////////
+	public void valueChanged(TreeSelectionEvent e) {
+//    System.out.println("coucou, value changed");
+		DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
+	  String selectedNode=(String)node.getUserObject();
+    if (!selectedNode.equals(NodesTree.TOP_NAME)){
+      Object mbsc=connectedNodes.get(selectedNode);
+      if (mbsc!=null){
+        a.firePropertyChangedEvent(Plugin.NEW_NODE_SELECTED, selectedNode, mbsc);
+      }else{
+        a.firePropertyChangedEvent(Plugin.EMPTY_NODE, null, "null");
+      }
+    }
+	}
+
+  ////////////////////////////////////////////////////
+  //            NotificationListener                //
+  ////////////////////////////////////////////////////
+  public void handleNotification(Notification notification, Object handback) {
+//    System.out.println("Connection ==> "+notification.getMessage()+":"+((JMXConnectionNotification)notification).getConnectionId()+":"+handback);
+    if ( !JMXConnectionNotification.OPENED.equals(notification.getType()) ){
+      this.disconnectFromNode((String)handback);
+      tree.treeDidChange();
+    }
+  }
+  
+  ////////////////////////////////////////////////////
+  //            Friend methods //
+  ///////////////////////////////////////////////////
+  void stop(){
+    this.cont=false;
+  }
+
+  boolean isNodeConnected(String s){
+    if (this.connectedNodes.get(s)==null){
+      return false;
+    }else{
+      return true;
+    }
+  }
+
+  ///////////////////////////////////////////////////
+  //           Private part //
+  ///////////////////////////////////////////////////
+  protected void createDefaultNodes(boolean createTreeNode) {
+    String profile;
+    String rmiPort;
+    String ip;
+    
+    int i=1;
+    profile=bc.getProperty("insa.jmxconsole.profile" + i);
+
+    while (profile!=null){
+      rmiPort=bc.getProperty("insa.jmxconsole.rmiport."+profile);
+      if (rmiPort==null){rmiPort="1099";}
+      String virtual=bc.getProperty("insa.jmxconsole.core."+profile);
+      ip=bc.getProperty("insa.jmxconsole.ip" + i);
+      String connString=ip+":"+rmiPort+"/"+profile;
+      if (createTreeNode){
+        DefaultMutableTreeNode dmtn=new DefaultMutableTreeNode(connString);
+        DefaultMutableTreeNode parent=top;
+        if (virtual==null){
+          nodes.put(connString, dmtn);
+        }else{
+          String parentString=ip+":"+virtual;
+          parent=(DefaultMutableTreeNode)nodes.get(parentString);
+        }
+        parent.add(dmtn);
+      }
+      this.connectToNode(connString);
+      i++;
+      profile=bc.getProperty("insa.jmxconsole.profile" + i);
+    }
+      
+    if (i==1){
+      try{
+        System.out.println("No property insa.jmxconsole.profile, managing local profile");
+		String prof=bc.getProperty(BundleCache.CACHE_PROFILE_PROP);
+    	if (prof==null){
+	      prof=System.getProperty(BundleCache.CACHE_PROFILE_PROP);
+		}
+        String connString=java.net.InetAddress.getLocalHost().getHostAddress()+":1099/"+prof;
+        if (createTreeNode){
+          top.add(new DefaultMutableTreeNode(connString));
+        }
+//        this.connectToNode(connString);
+      }catch(Exception e){
+        e.printStackTrace();
+      }
+    }
+  }
+
+  private void disconnectFromNode(String connString){
+    JMXConnector jmxc=(JMXConnector)this.jmxConnectors.remove(connString);
+    MBeanServerConnection mbscl=(MBeanServerConnection)this.connectedNodes.remove(connString);
+    try{
+      jmxc.removeConnectionNotificationListener(this);
+      //mbscl.removeNotificationListener(new ObjectName("OSGI:name=OSGi
+      // Server"), this); // Does not work since the connexion is lost !!
+      jmxc.close();
+      a.firePropertyChangedEvent(Plugin.EMPTY_NODE, null, "null");
+    }catch (Exception e){
+      e.printStackTrace();
+    }
+    jmxc=null;
+    mbscl=null;
+  }
+     
+  private void connectToNode(String connString){
+    Object ls=this.connectedNodes.get(connString);
+    if (ls==null){
+      JMXConnector jmxc = null;
+      try {
+
+        JMXServiceURL surl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + connString);
+/*
+Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+System.out.println("=====> "+java.util.logging.Logger.getLogger("javax.management.remote.misc"));
+java.util.logging.Logger.getLogger("javax.management.remote.misc").setLevel(java.util.logging.Level.FINEST);
+java.util.logging.Logger.getLogger("javax.management.remote.rmi").setLevel(java.util.logging.Level.FINEST);
+
+java.util.logging.ConsoleHandler ch=new java.util.logging.ConsoleHandler();
+ch.setLevel(java.util.logging.Level.FINEST);
+java.util.logging.Logger.getLogger("javax.management.remote.misc").addHandler(ch);
+java.util.logging.Logger.getLogger("javax.management.remote.rmi").addHandler(ch);
+*/
+				
+        jmxc = JMXConnectorFactory.connect(surl);
+        MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
+        if (mbsc.isRegistered(new ObjectName("OSGI:name=Remote Logger"))){
+          jmxc.addConnectionNotificationListener(this, null, connString);
+          mbsc.addNotificationListener(new ObjectName("TabUI:name=OsgiProbes"), this, null, null); //Needed,
+
+          this.connectedNodes.put(connString, mbsc);
+          this.jmxConnectors.put(connString, jmxc);
+          a.firePropertyChangedEvent(Plugin.NEW_NODE_CONNECTION, connString, mbsc);
+ System.out.println("Node "+connString+" connected");
+        }else {
+System.out.println("The Remote Logger of "+connString+" is not started");
+        }
+      }catch(java.io.IOException ex){
+System.out.println("Impossible to connect to "+connString);
+      }catch(MalformedObjectNameException e){
+        e.printStackTrace();
+      }catch(Exception e){
+        e.printStackTrace();
+      }
+    }else{
+      a.firePropertyChangedEvent(Plugin.NEW_NODE_CONNECTION, connString, ls);
+    }
+  }
+
+  protected class PoolingThread implements Runnable{
+    public void run(){
+      while (cont){
+        createDefaultNodes(false);
+        tree.treeDidChange();
+        try{
+          Thread.sleep(POOLING_TIME);
+        }catch(InterruptedException e){
+          e.printStackTrace();
+        }
+      }
+    }
+  }
+}
diff --git a/org.apache.felix.mosgi.console.gui/src/main/resources/images/GraphSettings.gif b/org.apache.felix.mosgi.console.gui/src/main/resources/images/GraphSettings.gif
new file mode 100644
index 0000000..982e2dc
--- /dev/null
+++ b/org.apache.felix.mosgi.console.gui/src/main/resources/images/GraphSettings.gif
Binary files differ
diff --git a/org.apache.felix.mosgi.console.gui/src/main/resources/images/ServerBlocked.gif b/org.apache.felix.mosgi.console.gui/src/main/resources/images/ServerBlocked.gif
new file mode 100644
index 0000000..50459cb
--- /dev/null
+++ b/org.apache.felix.mosgi.console.gui/src/main/resources/images/ServerBlocked.gif
Binary files differ
diff --git a/org.apache.felix.mosgi.console.gui/src/main/resources/images/ServerRunning.gif b/org.apache.felix.mosgi.console.gui/src/main/resources/images/ServerRunning.gif
new file mode 100644
index 0000000..ab3c237
--- /dev/null
+++ b/org.apache.felix.mosgi.console.gui/src/main/resources/images/ServerRunning.gif
Binary files differ
diff --git a/org.apache.felix.mosgi.console.gui/src/main/resources/images/logo.gif b/org.apache.felix.mosgi.console.gui/src/main/resources/images/logo.gif
new file mode 100644
index 0000000..b523df7
--- /dev/null
+++ b/org.apache.felix.mosgi.console.gui/src/main/resources/images/logo.gif
Binary files differ