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  package org.apache.log4j.chainsaw.receivers;
19  
20  import org.apache.log4j.LogManager;
21  import org.apache.log4j.Logger;
22  import org.apache.log4j.plugins.Plugin;
23  import org.apache.log4j.plugins.PluginEvent;
24  import org.apache.log4j.plugins.PluginListener;
25  import org.apache.log4j.plugins.Receiver;
26  import org.apache.log4j.spi.LoggerRepository;
27  import org.apache.log4j.spi.LoggerRepositoryEx;
28  
29  import javax.swing.tree.DefaultMutableTreeNode;
30  import javax.swing.tree.DefaultTreeModel;
31  import javax.swing.tree.TreeNode;
32  import java.beans.PropertyChangeListener;
33  import java.util.Collection;
34  import java.util.Enumeration;
35  import java.util.Vector;
36  
37  
38  /**
39   * A TreeModel that encapsulates the details of all the Receivers and their
40   * related information in the Log4j framework
41   *
42   * @author Paul Smith <psmith@apache.org>
43   */
44  public class ReceiversTreeModel extends DefaultTreeModel
45      implements PluginListener {
46      private static final String ROOTNODE_LABEL = "Receivers";
47      final DefaultMutableTreeNode NoReceiversNode =
48          new DefaultMutableTreeNode("No Receivers defined");
49      final DefaultMutableTreeNode RootNode;
50      private final Logger logger = LogManager.getLogger(ReceiversTreeModel.class);
51  
52      ReceiversTreeModel() {
53          super(new DefaultMutableTreeNode(ROOTNODE_LABEL));
54          RootNode = (DefaultMutableTreeNode) getRoot();
55          refresh();
56      }
57  
58      /**
59       * Creates a new ReceiversTreeModel by querying the Log4j Plugin Repository
60       * and building up the required information.
61       *
62       * @return ReceiversTreeModel
63       */
64      public final synchronized ReceiversTreeModel refresh() {
65          RootNode.removeAllChildren();
66  
67          LoggerRepository repo = LogManager.getLoggerRepository();
68          Collection receivers;
69          if (repo instanceof LoggerRepositoryEx) {
70              receivers = ((LoggerRepositoryEx) repo).getPluginRegistry().getPlugins(Receiver.class);
71          } else {
72              receivers = new Vector();
73          }
74  
75          updateRootDisplay();
76  
77          if (receivers.size() == 0) {
78              getRootNode().add(NoReceiversNode);
79          } else {
80              for (Object receiver : receivers) {
81                  final Receiver item = (Receiver) receiver;
82                  final DefaultMutableTreeNode receiverNode = new DefaultMutableTreeNode(item);
83  
84                  item.addPropertyChangeListener(creatPluginPropertyChangeListener(item, receiverNode));
85                  getRootNode().add(receiverNode);
86              }
87          }
88  
89          reload();
90  
91          return this;
92      }
93  
94      private PropertyChangeListener creatPluginPropertyChangeListener(final Receiver item, final DefaultMutableTreeNode receiverNode) {
95          return evt -> {
96              logger.debug(evt.toString());
97              ReceiversTreeModel.this.fireTreeNodesChanged(item, receiverNode.getPath(), null, null);
98  
99          };
100     }
101 
102     /**
103      * Ensure the Root node of this tree is updated with the latest information
104      * and that listeners are notified.
105      */
106     void updateRootDisplay() {
107         getRootNode().setUserObject(ROOTNODE_LABEL);
108         nodeChanged(getRootNode());
109     }
110 
111     DefaultMutableTreeNode getRootNode() {
112         return (DefaultMutableTreeNode) getRoot();
113     }
114 
115     /* (non-Javadoc)
116      * @see org.apache.log4j.plugins.PluginListener#pluginStarted(org.apache.log4j.plugins.PluginEvent)
117      */
118     public void pluginStarted(PluginEvent e) {
119         if (e.getPlugin() instanceof Receiver) {
120             if (NoReceiversNode.getParent() == getRootNode()) {
121                 int index = getRootNode().getIndex(NoReceiversNode);
122                 getRootNode().remove(NoReceiversNode);
123                 nodesWereRemoved(
124                     getRootNode(), new int[]{index}, new Object[]{NoReceiversNode});
125             }
126 
127             Receiver receiver = (Receiver) e.getPlugin();
128             DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(receiver);
129             getRootNode().add(newNode);
130             receiver.addPropertyChangeListener(creatPluginPropertyChangeListener(receiver, newNode));
131             nodesWereInserted(
132                 getRootNode(), new int[]{getRootNode().getIndex(newNode)});
133         }
134     }
135 
136     TreeNode resolvePluginNode(Plugin p) {
137         /**
138          * Lets walk the tree, top-down until we find the node with the plugin
139          * attached.
140          *
141          * Since the tree hierachy is quite flat, this is should not
142          * be a performance issue at all, but if it is,
143          * then "I have no recollection of that Senator".
144          */
145         TreeNode treeNode = null;
146         Enumeration e = getRootNode().breadthFirstEnumeration();
147         while (e.hasMoreElements()) {
148             DefaultMutableTreeNode node = (DefaultMutableTreeNode) e.nextElement();
149             if (node.getUserObject().equals(p)) {
150                 treeNode = node;
151                 break;
152             }
153         }
154         return treeNode;
155     }
156 
157     /* (non-Javadoc)
158      * @see org.apache.log4j.plugins.PluginListener#pluginStopped(org.apache.log4j.plugins.PluginEvent)
159      */
160     public void pluginStopped(PluginEvent e) {
161         if (e.getPlugin() instanceof Receiver) {
162             Receiver receiver = (Receiver) e.getPlugin();
163             DefaultMutableTreeNode node =
164                 (DefaultMutableTreeNode) resolvePluginNode(receiver);
165             if (node != null) {
166                 int index = getRootNode().getIndex(node);
167                 getRootNode().remove(node);
168                 nodesWereRemoved(
169                     getRootNode(), new int[]{index}, new Object[]{node});
170             }
171 
172             if (getRootNode().getChildCount() == 0) {
173                 getRootNode().add(NoReceiversNode);
174 
175                 int index = getRootNode().getIndex(NoReceiversNode);
176                 nodesWereInserted(getRootNode(), new int[]{index});
177             }
178         }
179     }
180 }