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