FELIX-610
---------
JMX console allows any JMX connector protocol. The JMXServiceURL is built with new properties form the configuration properties file. In addition, non classic protocol classes can be provided by other bundle through dynamic import. The protocol package can be provided dynamically.

 - mosgi.jmxconsole.id.<number>.nickname is an optional property used by the GUI (default value is the gateway number)
 - mosgi.jmxconsole.id.<number>.profile is the remote gateway OSGi profile name (default value is core)
 - mosgi.jmxconsole.id.<number>.host is the remote gateway ip (default value is 127.0.0.1)
 - mosgi.jmxconsole.id.<number>.protocol is the protocol used by the JMX connector (default is rmi)
 - mosgi.jmxconsole.id.<number>.port is the port used by the JMX connector (default is 1099)
 - mosgi.jmxconsole.protocol.<protocol>.package (default is the "jmx.remote.protocol.provider.pkgs" property value used by the standard javax.management.JMXConnectorFactory class)

Minor modification :
 - Customisable pooling time (refresh time on top of node tree panel)
 - Refresh buton (appears if refresh time is set to 0)
 - Tree aspect
 - Node tooltip.



git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@668577 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/mosgi/console.component/src/main/java/org/apache/felix/mosgi/console/component/Activator.java b/mosgi/console.component/src/main/java/org/apache/felix/mosgi/console/component/Activator.java
index 9530341..6897558 100644
--- a/mosgi/console.component/src/main/java/org/apache/felix/mosgi/console/component/Activator.java
+++ b/mosgi/console.component/src/main/java/org/apache/felix/mosgi/console/component/Activator.java
@@ -20,8 +20,19 @@
 import org.osgi.framework.BundleContext;
 import org.apache.felix.mosgi.console.ifc.CommonPlugin;
 import java.lang.String;
+import javax.management.ObjectName;
+import javax.management.MalformedObjectNameException;
 
 public class Activator implements BundleActivator {
+
+  public static ObjectName REMOTE_LOGGER_ON = null;
+  static {
+    try {
+      REMOTE_LOGGER_ON = new ObjectName("OSGI:name=Remote Logger");
+    } catch (MalformedObjectNameException mone) {
+      //
+    }
+  }
   
   public void start(BundleContext context) throws Exception{ 
     String propVal=new String("both");
diff --git a/mosgi/console.component/src/main/java/org/apache/felix/mosgi/console/component/RemoteLogger_jtable.java b/mosgi/console.component/src/main/java/org/apache/felix/mosgi/console/component/RemoteLogger_jtable.java
index 912fd54..192fa6d 100644
--- a/mosgi/console.component/src/main/java/org/apache/felix/mosgi/console/component/RemoteLogger_jtable.java
+++ b/mosgi/console.component/src/main/java/org/apache/felix/mosgi/console/component/RemoteLogger_jtable.java
@@ -129,7 +129,7 @@
         MBeanServerConnection mbs=(MBeanServerConnection)e.getNewValue();
         if (nodes.get(mbs)==null){
 	  //System.out.println("Ajout d'un listener " +mbs);
-          ((MBeanServerConnection)e.getNewValue()).addNotificationListener(new ObjectName("OSGI:name=Remote Logger"), this, null, e.getOldValue());
+          ((MBeanServerConnection)e.getNewValue()).addNotificationListener(Activator.REMOTE_LOGGER_ON, this, null, e.getOldValue());
           nodes.put(mbs, "ok");
         }
       }catch(Exception ex){
@@ -138,6 +138,9 @@
     }
   }
 
+  private static final DateFormat dateF = DateFormat.getDateInstance(DateFormat.SHORT);
+  private static final DateFormat timeF = DateFormat.getTimeInstance(DateFormat.MEDIUM);
+
   public void handleNotification(Notification notification, Object handback) {
     StringTokenizer st = new StringTokenizer(notification.getMessage(),"*");
     
@@ -147,8 +150,8 @@
     if (ts!=0){ // means it's not an old log
       Date d=new Date(ts);
       //DateFormat dateFormat = new SimpleDateFormat("hh'h'mm dd-MM-yy");
-      date=DateFormat.getDateInstance(DateFormat.SHORT).format(d);
-      time=DateFormat.getTimeInstance(DateFormat.MEDIUM).format(d);
+      date = dateF.format(d);
+      time = timeF.format(d);
     }
     String id=st.nextToken();
     String name=st.nextToken();
diff --git a/mosgi/console.component/src/main/java/org/apache/felix/mosgi/console/component/RemoteLogger_jtree.java b/mosgi/console.component/src/main/java/org/apache/felix/mosgi/console/component/RemoteLogger_jtree.java
index 813ef83..a75ad25 100644
--- a/mosgi/console.component/src/main/java/org/apache/felix/mosgi/console/component/RemoteLogger_jtree.java
+++ b/mosgi/console.component/src/main/java/org/apache/felix/mosgi/console/component/RemoteLogger_jtree.java
@@ -190,19 +190,21 @@
       try {
         MBeanServerConnection mbsc=(MBeanServerConnection)e.getNewValue();
 	if ( !ht_connectedGateway.containsValue(mbsc) ) {
-	  String connString=(String) e.getOldValue();
-	  mbsc.addNotificationListener(new ObjectName("OSGI:name=Remote Logger"), this, null, connString);
+	  String jmxsurl = (String) e.getOldValue();
+	  mbsc.addNotificationListener(Activator.REMOTE_LOGGER_ON, this, null, jmxsurl);
+	  // At gateway connection time : add into the tree a "port/profileName" node under an "ip" node
+	  String ref = jmxsurl.substring(jmxsurl.lastIndexOf(":")+1);
+	  String ip_tmp = jmxsurl.substring(0, jmxsurl.lastIndexOf(":"));
+	  String ip = ip_tmp.substring(ip_tmp.lastIndexOf("/")+1);
+	  String connString = jmxsurl.substring(ip_tmp.lastIndexOf("/")+1);
 	  ht_connectedGateway.put(connString, mbsc);
-	  // At gateway connection time : add into the tree an rmiport/profileName node under an ip node
-          String ip=connString.split(":")[0];
-          String ref=connString.split(":")[1];
           DefaultMutableTreeNode dmtn_ip=createIfNeed(ip, rootNode);
           DefaultMutableTreeNode dmtn_ref=createIfNeed(ref, dmtn_ip);
-          Integer lL=this.getLogLvl(connString);
+          Integer lL = this.getLogLvl(connString);
           ht_logLvl.put(dmtn_ref, lL);
           // ask for old log management choice :
           if (oldLogChoice==OLDLOG_THIS_TIME | oldLogChoice==OLDLOG_NOT_THIS_TIME) {
-            JOptionPane jop = new JOptionPane("Do you want old log from gateway :\n"+connString+" ?", JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, new String[] {OLDLOG_THIS_TIME, OLDLOG_NOT_THIS_TIME, OLDLOG_ALWAYS, OLDLOG_NEVER}, OLDLOG_THIS_TIME);
+            JOptionPane jop = new JOptionPane("Do you want old log from gateway :\n"+jmxsurl+" ?", JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, new String[] {OLDLOG_THIS_TIME, OLDLOG_NOT_THIS_TIME, OLDLOG_ALWAYS, OLDLOG_NEVER}, OLDLOG_THIS_TIME);
             JDialog dialog = jop.createDialog(jp, "Old log management");
 	    //dialog.setModal(true);
 	    dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
@@ -213,7 +215,7 @@
 	    }
 	  } 
           if (oldLogChoice==OLDLOG_THIS_TIME | oldLogChoice==OLDLOG_ALWAYS) {
-            mbsc.invoke(new ObjectName("OSGI:name=Remote Logger"), "sendOldLog", new Object[]{}, new String[]{});
+            mbsc.invoke(Activator.REMOTE_LOGGER_ON, "sendOldLog", new Object[]{}, new String[]{});
 	  }
         }
       } catch(Exception ex){
@@ -222,22 +224,23 @@
     }
   }
  
+  private static final DateFormat dateFormat = new SimpleDateFormat("dd-MM-yy");
+  private static final DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss:SSS");
   ///////////////////////////////////////////////////
   //       NotificationListener implementation     //  
   ///////////////////////////////////////////////////
   public void handleNotification(Notification notification, Object handback) {
-    StringTokenizer st=new StringTokenizer(handback.toString(), ":");
-    String ip=st.nextToken();
-    String ref=st.nextToken();
+    String jmxsurl = handback.toString();
+    String ref = jmxsurl.substring(jmxsurl.lastIndexOf(":")+1);
+    String ip_tmp = jmxsurl.substring(0, jmxsurl.lastIndexOf(":"));
+    String ip = ip_tmp.substring(ip_tmp.lastIndexOf("/")+1);
   
-    st = new StringTokenizer(notification.getMessage(), "*");
+    StringTokenizer st = new StringTokenizer(notification.getMessage(), "*");
     long ts=notification.getTimeStamp();
     String time=JtreeCellRenderer.UNKNOWN_TIME;
     String date=JtreeCellRenderer.UNKNOWN_DATE;
     if (ts!=0) {
       Date timeDate=new Date(ts);
-      DateFormat dateFormat = new SimpleDateFormat("dd-MM-yy");
-      DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss:SSS");
       // if I use local date format there are indentations problems
       //DateFormat df = DateFormat.getTimeInstance(DateFormat.MEDIUM);
       //DateFormat df2 = DateFormat.getDateInstance(DateFormat.SHORT);
@@ -279,7 +282,7 @@
     Integer val=new Integer(0);
     try {
       MBeanServerConnection mb=(MBeanServerConnection) ht_connectedGateway.get(connString);
-      val=(Integer) mb.getAttribute(new ObjectName("OSGI:name=Remote Logger"), "LogLvl");
+      val=(Integer) mb.getAttribute(Activator.REMOTE_LOGGER_ON, "LogLvl");
     } catch (Exception exc) {
       exc.printStackTrace();
     }
@@ -288,12 +291,12 @@
 
   private void setLogLvl(TreePath tp) {
     Object[] o=tp.getPath();
-    String connS=""+o[1]+":"+o[2];
-    MBeanServerConnection mb=(MBeanServerConnection) ht_connectedGateway.get(connS);
+    String connString = o[1]+":"+o[2];
     try {
-      Integer curentVal=(Integer) mb.getAttribute(new ObjectName("OSGI:name=Remote Logger"), "LogLvl");
+      MBeanServerConnection mb=(MBeanServerConnection) ht_connectedGateway.get(connString);
+      Integer curentVal=(Integer) mb.getAttribute(Activator.REMOTE_LOGGER_ON, "LogLvl");
 
-      JOptionPane jop = new JOptionPane("Select a log level for \""+connS+"\" :", JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, LOG_LVL, LOG_LVL[curentVal.intValue()-1]);
+      JOptionPane jop = new JOptionPane("Select a log level for \""+connString+"\" :", JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, LOG_LVL, LOG_LVL[curentVal.intValue()-1]);
       JDialog dialog = jop.createDialog(jp, "Log level");
       dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
       dialog.show();
@@ -304,11 +307,11 @@
       else if (choice.equals("Info")) {newVal=new Integer(3);}
       else if (choice.equals("Debug")) {newVal=new Integer(4);}
 
-      mb.setAttribute(new ObjectName("OSGI:name=Remote Logger"), new Attribute("LogLvl", newVal));
+      mb.setAttribute(Activator.REMOTE_LOGGER_ON, new Attribute("LogLvl", newVal));
       DefaultMutableTreeNode ddmmttnn=(DefaultMutableTreeNode) tp.getLastPathComponent();
       ht_logLvl.put(ddmmttnn, newVal);
     } catch (Exception ex) {
-      JOptionPane.showMessageDialog(jp,"Error with \""+connS+"\" :\n"+ex, "Error :", JOptionPane.ERROR_MESSAGE);
+      JOptionPane.showMessageDialog(jp,"Error with \""+connString+"\" :\n"+ex, "Error :", JOptionPane.ERROR_MESSAGE);
       ex.printStackTrace();
     }
   }
diff --git a/mosgi/console.gui/pom.xml b/mosgi/console.gui/pom.xml
index 081b3d9..113179d 100644
--- a/mosgi/console.gui/pom.xml
+++ b/mosgi/console.gui/pom.xml
@@ -57,20 +57,6 @@
       <version>0.9.0-SNAPSHOT</version>
       <scope>provided</scope>
     </dependency>
-    <dependency>
-       <groupId>mx4j</groupId>
-       <artifactId>mx4j-jmx</artifactId>
-       <version>3.0.1</version>
-       <scope>provided</scope>
-    </dependency>
-    <dependency>
-       <groupId>mx4j</groupId>
-       <artifactId>mx4j-remote</artifactId>
-       <version>3.0.1</version>
-       <scope>provided</scope>
-    </dependency>
-
-    
   </dependencies>
 
   <build>
@@ -88,6 +74,7 @@
 	    <Bundle-Activator>org.apache.felix.mosgi.console.gui.Activator</Bundle-Activator>
             <Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
 	    <Private-Package>${pom.artifactId}</Private-Package>
+	    <DynamicImport-Package>*</DynamicImport-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/mosgi/console.gui/src/main/java/org/apache/felix/mosgi/console/gui/Gateway.java b/mosgi/console.gui/src/main/java/org/apache/felix/mosgi/console/gui/Gateway.java
new file mode 100644
index 0000000..5556307
--- /dev/null
+++ b/mosgi/console.gui/src/main/java/org/apache/felix/mosgi/console/gui/Gateway.java
@@ -0,0 +1,232 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.felix.mosgi.console.gui;
+
+import org.osgi.framework.BundleContext;
+import java.util.Hashtable;
+import java.util.Vector;
+import javax.swing.JOptionPane;
+import javax.management.remote.JMXServiceURL;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotificationListener;
+import java.net.MalformedURLException;
+
+public class Gateway extends JMXServiceURL {
+
+  private static final String JMX_SERVICE = "service:jmx:";
+
+  private static final String DEFAULT_PROFILE  = "core";
+  private static final String DEFAULT_HOST     = "127.0.0.1";
+  private static final String DEFAULT_PROTOCOL = "rmi";
+  private static final String DEFAULT_PORT     = "1099";
+
+  private static Hashtable HT_GATEWAY = new Hashtable(); // used to manage virtuals gateways
+
+  private JMXConnector jmxc;
+  private MBeanServerConnection mbsc;
+
+  private String nickname; // used to manage virtuals gateways
+  private String name; // name for the GUI = this.nickname+" : "+this.toString()
+  private Gateway parentGateway;
+  private String toolTipText;
+  private boolean isConnected;
+  
+  public String getName() {
+    return this.name;
+  }
+
+  public MBeanServerConnection getMbsc() {
+    return this.mbsc;
+  }
+
+  public boolean isConnected() {
+    return this.isConnected;
+  }
+
+  public String getToolTipText() {
+    return this.toolTipText;
+  }
+
+  public Gateway getParent() {
+    return parentGateway;
+  }
+
+  // The constructor (private)
+  private Gateway(String nickname, String surl, Gateway vosgi) throws MalformedURLException {
+    super(surl);
+    this.nickname = nickname;
+    this.name = nickname+" : \""+this.toString().substring(JMX_SERVICE.length())+"\"";
+    this.parentGateway = vosgi;
+    this.isConnected = false;
+    this.toolTipText = "<html><B>\""+nickname+"\" JMXServiceURL =<br>"+
+      "- protocol=</B>"+this.getProtocol()+"<br><B>"+
+      "- host=</B>"+this.getHost()+"<br><B>"+
+      "- port=</B>"+this.getPort()+"<br><B>"+
+      "- URLPath=</B>"+this.getURLPath()+"</html>";
+    HT_GATEWAY.put(nickname, this);
+  }
+
+  // Intermediate private Gateway creator
+  private static Gateway newGateway(String nickname, String serviceURL, String parent_gateway) throws Exception {
+    if ( serviceURL.contains("null") ) {
+      throw new Exception("Invalid service URL \""+serviceURL+"\"");
+    }
+    
+    Gateway vosgiGateway = null;
+    if ( parent_gateway != null && !parent_gateway.equals("") && !parent_gateway.equals("null") ) {
+      vosgiGateway = (Gateway) HT_GATEWAY.get(parent_gateway);
+      if ( vosgiGateway == null ) {
+        throw new Exception("Parent gateway \""+parent_gateway+"\" doesn't exist.");
+      }
+    }
+
+    Gateway newGateway = new Gateway(nickname, serviceURL, vosgiGateway);
+    return newGateway;
+  }
+
+  // Creation of Gateways from the config properties file
+  public static Gateway[] newGateways(BundleContext bc) {
+    Vector v_gateways = new Vector();
+    String protocol, host, profile, port, nickname, parent_gateway;
+    int port_int;
+
+    int i = 1;
+    profile = bc.getProperty("mosgi.jmxconsole.id."+i+".profile");
+    if ( profile == null) { profile = DEFAULT_PROFILE; }
+  
+    while ( profile != null ) {
+      host = bc.getProperty("mosgi.jmxconsole.id."+i+".host");
+      if ( host == null ) { host = DEFAULT_HOST; }
+      protocol = bc.getProperty("mosgi.jmxconsole.id."+i+".protocol");
+      if ( protocol == null ) { protocol = DEFAULT_PROTOCOL; }
+      port = bc.getProperty("mosgi.jmxconsole.id."+i+".port");
+      if ( port == null ) { port = DEFAULT_PORT; }
+      try {
+        port_int = Integer.parseInt(port);
+      } catch (Exception exep) { try { port_int = Integer.parseInt(DEFAULT_PORT); } catch (Exception e) {} }
+      String serviceURL = JMX_SERVICE+protocol+":///jndi/"+"rmi"+"://"+host+":"+port+"/"+profile;
+      parent_gateway = bc.getProperty("mosgi.jmxconsole.id."+i+".virtual");
+      Gateway g = null;
+      nickname =  bc.getProperty("mosgi.jmxconsole.id."+i+".nickname");
+      if (nickname == null ) { nickname = ""+i; };
+      try {
+        g = Gateway.newGateway(nickname, serviceURL, parent_gateway);
+        if ( g != null ) {
+          v_gateways.addElement(g);
+        }
+      } catch (Exception exep) {
+        System.out.println(""+exep);
+      }
+      i++;
+      profile = bc.getProperty("mosgi.jmxconsole.id."+i+".profile");
+    }
+    Gateway[] gateways=new Gateway[v_gateways.size()];
+    v_gateways.toArray(gateways);
+    return gateways;
+  }
+
+  // GUI gateway creator
+  public static Gateway newGateway() {
+    String nickname = JOptionPane.showInputDialog("Profil nickname", "");
+    if ( nickname == null) return null; // should check nickname is unique
+    String host = JOptionPane.showInputDialog("Host", DEFAULT_HOST);
+    if ( host == null ) return null;
+    String protocol = JOptionPane.showInputDialog("Protocol", DEFAULT_PROTOCOL);
+    if ( protocol==null ) return null;
+    String port = JOptionPane.showInputDialog("Port", DEFAULT_PORT);
+    try { Integer.parseInt(port); } catch (Exception ex) { return null; }
+    String profile = JOptionPane.showInputDialog("OSGi profil name", "");
+    if (profile==null) return null;
+    Object gateway_list[] = HT_GATEWAY.keySet().toArray();
+    Object gateway_list2[] = new Object[gateway_list.length+1];
+    System.arraycopy(gateway_list, 0, gateway_list2, 1, gateway_list.length);
+    gateway_list2[0] = "None";
+    java.util.Arrays.sort(gateway_list);
+    int val = JOptionPane.showOptionDialog(new javax.swing.JFrame(), "Virtual of", "Is it a virtual gateway ?", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, gateway_list2, gateway_list2[0]);
+    String virtual = "";
+    if ( val != JOptionPane.CLOSED_OPTION ) { virtual = ""+gateway_list2[val]; }
+    if ( val == 0 ) { virtual = ""; }
+    String serviceURL = JMX_SERVICE+protocol+":///jndi/"+protocol+"://"+host+":"+port+"/"+profile;
+    Gateway g = null;
+    try { 
+      g = Gateway.newGateway(nickname, serviceURL, virtual);
+    } catch (Exception exep) {
+      System.out.println(""+exep);
+      return null;
+    }
+    return g;
+  }
+
+  public boolean connect(NotificationListener notificationListener) {
+    if ( this.isConnected ) {
+      return true;
+    } else {
+      try {
+        //System.out.println("\nconnectToNode("+this+")...");
+        java.util.HashMap env=new java.util.HashMap();
+        env.put("jmx.remote.protocol.provider.class.loader", this.getClass().getClassLoader());
+        env.put("jmx.remote.protocol.provider.pkgs", NodesTree.getProtocolPackageProvider(this.getProtocol())); // efficacite partielle... Le reste etant assure par du codage en dur dans les classes du protocol murmi
+        this.jmxc = JMXConnectorFactory.newJMXConnector(this, env);
+          //System.out.println("jmxc = "+jmxc);
+        this.jmxc.connect(env);
+          //System.out.println("jmxc connected = "+jmxc);
+        this.mbsc = jmxc.getMBeanServerConnection();
+        if ( this.mbsc.isRegistered(new ObjectName("OSGI:name=Remote Logger")) ) {
+	  jmxc.addConnectionNotificationListener(notificationListener, null, this);
+	  //mbsc.addNotificationListener(new ObjectName("TabUI:name=OsgiProbes"), notificationListener, null, null); //Needed ? Osgiprobes is a NotficationBroadcasterSupport but do nothing with... ?
+          this.isConnected = true;
+          System.out.println("Node \""+this.toString()+"\" connected");
+          return true;
+        } else {
+          System.out.println("The Remote Logger of \""+this.toString()+"\" is not started");
+          return false;
+        }
+      } catch(java.io.IOException ex){
+        //System.out.println("Impossible to connect to "+this.toString());
+      } catch(MalformedObjectNameException e){
+        //
+      } catch(Exception e){
+        //use one thread per node to avoid being freeze by a timeOutConnection
+        //System.out.println("gui.NodesTree.connectToNode("+this.toString()+") : "+e);
+        //System.out.println("  => Delete this node ? to implement... ?");
+      }
+    }
+    return false;
+  }
+
+  public void disconnect(NotificationListener nl) {
+    //System.out.println(this+".disconnect() ...)");
+    if ( this.isConnected ) {
+      try {
+        jmxc.removeConnectionNotificationListener(nl);
+        this.jmxc.close();
+      } catch (Exception e){
+        //e.printStackTrace();
+      }
+      this.jmxc = null;
+    }
+    this.mbsc = null;
+    this.isConnected = false;
+  }
+
+}
diff --git a/mosgi/console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodeCellRenderer.java b/mosgi/console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodeCellRenderer.java
index 9b47435..2c92433 100644
--- a/mosgi/console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodeCellRenderer.java
+++ b/mosgi/console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodeCellRenderer.java
@@ -18,37 +18,42 @@
 */
 package org.apache.felix.mosgi.console.gui;
 
+import org.osgi.framework.BundleContext;
 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;
+import javax.swing.tree.DefaultMutableTreeNode;
 
 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;
+    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)){
+    Object o = ((DefaultMutableTreeNode) value).getUserObject();
+    if ( !o.equals(NodesTree.TOP_NAME) ) {
+      Gateway g = (Gateway) o;
+      super.getTreeCellRendererComponent(tree, g.getName(), sel, expanded, leaf, row, hasFocus);
+      if ( g.isConnected() ) {
         setIcon(iconConnected);
-      }else{
+      } else {
         setIcon(iconStopped);
       }
+      setToolTipText(g.getToolTipText());
+    } else {
+      super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
     }
     return this;
   }
+
 }
 
diff --git a/mosgi/console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodesTree.java b/mosgi/console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodesTree.java
index f099311..8fdc83b 100644
--- a/mosgi/console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodesTree.java
+++ b/mosgi/console.gui/src/main/java/org/apache/felix/mosgi/console/gui/NodesTree.java
@@ -25,6 +25,7 @@
 import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.Toolkit;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
@@ -36,76 +37,67 @@
 import javax.swing.tree.TreeSelectionModel;
 import javax.swing.tree.TreePath;
 import javax.swing.JButton;
-
-import java.util.Hashtable;
+import javax.swing.JTextField;
+import javax.swing.ImageIcon;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
 import java.util.Enumeration;
+import java.util.Hashtable;
 import org.osgi.framework.BundleContext;
 import org.apache.felix.mosgi.console.ifc.Plugin;
 import org.apache.felix.mosgi.console.ifc.CommonPlugin;
-import org.apache.felix.framework.cache.BundleCache;
-
-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 javax.jmdns.ServiceInfo;
-
 public class NodesTree extends JPanel implements TreeSelectionListener, NotificationListener, ActionListener, PropertyChangeListener {
 
-  static String TOP_NAME="Servers";
-  static int POOLING_TIME=2000;
-  static String JMX_SERVICE_URL="service:jmx:rmi:///jndi/rmi://";
-  private static boolean useSystemLookAndFeel = false;
+  private static Hashtable PROTOCOL_PACKAGE_PROVIDER = new Hashtable();
+  protected static final String TOP_NAME = "Servers";
+  private static int POOLING_TIME = 2500;
   
-  private Activator a;
-  private BundleContext bc;
+  private Activator activator;
+  private static BundleContext bc;
   
   protected JTree tree;
   private DefaultTreeModel dtm;
   private DefaultMutableTreeNode top = null;
-  private NodeCellRenderer ncr;
-  private JButton addNodeButton;
-  private JButton removeNodeButton;
+  private JButton jb_addNode;
+  private JButton jb_removeNode;
+  private JTextField jtf_pool;
+  private JButton jb_refresh;
 
-  private Hashtable connectedNodes = new Hashtable();
-  private Hashtable jmxConnectors = new Hashtable();
-  private Hashtable nodes=new Hashtable();
- 
-  protected boolean cont=true; 
+  private boolean cont = true; 
   private PoolingThread pt;
-  protected Thread poolThread;
-  
-  private boolean isAllNodesConnected=false;
+  private boolean isAllNodesConnected = false;
 
-  public NodesTree(Activator a,BundleContext bc) {
+  public NodesTree(Activator activator, BundleContext bc) {
     super(new BorderLayout());
-    this.a=a;
-    this.bc=bc;
-    this.pt=new PoolingThread();
+    this.activator = activator;
+    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));
+    top = new DefaultMutableTreeNode(NodesTree.TOP_NAME);
+    dtm = new DefaultTreeModel(top);
+    tree = new JTree(dtm);
+    tree.setCellRenderer(new NodeCellRenderer(bc, this));
     tree.addTreeSelectionListener(this);
     tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+    javax.swing.ToolTipManager.sharedInstance().registerComponent(tree);
 
-    JScrollPane treeView=new JScrollPane(tree);
+    JScrollPane treeView = new JScrollPane(tree);
     add(createButtonPanel(), BorderLayout.NORTH);
     add(treeView, BorderLayout.CENTER);
   }
 
   public void runDiscovery(){
-    this.createDefaultNodes();
-    poolThread=new Thread(this.pt);
-    poolThread.start();
+    Gateway[] g = Gateway.newGateways(bc);
+    for (int i = 0 ; i < g.length ; i++) {
+      this.createTreeNode(g[i]);
+    }
+    (new Thread(this.pt)).start();
+    tree.expandPath(new TreePath(((DefaultMutableTreeNode)(dtm.getRoot())).getPath())); // expand root node
   }
 
   //////////////////////////////////////////////////
@@ -113,12 +105,14 @@
   //////////////////////////////////////////////////
   public void propertyChange(PropertyChangeEvent event) {
     if (event.getPropertyName().equals(CommonPlugin.COMMON_PLUGIN_ADDED)) {
-      Enumeration enu=connectedNodes.keys();
-      while (enu.hasMoreElements()) {
+      Enumeration enu = top.breadthFirstEnumeration();
+      enu.nextElement(); // Skip top node
+      while ( enu.hasMoreElements() ) {
         // Common plugin added after a gateway connection so firePCE(Plugin.NEW_NODE_CONNECTION, connString , mbsc) again :
-        String key=(String) enu.nextElement();
-        System.out.println("   "+key+"="+connectedNodes.get(key));
-        a.firePropertyChangedEvent(Plugin.NEW_NODE_CONNECTION, key, connectedNodes.get(key));
+	Gateway g = (Gateway) ((DefaultMutableTreeNode) enu.nextElement()).getUserObject();
+	if ( g.isConnected() ) {
+          activator.firePropertyChangedEvent(Plugin.NEW_NODE_CONNECTION, g.toString(), g.getMbsc());
+        }
       }
     }
   }
@@ -127,18 +121,16 @@
   //               TreeSelectionListener              //
   //////////////////////////////////////////////////////
   public void valueChanged(TreeSelectionEvent e) {
-    //System.out.println("Value changed : e="+e);
     DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
     if (node!=null) {
-      String selectedNode=(String)node.getUserObject();
-      if (!selectedNode.equals(NodesTree.TOP_NAME)){
-        Object mbsc=connectedNodes.get(selectedNode);
-        if (mbsc!=null){
-	  //tryToConnectAllNodes();
-	  //createDefaultNodes(false);
-          a.firePropertyChangedEvent(Plugin.NEW_NODE_SELECTED, selectedNode, mbsc);
-        }else{
-          a.firePropertyChangedEvent(Plugin.EMPTY_NODE, null, "null");
+      Object selected = node.getUserObject();
+      if ( !selected.equals(NodesTree.TOP_NAME) ) {
+        Gateway g = (Gateway) selected;
+        Object mbsc = g.getMbsc();
+        if ( mbsc != null ){
+          activator.firePropertyChangedEvent(Plugin.NEW_NODE_SELECTED, g.toString(), mbsc);
+        } else {
+          activator.firePropertyChangedEvent(Plugin.EMPTY_NODE, null, "null");
         }
       }
     }
@@ -148,259 +140,199 @@
   //            NotificationListener                //
   ////////////////////////////////////////////////////
   public void handleNotification(Notification notification, Object handback) {
-    //    System.out.println("Connection ==> "+notification.getMessage()+":"+((JMXConnectionNotification)notification).getConnectionId()+":"+handback);
+    //System.out.println("Connection ==> "+notification.getMessage()+":"+((JMXConnectionNotification)notification).getConnectionId()+":"+handback);
     if ( !JMXConnectionNotification.OPENED.equals(notification.getType()) ){
-      this.disconnectFromNode((String)handback);
-      tree.treeDidChange();
-      isAllNodesConnected=false;
+      Enumeration enu = top.breadthFirstEnumeration();
+      enu.nextElement(); // Skip top node
+      while ( enu.hasMoreElements() ) {
+        Object o = ((DefaultMutableTreeNode) enu.nextElement()).getUserObject();
+	Gateway g = (Gateway) o;
+	if ( g.toString().equals(handback.toString()) ) {
+	  if ( g.isConnected() ) {
+	    g.disconnect(this);
+	    DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); 
+	    if ( selectedNode != null ) {
+	      Gateway g_selected = (Gateway) selectedNode.getUserObject();
+	      if ( g_selected.toString().equals(g.toString()) ) {
+	        activator.firePropertyChangedEvent(Plugin.EMPTY_NODE, null, "null");
+	      }
+	    }
+            tree.treeDidChange();
+            isAllNodesConnected = false;
+	  }
+	}
+      }
     }
   }
   
   ////////////////////////////////////////////////////
   //            Friend methods                      //
   ////////////////////////////////////////////////////
-  void stop(){ //Never used ... ???
-    this.cont=false;
+  void stop() {
+    this.cont = false;
   }
 
-  boolean isNodeConnected(String s){//Never used ... ???
-    if (this.connectedNodes.get(s)==null){
-      return false;
-    }else{
-      return true;
-    }
-  }
-
-  public void actionPerformed(ActionEvent e) {
-    // TODO : 
-    Object object = e.getSource();
-    if (object==addNodeButton) { // Add a new node into tree
-      String connString = JOptionPane.showInputDialog("Please input a connection string : ", "127.0.0.1:1099/vosgi");
-      TreePath tp=tree.getSelectionPath();
-      if (connString!=null) {
-	createTreeNode(connString,null,null);
-	dtm.reload(top);
-	isAllNodesConnected=false;
-	tree.setSelectionPath(tp);
+  public void actionPerformed(ActionEvent ae) {
+    Object object = ae.getSource();
+    if ( object == jb_addNode ) { // Add a new node into tree
+      Gateway g = Gateway.newGateway();
+      if ( g != null ) {
+        TreePath tp = tree.getSelectionPath();
+        this.createTreeNode(g);
+        dtm.reload(top);
+        isAllNodesConnected = false;
+        tree.setSelectionPath(tp);
       }
-    } else if (object==removeNodeButton) { // Remove a nod from tree
+    } else if ( object == jb_removeNode ) { // Remove a node from tree
       DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
-      String connString=(String) node.getUserObject();
-      if (connString!=null){
-        if (!node.equals(top)){
-	  if(JOptionPane.showConfirmDialog(null,"Sure we remove \""+connString+"\" node ?")==JOptionPane.YES_OPTION) {
-	    if (top.getChildCount()>1){
-              disconnectFromNode(connString);
-	      dtm.removeNodeFromParent(node);
-	      System.out.println("Remove node : "+(String) (node.getUserObject()));
-	    }
+      if ( node != top) {
+        Gateway g = (Gateway) node.getUserObject();
+        if ( !node.equals(top) ){
+	  if( JOptionPane.showConfirmDialog(null, "Sure we remove this gateway \""+g.getName()+"\" ?\n "+g.toString()) == JOptionPane.YES_OPTION ) {
+            g.disconnect(this);
+	    dtm.removeNodeFromParent(node);
+	    System.out.println("Remove node : "+g);
           }
 	}
       }
+    } else if ( object == jtf_pool) {
+      try {
+        POOLING_TIME = Integer.parseInt(jtf_pool.getText());
+	if ( POOLING_TIME > 0 & POOLING_TIME < 500 ) {
+          POOLING_TIME = 500;
+	} else if ( POOLING_TIME < 0 ) {
+	  POOLING_TIME = 0;
+	} else if ( POOLING_TIME > 9999 ) {
+          POOLING_TIME = 9999;
+	}
+      } catch (Exception exep) {
+        //
+      }
+      if ( POOLING_TIME >= 500 ) {
+        jb_refresh.setEnabled(false);
+      } else {
+        jb_refresh.setEnabled(true);
+      }
+      jtf_pool.setText(""+POOLING_TIME);
+    } else if ( object == jb_refresh) {
+      tryToConnectAllNodes();
     }
   }
 
   ///////////////////////////////////////////////////
   //           Private part                        //
   ///////////////////////////////////////////////////
-  protected void tryToConnectAllNodes(){
-    //boolean oldTreeState=isAllNodesConnected;
-    isAllNodesConnected=true;
-    String connString="";
-    Enumeration enu=top.breadthFirstEnumeration();
-    while (enu.hasMoreElements()) {
-      DefaultMutableTreeNode dmtn_tmp=(DefaultMutableTreeNode) enu.nextElement();
-      if (dmtn_tmp!=top) {
-        connString=(String) dmtn_tmp.getUserObject();
-        if (!this.connectToNode(connString)) {
-          isAllNodesConnected=false;
-        }
-      }
-    }
-    /*Enumeration dmtns_std=top.children();
-    while (dmtns_std.hasMoreElements()){
-      DefaultMutableTreeNode dmtn_std=(DefaultMutableTreeNode) dmtns_std.nextElement();
-      connString=(String) dmtn_std.getUserObject();
-      //System.out.println("   -connectToNode("+connString+")");
-      if (!this.connectToNode(connString)) {
-        isAllNodesConnected=false;
-      }
-      Enumeration dmtns_virtual=dmtn_std.children();
-      while (dmtns_virtual.hasMoreElements()){
-        DefaultMutableTreeNode dmtn_virtual=(DefaultMutableTreeNode) dmtns_virtual.nextElement();
-        connString=(String) dmtn_virtual.getUserObject();
-	//System.out.println("      -connectToNode("+connString+")");
-        if (!this.connectToNode(connString)) {
-          isAllNodesConnected=false;
-        }
-      }
-    }*/
-    //if(oldTreeState!=isAllNodesConnected){
-    //  System.out.println("AllNodesConnected="+isAllNodesConnected);
-    //}
-  }
-
-  private boolean connectToNode(String connString){
-    Object ls=this.connectedNodes.get(connString);
-    if (ls==null){
-      JMXConnector jmxc=null;
-      try {
-        JMXServiceURL surl=new JMXServiceURL(NodesTree.JMX_SERVICE_URL+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);
-	  // If new connected is the selected one then create a false valueChanged in order to load the NodePanel :
-	  DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(); 
-	  if (node!=null) {
-  	    if (connString.equals((String)node.getUserObject())){
-	      this.valueChanged(null);
-            }
-	  }
-	  System.out.println("Node "+connString+" connected");
-	  return true;
-        }else {
-          System.out.println("The Remote Logger of "+connString+" is not started");
-	  return false;
-        }
-      }catch(java.io.IOException ex){
-        //System.out.println("Impossible to connect to "+connString);
-      }catch(MalformedObjectNameException e){
-        e.printStackTrace();
-      }catch(Exception e){
-	//use one thread per node to avoid being freeze by a timeOutConnection
-	System.out.println("gui.NodesTree.connectToNode("+connString+") : "+e);
-	System.out.println("  => Delete this node ? to implement... ?");
-
-      }
-    }else{
-      return true;
-    }
-  return false;
-  }
-
-  protected class PoolingThread implements Runnable{
-    public void run(){
-      while (cont){
-        if (!isAllNodesConnected) {
-	  tryToConnectAllNodes();
+  private void tryToConnectAllNodes(){
+    isAllNodesConnected = true;
+    Enumeration enu = top.breadthFirstEnumeration();
+    enu.nextElement(); // Skip top node
+    while ( enu.hasMoreElements() ) {
+      Gateway g = (Gateway) (((DefaultMutableTreeNode) enu.nextElement()).getUserObject());
+      if ( !g.isConnected() ) {
+        if ( !g.connect(this) ) {
+          isAllNodesConnected = false;
+        } else {
           tree.treeDidChange();
-        } 
-	try{
-          Thread.sleep(POOLING_TIME);
-        }catch(InterruptedException e){
-          e.printStackTrace();
-        }
-      }
-    }
-  }
-
-  private void createTreeNode(String connString, String ip, String virtual){
-    System.out.println("Add a gateway : ip="+ip+" connString="+connString+" virtual="+virtual);
-    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);
-  }
-
-  protected void createDefaultNodes() {
-    String profile;
-    String rmiPort;
-    String ip;
-    int i=1;
-    profile=bc.getProperty("mosgi.jmxconsole.profile." + i);
-
-    while (profile!=null){
-      rmiPort=bc.getProperty("mosgi.jmxconsole.rmiport."+profile);
-      if (rmiPort==null) {rmiPort="1099";}
-      String virtual=bc.getProperty("mosgi.jmxconsole.core."+profile);
-      ip=bc.getProperty("mosgi.jmxconsole.ip."+i);
-      String connString=ip+":"+rmiPort+"/"+profile;
-      createTreeNode(connString, ip, virtual);
-      i++;
-      profile=bc.getProperty("mosgi.jmxconsole.profile." + i);
-    }
-
-    // Kesako ???
-    if (i==1){
-      try{
-        System.out.println("No property mosgi.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;
-        top.add(new DefaultMutableTreeNode(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);
-    System.out.println("mbscl="+mbscl);
-    if (jmxc!=null) {
-      try{
-        jmxc.removeConnectionNotificationListener(this);
-        //mbscl.removeNotificationListener(new ObjectName("OSGI:name=OSGi
-        // Server"), this); // Does not work since the connexion is lost !!
-        jmxc.close();
-
-        // firePCE Plugin.EMPTY_NODE only if it's the selected one
-        DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(); 
-        if (node!=null) {
-	  if (connString.equals((String)node.getUserObject())){
-            a.firePropertyChangedEvent(Plugin.EMPTY_NODE, null, "null");
+          activator.firePropertyChangedEvent(Plugin.NEW_NODE_CONNECTION, g.toString(), g.getMbsc());
+          // If new connected is the selected one then create a false valueChanged in order to load the NodePanel :
+          DefaultMutableTreeNode selected_node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
+          if ( selected_node != null &&  !selected_node.equals(top) ) {
+            Gateway g_selected = (Gateway) (selected_node.getUserObject());
+            if ( g_selected == g ) {
+	      this.valueChanged(null);
+	    } else {
+	    }
 	  }
-        }
-      }catch (Exception e){
-        e.printStackTrace();
+	}
       }
-      jmxc=null;
     }
-    mbscl=null;
   }
-     
+
+  private class PoolingThread implements Runnable {
+    public void run() {
+      while ( cont ) {
+        if ( !isAllNodesConnected && POOLING_TIME > 0 ) {
+	  tryToConnectAllNodes();
+        } 
+	try {
+          Thread.sleep(POOLING_TIME);
+        } catch(InterruptedException e) {
+          //e.printStackTrace();
+        }
+      }
+    }
+  }
+
+  protected static String getProtocolPackageProvider(String protoName) {
+    Object o = PROTOCOL_PACKAGE_PROVIDER.get(protoName);
+    if ( o != null) {
+      return (String) o;
+    } else {
+      String packages = bc.getProperty("mosgi.jmxconsole.protocol."+protoName+".package");
+      if ( packages == null ) {
+        packages = "";
+      }
+      System.out.println("Protocol provider package for \""+protoName+"\" = "+packages);
+      PROTOCOL_PACKAGE_PROVIDER.put(protoName, packages);
+      return packages;
+    }
+  }
+
+  private void createTreeNode(Gateway g) {
+    DefaultMutableTreeNode dmtn = new DefaultMutableTreeNode(g);
+    DefaultMutableTreeNode parentNode = null;
+    Gateway parent = g.getParent();
+    if ( parent != null ) {
+      Enumeration enu = top.breadthFirstEnumeration();
+      while ( enu.hasMoreElements() ) {
+        DefaultMutableTreeNode dmtn_tmp = (DefaultMutableTreeNode) enu.nextElement();
+        if ( dmtn_tmp.getUserObject().equals(parent) ) {
+          parentNode = dmtn_tmp;
+          break;
+        }
+      }
+    }
+    if ( parentNode == null ) { parentNode = top; }
+    parentNode.add(dmtn);
+  }
+
   private JPanel createButtonPanel(){
-    JPanel buttonPanel=new JPanel(new FlowLayout(FlowLayout.CENTER,2,2));
+    JPanel buttonPanel = new JPanel();
+    buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
     //border...
-    addNodeButton=new MyButton('a', " + ", this, buttonPanel);
-    removeNodeButton=new MyButton('d', " - ", this, buttonPanel);
+    buttonPanel.add(Box.createHorizontalGlue());
+    jb_addNode = new MyButton('a', "ADD.gif", "Add a gateway", this, buttonPanel);
+    buttonPanel.add(Box.createRigidArea(new Dimension(2,0)));
+    jb_removeNode = new MyButton('d', "REMOVE.gif", "Remove selected gateway", this, buttonPanel);
+    buttonPanel.add(Box.createHorizontalGlue());
+    buttonPanel.add(Box.createRigidArea(new Dimension(2,0)));
+    buttonPanel.add(Box.createHorizontalGlue());
+    jtf_pool = new JTextField(""+POOLING_TIME);
+    jtf_pool.addActionListener(this);
+    jtf_pool.setToolTipText("<html>Pooling time in millisecond<br>Value range is 500 to 9999<br>A value of 0 means no refresh.</html>");
+    jtf_pool.setPreferredSize(new Dimension(40,21));
+    jtf_pool.setMaximumSize(new Dimension(40,21));
+    buttonPanel.add(jtf_pool);
+    buttonPanel.add(Box.createRigidArea(new Dimension(2,0)));
+    jb_refresh = new JButton(new ImageIcon(Toolkit.getDefaultToolkit().getImage(bc.getBundle().getResource("images/"+"REFRESH.gif"))));
+    jb_refresh.setOpaque(true);
+    jb_refresh.setToolTipText("<html>Try to connect gateways now.<br>Enable only if there is no pooling time.</html>");
+    jb_refresh.addActionListener(this);
+    jb_refresh.setPreferredSize(new Dimension(18, 18));
+    jb_refresh.setEnabled(false);
+    buttonPanel.add(jb_refresh);
+    buttonPanel.add(Box.createHorizontalGlue());
     return buttonPanel;
   }
 
   static class MyButton extends JButton {
-    private int W =55;
-    private int H = 25;
-
-    public MyButton(char c, String name, NodesTree listener, JPanel panel) {
-      super.setText(name);
+    private final int W = 18, H = 18;
+    public MyButton(char c, String iconName, String ttt, NodesTree listener, JPanel panel) {
+      super(new ImageIcon(Toolkit.getDefaultToolkit().getImage(bc.getBundle().getResource("images/"+iconName))));
       super.setMnemonic(c);
-      super.setMinimumSize(new Dimension(W, H));
+      super.setToolTipText(ttt);
+      super.setBorder(null);
       super.setPreferredSize(new Dimension(W, H));
-      super.setMaximumSize(new Dimension(W, H));
       super.addActionListener(listener);
       panel.add(this);
     }
diff --git a/mosgi/console.gui/src/main/resources/images/ADD.gif b/mosgi/console.gui/src/main/resources/images/ADD.gif
new file mode 100644
index 0000000..c9dbc3d
--- /dev/null
+++ b/mosgi/console.gui/src/main/resources/images/ADD.gif
Binary files differ
diff --git a/mosgi/console.gui/src/main/resources/images/REFRESH.gif b/mosgi/console.gui/src/main/resources/images/REFRESH.gif
new file mode 100644
index 0000000..788fb75
--- /dev/null
+++ b/mosgi/console.gui/src/main/resources/images/REFRESH.gif
Binary files differ
diff --git a/mosgi/console.gui/src/main/resources/images/REMOVE.gif b/mosgi/console.gui/src/main/resources/images/REMOVE.gif
new file mode 100644
index 0000000..13f9a79
--- /dev/null
+++ b/mosgi/console.gui/src/main/resources/images/REMOVE.gif
Binary files differ
diff --git a/mosgi/doc/config.properties.core b/mosgi/doc/config.properties.core
index 61caaa4..782170d 100644
--- a/mosgi/doc/config.properties.core
+++ b/mosgi/doc/config.properties.core
@@ -1,4 +1,5 @@
 felix.cache.profile=core
+mosgi.jmxconsole.rmiport.core=1099
 
 #
 # Framework config properties.
@@ -39,7 +40,6 @@
 mosgi.jmxconsole.tab.url.memoryprobetab=http://perso.citi.insa-lyon.fr/sfrenot/devel/mosgi/managedelements/trunk/mosgi.managedelements.memoryprobe.tab/target/org.apache.felix.mosgi.managedelements.memoryprobe.tab-0.8.0-SNAPSHOT.jar
 mosgi.jmxconsole.tab.url.linuxprobestab=http://perso.citi.insa-lyon.fr/sfrenot/devel/mosgi/managedelements/trunk/mosgi.managedelements.linuxprobes.tab/target/org.apache.felix.mosgi.managedelements.linuxprobes.tab-0.8.0-SNAPSHOT.jar
 
-#mosgi.jmxconsole.rmiport.core=1100
 
 felix.startlevel.framework=1
 felix.startlevel.bundle=1
diff --git a/mosgi/doc/config.properties.jmxconsole b/mosgi/doc/config.properties.jmxconsole
index 97da86b..ec7bb55 100644
--- a/mosgi/doc/config.properties.jmxconsole
+++ b/mosgi/doc/config.properties.jmxconsole
@@ -20,16 +20,32 @@
  file:../mosgi/console.gui/target/org.apache.felix.mosgi.console.gui-0.9.0-SNAPSHOT.jar \
  file:../mosgi/console.component/target/org.apache.felix.mosgi.console.component-0.9.0-SNAPSHOT.jar
 
+# file:/home/dni/gforge/mosgi/tosgi/src/murmi/target/fr.inria.amazones.murmi-0.1.jar \
+# file:/home/dni/gforge/mosgi/ws/src/ws/target/fr.inria.amazones.ws-0.1.jar \
+
 #possible values : both treeonly tableonly none (default=both)
 mosgi.jmxconsole.remotelogger.componentfilter=both
 
-mosgi.jmxconsole.ip.1=127.0.0.1
-mosgi.jmxconsole.profile.1=core
-#mosgi.jmxconsole.rmiport.core=1100
+mosgi.jmxconsole.protocol.murmi.package=fr.inria.amazones.remote.provider
+mosgi.jmxconsole.protocol.ws.package=fr.inria.amazones.remote.provider
 
-#mosgi.jmxconsole.ip.2=127.0.0.1
-#mosgi.jmxconsole.profile.2=core2
-#mosgi.jmxconsole.rmiport.core2=1200
+# OLD :
+# mosgi.jmxconsole.ip.1=127.0.0.1
+# mosgi.jmxconsole.profile.1=core
+# mosgi.jmxconsole.rmiport.core=1099
+
+# NEW :
+mosgi.jmxconsole.id.1.nickname=main
+mosgi.jmxconsole.id.1.profile=core
+mosgi.jmxconsole.id.1.host=127.0.0.1
+mosgi.jmxconsole.id.1.protocol=rmi
+mosgi.jmxconsole.id.1.port=1099
+#mosgi.jmxconsole.id.1.jmxserviceurl=service:jmx:rmi:///jndi/rmi://127.0.0.1:1099/core
+
+mosgi.jmxconsole.id.2.profile=core2
+mosgi.jmxconsole.id.2.host=127.0.0.1
+mosgi.jmxconsole.id.2.protocol=rmi
+mosgi.jmxconsole.id.2.port=1100
 
 felix.startlevel.framework=1
 felix.startlevel.bundle=1
@@ -230,6 +246,9 @@
  version="1.4.0"
 
 jre-1.5=, \
+ org.apache.log.output.io; \
+ javax.servlet; \
+ javax.management.remote; \
  javax.accessibility; \
  javax.activity; \
  javax.imageio; \
diff --git a/mosgi/doc/core.sh b/mosgi/doc/core.sh
index 371e96d..ec22190 100755
--- a/mosgi/doc/core.sh
+++ b/mosgi/doc/core.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
-
+rm -rf ~/.felix/core
 
 echo "cd into felix directory"
 cd ../../main
diff --git a/mosgi/doc/jmxconsole.sh b/mosgi/doc/jmxconsole.sh
index 4f8ca9c..f4b5bf7 100755
--- a/mosgi/doc/jmxconsole.sh
+++ b/mosgi/doc/jmxconsole.sh
@@ -1,4 +1,6 @@
 #!/bin/sh
+rm -rf ~/.felix/jmxconsole
+
 echo "cd into felix directory"
 cd ../../main
 
diff --git a/mosgi/managedelements.bundlesprobes.tab/src/main/java/org/apache/felix/mosgi/managedelements/bundlesprobes/tab/BundlesProbesModelTabUI.java b/mosgi/managedelements.bundlesprobes.tab/src/main/java/org/apache/felix/mosgi/managedelements/bundlesprobes/tab/BundlesProbesModelTabUI.java
index 5a064f3..71ba253 100644
--- a/mosgi/managedelements.bundlesprobes.tab/src/main/java/org/apache/felix/mosgi/managedelements/bundlesprobes/tab/BundlesProbesModelTabUI.java
+++ b/mosgi/managedelements.bundlesprobes.tab/src/main/java/org/apache/felix/mosgi/managedelements/bundlesprobes/tab/BundlesProbesModelTabUI.java
@@ -128,11 +128,11 @@
     if (this.mbsc!=null){

       try{

         mbsc.removeNotificationListener(this.osgiON, this);

-        this.mbsc=null;

-        this.removeAll();

       }catch(Exception e){

         e.printStackTrace();

       }

+      this.mbsc=null;

+      this.removeAll();

     }

   }