1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.log4j.chainsaw;
21
22 import java.util.Collections;
23 import java.util.Comparator;
24 import java.util.Enumeration;
25 import java.util.HashMap;
26 import java.util.Map;
27 import java.util.StringTokenizer;
28
29 import javax.swing.SwingUtilities;
30 import javax.swing.tree.DefaultMutableTreeNode;
31 import javax.swing.tree.DefaultTreeModel;
32 import javax.swing.tree.MutableTreeNode;
33
34 import org.apache.log4j.LogManager;
35 import org.apache.log4j.Logger;
36
37
38 /***
39 *
40 * A TreeModel that represents the Loggers for a given LogPanel
41 *
42 * @author Paul Smith <psmith@apaceh.org>
43 */
44 class LogPanelLoggerTreeModel extends DefaultTreeModel
45 implements LoggerNameListener {
46 private Map fullPackageMap = new HashMap();
47 private final Logger logger = LogManager.getLogger(LogPanelLoggerTreeModel.class);
48
49 LogPanelLoggerTreeModel() {
50 super(new LogPanelTreeNode("Root Logger"));
51 }
52
53
54
55
56 public void loggerNameAdded(final String loggerName) {
57 SwingUtilities.invokeLater(
58 new Runnable() {
59 public void run() {
60 addLoggerNameInDispatchThread(loggerName);
61 }
62 });
63 }
64
65 private void addLoggerNameInDispatchThread(final String loggerName) {
66 String[] packages = tokenize(loggerName);
67
68 /***
69 * The packages array is effectively the tree
70 * path that must exist within the tree, so
71 * we walk the tree ensuring each level is present
72 */
73 DefaultMutableTreeNode current = (DefaultMutableTreeNode) getRoot();
74
75
76 /***
77 * This label is used to break out when descending the
78 * current tree hierachy, and it has matched a package name
79 * with an already existing TreeNode.
80 */
81 outerFor:
82 for (int i = 0; i < packages.length; i++) {
83 String packageName = packages[i];
84 Enumeration enumeration = current.children();
85
86 while (enumeration.hasMoreElements()) {
87 DefaultMutableTreeNode child =
88 (DefaultMutableTreeNode) enumeration.nextElement();
89 String childName = child.getUserObject().toString();
90
91 if (childName.equals(packageName)) {
92 /***
93 * This the current known branch to descend
94 */
95 current = child;
96
97 /***
98 * we've found it, so break back to the outer
99 * for loop to continue processing further
100 * down the tree
101 */
102 continue outerFor;
103 }
104 }
105
106
107
108
109
110 final LogPanelTreeNode newChild = new LogPanelTreeNode(packageName);
111
112 StringBuffer fullPackageBuf = new StringBuffer();
113
114 for (int j = 0; j <= i; j++) {
115 fullPackageBuf.append(packages[j]);
116
117 if (j < i) {
118 fullPackageBuf.append(".");
119 }
120 }
121
122 logger.debug("Adding to Map " + fullPackageBuf.toString());
123 fullPackageMap.put(fullPackageBuf.toString(), newChild);
124
125 final DefaultMutableTreeNode changedNode = current;
126
127 changedNode.add(newChild);
128
129 final int[] changedIndices = new int[changedNode.getChildCount()];
130
131 for (int j = 0; j < changedIndices.length; j++) {
132 changedIndices[j] = j;
133 }
134
135 nodesWereInserted(
136 changedNode, new int[] { changedNode.getIndex(newChild) });
137 nodesChanged(changedNode, changedIndices);
138 current = newChild;
139 }
140 }
141
142 LogPanelTreeNode lookupLogger(String newLogger) {
143 if (fullPackageMap.containsKey(newLogger)) {
144 return (LogPanelTreeNode) fullPackageMap.get(newLogger);
145 }else{
146 logger.debug("No logger found matching '" + newLogger + "'");
147 logger.debug("Map Dump: " + fullPackageMap);
148 }
149
150 return null;
151 }
152
153 /***
154 * Takes the loggerName and tokenizes it into it's
155 * package name lements returning the elements
156 * via the Stirng[]
157 * @param loggerName
158 * @return array of strings representing the package hierarchy
159 */
160 private String[] tokenize(String loggerName) {
161 StringTokenizer tok = new StringTokenizer(loggerName, ".");
162
163 String[] tokens = new String[tok.countTokens()];
164
165 int index = 0;
166
167 while (tok.hasMoreTokens()) {
168 tokens[index++] = tok.nextToken();
169 }
170
171 return tokens;
172 }
173
174 private static class LogPanelTreeNode extends DefaultMutableTreeNode {
175 protected static Comparator nodeComparator =
176 new Comparator() {
177 public int compare(Object o1, Object o2) {
178 return o1.toString().compareToIgnoreCase(o2.toString());
179 }
180
181 public boolean equals(Object obj) {
182 return false;
183 }
184 };
185
186 private LogPanelTreeNode(String logName) {
187 super(logName);
188 }
189
190 public void insert(MutableTreeNode newChild, int childIndex) {
191
192
193 super.insert(newChild, childIndex);
194
195
196 Collections.sort(this.children, nodeComparator);
197
198
199 }
200 }
201 }