package iiuf.log; import java.util.HashMap; import java.util.TreeMap; import java.util.ArrayList; import java.util.Date; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Font; import java.net.InetAddress; import javax.swing.JTabbedPane; import javax.swing.JPanel; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.ImageIcon; import javax.swing.JSplitPane; import javax.swing.JTextArea; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreeSelectionModel; import javax.swing.tree.TreePath; import javax.swing.event.TreeSelectionListener; import javax.swing.event.TreeSelectionEvent; /** Graphical log overview implementation. Set "log.cleronconnect" property to any value to clear the log each time a new client connection is made.<p> (c) 2000, 2001, IIUF, DIUF<p> @author $Author: ohitz $ @version $Name: $ $Revision: 1.1 $ */ public class Overview extends JFrame implements LogMessageListener { private static final ImageIcon DOC_ICON = new ImageIcon(Const.class.getResource("doc.gif")); private static final Font MONOSPACE = new Font("Monospaced", Font.PLAIN, 12); private static Font DEFAULT; private JTabbedPane threadPanes = new JTabbedPane(); private HashMap threads = new HashMap(); private ThreadPane all = new ThreadPane("All", 0); private JTextArea info = new JTextArea("", 15, 80); class ThreadPane extends JPanel { Priority[] priorities = new Priority[Const.LOG_ALL]; DefaultMutableTreeNode root = new DefaultMutableTreeNode(); DefaultTreeModel treeModel = new DefaultTreeModel(root); JTree jtree = new JTree(treeModel); TreePath rootpath = new TreePath(root); class TreeRenderer extends DefaultTreeCellRenderer { 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); if(value instanceof Priority) setIcon(Const.LOG_ICONS[((Priority)value).priority]); if(value instanceof LogMessageNode && !((LogMessageNode)value).m.exception.equals("")) if(Const.STDOUT.equals(((LogMessageNode)value).m.message) || Const.STDERR.equals(((LogMessageNode)value).m.message)) setIcon(null); else setIcon(DOC_ICON); return this; } } class Priority extends DefaultMutableTreeNode { TreeMap map = new TreeMap(); int priority; Priority(int priority_) { priority = priority_; } public String toString() { return Const.LOG_STRINGS[priority] + " (" + countMsgs() + ")"; } int countMsgs() { LogMessages[] msgs = (LogMessages[])map.values().toArray(new LogMessages[map.size()]); int result = 0; for(int i = 0; i < msgs.length; i++) result += msgs[i].getChildCount(); return result; } LogMessages get(LogMessage m) { LogMessages result = (LogMessages)map.get(m.message); if(result == null) { result = new LogMessages(m.message); map.put(m.message, result); treeModel.insertNodeInto(result, this, getChildCount()); } return result; } } class LogMessageNode extends DefaultMutableTreeNode { LogMessage m; LogMessageNode(LogMessage message) { m = message; } public String toString() { if(Const.STDOUT.equals(m.message) || Const.STDERR.equals(m.message)) return m.exception; else return new Date(m.time).toString(); } } class LogMessages extends DefaultMutableTreeNode { String message; boolean stdoutExp; boolean stderrExp; TreePath path; LogMessages(String message_) { message = message_; } void add(LogMessage m) { if(path == null) path = new TreePath(new Object[] {root, getParent(), this}); LogMessageNode node = new LogMessageNode(m); treeModel.insertNodeInto(node, this, getChildCount()); if(! stdoutExp && Const.STDOUT.equals(m.message)) { jtree.expandPath(path); stdoutExp = true; } if(! stderrExp && Const.STDERR.equals(m.message)) { jtree.expandPath(path); stderrExp = true; } treeModel.nodeChanged(this); if(jtree.isExpanded(path)) jtree.scrollPathToVisible(new TreePath(new Object[] {root, getParent(), this, node})); } public String toString() { return message + " (" + getChildCount() + ")"; } } int msgCount; String name; int tabIdx; ThreadPane(String name_, int tabIdx_) { name = name_; tabIdx = tabIdx_; setLayout(new BorderLayout()); setName(name + " (" + msgCount + ")"); jtree.setRootVisible(false); jtree.setShowsRootHandles(true); jtree.setCellRenderer(new TreeRenderer()); jtree.setScrollsOnExpand(true); jtree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); jtree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() { public void valueChanged(TreeSelectionEvent e) { if(e.getNewLeadSelectionPath() == null) return; if(e.getNewLeadSelectionPath().getLastPathComponent() instanceof LogMessageNode) { LogMessage m = ((LogMessageNode)e.getNewLeadSelectionPath().getLastPathComponent()).m; info.setText(Const.LOG_STRINGS[m.priority] + " from " + m.thread + " @ " + new Date(m.time).toString() + "\n" + m.message + "\n" + m.getException()); } } }); add(new JScrollPane(jtree), BorderLayout.CENTER); } void add(LogMessage m) { Priority priority = priorities[m.priority]; if(priority == null) { priority = new Priority(m.priority); int idx = 0; for(int i = 0; i < m.priority; i++) if(priorities[i] != null) idx++; priorities[m.priority] = priority; treeModel.insertNodeInto(priority, root, idx); treeModel.nodeChanged(priority); } priority.get(m).add(m); jtree.expandPath(rootpath); msgCount++; threadPanes.setTitleAt(tabIdx, name + " (" + msgCount + ")"); } } public Overview() { super("Log overview by thread"); threadPanes.add(all); info.setFont(MONOSPACE); getContentPane().add(new JSplitPane(JSplitPane.VERTICAL_SPLIT, threadPanes, new JScrollPane(info))); pack(); setSize(500, 500); setVisible(true); } int tabIdx = 1; public synchronized void newConnection(InetAddress host) { if(System.getProperty("log.clearonconnect") != null) { threads = new HashMap(); all = new ThreadPane("All", 0); tabIdx = 1; threadPanes.removeAll(); System.gc(); threadPanes.add(all); info.setText(""); } } public synchronized void handle(LogMessage m) { ThreadPane pane = (ThreadPane)threads.get(m.thread); if(pane == null) { pane = new ThreadPane(m.thread, tabIdx++); threads.put(m.thread, pane); threadPanes.add(pane); } all.add(m); pane.add(m); } } /* $Log: Overview.java,v $ Revision 1.1 2002/07/11 12:24:01 ohitz Initial checkin Revision 1.9 2001/03/05 17:55:07 schubige Still working on soundium properties panel Revision 1.8 2001/01/17 09:55:46 schubige Logger update Revision 1.7 2001/01/04 16:28:36 schubige Header update for 2001 and DIUF Revision 1.6 2000/11/09 07:48:43 schubige early checkin for DCJava Revision 1.5 2000/10/17 15:35:59 schubige Added watcher preferences Revision 1.4 2000/10/10 16:32:12 schubige Added subtree display to TreeView, fixed some bugs Revision 1.3 2000/10/09 07:29:15 schubige Features, features, features Revision 1.2 2000/10/09 06:47:56 schubige Updated logger stuff Revision 1.1 2000/10/05 14:59:30 schubige Added loging stuff */