blob: 6ce8bdf3fdd74eb90961e397e7a55eb9261b3320 [file] [log] [blame]
/*
* 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.log4j.chainsaw;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
/**
*
* A TreeModel that represents the Loggers for a given LogPanel
*
* @author Paul Smith <psmith@apache.org>
*/
class LogPanelLoggerTreeModel extends DefaultTreeModel
implements LoggerNameListener {
private Map<String, LogPanelTreeNode> fullPackageMap = new HashMap<>();
private final Logger logger = LogManager.getLogger(LogPanelLoggerTreeModel.class);
LogPanelLoggerTreeModel() {
super(new LogPanelTreeNode("Root Logger"));
}
/* (non-Javadoc)
* @see org.apache.log4j.chainsaw.LoggerNameListener#loggerNameAdded(java.lang.String)
*/
public void loggerNameAdded(final String loggerName) {
//invoke later, not on current EDT
SwingUtilities.invokeLater(
() -> addLoggerNameInDispatchThread(loggerName));
}
public void reset() {
DefaultMutableTreeNode current = (DefaultMutableTreeNode) getRoot();
current.removeAllChildren();
fullPackageMap.clear();
nodeStructureChanged(current);
}
private void addLoggerNameInDispatchThread(final String loggerName) {
String[] packages = tokenize(loggerName);
/**
* The packages array is effectively the tree
* path that must exist within the tree, so
* we walk the tree ensuring each level is present
*/
DefaultMutableTreeNode current = (DefaultMutableTreeNode) getRoot();
/**
* This label is used to break out when descending the
* current tree hierachy, and it has matched a package name
* with an already existing TreeNode.
*/
outerFor:
for (int i = 0; i < packages.length; i++) {
String packageName = packages[i];
Enumeration enumeration = current.children();
while (enumeration.hasMoreElements()) {
DefaultMutableTreeNode child =
(DefaultMutableTreeNode) enumeration.nextElement();
String childName = child.getUserObject().toString();
if (childName.equals(packageName)) {
/**
* This the current known branch to descend
*/
current = child;
/**
* we've found it, so break back to the outer
* for loop to continue processing further
* down the tree
*/
continue outerFor;
}
}
/*
* So we haven't found this index in the current children,
* better create the child
*/
final LogPanelTreeNode newChild = new LogPanelTreeNode(packageName);
StringBuilder fullPackageBuf = new StringBuilder();
for (int j = 0; j <= i; j++) {
fullPackageBuf.append(packages[j]);
if (j < i) {
fullPackageBuf.append(".");
}
}
logger.debug("Adding to Map " + fullPackageBuf.toString());
fullPackageMap.put(fullPackageBuf.toString(), newChild);
final DefaultMutableTreeNode changedNode = current;
changedNode.add(newChild);
final int[] changedIndices = new int[changedNode.getChildCount()];
for (int j = 0; j < changedIndices.length; j++) {
changedIndices[j] = j;
}
nodesWereInserted(
changedNode, new int[] { changedNode.getIndex(newChild) });
nodesChanged(changedNode, changedIndices);
current = newChild;
}
}
LogPanelTreeNode lookupLogger(String newLogger) {
if (fullPackageMap.containsKey(newLogger)) {
return fullPackageMap.get(newLogger);
}else{
logger.debug("No logger found matching '" + newLogger + "'");
logger.debug("Map Dump: " + fullPackageMap);
}
return null;
}
/**
* Takes the loggerName and tokenizes it into it's
* package name lements returning the elements
* via the Stirng[]
* @param loggerName
* @return array of strings representing the package hierarchy
*/
private String[] tokenize(String loggerName) {
StringTokenizer tok = new StringTokenizer(loggerName, ".");
String[] tokens = new String[tok.countTokens()];
int index = 0;
while (tok.hasMoreTokens()) {
tokens[index++] = tok.nextToken();
}
return tokens;
}
private static class LogPanelTreeNode extends DefaultMutableTreeNode {
protected static Comparator nodeComparator =
(o1, o2) -> o1.toString().compareToIgnoreCase(o2.toString());
private LogPanelTreeNode(String logName) {
super(logName);
}
public void insert(MutableTreeNode newChild, int childIndex) {
// logger.debug("[" + this.getUserObject() + "] inserting child " + newChild + " @ index " + childIndex);
// logger.debug("Children now: " + this.children);
super.insert(newChild, childIndex);
// logger.debug("Children after insert: " + this.children);
this.children.sort(nodeComparator);
// logger.debug("Children after sort: " + this.children);
}
}
}