1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.log4j.chainsaw.receivers;
19
20 import java.awt.BorderLayout;
21 import java.awt.Component;
22 import java.awt.Container;
23 import java.awt.event.ActionEvent;
24 import java.awt.event.ActionListener;
25 import java.awt.event.KeyEvent;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.Collection;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32
33 import java.beans.BeanInfo;
34 import java.beans.Introspector;
35 import java.beans.PropertyDescriptor;
36 import java.io.File;
37 import java.io.FileOutputStream;
38
39 import javax.swing.AbstractAction;
40 import javax.swing.Action;
41 import javax.swing.BorderFactory;
42 import javax.swing.Box;
43 import javax.swing.Icon;
44 import javax.swing.ImageIcon;
45 import javax.swing.JComponent;
46 import javax.swing.JDialog;
47 import javax.swing.JFrame;
48 import javax.swing.JMenuItem;
49 import javax.swing.JOptionPane;
50 import javax.swing.JPanel;
51 import javax.swing.JPopupMenu;
52 import javax.swing.JRadioButtonMenuItem;
53 import javax.swing.JScrollPane;
54 import javax.swing.JSplitPane;
55 import javax.swing.JToolBar;
56 import javax.swing.JTree;
57 import javax.swing.SwingUtilities;
58 import javax.swing.event.TreeExpansionEvent;
59 import javax.swing.event.TreeModelEvent;
60 import javax.swing.event.TreeModelListener;
61 import javax.swing.event.TreeSelectionEvent;
62 import javax.swing.event.TreeSelectionListener;
63 import javax.swing.event.TreeWillExpandListener;
64 import javax.swing.tree.DefaultMutableTreeNode;
65 import javax.swing.tree.ExpandVetoException;
66 import javax.swing.tree.TreePath;
67 import javax.xml.transform.TransformerFactory;
68 import javax.xml.transform.Transformer;
69 import javax.xml.transform.stream.StreamResult;
70 import javax.xml.transform.dom.DOMSource;
71 import javax.xml.parsers.DocumentBuilderFactory;
72 import javax.xml.parsers.DocumentBuilder;
73
74 import org.apache.log4j.Level;
75 import org.apache.log4j.LogManager;
76 import org.apache.log4j.Logger;
77 import org.apache.log4j.chainsaw.PopupListener;
78 import org.apache.log4j.chainsaw.SmallButton;
79 import org.apache.log4j.chainsaw.prefs.SettingsManager;
80 import org.apache.log4j.chainsaw.prefs.SettingsListener;
81 import org.apache.log4j.chainsaw.prefs.SaveSettingsEvent;
82 import org.apache.log4j.chainsaw.prefs.LoadSettingsEvent;
83 import org.apache.log4j.chainsaw.help.HelpManager;
84 import org.apache.log4j.chainsaw.helper.SwingHelper;
85 import org.apache.log4j.chainsaw.icons.ChainsawIcons;
86 import org.apache.log4j.chainsaw.icons.LevelIconFactory;
87 import org.apache.log4j.chainsaw.icons.LineIconFactory;
88 import org.apache.log4j.chainsaw.messages.MessageCenter;
89 import org.apache.log4j.net.SocketNodeEventListener;
90 import org.apache.log4j.net.SocketReceiver;
91 import org.apache.log4j.plugins.Pauseable;
92 import org.apache.log4j.plugins.Plugin;
93 import org.apache.log4j.plugins.PluginEvent;
94 import org.apache.log4j.plugins.PluginListener;
95 import org.apache.log4j.plugins.PluginRegistry;
96 import org.apache.log4j.plugins.Receiver;
97 import org.apache.log4j.spi.LoggerRepository;
98 import org.apache.log4j.spi.LoggerRepositoryEx;
99 import org.w3c.dom.Element;
100 import org.w3c.dom.Document;
101
102
103 /***
104 * This panel is used to manage all the Receivers configured within Log4j
105 *
106 *
107 * @author Paul Smith <psmith@apache.org>
108 * @author Scott Deboy <sdeboy@apache.org>
109 */
110 public class ReceiversPanel extends JPanel implements SettingsListener {
111 final Action newReceiverButtonAction;
112 final Action pauseReceiverButtonAction;
113 final Action playReceiverButtonAction;
114 final Action shutdownReceiverButtonAction;
115 final Action restartReceiverButtonAction;
116 private final Action showReceiverHelpAction;
117 private final Action startAllAction;
118 private final JPopupMenu popupMenu = new ReceiverPopupMenu();
119 private final JTree receiversTree = new JTree();
120 private final NewReceiverPopupMenu newReceiverPopup =
121 new NewReceiverPopupMenu();
122 private final ReceiverToolbar buttonPanel;
123 private final JSplitPane splitter = new JSplitPane();
124 private final PluginPropertyEditorPanel pluginEditorPanel =
125 new PluginPropertyEditorPanel();
126 private final Logger logger = LogManager.getLogger(ReceiversPanel.class);
127
128 private final PluginRegistry pluginRegistry;
129
130
131 public ReceiversPanel() {
132 super(new BorderLayout());
133 LoggerRepository repo = LogManager.getLoggerRepository();
134 final ReceiversTreeModel model = new ReceiversTreeModel();
135 if (repo instanceof LoggerRepositoryEx) {
136 pluginRegistry = ((LoggerRepositoryEx) repo).getPluginRegistry();
137 pluginRegistry.addPluginListener(model);
138
139
140 Collection c = pluginRegistry.getPlugins(VisualReceiver.class);
141 for (Iterator iter = c.iterator();iter.hasNext();) {
142 ((VisualReceiver)iter.next()).setContainer(this);
143 }
144
145 pluginRegistry.addPluginListener(new PluginListener() {
146 public void pluginStarted(PluginEvent e) {
147
148 if (e.getPlugin() instanceof VisualReceiver) {
149 ((VisualReceiver)e.getPlugin()).setContainer(ReceiversPanel.this);
150 }
151 }
152
153 public void pluginStopped(PluginEvent e) {
154 }
155 });
156 } else {
157 pluginRegistry = null;
158 }
159
160 receiversTree.setModel(model);
161
162 receiversTree.setExpandsSelectedPaths(true);
163 model.addTreeModelListener(
164 new TreeModelListener() {
165 public void treeNodesChanged(TreeModelEvent e) {
166 expandRoot();
167 }
168
169 public void treeNodesInserted(TreeModelEvent e) {
170 expandRoot();
171 }
172
173 public void treeNodesRemoved(TreeModelEvent e) {
174 expandRoot();
175 }
176
177 public void treeStructureChanged(TreeModelEvent e) {
178 expandRoot();
179 }
180
181 private void expandRoot() {
182 receiversTree.expandPath(
183 new TreePath(model.getPathToRoot(model.RootNode)));
184 }
185 });
186 receiversTree.expandPath(
187 new TreePath(model.getPathToRoot(model.RootNode)));
188
189 receiversTree.addTreeWillExpandListener(
190 new TreeWillExpandListener() {
191 public void treeWillCollapse(TreeExpansionEvent event)
192 throws ExpandVetoException {
193 if (event.getPath().getLastPathComponent() == model.RootNode) {
194 throw new ExpandVetoException(event);
195 }
196 }
197
198 public void treeWillExpand(TreeExpansionEvent event)
199 throws ExpandVetoException {
200 }
201 });
202
203 receiversTree.addTreeSelectionListener(
204 new TreeSelectionListener() {
205 public void valueChanged(TreeSelectionEvent e) {
206 TreePath path = e.getNewLeadSelectionPath();
207
208 if (path != null) {
209 DefaultMutableTreeNode node =
210 (DefaultMutableTreeNode) path.getLastPathComponent();
211
212 if (
213 (node != null) && (node.getUserObject() != null)
214 && (node.getUserObject() instanceof Plugin)) {
215 Plugin p = (Plugin) node.getUserObject();
216 logger.debug("plugin=" + p);
217 pluginEditorPanel.setPlugin(p);
218 } else {
219 pluginEditorPanel.setPlugin(null);
220 }
221 }
222 }
223 });
224
225 receiversTree.setToolTipText("Allows you to manage Log4j Receivers");
226 newReceiverButtonAction =
227 new AbstractAction() {
228 public void actionPerformed(ActionEvent e) {
229 newReceiverPopup.show(
230 buttonPanel.newReceiverButton, 0,
231 buttonPanel.newReceiverButton.getHeight());
232 }
233 };
234 newReceiverButtonAction.putValue(
235 Action.SMALL_ICON, new ImageIcon(ChainsawIcons.ICON_NEW_RECEIVER));
236 newReceiverButtonAction.putValue(
237 Action.SHORT_DESCRIPTION, "Creates and configures a new Receiver");
238 newReceiverButtonAction.putValue(Action.NAME, "New Receiver");
239 newReceiverButtonAction.putValue(
240 Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_N));
241
242 newReceiverButtonAction.setEnabled(true);
243
244 playReceiverButtonAction =
245 new AbstractAction() {
246 public void actionPerformed(ActionEvent e) {
247 playCurrentlySelectedReceiver();
248 }
249 };
250
251 playReceiverButtonAction.putValue(
252 Action.SHORT_DESCRIPTION, "Resumes the selected Node");
253 playReceiverButtonAction.putValue(Action.NAME, "Resume");
254 playReceiverButtonAction.putValue(
255 Action.SMALL_ICON, new ImageIcon(ChainsawIcons.ICON_RESUME_RECEIVER));
256 playReceiverButtonAction.setEnabled(false);
257 playReceiverButtonAction.putValue(
258 Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_R));
259
260 pauseReceiverButtonAction =
261 new AbstractAction() {
262 public void actionPerformed(ActionEvent e) {
263 pauseCurrentlySelectedReceiver();
264 }
265 };
266
267 pauseReceiverButtonAction.putValue(
268 Action.SHORT_DESCRIPTION,
269 "Pause the selected Receiver. All events received will be discarded.");
270 pauseReceiverButtonAction.putValue(Action.NAME, "Pause");
271
272 pauseReceiverButtonAction.putValue(
273 Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_P));
274
275 pauseReceiverButtonAction.putValue(
276 Action.SMALL_ICON, new ImageIcon(ChainsawIcons.PAUSE));
277 pauseReceiverButtonAction.setEnabled(false);
278
279 shutdownReceiverButtonAction =
280 new AbstractAction() {
281 public void actionPerformed(ActionEvent e) {
282 shutdownCurrentlySelectedReceiver();
283 }
284 };
285
286 shutdownReceiverButtonAction.putValue(
287 Action.SHORT_DESCRIPTION,
288 "Shuts down the selected Receiver, and removes it from the Plugin registry");
289 shutdownReceiverButtonAction.putValue(Action.NAME, "Shutdown");
290
291 shutdownReceiverButtonAction.putValue(
292 Action.SMALL_ICON, new ImageIcon(ChainsawIcons.ICON_STOP_RECEIVER));
293 shutdownReceiverButtonAction.putValue(
294 Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_S));
295
296 shutdownReceiverButtonAction.setEnabled(false);
297 restartReceiverButtonAction =
298 new AbstractAction() {
299 public void actionPerformed(ActionEvent e) {
300 Receiver selectedReceiver = getCurrentlySelectedReceiver();
301 if(selectedReceiver == null){
302 return;
303 }
304 selectedReceiver.shutdown();
305 selectedReceiver.activateOptions();
306 }
307 };
308
309 restartReceiverButtonAction.putValue(
310 Action.SHORT_DESCRIPTION,
311 "Restarts the selected Receiver");
312 restartReceiverButtonAction.putValue(Action.NAME, "Restart");
313
314 restartReceiverButtonAction.putValue(
315 Action.SMALL_ICON, new ImageIcon(ChainsawIcons.ICON_RESTART));
316 restartReceiverButtonAction.putValue(
317 Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_R));
318
319 restartReceiverButtonAction.setEnabled(false);
320
321 showReceiverHelpAction =
322 new AbstractAction("Help") {
323 public void actionPerformed(ActionEvent e) {
324 Receiver receiver = getCurrentlySelectedReceiver();
325
326 if (receiver != null) {
327 HelpManager.getInstance().showHelpForClass(receiver.getClass());
328 }
329 }
330 };
331
332 showReceiverHelpAction.putValue(
333 Action.SMALL_ICON, new ImageIcon(ChainsawIcons.HELP));
334 showReceiverHelpAction.putValue(
335 Action.SHORT_DESCRIPTION, "Displays the JavaDoc page for this Plugin");
336
337 startAllAction =
338 new AbstractAction(
339 "(Re)start All Receivers", new ImageIcon(ChainsawIcons.ICON_RESTART_ALL)) {
340 public void actionPerformed(ActionEvent e) {
341 if (
342 JOptionPane.showConfirmDialog(
343 null,
344 "This will cause any active Receiver to stop, and disconnect. Is this ok?",
345 "Confirm", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
346 new Thread(
347 new Runnable() {
348 public void run() {
349 Collection allReceivers =
350 pluginRegistry.getPlugins(Receiver.class);
351
352 for (Iterator iter = allReceivers.iterator();
353 iter.hasNext();) {
354 Receiver item = (Receiver) iter.next();
355 item.shutdown();
356 item.activateOptions();
357 }
358
359 updateReceiverTreeInDispatchThread();
360 MessageCenter.getInstance().getLogger().info(
361 "All Receivers have been (re)started");
362 }
363 }).start();
364 }
365 }
366 };
367
368 startAllAction.putValue(
369 Action.SHORT_DESCRIPTION,
370 "Ensures that any Receiver that isn't active, is started, and any started action is stopped, and then restarted");
371
372 receiversTree.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
373 receiversTree.setCellRenderer(new ReceiverTreeCellRenderer());
374
375 buttonPanel = new ReceiverToolbar();
376 receiversTree.addTreeSelectionListener(buttonPanel);
377
378 PopupListener popupListener = new PopupListener(popupMenu);
379 receiversTree.addMouseListener(popupListener);
380 this.addMouseListener(popupListener);
381
382 JComponent component = receiversTree;
383 JScrollPane pane = new JScrollPane(component);
384
385 splitter.setOrientation(JSplitPane.VERTICAL_SPLIT);
386
387 splitter.setTopComponent(pane);
388 splitter.setBottomComponent(pluginEditorPanel);
389
390 splitter.setResizeWeight(0.7);
391 add(buttonPanel, BorderLayout.NORTH);
392 add(splitter, BorderLayout.CENTER);
393
394 /***
395 * This Tree likes to be notified when Socket's are accepted so
396 * we listen for them and update the Tree.
397 */
398 SocketNodeEventListener listener =
399 new SocketNodeEventListener() {
400 public void socketOpened(String remoteInfo) {
401 updateReceiverTreeInDispatchThread();
402 }
403
404 public void socketClosedEvent(Exception e) {
405 updateReceiverTreeInDispatchThread();
406 }
407 };
408
409 /***
410 * add this listener to all SocketReceivers
411 */
412 if (pluginRegistry == null) {
413 List socketReceivers =
414 pluginRegistry.getPlugins(SocketReceiver.class);
415
416 for (Iterator iter = socketReceivers.iterator(); iter.hasNext();) {
417 SocketReceiver element = (SocketReceiver) iter.next();
418 element.addSocketNodeEventListener(listener);
419 }
420 }
421 }
422
423 protected ReceiversTreeModel getReceiverTreeModel() {
424 return ((ReceiversTreeModel) receiversTree.getModel());
425 }
426
427 /***
428 *
429 */
430 protected void updateCurrentlySelectedNodeInDispatchThread() {
431 SwingUtilities.invokeLater(
432 new Runnable() {
433 public void run() {
434 DefaultMutableTreeNode node =
435 (DefaultMutableTreeNode) receiversTree
436 .getLastSelectedPathComponent();
437
438 if (node == null) {
439 return;
440 }
441
442 getReceiverTreeModel().nodeChanged(node);
443 updateActions();
444 }
445 });
446 }
447
448 /***
449 * Returns the currently selected Receiver, or null if there is no
450 * selected Receiver (this could be because a) nothing at all is selected
451 * or b) a non Receiver type node is selected
452 *
453 * @return Receiver or null
454 */
455 private Receiver getCurrentlySelectedReceiver() {
456 DefaultMutableTreeNode node =
457 (DefaultMutableTreeNode) receiversTree.getLastSelectedPathComponent();
458
459 if (node == null) {
460 return null;
461 }
462
463 Object userObject = node.getUserObject();
464
465 if (userObject instanceof Receiver) {
466 return (Receiver) userObject;
467 }
468
469 return null;
470 }
471
472 private Receiver[] getSelectedReceivers() {
473 TreePath[] paths = receiversTree.getSelectionPaths();
474 Collection receivers = new ArrayList();
475
476 for (int i = 0; i < paths.length; i++) {
477 TreePath path = paths[i];
478 DefaultMutableTreeNode node =
479 (DefaultMutableTreeNode) path.getLastPathComponent();
480
481 if ((node != null) && node.getUserObject() instanceof Receiver) {
482 receivers.add(node.getUserObject());
483 }
484 }
485
486 return (Receiver[]) receivers.toArray(new Receiver[0]);
487 }
488
489 /***
490 * Returns the currently seleted node's User Object, or null
491 * if there is no selected node, or if the currently selected node has
492 * not user Object
493 * @return Object representing currently seleted Node's User Object
494 */
495 private Object getCurrentlySelectedUserObject() {
496 DefaultMutableTreeNode node =
497 (DefaultMutableTreeNode) receiversTree.getLastSelectedPathComponent();
498
499 if (node == null) {
500 return null;
501 }
502
503 return node.getUserObject();
504 }
505
506 /***
507 * Takes the currently selected Receiver and pauess it, effectively
508 * discarding any received event BEFORE it is even posted to the logger
509 * repository.
510 *
511 * The user is NOT asked to confirm this operation
512 *
513 */
514 private void pauseCurrentlySelectedReceiver() {
515 new Thread(
516 new Runnable() {
517 public void run() {
518 Object obj = getCurrentlySelectedUserObject();
519
520 if ((obj != null) && obj instanceof Pauseable) {
521 ((Pauseable) obj).setPaused(true);
522 updateCurrentlySelectedNodeInDispatchThread();
523 }
524 }
525 }).start();
526 }
527
528 /***
529 * Ensures that the currently selected receiver active property is set to
530 * true
531 *
532 */
533 private void playCurrentlySelectedReceiver() {
534 new Thread(
535 new Runnable() {
536 public void run() {
537 Object obj = getCurrentlySelectedUserObject();
538
539 if ((obj != null) && obj instanceof Pauseable) {
540 ((Pauseable) obj).setPaused(false);
541
542 updateCurrentlySelectedNodeInDispatchThread();
543 }
544 }
545 }).start();
546 }
547
548 /***
549 * Takes the currently selected Receiver and stops it, which effectively
550 * removes it from the PluginRegistry.
551 *
552 * The user is asked to confirm this operation
553 *
554 */
555 private void shutdownCurrentlySelectedReceiver() {
556 if (
557 JOptionPane.showConfirmDialog(
558 null,
559 "Are you sure you wish to shutdown this receiver?\n\nThis will disconnect any network resources, and remove it from the PluginRegistry.",
560 "Confirm stop of Receiver", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
561 new Thread(
562 new Runnable() {
563 public void run() {
564 Receiver[] receivers = getSelectedReceivers();
565
566 if (receivers != null) {
567 for (int i = 0; i < receivers.length; i++) {
568 pluginRegistry.stopPlugin(receivers[i].getName());
569 }
570 }
571 }
572 }).start();
573 }
574 }
575
576 /***
577 * Sets the state of actions depending on certain conditions (i.e what is
578 * currently selected etc.)
579 */
580 private void updateActions() {
581 Object object = getCurrentlySelectedUserObject();
582
583 if ((object != null) && object instanceof Pauseable) {
584 Pauseable pauseable = (Pauseable) object;
585
586 if (!pauseable.isPaused()) {
587 pauseReceiverButtonAction.setEnabled(true);
588 playReceiverButtonAction.setEnabled(false);
589 } else {
590 pauseReceiverButtonAction.setEnabled(false);
591 playReceiverButtonAction.setEnabled(true);
592 }
593 } else {
594 pauseReceiverButtonAction.setEnabled(false);
595 playReceiverButtonAction.setEnabled(false);
596 }
597
598 if (object instanceof Receiver) {
599 newReceiverButtonAction.setEnabled(true);
600 shutdownReceiverButtonAction.setEnabled(true);
601 restartReceiverButtonAction.setEnabled(true);
602 } else {
603 shutdownReceiverButtonAction.setEnabled(false);
604 restartReceiverButtonAction.setEnabled(false);
605 }
606 }
607
608 /***
609 * Ensures that the Receiver tree is updated with the latest information
610 * and that this operation occurs in the Swing Event Dispatch thread.
611 *
612 */
613 public void updateReceiverTreeInDispatchThread() {
614 logger.debug(
615 "updateReceiverTreeInDispatchThread, should not be needed now");
616
617
618
619
620
621
622 }
623
624
625
626
627 public void setVisible(boolean aFlag) {
628 boolean oldValue = isVisible();
629 super.setVisible(aFlag);
630 firePropertyChange("visible", oldValue, isVisible());
631 }
632
633 public void loadSettings(LoadSettingsEvent event){}
634
635 /***
636 * Saves all the receivers which are active at shut down as a configuration
637 * file which can be loaded when Chainsaw will be restarted.
638 */
639
640 public void saveSettings(SaveSettingsEvent event){
641 List pluginList = pluginRegistry.getPlugins();
642
643 try {
644 if (pluginList.size() != 0) {
645 File file = new File(SettingsManager.getInstance().getSettingsDirectory(), "receiver-configs.xml");
646 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
647 factory.setNamespaceAware(true);
648 DocumentBuilder builder = factory.newDocumentBuilder();
649 Document document = builder.newDocument();
650 Element rootElement = document.createElementNS("http://jakarta.apache.org/log4j/", "configuration");
651 rootElement.setPrefix("log4j");
652 rootElement.setAttribute("xmlns:log4j", "http://jakarta.apache.org/log4j/");
653 rootElement.setAttribute("debug", "true");
654
655 for (int i = 0; i < pluginList.size(); i++) {
656 Receiver receiver;
657
658 if (pluginList.get(i) instanceof Receiver) {
659 receiver = (Receiver) pluginList.get(i);
660 } else {
661 continue;
662 }
663
664 Element pluginElement = document.createElement("plugin");
665 pluginElement.setAttribute("name", receiver.getName());
666 pluginElement.setAttribute("class", receiver.getClass().getName());
667
668 BeanInfo beanInfo = Introspector.getBeanInfo(receiver.getClass());
669 List list = new ArrayList(Arrays.asList(beanInfo.getPropertyDescriptors()));
670
671 for (int j = 0; j < list.size(); j++) {
672 PropertyDescriptor d = (PropertyDescriptor) list.get(j);
673
674 Object o = d.getReadMethod().invoke(receiver, new Object[] {} );
675 if (o != null) {
676 Element paramElement = document.createElement("param");
677 paramElement.setAttribute("name", d.getName());
678 paramElement.setAttribute("value", o.toString());
679 pluginElement.appendChild(paramElement);
680 }
681 }
682
683 rootElement.appendChild(pluginElement);
684
685 }
686
687 TransformerFactory transformerFactory = TransformerFactory.newInstance();
688 Transformer transformer = transformerFactory.newTransformer();
689 DOMSource source = new DOMSource(rootElement);
690 FileOutputStream stream = new FileOutputStream(file);
691 StreamResult result = new StreamResult(stream);
692 transformer.transform(source, result);
693 stream.close();
694 }
695
696 } catch (Exception e) {
697 e.printStackTrace();
698 logger.error("Error while writing receiver configurations to the configuration file");
699 }
700
701 }
702
703 /***
704 * A popup menu that allows the user to choose which
705 * style of Receiver to create, which spawns a relevant Dialog
706 * to enter the information and create the Receiver
707 *
708 * @author Paul Smith <psmith@apache.org>
709 *
710 */
711 class NewReceiverPopupMenu extends JPopupMenu {
712 NewReceiverPopupMenu() {
713 try {
714 final List receiverList =
715 ReceiversHelper.getInstance().getKnownReceiverClasses();
716 String separatorCheck = null;
717
718 for (Iterator iter = receiverList.iterator(); iter.hasNext();) {
719 final Class toCreate = (Class) iter.next();
720 Package thePackage = toCreate.getPackage();
721 final String name =
722 toCreate.getName().substring(thePackage.getName().length() + 1);
723
724 if (separatorCheck == null) {
725 separatorCheck = name.substring(0, 1);
726 } else {
727 String current = name.substring(0, 1);
728
729 if (!current.equals(separatorCheck)) {
730 addSeparator();
731 separatorCheck = current;
732 }
733 }
734
735 add(
736 new AbstractAction("New " + name + "...") {
737 public void actionPerformed(ActionEvent e) {
738 Container container = SwingUtilities.getAncestorOfClass(JFrame.class, ReceiversPanel.this);
739 final JDialog dialog = new JDialog((JFrame) container,"New " + toCreate.getName() + "..." ,true);
740
741 try {
742 final NewReceiverDialogPanel panel =
743 NewReceiverDialogPanel.create(toCreate);
744 dialog.getContentPane().add(panel);
745 dialog.pack();
746 SwingHelper.centerOnScreen(dialog);
747
748 /***
749 * Make the default button the ok button
750 */
751 dialog.getRootPane().setDefaultButton(panel.getOkPanel().getOkButton());
752
753 /***
754 * Use the standard Cancel metaphor
755 */
756 SwingHelper.configureCancelForDialog(dialog, panel.getOkPanel().getCancelButton());
757
758
759 panel.getOkPanel().getOkButton().addActionListener(
760 new ActionListener() {
761 public void actionPerformed(ActionEvent e2) {
762 dialog.dispose();
763 Plugin plugin = panel.getPlugin();
764 pluginRegistry.addPlugin(plugin);
765 plugin.activateOptions();
766 MessageCenter.getInstance().addMessage("Plugin '" + plugin.getName() + "' started");
767 }
768 });
769 dialog.setVisible(true);
770 } catch (Exception e1) {
771 e1.printStackTrace();
772 MessageCenter.getInstance().getLogger().error(
773 "Failed to create the new Receiver dialog", e1);
774 }
775 }
776 });
777 }
778 } catch (Exception e) {
779 e.printStackTrace();
780 throw new RuntimeException(e.getMessage());
781 }
782 }
783 }
784
785 /***
786 * A popup menu class for when the user uses the popup trigger action
787 * on a node in the Receiver tree.
788 *
789 * @author Paul Smith <psmith@apache.org>
790 *
791 */
792 class ReceiverPopupMenu extends JPopupMenu {
793 ReceiverPopupMenu() {
794 }
795
796
797
798
799 public void show(Component invoker, int x, int y) {
800 DefaultMutableTreeNode node =
801 (DefaultMutableTreeNode) receiversTree.getLastSelectedPathComponent();
802
803 if (node == null) {
804 return;
805 }
806
807 Object userObject = node.getUserObject();
808 removeAll();
809
810 if (userObject == getRootOfTree().getUserObject()) {
811 buildForReceiversRoot();
812 } else if (getCurrentlySelectedReceiver() != null) {
813 buildForReceiverNode();
814 } else {
815 return;
816 }
817
818 this.invalidate();
819 this.validate();
820
821 super.show(invoker, x, y);
822 }
823
824 /***
825 *
826 */
827 private DefaultMutableTreeNode getRootOfTree() {
828 return (DefaultMutableTreeNode) receiversTree.getModel().getRoot();
829 }
830
831 /***
832 * Builds the popup menu with relevant items for a selected
833 * Receiver node in the Tree.
834 */
835 private void buildForReceiverNode() {
836
837 add(playReceiverButtonAction);
838 add(pauseReceiverButtonAction);
839 add(restartReceiverButtonAction);
840 add(shutdownReceiverButtonAction);
841 addSeparator();
842
843 final Receiver r = getCurrentlySelectedReceiver();
844 add(createLevelRadioButton(r, Level.TRACE));
845 add(createLevelRadioButton(r, Level.DEBUG));
846 add(createLevelRadioButton(r, Level.INFO));
847 add(createLevelRadioButton(r, Level.WARN));
848 add(createLevelRadioButton(r, Level.ERROR));
849 addSeparator();
850 add(createLevelRadioButton(r, Level.OFF));
851 add(createLevelRadioButton(r, Level.ALL));
852 addSeparator();
853 add(showReceiverHelpAction);
854 }
855
856 private JRadioButtonMenuItem createLevelRadioButton(
857 final Receiver r, final Level l) {
858 Map levelIconMap = LevelIconFactory.getInstance().getLevelToIconMap();
859
860 Action action =
861 new AbstractAction(
862 l.toString(), (Icon) levelIconMap.get(l.toString())) {
863 public void actionPerformed(ActionEvent e) {
864 if (r != null) {
865 r.setThreshold(l);
866 updateCurrentlySelectedNodeInDispatchThread();
867 }
868 }
869 };
870
871 JRadioButtonMenuItem item = new JRadioButtonMenuItem(action);
872 item.setSelected(r.getThreshold() == l);
873
874 return item;
875 }
876
877 /***
878 * Builds a relevant set of menus for when the Root node in the Receiver
879 * tree has been selected
880 *
881 */
882 private void buildForReceiversRoot() {
883 JMenuItem startAll = new JMenuItem(startAllAction);
884
885 add(newReceiverButtonAction);
886
887 addSeparator();
888 add(startAll);
889 }
890 }
891
892 /***
893 * A simple Panel that has toolbar buttons for restarting,
894 * playing, pausing, and stoping receivers
895 *
896 * @author Paul Smith <psmith@apache.org>
897 *
898 */
899 private class ReceiverToolbar extends JToolBar
900 implements TreeSelectionListener {
901 final SmallButton newReceiverButton;
902
903 private ReceiverToolbar() {
904 setFloatable(false);
905
906 SmallButton restartReceiverButton = new SmallButton(restartReceiverButtonAction);
907 restartReceiverButton.setText(null);
908
909 SmallButton shutdownReceiverButton =
910 new SmallButton(shutdownReceiverButtonAction);
911 shutdownReceiverButton.setText(null);
912
913 SmallButton restartAllButton = new SmallButton(startAllAction);
914 restartAllButton.setText(null);
915
916
917
918 newReceiverButton = new SmallButton(newReceiverButtonAction);
919 newReceiverButton.setText(null);
920 newReceiverButton.addMouseListener(new PopupListener(newReceiverPopup));
921
922 add(newReceiverButton);
923 add(restartAllButton);
924
925 addSeparator();
926
927 add(restartReceiverButton);
928 add(shutdownReceiverButton);
929
930 addSeparator();
931
932 Action closeAction =
933 new AbstractAction(null, LineIconFactory.createCloseIcon()) {
934 public void actionPerformed(ActionEvent e) {
935 ReceiversPanel.this.setVisible(false);
936 }
937 };
938
939 closeAction.putValue(
940 Action.SHORT_DESCRIPTION, "Closes the Receiver panel");
941
942 add(Box.createHorizontalGlue());
943
944 add(new SmallButton(closeAction));
945
946 add(Box.createHorizontalStrut(5));
947 }
948
949 /***
950 * Ensures the enabled property of the actions is set properly
951 * according to the currently selected node in the tree
952 */
953 public void valueChanged(TreeSelectionEvent e) {
954 updateActions();
955 }
956 }
957 }