| /* |
| * 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.MyTree; |
| import org.osgi.framework.BundleContext; |
| import java.beans.PropertyChangeEvent; |
| import javax.swing.JPanel; |
| import javax.swing.JPopupMenu; |
| import javax.swing.JMenuItem; |
| import javax.swing.JScrollPane; |
| import javax.swing.JScrollBar; |
| import javax.swing.tree.DefaultTreeModel; |
| import javax.swing.tree.DefaultMutableTreeNode; |
| import javax.swing.tree.TreePath; |
| import javax.swing.JOptionPane; |
| import javax.swing.JDialog; |
| import java.awt.Component; |
| import java.awt.BorderLayout; |
| import java.awt.Dimension; |
| import java.awt.event.ActionListener; |
| import java.awt.event.MouseListener; |
| import java.awt.event.MouseEvent; |
| import java.awt.event.ActionEvent; |
| import javax.management.Notification; |
| import javax.management.NotificationListener; |
| import javax.management.ObjectName; |
| import javax.management.MBeanServerConnection; |
| import javax.management.Attribute; |
| import java.util.Hashtable; |
| import java.util.StringTokenizer; |
| import java.util.Vector; |
| import java.util.Date; |
| import java.util.Enumeration; |
| import java.text.DateFormat; |
| import java.text.SimpleDateFormat; |
| //import org.osgi.service.prefs.Preferences; |
| |
| public class RemoteLogger_jtree extends DefaultTreeModel implements CommonPlugin, NotificationListener, MouseListener { |
| |
| private static final String OLDLOG_THIS_TIME ="This time"; |
| private static final String OLDLOG_NOT_THIS_TIME ="Not this time"; |
| private static final String OLDLOG_ALWAYS ="Always"; |
| private static final String OLDLOG_NEVER ="Never"; |
| private static final String[] LOG_LVL=new String[] {"Error", "Warning", "Info", "Debug"}; |
| |
| private String oldLogChoice=OLDLOG_THIS_TIME; |
| private Hashtable ht_connectedGateway=new Hashtable(); // connString/mbsc |
| protected Hashtable ht_logLvl=new Hashtable(); // DefaultMutableTreeNode/Integer_logLvl |
| protected Vector v_ul=new Vector(); // tree node containing not visible log yet (placer ce vecteur dans le renderer ???) |
| |
| private MyTree logTree; |
| private TreePath selPath; |
| private JPanel jp; |
| private DefaultMutableTreeNode rootNode=new DefaultMutableTreeNode(""); |
| private JScrollBar jsb_horizontal=null; |
| private JScrollBar jsb_vertical=null; |
| |
| public RemoteLogger_jtree (BundleContext bdlCtx){ |
| super(null); |
| setRoot(rootNode); |
| |
| this.jp=new JPanel(); |
| this.jp.setLayout(new BorderLayout()); |
| |
| this.logTree=new MyTree(this); |
| JtreeCellRenderer treeCellRenderer=new JtreeCellRenderer(bdlCtx, this); |
| this.logTree.setCellRenderer(treeCellRenderer); |
| this.logTree.setLargeModel(true); |
| this.logTree.setToggleClickCount(-1); |
| this.logTree.setScrollsOnExpand(false); |
| // if I do this.logTree.setRootVisible(false) => Create an invisible tree, even if I use an "expand" |
| // then need to expand after the first insert into the tree so i give up with root not visible. |
| this.logTree.addMouseListener(this); |
| |
| JScrollPane jsp=new JScrollPane(logTree); |
| this.jsb_horizontal=jsp.getHorizontalScrollBar(); |
| this.jsb_vertical=jsp.getVerticalScrollBar(); |
| jp.add(jsp, BorderLayout.CENTER); |
| jp.setMinimumSize(new Dimension(500,25)); |
| } |
| |
| ///////////////////////////////////////////////////// |
| // Mouse Listener Interface // |
| ///////////////////////////////////////////////////// |
| public void mouseEntered(MouseEvent e){} |
| public void mouseClicked(MouseEvent e) {} |
| public void mouseExited(MouseEvent e){} |
| public void mouseReleased(MouseEvent e){} |
| public void mousePressed(MouseEvent e) { |
| final int selRow = logTree.getRowForLocation(e.getX(), e.getY()); |
| selPath = logTree.getPathForLocation(e.getX(), e.getY()); |
| |
| if ( e.getClickCount()==1 & selRow!=-1 & e.getButton()>1 ) { // show JPopupMenu |
| String nodeString="\""+((DefaultMutableTreeNode) selPath.getLastPathComponent()).getUserObject()+"\""; |
| JPopupMenu jpopup=new JPopupMenu(); |
| JMenuItem jmiRemove=new JMenuItem("Remove logs \""+nodeString.substring(0,Math.min(15,nodeString.length()))+((nodeString.length()>15)?"...\"":"\"")); |
| jmiRemove.addActionListener(new ActionListener(){ |
| public void actionPerformed(ActionEvent e){ |
| removeLog_actionPerformed(selRow); |
| } |
| }); |
| jpopup.add(jmiRemove); |
| if (selPath.getPath().length==3) { |
| JMenuItem jmiLogLvl=new JMenuItem("Set log level"); |
| jmiLogLvl.addActionListener(new ActionListener(){ |
| public void actionPerformed(ActionEvent e){ |
| setLogLvl(selPath); |
| } |
| }); |
| jpopup.add(jmiLogLvl); |
| } |
| jpopup.show(jp, e.getX()-jsb_horizontal.getValue(), e.getY()-jsb_vertical.getValue()); |
| /*} else if ( e.getClickCount()==2 & selPath!=null) { // expand selected path |
| if (logTree.isExpanded(selPath)) { |
| logTree.collapsePath(selPath); |
| } else { |
| logTree.expandPath(selPath); |
| } */ |
| } else if ( e.getClickCount()==1 & selPath!=null ) { // reload logTree and let selected path location |
| reloadTree(selRow); |
| } |
| } |
| |
| private void reloadTree(int selRow) { |
| int horizontal_jsb_init_value = jsb_horizontal.getValue(); |
| int vertical_jsb_init_value = jsb_vertical.getValue(); |
| int row_y_init_loc = (int) ((logTree.getRowBounds(selRow)).getY()); |
| Enumeration enu = logTree.getExpandedDescendants(new TreePath(rootNode)); |
| reload(); |
| if ( enu != null ) { // necessaire ce test ? |
| while (enu.hasMoreElements()) { |
| logTree.expandPath((TreePath) enu.nextElement()); |
| } |
| } |
| // Redefini tous les noeuds rmiport/profilName comme a jour |
| this.v_ul.removeAllElements(); |
| // without next line if scrollbar_value=scrollbar_max it's generate a bad shift (may be vertical scrollbar height) |
| logTree.scrollPathToVisible(selPath); |
| int row_y_new_loc = (int) ((logTree.getRowBounds(logTree.getRowForPath(selPath))).getY()); |
| int vertical_jsb_new_value = vertical_jsb_init_value+(row_y_new_loc-row_y_init_loc); |
| jsb_vertical.setValue(vertical_jsb_new_value); |
| jsb_horizontal.setValue(horizontal_jsb_init_value); |
| logTree.setSelectionPath(selPath); |
| logTree.repaint(); |
| } |
| |
| ///////////////////////////////////// |
| // 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 mbsc=(MBeanServerConnection)e.getNewValue(); |
| if ( !ht_connectedGateway.containsValue(mbsc) ) { |
| 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); |
| DefaultMutableTreeNode dmtn_ip=createIfNeed(ip, rootNode); |
| DefaultMutableTreeNode dmtn_ref=createIfNeed(ref, dmtn_ip); |
| 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"+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); |
| dialog.show(); |
| oldLogChoice = (String) jop.getValue(); |
| if (oldLogChoice==JOptionPane.UNINITIALIZED_VALUE) { |
| oldLogChoice=OLDLOG_THIS_TIME; // *1) |
| } |
| } |
| if (oldLogChoice==OLDLOG_THIS_TIME | oldLogChoice==OLDLOG_ALWAYS) { |
| mbsc.invoke(Activator.REMOTE_LOGGER_ON, "sendOldLog", new Object[]{}, new String[]{}); |
| } |
| } |
| } catch(Exception ex){ |
| System.out.println("[RemoteLogger_jtree] error : "+ex); |
| } |
| } |
| } |
| |
| 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) { |
| 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); |
| |
| 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); |
| // if I use local date format there are indentations problems |
| //DateFormat df = DateFormat.getTimeInstance(DateFormat.MEDIUM); |
| //DateFormat df2 = DateFormat.getDateInstance(DateFormat.SHORT); |
| time=timeFormat.format(timeDate); |
| date=dateFormat.format(timeDate); |
| } |
| String id=st.nextToken(); |
| String name=st.nextToken(); |
| String idname=new String(id+" : "+name); |
| // bundle state juste after remote loger received a the log entry (in old log case do state="") |
| String state=(String) JtreeCellRenderer.ht_num2string.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(time+" | "+date+" | "+state+" | "+lvl+" | "+msg,false); |
| this.insertNodeInto(dmtn, dmtn_idname, 0); |
| // if usefull save nodes which contains new log |
| if ( !v_ul.contains(dmtn_ip) ) { |
| v_ul.add(dmtn_ip); |
| v_ul.add(dmtn_ref); |
| v_ul.add(dmtn_idname); |
| } else if ( !v_ul.contains(dmtn_ref) ) { |
| v_ul.add(dmtn_ref); |
| v_ul.add(dmtn_idname); |
| } else if ( !v_ul.contains(dmtn_idname) ) { |
| v_ul.add(dmtn_idname); |
| } |
| this.logTree.repaint(); |
| } |
| |
| ////////////////////////////////////////// |
| // MBean attribute manipulation // |
| ////////////////////////////////////////// |
| private Integer getLogLvl(String connString) { |
| Integer val=new Integer(0); |
| try { |
| MBeanServerConnection mb=(MBeanServerConnection) ht_connectedGateway.get(connString); |
| val=(Integer) mb.getAttribute(Activator.REMOTE_LOGGER_ON, "LogLvl"); |
| } catch (Exception exc) { |
| exc.printStackTrace(); |
| } |
| return val; |
| } |
| |
| private void setLogLvl(TreePath tp) { |
| Object[] o=tp.getPath(); |
| String connString = o[1]+":"+o[2]; |
| try { |
| MBeanServerConnection mb=(MBeanServerConnection) ht_connectedGateway.get(connString); |
| Integer curentVal=(Integer) mb.getAttribute(Activator.REMOTE_LOGGER_ON, "LogLvl"); |
| |
| int val = JOptionPane.showOptionDialog(jp, "Select a log level for \"..."+connString+"\" :", "Log level", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, LOG_LVL, LOG_LVL[curentVal.intValue()-1]); |
| if ( val == JOptionPane.CLOSED_OPTION ) { return; } |
| Integer newVal = new Integer(val+1); |
| |
| 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 \"..."+connString+"\" :\n"+ex, "Error :", JOptionPane.ERROR_MESSAGE); |
| ex.printStackTrace(); |
| } |
| } |
| |
| ////////////////////////////////////////// |
| // PRIVATE TOOLS // |
| ////////////////////////////////////////// |
| private void removeLog_actionPerformed(int selRow) { |
| //System.out.println("selected path="+this.selPath); |
| Object[] o= this.selPath.getPath(); |
| DefaultMutableTreeNode selectedDmtn=(DefaultMutableTreeNode) this.selPath.getLastPathComponent(); |
| if (o.length==5) { |
| // Can't remove first child of a bundle to avoid modify tree node color |
| if ( ((DefaultMutableTreeNode) selectedDmtn.getParent()).getFirstChild()!=selectedDmtn ) { |
| removeNodeFromParent(selectedDmtn); |
| } |
| } else if (o.length==4) { |
| removeNodeFromParent(selectedDmtn); |
| } else if (o.length==3) { |
| selectedDmtn.removeAllChildren(); |
| reloadTree(selRow); |
| } else if (o.length==2) { |
| Enumeration enu_1=selectedDmtn.children(); |
| while (enu_1.hasMoreElements()) { |
| DefaultMutableTreeNode dmtn_child=(DefaultMutableTreeNode) enu_1.nextElement(); |
| dmtn_child.removeAllChildren(); |
| } |
| reloadTree(selRow); |
| } else if (o.length==1) { |
| Enumeration enume=rootNode.children(); |
| while (enume.hasMoreElements()) { |
| DefaultMutableTreeNode dmtn_child=(DefaultMutableTreeNode) enume.nextElement(); |
| Enumeration enume2=dmtn_child.children(); |
| while (enume2.hasMoreElements()) { |
| DefaultMutableTreeNode dmtn_child_child=(DefaultMutableTreeNode) enume2.nextElement(); |
| dmtn_child_child.removeAllChildren(); |
| } |
| } |
| reloadTree(selRow); |
| } |
| } |
| |
| 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); |
| this.insertNodeInto(theNode, parent, 0); |
| if ( parent==rootNode ) { |
| v_ul.add(rootNode); |
| } |
| } |
| |
| return theNode; |
| } |
| |
| protected String getLogLvl(DefaultMutableTreeNode dmtn) { |
| // used by treeCellRenderer |
| return LOG_LVL[ ((Integer) ht_logLvl.get(dmtn)).intValue() - 1 ]; |
| } |
| |
| protected void fireTreeNodesInserted(Object source, Object path[], int childIndices[], Object children[]) { |
| // Do nothing to avoid refresh jtree after each log. |
| } |
| |
| } |