/* * Copyright 1999-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.log4j.lf5; import org.apache.log4j.lf5.util.Resource; import org.apache.log4j.lf5.viewer.LogBrokerMonitor; import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.spi.LocationInfo; import org.apache.log4j.spi.LoggingEvent; import java.awt.*; /** * <code>LF5Appender</code> logs events to a swing based logging * console. The swing console supports turning categories on and off, * multiple detail level views, as well as full text searching and many * other capabilties. * * @author Brent Sprecher */ // Contributed by ThoughtWorks Inc. public class LF5Appender extends AppenderSkeleton { //-------------------------------------------------------------------------- // Constants: //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // Protected Variables: //-------------------------------------------------------------------------- protected LogBrokerMonitor _logMonitor; protected static LogBrokerMonitor _defaultLogMonitor; protected static AppenderFinalizer _finalizer; //-------------------------------------------------------------------------- // Private Variables: //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // Constructors: //-------------------------------------------------------------------------- /** * Constructs a <code>LF5Appender</code> using the default instance of * the <code>LogBrokerMonitor</code>. This constructor should <bold>always * </bold> be preferred over the * <code>LF5Appender(LogBrokerMonitor monitor)</code> * constructor, unless you need to spawn additional log monitoring * windows. */ public LF5Appender() { this(getDefaultInstance()); } /** * Constructs a <code>LF5Appender<code> using an instance of * a <code>LogBrokerMonitor<code> supplied by the user. This * constructor should only be used when you need to spawn * additional log monitoring windows. * * @param monitor An instance of a <code>LogBrokerMonitor<code> * created by the user. */ public LF5Appender(LogBrokerMonitor monitor) { if (monitor != null) { _logMonitor = monitor; } } //-------------------------------------------------------------------------- // Public Methods: //-------------------------------------------------------------------------- /** * Appends a <code>LoggingEvent</code> record to the * <code>LF5Appender</code>. * @param event The <code>LoggingEvent</code> * to be appended. */ public void append(LoggingEvent event) { // Retrieve the information from the log4j LoggingEvent. String category = event.getLoggerName(); String logMessage = event.getRenderedMessage(); String nestedDiagnosticContext = event.getNDC(); String threadDescription = event.getThreadName(); String level = event.getLevel().toString(); long time = event.timeStamp; LocationInfo locationInfo = event.getLocationInformation(); // Add the logging event information to a LogRecord Log4JLogRecord record = new Log4JLogRecord(); record.setCategory(category); record.setMessage(logMessage); record.setLocation(locationInfo.fullInfo); record.setMillis(time); record.setThreadDescription(threadDescription); if (nestedDiagnosticContext != null) { record.setNDC(nestedDiagnosticContext); } else { record.setNDC(""); } if (event.getThrowableInformation() != null) { record.setThrownStackTrace(event.getThrowableInformation()); } try { record.setLevel(LogLevel.valueOf(level)); } catch (LogLevelFormatException e) { // If the priority level doesn't match one of the predefined // log levels, then set the level to warning. record.setLevel(LogLevel.WARN); } if (_logMonitor != null) { _logMonitor.addMessage(record); } } /** * This method is an empty implementation of the close() method inherited * from the <code>org.apache.log4j.Appender</code> interface. */ public void close() { } /** * Returns a value that indicates whether this appender requires a * <code>Layout</code>. This method always returns false. * No layout is required for the <code>LF5Appender</code>. */ public boolean requiresLayout() { return false; } /** * This method is used to set the property that controls whether * the <code>LogBrokerMonitor</code> is hidden or closed when a user * exits * the monitor. By default, the <code>LogBrokerMonitor</code> will hide * itself when the log window is exited, and the swing thread will * continue to run in the background. If this property is * set to true, the <code>LogBrokerMonitor</code> will call System.exit(0) * and will shut down swing thread and the virtual machine. * * @param callSystemExitOnClose A boolean value indicating whether * to call System.exit(0) when closing the log window. */ public void setCallSystemExitOnClose(boolean callSystemExitOnClose) { _logMonitor.setCallSystemExitOnClose(callSystemExitOnClose); } /** * The equals method compares two LF5Appenders and determines whether * they are equal. Two <code>Appenders</code> will be considered equal * if, and only if, they both contain references to the same <code> * LogBrokerMonitor</code>. * * @param compareTo A boolean value indicating whether * the two LF5Appenders are equal. */ public boolean equals(LF5Appender compareTo) { // If both reference the same LogBrokerMonitor, they are equal. return _logMonitor == compareTo.getLogBrokerMonitor(); } public LogBrokerMonitor getLogBrokerMonitor() { return _logMonitor; } public static void main(String[] args) { new LF5Appender(); } public void setMaxNumberOfRecords(int maxNumberOfRecords) { _defaultLogMonitor.setMaxNumberOfLogRecords(maxNumberOfRecords); } //-------------------------------------------------------------------------- // Protected Methods: //-------------------------------------------------------------------------- /** * @return The default instance of the <code>LogBrokerMonitor</code>. */ protected static synchronized LogBrokerMonitor getDefaultInstance() { if (_defaultLogMonitor == null) { try { _defaultLogMonitor = new LogBrokerMonitor(LogLevel.getLog4JLevels()); _finalizer = new AppenderFinalizer(_defaultLogMonitor); _defaultLogMonitor.setFrameSize(getDefaultMonitorWidth(), getDefaultMonitorHeight()); _defaultLogMonitor.setFontSize(12); _defaultLogMonitor.show(); } catch (SecurityException e) { _defaultLogMonitor = null; } } return _defaultLogMonitor; } /** * @return the screen width from Toolkit.getScreenSize() * if possible, otherwise returns 800 * @see java.awt.Toolkit */ protected static int getScreenWidth() { try { return Toolkit.getDefaultToolkit().getScreenSize().width; } catch (Throwable t) { return 800; } } /** * @return the screen height from Toolkit.getScreenSize() * if possible, otherwise returns 600 * @see java.awt.Toolkit */ protected static int getScreenHeight() { try { return Toolkit.getDefaultToolkit().getScreenSize().height; } catch (Throwable t) { return 600; } } protected static int getDefaultMonitorWidth() { return (3 * getScreenWidth()) / 4; } protected static int getDefaultMonitorHeight() { return (3 * getScreenHeight()) / 4; } //-------------------------------------------------------------------------- // Private Methods: //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // Nested Top-Level Classes or Interfaces: //-------------------------------------------------------------------------- }