FELIX-151

Improve remote logger panel whith colored jtree and jtable



git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@448510 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/mosgi.console.component/pom.xml b/mosgi.console.component/pom.xml
index 9a3ecd5..4397381 100644
--- a/mosgi.console.component/pom.xml
+++ b/mosgi.console.component/pom.xml
@@ -43,7 +43,8 @@
 						  javax.management;specification-version="1.0.0",
 						  javax.swing;specification-version="1.0.0",
 						  javax.swing.table;specification-version="1.0.0",
-						  org.osgi.framework;specification-version="1.0.0"
+						  org.osgi.framework;specification-version="1.0.0",
+						  javax.swing.tree;specification-version="1.0.0"
 						</importPackage>
           </osgiManifest>
         </configuration>
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 94b1d81..9530341 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
@@ -1,45 +1,57 @@
-/* 
- * 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.    
-*/
+/*
+ *   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.component;
 
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.apache.felix.mosgi.console.ifc.CommonPlugin;
+import java.lang.String;
 
-public class Activator implements BundleActivator
-{
-    private BundleContext m_context = null;
+public class Activator implements BundleActivator {
+  
+  public void start(BundleContext context) throws Exception{ 
+    String propVal=new String("both");
+    String propValue=context.getProperty("mosgi.jmxconsole.remotelogger.componentfilter");
+    if (propValue!=null) {
+      if (propValue.equals("treeonly") | propValue.equals("tableonly") | propValue.equals("both") | propValue.equals("none")) {
+        propVal=propValue;
+      }else {
+        propVal="both";
+      }
+    }
 
-    public void start(BundleContext context) throws Exception
-    {
-        m_context = context;
-        m_context.registerService( CommonPlugin.class.getName(), new RemoteLogger(), null);
+    if (propVal.equals("treeonly") | propVal.equals("both")) {
+      context.registerService(CommonPlugin.class.getName(), new RemoteLogger_jtree(context), null);
+    }
+    if (propVal.equals("tableonly") | propVal.equals("both")) {
+      context.registerService(CommonPlugin.class.getName(), new RemoteLogger_jtable(), null);
+    }
+  }
+
+  public void stop(BundleContext context) {
+  }
+
 //        m_context.registerService( Plugin.class.getName(), new NodeDetails(), null);
 //        m_context.registerService( Plugin.class.getName(), new BundleListPanel(), null);
-
+//
 //        m_context.registerService( CommonPlugin.class.getName(), new OBRPlugin(context), null);
-
-        //        m_context.registerService( Plugin.class.getName(), new MemoryLauncher(context), null);
+//
+//        m_context.registerService( Plugin.class.getName(), new MemoryLauncher(context), null);
 //        m_context.registerService( Plugin.class.getName(), new LinuxDetails(), null);
-    }
+//
 
-    public void stop(BundleContext context)
-    {
-    }
 }
diff --git a/mosgi.console.component/src/main/java/org/apache/felix/mosgi/console/component/JtableCellRenderer.java b/mosgi.console.component/src/main/java/org/apache/felix/mosgi/console/component/JtableCellRenderer.java
new file mode 100644
index 0000000..2d95879
--- /dev/null
+++ b/mosgi.console.component/src/main/java/org/apache/felix/mosgi/console/component/JtableCellRenderer.java
@@ -0,0 +1,60 @@
+/*
+ *   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.component;
+
+import org.osgi.framework.Bundle;
+
+import java.util.Hashtable;
+import java.awt.Color;
+import javax.swing.JTable;
+import javax.swing.JLabel;
+import javax.swing.table.TableCellRenderer;
+import java.awt.Component;
+
+public class JtableCellRenderer extends JLabel implements TableCellRenderer {
+
+  private Hashtable eventName=new Hashtable();
+
+  public JtableCellRenderer() {
+    super();
+    eventName.put(new Integer( Bundle.ACTIVE      ), Color.green  );
+    eventName.put(new Integer( Bundle.INSTALLED   ), Color.orange );
+    eventName.put(new Integer( Bundle.RESOLVED    ), Color.red    );
+    eventName.put(new Integer( Bundle.STARTING    ), Color.gray   );
+    eventName.put(new Integer( Bundle.STOPPING    ), Color.gray   );
+    eventName.put(new Integer( Bundle.UNINSTALLED ), Color.black  );
+  }
+
+  public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
+  						 boolean hasFocus, int row, int column) {
+    setOpaque(true);
+    if (column==0){
+      Integer state;
+      try{
+        state=new Integer(Integer.parseInt((String) table.getValueAt(row,5)));
+      }catch (NumberFormatException nfe) {
+        state=new Integer(-1);
+      }
+      setBackground((Color) eventName.get(state));
+    }
+    setText((String) value);
+
+    return this;
+  }	
+
+}
diff --git a/mosgi.console.component/src/main/java/org/apache/felix/mosgi/console/component/JtreeCellRenderer.java b/mosgi.console.component/src/main/java/org/apache/felix/mosgi/console/component/JtreeCellRenderer.java
new file mode 100644
index 0000000..d6c33d9
--- /dev/null
+++ b/mosgi.console.component/src/main/java/org/apache/felix/mosgi/console/component/JtreeCellRenderer.java
@@ -0,0 +1,101 @@
+/*
+ *   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.component;
+
+import org.osgi.framework.BundleContext;
+
+import java.awt.Color;
+import javax.swing.JTree;
+import javax.swing.JLabel;
+import java.util.StringTokenizer;
+
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.TreeCellRenderer;
+import java.awt.Component;
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.awt.Graphics;
+import java.util.NoSuchElementException;
+import java.awt.Font;
+import java.awt.Dimension;
+
+import javax.swing.ImageIcon;
+import java.awt.Toolkit;
+
+public class JtreeCellRenderer extends DefaultTreeCellRenderer {
+
+  private boolean isLeaf=false;
+  //private int maxL;
+
+  private String[] states=new String[]{"ACTIVE","INSTALLED","RESOLVED","STARTING","STOPPING","UNINSTALLED"};
+  private Color[] colors=new Color[]{Color.green,Color.orange,Color.red,Color.white,Color.white,Color.black};
+  private ImageIcon[] ii=new ImageIcon[6];
+
+  public JtreeCellRenderer(BundleContext bdlCtx){
+    for (int i=0 ; i<states.length ; i++){
+      this.ii[i]=new ImageIcon(Toolkit.getDefaultToolkit().getImage(bdlCtx.getBundle().getResource("icons/"+states[i]+".gif")));
+    }
+  }
+
+  public Dimension getPreferredSize() {
+    Dimension dim = super.getPreferredSize();
+    //maxL=(isLeaf)?Math.max(maxL,dim.width):maxL;
+    //
+    return (isLeaf)?dim:new Dimension(800/*maxL*/,dim.height);
+  }
+
+  public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
+    this.isLeaf=leaf;
+
+    super.getTreeCellRendererComponent(tree,value,sel,expanded,leaf,row,hasFocus);
+    setOpaque(true);
+    setBackground(Color.white);
+    setFont(new Font("Monospaced",Font.BOLD,12));
+
+    StringTokenizer st=null;
+    DefaultMutableTreeNode dmtn=(DefaultMutableTreeNode)value;
+    int lvl=dmtn.getLevel(); 
+    if(lvl==3 & dmtn.getChildCount()>0){
+      st=new StringTokenizer(dmtn.getFirstChild().toString()," | ");
+    }
+    if (lvl==4){
+      st=new StringTokenizer(dmtn.toString()," | ");
+    }
+
+    if(st!=null){
+      st.nextToken();
+      st.nextToken();
+      String state=st.nextToken();
+      for (int i=0 ; i<states.length ; i++){
+        if (state.equals(states[i])){
+          if (lvl==4){
+            setIcon(ii[i]);
+	    setFont(new Font("Monospaced",Font.PLAIN,10));
+          }else{ 
+            StringTokenizer st2 = new StringTokenizer(((DefaultMutableTreeNode)dmtn.getFirstChild()).toString()," | ");
+            setToolTipText("<html><B>IP = </B>"+/*IP=<ip> Profil=<port>/<profil>*/dmtn.getParent().getParent()+"<B> Profil =</B>"+dmtn.getParent()+"<br><B>Bundle : </B>"+/*Bundle : Id=<bundleId> : <bundleSymbolicName>*/dmtn+"<br><B>Date : </B>"+/*<date> - <time>*/st2.nextToken()+" - "+st2.nextToken()+"<br><B>State : </B>"+/*<bundleState>*/st2.nextToken()+"<B><br>Event "+/*Event <eventNumber> : <logLevel> : <message>*/dmtn.getChildCount()+" : "+st2.nextToken()+" : "+st2.nextToken()+"</B></html>");
+            setBackground(colors[i]);
+          }
+	break;
+        }
+      }
+    }	
+	
+    return this;
+  }	
+
+}
diff --git a/mosgi.console.component/src/main/java/org/apache/felix/mosgi/console/component/MyTree.java b/mosgi.console.component/src/main/java/org/apache/felix/mosgi/console/component/MyTree.java
new file mode 100644
index 0000000..4157140
--- /dev/null
+++ b/mosgi.console.component/src/main/java/org/apache/felix/mosgi/console/component/MyTree.java
@@ -0,0 +1,48 @@
+/*
+ *   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.component;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.ToolTipManager;
+import javax.swing.UIManager;
+
+public class MyTree extends JTree{
+
+  public MyTree(DefaultTreeModel dtm){
+    super(dtm);
+    //setRowHeight(0); // so DefaultTreeModel.getPreferedSize() is always call
+    ToolTipManager.sharedInstance().registerComponent(this);
+    ToolTipManager.sharedInstance().setInitialDelay(700);
+    ToolTipManager.sharedInstance().setDismissDelay(7000);
+    //ToolTipManager.setReshownDelay();
+    //ToolTipManager.setEnabled();
+  }
+
+  public String convertValueToText(Object value,boolean selected,boolean expanded,boolean leaf,int row,boolean hasFocus){
+    DefaultMutableTreeNode dmtn=(DefaultMutableTreeNode) value;
+      if (dmtn.getLevel()==3) {
+        int childNumber=dmtn.getChildCount();
+        //String lastMsg=new String((childNumber==0)?"":dmtn.getFirstChild().toString());
+        return value.toString()+" ("+dmtn.getChildCount()+" events)";//+lastMsg;
+      }else{
+        return value.toString();
+      }
+  }
+
+}
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
new file mode 100644
index 0000000..38318a1
--- /dev/null
+++ b/mosgi.console.component/src/main/java/org/apache/felix/mosgi/console/component/RemoteLogger_jtable.java
@@ -0,0 +1,184 @@
+/*
+ *   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.component;
+
+import org.apache.felix.mosgi.console.ifc.CommonPlugin;
+import org.apache.felix.mosgi.console.ifc.Plugin;
+//import org.apache.felix.mosgi.console.component.JtableCellRenderer;
+
+import javax.swing.table.DefaultTableModel;
+import javax.swing.JTable;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import java.awt.Component;
+
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.MBeanServerConnection;
+import javax.swing.ListSelectionModel;
+
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+import java.beans.PropertyChangeEvent;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.util.Vector;
+
+import java.io.PrintStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import javax.swing.JFileChooser;
+		
+import java.util.Date;
+import java.text.DateFormat;
+//import java.text.SimpleDateFormat;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.tree.DefaultMutableTreeNode;
+
+public class RemoteLogger_jtable extends DefaultTableModel implements CommonPlugin, NotificationListener{
+
+  private JTable logList;
+  private JButton jb_save;
+  private JPanel jbPanel;
+  private JPanel jp;
+  private Hashtable nodes=new Hashtable();
+
+  public void jb_actionPerformed(ActionEvent e) {
+    String compoName=((Component) e.getSource()).getName();
+	
+    if (compoName.equals("jb_save")){
+      PrintStream ps=System.out;
+      JFileChooser jfc=new JFileChooser();
+      if (jfc.showSaveDialog(null)==JFileChooser.APPROVE_OPTION & jfc.getSelectedFile()!=null){	
+      try{
+        ps=new PrintStream(jfc.getSelectedFile());
+        System.out.println("Save remote log into \""+jfc.getSelectedFile().getName()+"\""); }
+      catch (FileNotFoundException fnfe){
+        System.out.println("err : "+fnfe); }
+      }
+      int col=this.logList.getColumnCount(); // TODO : try this.getColumnCount()
+      int line=this.logList.getRowCount() - 1; // last line always empty
+      //ps.print(col+" "+line);
+      Vector tableData=new Vector();
+      tableData=this.getDataVector();
+      for (int i=0 ; i<line ; i++){
+        ps.print(i+" : ");
+        for (int j=0 ; j<col ; j++){
+	  ps.print((String) ( ((Vector) (tableData.elementAt(i))).elementAt(j) )+" | ");	
+        }
+        ps.print("\n");
+      }
+    }
+  }
+
+  public RemoteLogger_jtable (){
+    super(new String[]{"Date","Time", "Src", "Id", "Name", "State", "Lvl", "Msg"},1);
+    System.out.println("JTable Remote logger");
+   
+    this.jp=new JPanel();
+    this.jp.setLayout(new BorderLayout());
+   
+    this.jbPanel=new JPanel();
+    this.jbPanel.setSize(300,25);
+
+    this.jb_save=new JButton("Save log on file");
+    this.jb_save.setName("jb_save");
+
+    ActionListener al = new ActionListener(){
+        public void actionPerformed(ActionEvent e){
+            jb_actionPerformed(e);
+        }
+    };
+    this.jb_save.addActionListener(al);
+
+    logList=new JTable(this);
+    JtableCellRenderer cellRenderer=new JtableCellRenderer();
+    logList.setDefaultRenderer(Object.class,cellRenderer);
+
+    logList.setPreferredScrollableViewportSize(new java.awt.Dimension(600, 70));
+    
+    logList.getColumnModel().getColumn(0).setPreferredWidth(50);
+    logList.getColumnModel().getColumn(1).setPreferredWidth(40);
+    logList.getColumnModel().getColumn(2).setPreferredWidth(120);
+    logList.getColumnModel().getColumn(3).setPreferredWidth(15);
+    logList.getColumnModel().getColumn(4).setPreferredWidth(70);
+    logList.getColumnModel().getColumn(5).setPreferredWidth(15);
+    logList.getColumnModel().getColumn(6).setPreferredWidth(40);
+    logList.getColumnModel().getColumn(7).setPreferredWidth(180);    
+
+    logList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+    logList.getTableHeader().setReorderingAllowed(true);//false); // true c'est sympa pourtant... ?
+    
+    this.jbPanel.add(jb_save);
+    jp.add(this.jbPanel, BorderLayout.NORTH);
+    jp.add(new JScrollPane(logList), BorderLayout.CENTER);    
+  }
+
+  /////////////////////////////////////
+  //  Plugin Interface ////////////////
+  /////////////////////////////////////
+  public String getName(){ return "JTable Remote Logger";}
+  public Component getGUI(){return this.jp;}
+
+/* a supprimer si on enleve l'heritage CommonPlugin -> Plugin */
+  public String pluginLocation(){
+    return null;
+  }
+  public void registerServicePlugin(){}
+  public void unregisterServicePlugin(){}
+/* fin a supprimer */
+
+  
+  public void propertyChange(PropertyChangeEvent e){
+    if (e.getPropertyName().equals(Plugin.NEW_NODE_CONNECTION)){
+      try{
+        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());
+          nodes.put(mbs, "ok");
+        }
+      }catch(Exception ex){
+        ex.printStackTrace();
+      }
+    }
+  }
+
+  public void handleNotification(Notification notification, Object handback) {
+    StringTokenizer st = new StringTokenizer(notification.getMessage(),":");
+    Date d=new Date(notification.getTimeStamp());
+    //DateFormat dateFormat = new SimpleDateFormat("hh'h'mm dd-MM-yy");
+    DateFormat df = DateFormat.getTimeInstance(DateFormat.MEDIUM); // utilise le format de date local
+    DateFormat df2 = DateFormat.getDateInstance(DateFormat.SHORT);
+    String id=st.nextToken();
+    String name=st.nextToken();
+    String shortName=name.substring(name.lastIndexOf(".")+1,name.length());
+    String state=st.nextToken();
+    String lvl=st.nextToken();
+    String msg=st.nextToken();
+    Object [] event = new Object []{df2.format(d),df.format(d),handback,id,shortName,state,lvl,msg};
+				    
+    this.insertRow(0,event); 
+    this.fireTableRowsInserted(0, 0);
+  }
+  
+}
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
new file mode 100644
index 0000000..a7a5863
--- /dev/null
+++ b/mosgi.console.component/src/main/java/org/apache/felix/mosgi/console/component/RemoteLogger_jtree.java
@@ -0,0 +1,187 @@
+/*
+ *   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.component;
+
+import org.apache.felix.mosgi.console.ifc.CommonPlugin;
+import org.apache.felix.mosgi.console.ifc.Plugin;
+//import org.apache.felix.mosgi.console.component.JtreeCellRenderer;
+import org.apache.felix.mosgi.console.component.MyTree;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Bundle;
+
+import javax.swing.table.DefaultTableModel;
+import javax.swing.JTable;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import java.awt.Component;
+
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.MBeanServerConnection;
+import javax.swing.ListSelectionModel;
+
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+import java.beans.PropertyChangeEvent;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.util.Vector;
+
+import java.io.PrintStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import javax.swing.JFileChooser;
+		
+import java.util.Date;
+import java.text.DateFormat;
+//import java.text.SimpleDateFormat;
+
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.JFrame;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreePath;
+
+//import org.osgi.service.prefs.Preferences;
+
+public class RemoteLogger_jtree extends DefaultTreeModel implements CommonPlugin, NotificationListener{
+
+  private MyTree logTree;
+  private JPanel jp;
+  private Hashtable nodes=new Hashtable();
+  private DefaultMutableTreeNode rootNode=new DefaultMutableTreeNode("root");
+  private Hashtable eventName=new Hashtable();
+
+  public RemoteLogger_jtree (BundleContext bdlCtx){
+    super(null);
+    setRoot(rootNode);
+    System.out.println("JTree Remote logger"); 
+
+    this.jp=new JPanel();
+    this.jp.setLayout(new BorderLayout());
+   
+    this.logTree=new MyTree(this);
+    JtreeCellRenderer treeCellRenderer=new JtreeCellRenderer(bdlCtx);
+    this.logTree.setCellRenderer(treeCellRenderer);
+    this.logTree.setLargeModel(true);
+    this.logTree.setToggleClickCount(1); 
+    this.logTree.setRootVisible(false);
+    // this create an invisible tree even if I use *expand* so...
+    // I use expand after the first insert into the tree
+  
+    jp.add(new JScrollPane(logTree), BorderLayout.CENTER);    
+    
+    eventName.put(new Integer(Bundle.ACTIVE),     "ACTIVE     ");
+    eventName.put(new Integer(Bundle.INSTALLED),  "INSTALLED  ");
+    eventName.put(new Integer(Bundle.RESOLVED),   "RESOLVED   ");
+    eventName.put(new Integer(Bundle.STARTING),   "STARTING   ");
+    eventName.put(new Integer(Bundle.STOPPING),   "STOPPING   ");
+    eventName.put(new Integer(Bundle.UNINSTALLED),"UNINSTALLED");
+  }
+
+  /////////////////////////////////////
+  //  Plugin Interface ////////////////
+  /////////////////////////////////////
+  public String getName(){ return "JTree Remote Logger";}
+  public Component getGUI(){return this.jp;}
+
+/* a supprimer si on enleve l'heritage CommonPlugin -> Plugin */
+  public String pluginLocation(){
+    return null;
+  }
+  public void registerServicePlugin(){}
+  public void unregisterServicePlugin(){}
+/* fin a supprimer */
+
+  
+  public void propertyChange(PropertyChangeEvent e){
+    if (e.getPropertyName().equals(Plugin.NEW_NODE_CONNECTION)){
+      try{
+        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());
+          nodes.put(mbs, "ok");
+        }
+      }catch(Exception ex){
+        ex.printStackTrace();
+      }
+    }
+  }
+
+  private DefaultMutableTreeNode createIfNeed(String nodeToCreateAndGet, DefaultMutableTreeNode parent){
+    int childNumber=this.getChildCount(parent);
+    DefaultMutableTreeNode theNode=null;
+    for (int i=0 ; i<childNumber ; i++){ // is node even exist ?
+      String string_pool=((DefaultMutableTreeNode)(this.getChild(parent, i))).toString();
+      if (string_pool.equals(nodeToCreateAndGet)){
+        theNode=(DefaultMutableTreeNode) (this.getChild(parent, i));
+          break;
+      }
+    }
+    if (theNode==null){ // create the node
+      theNode=new DefaultMutableTreeNode(nodeToCreateAndGet);	
+      // Unable to set tree expand whithout a first node
+      if (rootNode.getChildCount()==0){
+        this.insertNodeInto(theNode, parent, 0);
+        logTree.expandPath(new TreePath(rootNode.getPath()));
+      }else{
+        this.insertNodeInto(theNode, parent, 0);
+      }
+    }
+  return theNode;
+  }
+
+  public void handleNotification(Notification notification, Object handback) {
+    StringTokenizer st=new StringTokenizer(handback.toString(),":");
+    String ip=st.nextToken();
+    String ref=st.nextToken();
+    
+    st = new StringTokenizer(notification.getMessage(),":");
+    Date timeDate=new Date(notification.getTimeStamp());
+    //DateFormat dateFormat = new SimpleDateFormat("hh'h'mm dd-MM-yy");
+    DateFormat df = DateFormat.getTimeInstance(DateFormat.MEDIUM); // use local date format 
+    DateFormat df2 = DateFormat.getDateInstance(DateFormat.SHORT);
+    String time=df.format(timeDate);
+    String date=df2.format(timeDate);
+
+    String id=st.nextToken();
+    String name=st.nextToken();
+    String idname=new String(id+" : "+name);
+    String state=""+eventName.get(new Integer((int) Integer.parseInt(st.nextToken())));
+    String lvl=st.nextToken();
+    String msg=st.nextToken();
+
+    // Get and maybe create parents nodes : ip, ref, idname
+    DefaultMutableTreeNode dmtn_ip=createIfNeed(ip, rootNode);
+    DefaultMutableTreeNode dmtn_ref=createIfNeed(ref, dmtn_ip);
+    DefaultMutableTreeNode dmtn_idname=createIfNeed(idname, dmtn_ref);
+
+    // insert the leaf with message under id/ref/idname
+    DefaultMutableTreeNode dmtn=new DefaultMutableTreeNode(date+" | "+time+" | "+state+" | "+lvl+" | "+msg,false); 
+    this.insertNodeInto(dmtn, dmtn_idname, 0);
+
+    this.reload(dmtn_idname);
+    }
+  
+}
diff --git a/mosgi.console.component/src/main/resources/icons/ACTIVE.gif b/mosgi.console.component/src/main/resources/icons/ACTIVE.gif
new file mode 100644
index 0000000..e4747bb
--- /dev/null
+++ b/mosgi.console.component/src/main/resources/icons/ACTIVE.gif
Binary files differ
diff --git a/mosgi.console.component/src/main/resources/icons/INSTALLED.gif b/mosgi.console.component/src/main/resources/icons/INSTALLED.gif
new file mode 100644
index 0000000..eba380d
--- /dev/null
+++ b/mosgi.console.component/src/main/resources/icons/INSTALLED.gif
Binary files differ
diff --git a/mosgi.console.component/src/main/resources/icons/RESOLVED.gif b/mosgi.console.component/src/main/resources/icons/RESOLVED.gif
new file mode 100644
index 0000000..9ec50f6
--- /dev/null
+++ b/mosgi.console.component/src/main/resources/icons/RESOLVED.gif
Binary files differ
diff --git a/mosgi.console.component/src/main/resources/icons/STARTING.gif b/mosgi.console.component/src/main/resources/icons/STARTING.gif
new file mode 100644
index 0000000..8c20575
--- /dev/null
+++ b/mosgi.console.component/src/main/resources/icons/STARTING.gif
Binary files differ
diff --git a/mosgi.console.component/src/main/resources/icons/STOPPING.gif b/mosgi.console.component/src/main/resources/icons/STOPPING.gif
new file mode 100644
index 0000000..8c20575
--- /dev/null
+++ b/mosgi.console.component/src/main/resources/icons/STOPPING.gif
Binary files differ
diff --git a/mosgi.console.component/src/main/resources/icons/UNINSTALLED.gif b/mosgi.console.component/src/main/resources/icons/UNINSTALLED.gif
new file mode 100644
index 0000000..69368e4
--- /dev/null
+++ b/mosgi.console.component/src/main/resources/icons/UNINSTALLED.gif
Binary files differ
diff --git a/mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/Activator.java b/mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/Activator.java
index 68c1cff..f455f5d 100644
--- a/mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/Activator.java
+++ b/mosgi.console.gui/src/main/java/org/apache/felix/mosgi/console/gui/Activator.java
@@ -38,6 +38,10 @@
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.InvalidSyntaxException;
 
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+
 public class Activator implements BundleActivator {
   protected BundleContext m_context = null;
   protected ArrayList m_pluginList = null;
@@ -61,161 +65,165 @@
         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()+"))");
+          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);
         }
-        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);
+      }
+    };
+    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);
     }
 
-    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);
-            }
+    // 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);
+      m_frame.setIconImage(Toolkit.getDefaultToolkit().getImage(m_context.getBundle().getResource("images/logo.gif")));
+      //m_frame.setResizable(false);
+      //m_frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+      //add a windowListener to save screen size preference
+      m_frame.addWindowListener(new WindowAdapter() {
+        public void windowClosing(WindowEvent we) {
+          JFrame jf=(JFrame) we.getWindow();
+          System.out.println(" Console.gui : window closing ("+jf.getSize().height+"*"+jf.getSize().width+")");
+        }
+        public void windowClosed(WindowEvent we) {
+          JFrame jf=(JFrame) we.getWindow();
+          System.out.println(" Console.gui : window closed ("+jf.getSize().height+"*"+jf.getSize().width+")");
+        }
+      });
+	    
+      //Dimension wndSize = m_frame.getToolkit().getScreenSize();
+      //m_frame.setBounds(wndSize.width / 8, wndSize.height / 8, 1000, 700);
+      Dimension maxdim = m_frame.getToolkit().getScreenSize();
+      int m_width=maxdim.width-100;
+      int m_height=maxdim.height-100;
+      m_frame.setBounds( (int) ((maxdim.width-m_width)/2), 20, m_width, m_height);
+           
+      //Right panel
+      JSplitPane rightSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new NodePanel(this, context) , new CommonPanel(this));
+      rightSplitPane.setOneTouchExpandable(true);
+      rightSplitPane.setDividerLocation((int) (m_height*2/3));
+
+      //General Panel
+      this.nodesTree = new NodesTree(this, context);
+      JSplitPane gSplitPane=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, this.nodesTree , rightSplitPane);
+      gSplitPane.setOneTouchExpandable(true);
+      gSplitPane.setDividerLocation((int) (m_width/4));
+
+      m_frame.getContentPane().add(gSplitPane);
+    }
+
+    // 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);
-            }
+      }
+      // 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();
+      }
+    } 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);
       }
     }
+  }
 
-    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/mosgi.doc/config.properties.core b/mosgi.doc/config.properties.core
index 6a58279..d589e2c 100644
--- a/mosgi.doc/config.properties.core
+++ b/mosgi.doc/config.properties.core
@@ -37,7 +37,7 @@
 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.t1=1100
+#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 4e16b90..1430fab 100644
--- a/mosgi.doc/config.properties.jmxconsole
+++ b/mosgi.doc/config.properties.jmxconsole
@@ -19,10 +19,16 @@
  file:../mosgi.console.gui/target/org.apache.felix.mosgi.console.gui-0.8.0-SNAPSHOT.jar \
  file:../mosgi.console.component/target/org.apache.felix.mosgi.console.component-0.8.0-SNAPSHOT.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.rmiport.t1=1100
+#mosgi.jmxconsole.ip.2=127.0.0.1
+#mosgi.jmxconsole.profile.2=core2
+#mosgi.jmxconsole.rmiport.core2=1200
 
 felix.startlevel.framework=1
 felix.startlevel.bundle=1
diff --git a/mosgi.jmx.remotelogger/src/main/java/org/apache/felix/mosgi/jmx/remotelogger/Logger.java b/mosgi.jmx.remotelogger/src/main/java/org/apache/felix/mosgi/jmx/remotelogger/Logger.java
index 16db617..0a24fa2 100644
--- a/mosgi.jmx.remotelogger/src/main/java/org/apache/felix/mosgi/jmx/remotelogger/Logger.java
+++ b/mosgi.jmx.remotelogger/src/main/java/org/apache/felix/mosgi/jmx/remotelogger/Logger.java
@@ -1,23 +1,22 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *    http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.    
+/*
+ *   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.jmx.remotelogger;
 
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
@@ -66,48 +65,65 @@
     switch (serviceevent.getType()) {
       case ServiceEvent.REGISTERED :
         if (as[0].equals(LogReaderService.class.getName())){
-		      this.registerLogReaderService(servicereference);
+          this.registerLogReaderService(servicereference);
         }else if (as[0].equals(MBeanServer.class.getName())){
           this.registerToAgent(servicereference);
         }
-				break;
-			case ServiceEvent.UNREGISTERING :
+	break;
+      case ServiceEvent.UNREGISTERING :
         if (as[0].equals(LogReaderService.class.getName())){
 				  this.unRegisterLogReaderService(servicereference);
         }else if (as[0].equals(MBeanServer.class.getName())){
           this.unRegisterFromAgent();
         }
-				break;
-		}
-	}
+	break;
+    }
+  }
 
 
 //LogListener Interface
   public void logged(LogEntry log){
+    String reg=new String(":");
     StringBuffer message=new StringBuffer();
+    //System.out.print("mosgi.jmx.remotelogger : new log : ");
+
     synchronized (logMutex){
+      try{
+        message.append(""+log.getBundle().getBundleId());
+      }catch(NullPointerException e){
+        message.append("Unknown source");
+      }
+     
+      String lSymbolicName=log.getBundle().getSymbolicName();
+      if(lSymbolicName != null){
+        message.append(reg+lSymbolicName);
+      }else {
+        message.append(reg+"\"null\"");
+      }
+
+      message.append(reg+log.getBundle().getState());
+
       int lLevel=log.getLevel();
       if(debugLogFlag && lLevel==LogService.LOG_DEBUG){
-        message.append("DEBUG : ");
+        message.append(reg+"DEBUG  ");
       }else if (errorLogFlag && lLevel==LogService.LOG_ERROR){
-        message.append("ERROR : ");
+        message.append(reg+"ERROR  ");
       }else if(infoLogFlag && lLevel==LogService.LOG_INFO){
-        message.append("INFO : ");
+        message.append(reg+"INFO   ");
       }else if(warningLogFlag && lLevel==LogService.LOG_WARNING){
-        message.append("WARNING : ");
+        message.append(reg+"WARNING");
       }else {
-        message.append("NO LEVEL : ");
+        message.append(reg+"NOLEVEL");
       }
-      try{
-        message.append(log.getBundle().getBundleId()+" : ");
-      }catch(NullPointerException e){
-      	message.append("Unknown source");
-      }
-      message.append(log.getMessage());
+
+      message.append(reg+log.getMessage());
     }
-    System.out.println(message.toString());
-    if (this.agent!=null){
-      this.sendNotification(new  AttributeChangeNotification(this.remoteLoggerON, 0, 0,message.toString(), null, "Log", null, null));
+    //System.out.println(message.toString());
+    if (this.agent!=null){ // On envoie tous les logs a un MBeanServer
+      System.out.println("this.agent != null => remoteLogger.Logger.sendNotifiaction(...."+message.toString());
+      this.sendNotification(new  AttributeChangeNotification(this.remoteLoggerON, 0, 
+						             System.currentTimeMillis(),
+						             message.toString(), null, "Log", null, null));
     }
   }
 
@@ -136,7 +152,7 @@
     if (sr2!=null){
       this.registerToAgent(sr2);
     }
-		this.log(LogService.LOG_INFO, "Remote Logger started "+version);
+    this.log(LogService.LOG_INFO, "Remote Logger started "+version);
 
   }
      
@@ -159,8 +175,19 @@
 
 //private methods 
   private void registerLogReaderService(ServiceReference sr) {
+    //System.out.println("mosgi.jmx.remoteLogger.Logger.registerLogReaderService("+sr.toString()+") : oldLog=");
     this.lrs=(LogReaderService)this.bc.getService(sr);
     this.lrs.addLogListener(this);
+   
+    /*// old log :
+    System.out.println("oldLog=");
+    java.util.Enumeration oldLog = this.lrs.getLog();
+    int i=0;
+    while(oldLog.hasMoreElements()) {
+      LogEntry oldLogEntry = ((LogEntry) oldLog.nextElement());
+      System.out.println("   -"+(i++)+" : "+oldLogEntry.getMessage());
+      //logged(oldLogEntry);
+    }*/
   }
   
   private void unRegisterLogReaderService(ServiceReference sr) {
@@ -173,7 +200,16 @@
   private void registerToAgent(ServiceReference sr){
     this.agent=(MBeanServer)bc.getService(sr);
     try{   
-      this.agent.registerMBean(this, this.remoteLoggerON);
+      this.agent.registerMBean(this, this.remoteLoggerON); 
+      /*// old log :
+      System.out.println("oldLog=");
+      java.util.Enumeration oldLog = this.lrs.getLog();
+      int i=0;
+      while(oldLog.hasMoreElements()) {
+        LogEntry oldLogEntry = ((LogEntry) oldLog.nextElement());
+        System.out.println("   -"+(i++)+" : "+oldLogEntry.getMessage());
+        //logged(oldLogEntry);
+      }*/
     }catch(Exception e){
       e.printStackTrace();
     }
@@ -187,7 +223,7 @@
     }
   }
 
-	private void log (int level, String message){
+  private void log (int level, String message){
     ServiceReference lsn=bc.getServiceReference(LogService.class.getName());
     if (lsn!=null){
       LogService ls=(LogService)bc.getService(lsn);
@@ -195,7 +231,7 @@
     }else{
       System.out.println("ERROR : Logger.start : No service "+LogService.class.getName()+" is present");
     }
-	}
+  }
 
 
 }