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