View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    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 &lt;psmith@apache.org&gt;
    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    /* (non-Javadoc)
    54     * @see org.apache.log4j.chainsaw.LoggerNameListener#loggerNameAdded(java.lang.String)
    55     */
    56    public void loggerNameAdded(final String loggerName) {
    57      //invoke later, not on current EDT
    58      SwingUtilities.invokeLater(
    59        new Runnable() {
    60          public void run() {
    61            addLoggerNameInDispatchThread(loggerName);
    62          }
    63        });
    64    }
    65
    66    public void reset() {
    67        DefaultMutableTreeNode current = (DefaultMutableTreeNode) getRoot();
    68        current.removeAllChildren();
    69        fullPackageMap.clear();
    70        nodeStructureChanged(current);
    71    }
    72
    73    private void addLoggerNameInDispatchThread(final String loggerName) {
    74      String[] packages = tokenize(loggerName);
    75
    76      /**
    77       * The packages array is effectively the tree
    78       * path that must exist within the tree, so
    79       * we walk the tree ensuring each level is present
    80       */
    81      DefaultMutableTreeNode current = (DefaultMutableTreeNode) getRoot();
    82
    83
    84  /**
    85   * This label is used to break out when descending the
    86   * current tree hierachy, and it has matched a package name
    87   * with an already existing TreeNode.
    88   */
    89  outerFor:
    90      for (int i = 0; i < packages.length; i++) {
    91        String packageName = packages[i];
    92        Enumeration enumeration = current.children();
    93
    94        while (enumeration.hasMoreElements()) {
    95          DefaultMutableTreeNode child =
    96            (DefaultMutableTreeNode) enumeration.nextElement();
    97          String childName = child.getUserObject().toString();
    98
    99          if (childName.equals(packageName)) {
    100           /**
    101            * This the current known branch to descend
    102            */
    103           current = child;
    104
    105           /**
    106            * we've found it, so break back to the outer
    107            * for loop to continue processing further
    108            * down the tree
    109            */
    110           continue outerFor;
    111         }
    112       }
    113
    114       /*
    115        * So we haven't found this index in the current children,
    116        * better create the child
    117        */
    118       final LogPanelTreeNode newChild = new LogPanelTreeNode(packageName);
    119
    120       StringBuffer fullPackageBuf = new StringBuffer();
    121
    122       for (int j = 0; j <= i; j++) {
    123         fullPackageBuf.append(packages[j]);
    124
    125         if (j < i) {
    126           fullPackageBuf.append(".");
    127         }
    128       }
    129
    130       logger.debug("Adding to Map " + fullPackageBuf.toString());
    131       fullPackageMap.put(fullPackageBuf.toString(), newChild);
    132
    133       final DefaultMutableTreeNode changedNode = current;
    134
    135       changedNode.add(newChild);
    136
    137       final int[] changedIndices = new int[changedNode.getChildCount()];
    138
    139       for (int j = 0; j < changedIndices.length; j++) {
    140         changedIndices[j] = j;
    141       }
    142
    143       nodesWereInserted(
    144         changedNode, new int[] { changedNode.getIndex(newChild) });
    145       nodesChanged(changedNode, changedIndices);
    146       current = newChild;
    147     }
    148   }
    149
    150   LogPanelTreeNode lookupLogger(String newLogger) {
    151     if (fullPackageMap.containsKey(newLogger)) {
    152       return (LogPanelTreeNode) fullPackageMap.get(newLogger);
    153     }else{
    154         logger.debug("No logger found matching '" + newLogger + "'");
    155         logger.debug("Map Dump: " + fullPackageMap);
    156     }
    157
    158     return null;
    159   }
    160
    161   /**
    162      * Takes the loggerName and tokenizes it into it's
    163      * package name lements returning the elements
    164      * via the Stirng[]
    165      * @param loggerName
    166      * @return array of strings representing the package hierarchy
    167      */
    168   private String[] tokenize(String loggerName) {
    169     StringTokenizer tok = new StringTokenizer(loggerName, ".");
    170
    171     String[] tokens = new String[tok.countTokens()];
    172
    173     int index = 0;
    174
    175     while (tok.hasMoreTokens()) {
    176       tokens[index++] = tok.nextToken();
    177     }
    178
    179     return tokens;
    180   }
    181
    182   private static class LogPanelTreeNode extends DefaultMutableTreeNode {
    183     protected static Comparator nodeComparator =
    184       new Comparator() {
    185         public int compare(Object o1, Object o2) {
    186           return o1.toString().compareToIgnoreCase(o2.toString());
    187         }
    188       };
    189
    190     private LogPanelTreeNode(String logName) {
    191       super(logName);
    192     }
    193
    194     public void insert(MutableTreeNode newChild, int childIndex) {
    195       //      logger.debug("[" + this.getUserObject() + "] inserting child " + newChild + " @ index " + childIndex);
    196       //      logger.debug("Children now: " + this.children);
    197       super.insert(newChild, childIndex);
    198
    199       //	  logger.debug("Children after insert: " + this.children);
    200       Collections.sort(this.children, nodeComparator);
    201
    202       //	  logger.debug("Children after sort: " + this.children);
    203     }
    204   }
    205 }