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  package org.apache.log4j.chainsaw;
    18
    19  import java.awt.BorderLayout;
    20  import java.awt.Dimension;
    21  import java.awt.event.WindowAdapter;
    22  import java.awt.event.WindowEvent;
    23  import java.io.IOException;
    24  import java.util.Properties;
    25  import javax.swing.BorderFactory;
    26  import javax.swing.JFrame;
    27  import javax.swing.JMenu;
    28  import javax.swing.JMenuBar;
    29  import javax.swing.JMenuItem;
    30  import javax.swing.JOptionPane;
    31  import javax.swing.JPanel;
    32  import javax.swing.JScrollPane;
    33  import javax.swing.JSplitPane;
    34  import javax.swing.JTable;
    35  import javax.swing.ListSelectionModel;
    36  import org.apache.log4j.Logger;
    37  import org.apache.log4j.PropertyConfigurator;
    38
    39  /***
    40   * The main application.
    41   *
    42   * @author <a href="mailto:oliver@puppycrawl.com">Oliver Burn</a>
    43   */
    44  public class Main
    45      extends JFrame
    46  {
    47      /*** the default port number to listen on **/
    48      private static final int DEFAULT_PORT = 4445;
    49
    50      /*** name of property for port name **/
    51      public static final String PORT_PROP_NAME = "chainsaw.port";
    52
    53      /*** use to log messages **/
    54      private static final Logger LOG = Logger.getLogger(Main.class);
    55
    56
    57      /***
    58       * Creates a new <code>Main</code> instance.
    59       */
    60      private Main() {
    61          super("CHAINSAW - Log4J Log Viewer");
    62          // create the all important model
    63          final MyTableModel model = new MyTableModel();
    64
    65          //Create the menu bar.
    66          final JMenuBar menuBar = new JMenuBar();
    67          setJMenuBar(menuBar);
    68          final JMenu menu = new JMenu("File");
    69          menuBar.add(menu);
    70
    71          try {
    72              final LoadXMLAction lxa = new LoadXMLAction(this, model);
    73              final JMenuItem loadMenuItem = new JMenuItem("Load file...");
    74              menu.add(loadMenuItem);
    75              loadMenuItem.addActionListener(lxa);
    76          } catch (NoClassDefFoundError e) {
    77              LOG.info("Missing classes for XML parser", e);
    78              JOptionPane.showMessageDialog(
    79                  this,
    80                  "XML parser not in classpath - unable to load XML events.",
    81                  "CHAINSAW",
    82                  JOptionPane.ERROR_MESSAGE);
    83          } catch (Exception e) {
    84              LOG.info("Unable to create the action to load XML files", e);
    85              JOptionPane.showMessageDialog(
    86                  this,
    87                  "Unable to create a XML parser - unable to load XML events.",
    88                  "CHAINSAW",
    89                  JOptionPane.ERROR_MESSAGE);
    90          }
    91
    92          final JMenuItem exitMenuItem = new JMenuItem("Exit");
    93          menu.add(exitMenuItem);
    94          exitMenuItem.addActionListener(ExitAction.INSTANCE);
    95
    96          // Add control panel
    97          final ControlPanel cp = new ControlPanel(model);
    98          getContentPane().add(cp, BorderLayout.NORTH);
    99
    100         // Create the table
    101         final JTable table = new JTable(model);
    102         table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    103         final JScrollPane scrollPane = new JScrollPane(table);
    104         scrollPane.setBorder(BorderFactory.createTitledBorder("Events: "));
    105         scrollPane.setPreferredSize(new Dimension(900, 300));
    106
    107         // Create the details
    108         final JPanel details = new DetailPanel(table, model);
    109         details.setPreferredSize(new Dimension(900, 300));
    110
    111         // Add the table and stack trace into a splitter
    112         final JSplitPane jsp =
    113             new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPane, details);
    114         getContentPane().add(jsp, BorderLayout.CENTER);
    115
    116         addWindowListener(new WindowAdapter() {
    117                 public void windowClosing(WindowEvent aEvent) {
    118                     ExitAction.INSTANCE.actionPerformed(null);
    119                 }
    120             });
    121
    122         pack();
    123         setVisible(true);
    124
    125         setupReceiver(model);
    126     }
    127
    128     /***
    129      * Setup recieving messages.
    130      *
    131      * @param aModel a <code>MyTableModel</code> value
    132      */
    133     private void setupReceiver(MyTableModel aModel) {
    134         int port = DEFAULT_PORT;
    135         final String strRep = System.getProperty(PORT_PROP_NAME);
    136         if (strRep != null) {
    137             try {
    138                 port = Integer.parseInt(strRep);
    139             } catch (NumberFormatException nfe) {
    140                 LOG.fatal("Unable to parse " + PORT_PROP_NAME +
    141                           " property with value " + strRep + ".");
    142                 JOptionPane.showMessageDialog(
    143                     this,
    144                     "Unable to parse port number from '" + strRep +
    145                     "', quitting.",
    146                     "CHAINSAW",
    147                     JOptionPane.ERROR_MESSAGE);
    148                 System.exit(1);
    149             }
    150         }
    151
    152         try {
    153             final LoggingReceiver lr = new LoggingReceiver(aModel, port);
    154             lr.start();
    155         } catch (IOException e) {
    156             LOG.fatal("Unable to connect to socket server, quiting", e);
    157             JOptionPane.showMessageDialog(
    158                 this,
    159                 "Unable to create socket on port " + port + ", quitting.",
    160                 "CHAINSAW",
    161                 JOptionPane.ERROR_MESSAGE);
    162             System.exit(1);
    163         }
    164     }
    165
    166
    167     ////////////////////////////////////////////////////////////////////////////
    168     // static methods
    169     ////////////////////////////////////////////////////////////////////////////
    170
    171
    172     /*** initialise log4j **/
    173     private static void initLog4J() {
    174         final Properties props = new Properties();
    175         props.setProperty("log4j.rootLogger", "DEBUG, A1");
    176         props.setProperty("log4j.appender.A1",
    177                           "org.apache.log4j.ConsoleAppender");
    178         props.setProperty("log4j.appender.A1.layout",
    179                           "org.apache.log4j.TTCCLayout");
    180         PropertyConfigurator.configure(props);
    181     }
    182
    183     /***
    184      * The main method.
    185      *
    186      * @param aArgs ignored
    187      */
    188     public static void main(String[] aArgs) {
    189         initLog4J();
    190         new Main();
    191     }
    192 }