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.lf5;
    19
    20  import java.awt.Toolkit;
    21
    22  import org.apache.log4j.AppenderSkeleton;
    23  import org.apache.log4j.lf5.viewer.LogBrokerMonitor;
    24  import org.apache.log4j.spi.LocationInfo;
    25  import org.apache.log4j.spi.LoggingEvent;
    26
    27  /**
    28   * <code>LF5Appender</code> logs events to a swing based logging
    29   * console. The swing console supports turning categories on and off,
    30   * multiple detail level views, as well as full text searching and many
    31   * other capabilties.
    32   *
    33   * @author Brent Sprecher
    34   */
    35
    36  // Contributed by ThoughtWorks Inc.
    37
    38  public class LF5Appender extends AppenderSkeleton {
    39    //--------------------------------------------------------------------------
    40    // Constants:
    41    //--------------------------------------------------------------------------
    42
    43    //--------------------------------------------------------------------------
    44    // Protected Variables:
    45    //--------------------------------------------------------------------------
    46
    47    protected LogBrokerMonitor _logMonitor;
    48    protected static LogBrokerMonitor _defaultLogMonitor;
    49    protected static AppenderFinalizer _finalizer;
    50
    51    //--------------------------------------------------------------------------
    52    // Private Variables:
    53    //--------------------------------------------------------------------------
    54
    55    //--------------------------------------------------------------------------
    56    // Constructors:
    57    //--------------------------------------------------------------------------
    58
    59    /**
    60     * Constructs a <code>LF5Appender</code> using the default instance of
    61     * the <code>LogBrokerMonitor</code>. This constructor should <bold>always
    62     * </bold> be  preferred over the
    63     * <code>LF5Appender(LogBrokerMonitor monitor)</code>
    64     * constructor, unless you need to spawn additional log monitoring
    65     * windows.
    66     */
    67    public LF5Appender() {
    68      this(getDefaultInstance());
    69    }
    70
    71    /**
    72     * Constructs a <code>LF5Appender<code> using an instance of
    73     * a <code>LogBrokerMonitor<code> supplied by the user. This
    74     * constructor should only be used when you need to spawn
    75     * additional log monitoring windows.
    76     *
    77     * @param monitor An instance of a <code>LogBrokerMonitor<code>
    78     * created by the user.
    79     */
    80    public LF5Appender(LogBrokerMonitor monitor) {
    81
    82      if (monitor != null) {
    83        _logMonitor = monitor;
    84      }
    85    }
    86
    87    //--------------------------------------------------------------------------
    88    // Public Methods:
    89    //--------------------------------------------------------------------------
    90
    91    /**
    92     * Appends a <code>LoggingEvent</code> record to the
    93     * <code>LF5Appender</code>.
    94     * @param event The <code>LoggingEvent</code>
    95     * to be appended.
    96     */
    97    public void append(LoggingEvent event) {
    98      // Retrieve the information from the log4j LoggingEvent.
    99      String category = event.getLoggerName();
    100     String logMessage = event.getRenderedMessage();
    101     String nestedDiagnosticContext = event.getNDC();
    102     String threadDescription = event.getThreadName();
    103     String level = event.getLevel().toString();
    104     long time = event.timeStamp;
    105     LocationInfo locationInfo = event.getLocationInformation();
    106
    107     // Add the logging event information to a LogRecord
    108     Log4JLogRecord record = new Log4JLogRecord();
    109
    110     record.setCategory(category);
    111     record.setMessage(logMessage);
    112     record.setLocation(locationInfo.fullInfo);
    113     record.setMillis(time);
    114     record.setThreadDescription(threadDescription);
    115
    116     if (nestedDiagnosticContext != null) {
    117       record.setNDC(nestedDiagnosticContext);
    118     } else {
    119       record.setNDC("");
    120     }
    121
    122     if (event.getThrowableInformation() != null) {
    123       record.setThrownStackTrace(event.getThrowableInformation());
    124     }
    125
    126     try {
    127       record.setLevel(LogLevel.valueOf(level));
    128     } catch (LogLevelFormatException e) {
    129       // If the priority level doesn't match one of the predefined
    130       // log levels, then set the level to warning.
    131       record.setLevel(LogLevel.WARN);
    132     }
    133
    134     if (_logMonitor != null) {
    135       _logMonitor.addMessage(record);
    136     }
    137   }
    138
    139   /**
    140    * This method is an empty implementation of the close() method inherited
    141    * from the <code>org.apache.log4j.Appender</code> interface.
    142    */
    143   public void close() {
    144   }
    145
    146   /**
    147    * Returns a value that indicates whether this appender requires a
    148    * <code>Layout</code>. This method always returns false.
    149    * No layout is required for the <code>LF5Appender</code>.
    150    */
    151   public boolean requiresLayout() {
    152     return false;
    153   }
    154
    155   /**
    156    * This method is used to set the property that controls whether
    157    * the <code>LogBrokerMonitor</code> is hidden or closed when a user
    158    * exits
    159    * the monitor. By default, the <code>LogBrokerMonitor</code> will hide
    160    * itself when the log window is exited, and the swing thread will
    161    * continue to run in the background. If this property is
    162    * set to true, the <code>LogBrokerMonitor</code> will call System.exit(0)
    163    * and will shut down swing thread and the virtual machine.
    164    *
    165    * @param callSystemExitOnClose A boolean value indicating whether
    166    * to call System.exit(0) when closing the log window.
    167    */
    168   public void setCallSystemExitOnClose(boolean callSystemExitOnClose) {
    169     _logMonitor.setCallSystemExitOnClose(callSystemExitOnClose);
    170   }
    171
    172   /**
    173    * The equals method compares two LF5Appenders and determines whether
    174    * they are equal. Two <code>Appenders</code> will be considered equal
    175    * if, and only if, they both contain references to the same <code>
    176    * LogBrokerMonitor</code>.
    177    *
    178    * @param compareTo A boolean value indicating whether
    179    * the two LF5Appenders are equal.
    180    */
    181   public boolean equals(LF5Appender compareTo) {
    182     // If both reference the same LogBrokerMonitor, they are equal.
    183     return _logMonitor == compareTo.getLogBrokerMonitor();
    184   }
    185
    186   public LogBrokerMonitor getLogBrokerMonitor() {
    187     return _logMonitor;
    188   }
    189
    190   public static void main(String[] args) {
    191     new LF5Appender();
    192   }
    193
    194   public void setMaxNumberOfRecords(int maxNumberOfRecords) {
    195     _defaultLogMonitor.setMaxNumberOfLogRecords(maxNumberOfRecords);
    196   }
    197   //--------------------------------------------------------------------------
    198   // Protected Methods:
    199   //--------------------------------------------------------------------------
    200
    201   /**
    202    * @return The default instance of the <code>LogBrokerMonitor</code>.
    203    */
    204   protected static synchronized LogBrokerMonitor getDefaultInstance() {
    205     if (_defaultLogMonitor == null) {
    206       try {
    207         _defaultLogMonitor =
    208             new LogBrokerMonitor(LogLevel.getLog4JLevels());
    209         _finalizer = new AppenderFinalizer(_defaultLogMonitor);
    210
    211         _defaultLogMonitor.setFrameSize(getDefaultMonitorWidth(),
    212             getDefaultMonitorHeight());
    213         _defaultLogMonitor.setFontSize(12);
    214         _defaultLogMonitor.show();
    215
    216       } catch (SecurityException e) {
    217         _defaultLogMonitor = null;
    218       }
    219     }
    220
    221     return _defaultLogMonitor;
    222   }
    223
    224   /**
    225    * @return the screen width from Toolkit.getScreenSize()
    226    * if possible, otherwise returns 800
    227    * @see java.awt.Toolkit
    228    */
    229   protected static int getScreenWidth() {
    230     try {
    231       return Toolkit.getDefaultToolkit().getScreenSize().width;
    232     } catch (Throwable t) {
    233       return 800;
    234     }
    235   }
    236
    237   /**
    238    * @return the screen height from Toolkit.getScreenSize()
    239    * if possible, otherwise returns 600
    240    * @see java.awt.Toolkit
    241    */
    242   protected static int getScreenHeight() {
    243     try {
    244       return Toolkit.getDefaultToolkit().getScreenSize().height;
    245     } catch (Throwable t) {
    246       return 600;
    247     }
    248   }
    249
    250   protected static int getDefaultMonitorWidth() {
    251     return (3 * getScreenWidth()) / 4;
    252   }
    253
    254   protected static int getDefaultMonitorHeight() {
    255     return (3 * getScreenHeight()) / 4;
    256   }
    257   //--------------------------------------------------------------------------
    258   // Private Methods:
    259   //--------------------------------------------------------------------------
    260
    261
    262   //--------------------------------------------------------------------------
    263   // Nested Top-Level Classes or Interfaces:
    264   //--------------------------------------------------------------------------
    265
    266 }