net.sf.eBus.util.logging.PatternFormatter Maven / Gradle / Ivy
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later
// version.
//
// This library is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this library; if not, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA
// 02111-1307 USA
//
// The Initial Developer of the Original Code is Charles W. Rapp.
// Portions created by Charles W. Rapp are
// Copyright (C) 2001 - 2008, 2013. Charles W. Rapp.
// All Rights Reserved.
//
package net.sf.eBus.util.logging;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Formatter;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
/**
* Formats {@code LogRecord}s using {@code printf}-like
* format specifiers.
* The pattern string contains either plain characters and format
* specifiers. Plain characters are copied to the log message
* verbatim. The format string uses format specifiers
* similar to the C standard library {@code printf}
* subroutine.
*
* Format specifiers are of the form "%<letter>". The table
* below lists the supported specifier letters:
*
* Regular Expression Specifier Letters
*
* Specifier Letter
* Takes Modifiers?
* Description
*
*
*
* C
*
*
* Yes.
*
*
* Place the log record's source class name in the
* location.
*
*
*
*
* d
*
*
* Yes
*
*
* Place the current date and time in the location using
* the default Java format
* {@code java.text.DateFormat.DEFAULT}.
*
* The default may be overridden using the extended %d
* specifier %d{<date pattern>}
.
* <date pattern> will be passed to
* {@link java.text.SimpleDateFormat#SimpleDateFormat(String)}
* constructor (which see). If {@link SimpleDateFormat}
* rejects the date pattern by throwing an exception, the
* exception will pass through to your application.
*
*
*
*
* e
*
*
* Yes.
*
*
* Place the LogRecord's throwable message in the location.
* If the record's throwable is {@code null}, then
* nothing is output.
*
*
*
*
* E
*
*
* No.
*
*
* Place the LogRecord's throwable stack trace in the
* location but on the next line. If the record's throwable
* is {@code null}, then nothing is output.
*
* Note: the stack trace is written on a new line.
* It is not necessary to have "%n%E" in your pattern.
*
*
*
*
* l
*
*
* Yes.
*
*
* Place the log record's log level in the location.
*
*
*
*
* m
*
*
* Yes.
*
*
* Place the log record's message in the location.
*
*
*
*
* M
*
*
* Yes.
*
*
* Place the log record's source method name in the
* location.
*
*
*
*
* n
*
*
* No.
*
*
* Places the platform-dependent end-of-line marker at the
* location.
*
*
*
*
* N
*
*
* Yes.
*
*
* Place the log record's source Logger name in the
* location.
*
*
*
*
* s
*
*
* Yes.
*
*
* Place the log record's sequence number in the location.
*
*
*
*
* t
*
*
* Yes.
*
*
* Place the log record's thread identifier in the
* location.
*
*
*
*
* %
*
*
* No.
*
*
* Place the '%' character in the message at this location.
*
*
*
*
* These specifiers may be further modified with a justification
* marker, minimum width and maximum width. These modifiers are
* placed between the '%' and the specifier letter. The format
* specifier syntax is:
*
* %[-][min width][.max width]<letter>
.
*
* where a "-" denotes left justification. If "-" is used, then
* "min width" must also be used.
*
* The date specifier also allows for the date format suffix:
*
* %<modifiers>d{<date format>}
*
* The table below describes how these modifiers can be used
* in different combinations for different affects:
*
*
* Pattern Modifiers
*
* Format Modifier
* Justification
* Minimum Width
* Maximum Width
* Description
*
*
*
* %m
*
*
* None
*
*
* None
*
*
* None
*
*
* Output the localized log message in its entirity.
*
*
*
*
* %20m
*
*
* Right
*
*
* 20
*
*
* None
*
*
* Generates the localized log message. If the result is
* less than the minimum width, prepends spaces until the
* minimum width is reached.
*
*
*
*
* %-20m
*
*
* Left
*
*
* 20
*
*
* None
*
*
* Generates the localized log message. If the result is
* less than the minimum width, appends spaces until the
* minimum width is reached.
*
*
*
*
* %.40m
*
*
* None
*
*
* None
*
*
* 40
*
*
* Generates the localized log message. If the result is
* greater than the maximum width, truncates the characters
* beyond the maximum width.
*
*
*
*
* %20.40m
*
*
* Right
*
*
* 20
*
*
* 40
*
*
* Generates the localized log message. If the result is
* less than the minimum width, then prepends spaces until
* the minimum width is reached. If the result is greater
* than the maximum width, truncates the characters beyond
* the maximum width.
*
*
*
*
* %-20.40m
*
*
* Left
*
*
* 20
*
*
* 40
*
*
* Generates the localized log message. If the result is
* less than the minimum width, then appends spaces until
* the minimum width is reached. If the result is greater
* than the maximum width, truncates the characters beyond
* the maximum width.
*
*
*
*
* Configuration: {@code PatternFormatter}
* default configuration uses the following LogManager
* property. If the named property is either not defined or is
* invalid, then the default setting is used.
*
* -
* net.sf.eBus.util.logging.PatternFormatter.pattern (defaults to "%d{MM/dd/yyyy HH:mm:ss} %m%E")
*
*
*
* The idea for this class came from the Apache Jakarta's
* Log4j project class
* {@code org.apache.log4j.PatternLayout} but is in no
* way based on it.
*
* @author Charles Rapp
* @version $Id: PatternFormatter.java,v 1.4 2005/07/22 01:52:33 charlesr Exp $
*/
public final class PatternFormatter
extends Formatter
{
//---------------------------------------------------------------
// Member methods.
//
//-----------------------------------------------------------
// Constructors.
//
/**
* Creates a new {@link PatternFormatter} and configures
* it according to {@code LogManager} configuration
* properties.
*/
public PatternFormatter()
{
super ();
// Get the formatter property settings.
String pattern =
LogManager.getLogManager().getProperty(PATTERN_KEY);
if (pattern == null || pattern.length() == 0)
{
pattern = DEFAULT_PATTERN;
}
parsePattern(pattern);
} // end of PatternFormatter()
/**
* Constructs a {@code PatternFormatter} instance for
* the given pattern.
* @param pattern the log record pattern string.
* @exception IllegalArgumentException
* if {@code pattern} is not a valid pattern string.
*/
public PatternFormatter(final String pattern)
throws IllegalArgumentException
{
super ();
if (pattern == null || pattern.isEmpty() == true)
{
throw (
new IllegalArgumentException(
"null or empty pattern"));
}
parsePattern(pattern);
} // end of PatternFormatter(String)
//
// end of Constructors.
//-----------------------------------------------------------
/**
* Returns a localized {@code String} resulting from
* formatting the {@code LogRecord}.
* @param record Output this record to the log.
* @return a localized {@code String} resulting from
* formatting the {@code LogRecord}.
*/
@Override
public String format(final LogRecord record)
{
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
_subformats.forEach(
(format) -> { format.format(record, pw); });
pw.println();
return (sw.toString());
} // end of format(LogRecord)
// Parse the pattern string into its constituent parts and
// place them into the format list. If the parse fails, throw
// IllegalArgumentException explaining the error.
private void parsePattern(final String pattern)
throws IllegalArgumentException
{
final byte[] buffer =
pattern.getBytes(StandardCharsets.US_ASCII);
final StringBuilder text = new StringBuilder();
int i;
int state;
int justification = NO_JUSTIFY;
int minWidth = 0;
int maxWidth = 0;
_subformats = new ArrayList<>(20);
// Look for the next percent or the end of the string.
for (i = 0, state = TEXT; i < buffer.length; ++i)
{
switch (state)
{
case TEXT:
// Have we found a format specifier?
if (buffer[i] == '%')
{
// Yes. Don't create a constant pattern
// just yet because this could be either
// %% or %n.
state = PERCENT;
}
else
{
// No. Add the current character to the
// text buffer.
text.append((char) buffer[i]);
}
break;
case PERCENT:
// Is this a 'constant' specifier?
switch (buffer[i])
{
case '%':
text.append('%');
state = TEXT;
break;
case 'n':
// Create a constant format for collected
// text.
if (text.length() > 0)
{
_subformats.add(
new ConstantFormat(text.toString()));
text.delete(0, text.length());
}
// Create a new line format.
_subformats.add(new NewLineFormat());
state = TEXT;
break;
default:
// This is not a constant specifier, so
// create the constant format for any
// collected text.
if (text.length() > 0)
{
_subformats.add(
new ConstantFormat(
text.toString()));
text.delete(0, text.length());
}
// Are there any modifiers?
if (buffer[i] == '-')
{
// A '-' means right justify.
justification = RIGHT_JUSTIFY;
state = RIGHT_JUSTIFY;
}
else if (buffer[i] == '.')
{
// A '.' means the start of the
// maximum width.
justification = LEFT_JUSTIFY;
state = MAX_WIDTH;
}
else if (
Character.isDigit(
(char) buffer[i]) == true)
{
// A number means this is the start
// of the minimum width.
text.append((char) buffer[i]);
justification = LEFT_JUSTIFY;
state = MIN_WIDTH;
}
// There are no modifiers. Is this a
// valid specifier letter? Handle the
// date specifier separately.
else if (buffer[i] == 'd')
{
state = DATE_FORMAT;
}
else if (isValidLetter(buffer[i]) == true)
{
// Yes. Create the appropriate subformat
// object.
_subformats.add(
createSubFormat(buffer[i],
justification,
minWidth,
maxWidth));
state = TEXT;
}
else
{
text.delete(0, text.length());
text.append('\'');
text.append((char) buffer[i]);
text.append(
"' is not a valid specifier");
throw (
new IllegalArgumentException(
text.toString()));
}
}
break;
case RIGHT_JUSTIFY:
// The right justify character *must* be
// followed by a minimum width.
if (Character.isDigit((char) buffer[i]) == true)
{
text.append((char) buffer[i]);
state = MIN_WIDTH;
}
else
{
text.delete(0, text.length());
text.append("'-' not followed by ");
text.append("minimum width");
throw (
new IllegalArgumentException(
text.toString()));
}
break;
case MIN_WIDTH:
// Keep collecting digits until either a '.'
// or a valid specifier letter is seen.
// If not, throw an exception.
if (Character.isDigit((char) buffer[i]) == true)
{
text.append((char) buffer[i]);
}
else if (buffer[i] == '.')
{
minWidth = Integer.parseInt(text.toString());
text.delete(0, text.length());
state = MAX_WIDTH;
}
else if (buffer[i] == 'd')
{
state = DATE_FORMAT;
}
else if (buffer[i] == 'E')
{
throw (
new IllegalArgumentException(
"%E does not take modifiers"));
}
else if (isValidLetter(buffer[i]) == true)
{
// Convert the collected text into an
// integer and then create the subformat
// object
minWidth = Integer.parseInt(text.toString());
_subformats.add(
createSubFormat(buffer[i],
justification,
minWidth,
maxWidth));
text.delete(0, text.length());
justification = NO_JUSTIFY;
minWidth = 0;
maxWidth = 0;
state = TEXT;
}
else
{
text.append(" minimum width followed ");
text.append("by invalid character '");
text.append((char) buffer[i]);
text.append('\'');
throw (
new IllegalArgumentException(
text.toString()));
}
break;
case MAX_WIDTH:
// Keep collecting digits until a valid
// specifier letter is seen. If not, throw an
// exception.
if (Character.isDigit((char) buffer[i]) == true)
{
text.append((char) buffer[i]);
}
else if (buffer[i] == 'd')
{
state = DATE_FORMAT;
}
else if (buffer[i] == 'E')
{
throw (
new IllegalArgumentException(
"%E does not take modifiers"));
}
else if (isValidLetter(buffer[i]) == true)
{
// Convert the collected text into an
// integer and then create the subformat
// object
maxWidth =
Integer.parseInt(text.toString());
_subformats.add(
createSubFormat(buffer[i],
justification,
minWidth,
maxWidth));
text.delete(0, text.length());
justification = NO_JUSTIFY;
minWidth = 0;
maxWidth = 0;
state = TEXT;
}
else
{
text.append(" maximum width followed ");
text.append("by invalid character '");
text.append((char) buffer[i]);
text.append('\'');
throw (
new IllegalArgumentException(
text.toString()));
}
break;
case DATE_FORMAT:
// Was a date format given?
if (buffer[i] == '{')
{
// Yes. Start collecting it.
state = DATE_FORMAT_2;
}
else
{
// No. Use the default format.
_subformats.add(
new DateFormat(justification,
minWidth,
maxWidth));
// Since the current character is not
// part of the date format, place it
// in the constant text buffer.
text.append((char) buffer[i]);
state = TEXT;
}
break;
case DATE_FORMAT_2:
// Keep going until the end brace is seen.
if (buffer[i] == '}')
{
_subformats.add(
new DateFormat(text.toString(),
justification,
minWidth,
maxWidth));
text.delete(0, text.length());
justification = NO_JUSTIFY;
minWidth = 0;
maxWidth = 0;
state = TEXT;
}
else
{
text.append((char) buffer[i]);
}
break;
default:
}
}
// Did the pattern end in a valid state? The only valid
// state is TEXT. Anything else means that we stopped in
// the middle of a specifier.
if (state != TEXT)
{
throw (
new IllegalArgumentException(
"pattern ends with incomplete specifier"));
}
else
{
Iterator it;
// Create a constant pattern for any left over text.
if (text.length() > 0)
{
_subformats.add(
new ConstantFormat(text.toString()));
}
}
return;
} // end of parsePattern(String)
// Returns true if c is a valid specifier letter and false
// otherwise.
private boolean isValidLetter(final byte c)
{
return (SPECIFIER_LETTERS.indexOf(c) >= 0);
} // end of isValidLetter(byte)
// Create the appropriate SubFormat subclass for the given
// letter.
private SubFormat createSubFormat(final byte c,
final int justify,
final int minWidth,
final int maxWidth)
{
SubFormat retval = null;
switch (c)
{
case 'C':
retval =
new SourceClassFormat(
justify, minWidth, maxWidth);
break;
case 'e':
retval =
new ThrowableMessageFormat(
justify, minWidth, maxWidth);
break;
case 'E':
retval =
new StackTraceFormat(
justify, minWidth, maxWidth);
break;
case 'l':
retval =
new LevelFormat(
justify, minWidth, maxWidth);
break;
case 'm':
retval =
new MessageFormat(
justify, minWidth, maxWidth);
break;
case 'M':
retval =
new SourceMethodFormat(
justify, minWidth, maxWidth);
break;
case 'N':
retval =
new LoggerNameFormat(
justify, minWidth, maxWidth);
break;
case 's':
retval =
new SequenceFormat(
justify, minWidth, maxWidth);
break;
case 't':
retval =
new ThreadIdFormat(
justify, minWidth, maxWidth);
break;
default:
}
return (retval);
} // end of createSubFormat(byte, int, int, int)
//---------------------------------------------------------------
// Member data.
//
// Apply each of these formats in turn to produce the
// formatted log message.
private List _subformats;
//-----------------------------------------------------------
// Constants.
//
/**
* The default pattern is "%d{MM/dd/yyyy HH:mm:ss} %m%E".
*
* Example log record:
*
*
* 07/04/1776 10:04:32 John Hancock signed on.
* java.lang.IllegalStateException: cannot declare independence
* at net.sf.eBus.util.logging.PatternFormatterTest.setUpClass(PatternFormatterTest.java:66)
*
*/
public static final String DEFAULT_PATTERN =
"%d{MM/dd/yyyy HH:mm:ss} %m%E";
private static final int NO_JUSTIFY = 0;
private static final int LEFT_JUSTIFY = 1;
private static final int RIGHT_JUSTIFY = 2;
private static final String SPECIFIER_LETTERS = "CeElmMNst";
// Pattern parsing states.
private static final int TEXT = 0;
private static final int PERCENT = 1;
// State 2 is right justify.
private static final int MIN_WIDTH = 3;
private static final int MAX_WIDTH = 4;
private static final int DATE_FORMAT = 5;
private static final int DATE_FORMAT_2 = 6;
// Configuration property key.
private static final String PATTERN_KEY =
"net.sf.eBus.util.logging.PatternFormatter.pattern";
//-----------------------------------------------------------
// Inner classes.
// All subformats extend this super class.
private abstract class SubFormat
{
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
// Constructor.
protected SubFormat(final int justification,
final int minWidth,
final int maxWidth)
{
_justification = justification;
_minimumWidth = minWidth;
_maximumWidth = maxWidth;
} // end of SubFormat(int, int, int)
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// Abstract Methods.
//
// Append the formatted log record information to the
// buffer.
public abstract void format(LogRecord record,
PrintWriter pw);
//
// end of Abstract Methods.
//-------------------------------------------------------
// Do the necessary justification or truncating to the
// string before appending the result to the buffer.
protected String justify(final String s)
{
final String text = (s == null ? "" : s);
int length;
String retval;
length = text.length();
if (_justification == NO_JUSTIFY)
{
retval = text;
}
// Does this string need to be padded?
else if (_minimumWidth > 0 && length < _minimumWidth)
{
final StringBuilder buffer = new StringBuilder();
final int paddingLength = _minimumWidth - length;
char[] padding;
padding = new char[paddingLength];
Arrays.fill(padding, ' ');
// Prepend or append the padding?
if (_justification == LEFT_JUSTIFY)
{
// Prepend.
buffer.append(padding);
buffer.append(s);
}
else
{
// Append.
buffer.append(s);
buffer.append(padding);
}
retval = buffer.toString();
}
// Does this string need to be truncated?
else if (_maximumWidth > 0 && length > _maximumWidth)
{
retval = text.substring(0, _maximumWidth);
}
// Else the message length is just right.
else
{
retval = s;
}
return (retval);
} // end of justify(String)
//-----------------------------------------------------------
// Member data.
//
// Either LEFT_JUSTIFY, RIGHT_JUSTIFY or NO_JUSTIFY.
private int _justification;
// == 0 - no minimum width.
// > 0 - minimum width.
private int _minimumWidth;
// == 0 - no maximum width.
// > 0 - maximum width.
private int _maximumWidth;
} // end of class SubFormat
// This "format" contains a string constant and simply
// appends that to the buffer.
private final class ConstantFormat
extends SubFormat
{
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
// Constructor.
public ConstantFormat(final String s)
{
super (NO_JUSTIFY, 0, 0);
_string = s;
} // end of ConstantFormat(String)
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// SubFormat Abstract Method Implementation.
//
// Append the string to the buffer.
@Override
public void format(final LogRecord record,
final PrintWriter pw)
{
pw.print(_string);
return;
} // end of format(LogRecord, PrintWriter)
//
// end of SubFormat Abstract Method Implementation.
//-------------------------------------------------------
//-----------------------------------------------------------
// Member data.
//
// The constant string to be appended.
private final String _string;
} // end of class ConstantFormat
// This "format" appends end-of-line to the buffer.
private final class NewLineFormat
extends SubFormat
{
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
// Constructor.
public NewLineFormat()
{
super (NO_JUSTIFY, 0, 0);
} // end of NewLineFormat()
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// SubFormat Abstract Method Implementation.
//
// Append the string to the buffer.
@Override
public void format(final LogRecord record,
final PrintWriter pw)
{
pw.println();
return;
} // end of format(LogRecord, PrintWriter)
//
// end of SubFormat Abstract Method Implementation.
//-------------------------------------------------------
// Member data.
} // end of class NewLineFormat
// Use java.text.SimpleDateFormat to format the log record's
// timestamp.
private final class DateFormat
extends SubFormat
{
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
// Default constructor.
public DateFormat(final int justify,
final int minWidth,
final int maxWidth)
{
super (justify, minWidth, maxWidth);
_dateFormat = new SimpleDateFormat();
} // end of DateFormat(int, int, int)
// Specified format constructor.
public DateFormat(final String format,
final int justify,
final int minWidth,
final int maxWidth)
{
super (justify, minWidth, maxWidth);
_dateFormat = new SimpleDateFormat(format);
} // end of DateFormat(String, int, int, int)
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// SubFormat Abstract Method Implementation.
//
// Append the date to the buffer.
@Override
public void format(final LogRecord record,
final PrintWriter pw)
{
pw.print(
justify(
_dateFormat.format(
new Date(record.getMillis()))));
return;
} // end of format(LogRecord, PrintWriter)
//
// end of SubFormat Abstract Method Implementation.
//-------------------------------------------------------
//-----------------------------------------------------------
// Member data.
//
private final SimpleDateFormat _dateFormat;
} // end of class DateFormat
// Appends the localized log level name to the buffer.
private final class LevelFormat
extends SubFormat
{
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
public LevelFormat(final int justify,
final int minWidth,
final int maxWidth)
{
super (justify, minWidth, maxWidth);
} // end of LevelFormat(int, int, int)
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// SubFormat Abstract Method Implementation.
//
@Override
public void format(final LogRecord record,
final PrintWriter pw)
{
pw.print(
justify(record.getLevel().getLocalizedName()));
return;
} // end of format(LogRecord, PrintWriter)
//
// end of SubFormat Abstract Method Implementation.
//-------------------------------------------------------
//-----------------------------------------------------------
// Member data.
//
} // end of class LevelFormat
// Appends the source logger's name to the buffer.
private final class LoggerNameFormat
extends SubFormat
{
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
public LoggerNameFormat(final int justify,
final int minWidth,
final int maxWidth)
{
super (justify, minWidth, maxWidth);
} // end of LoggerNameFormat(int, int, int)
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// SubFormat Abstract Method Implementation.
//
@Override
public void format(final LogRecord record,
final PrintWriter pw)
{
pw.print(record.getLoggerName());
return;
} // end of format(LogRecord, PrintWriter)
//
// end of SubFormat Abstract Method Implementation.
//-------------------------------------------------------
//-----------------------------------------------------------
// Member data.
//
} // end of class LoggerNameFormat
// Appends the localized message string to the buffer.
private final class MessageFormat
extends SubFormat
{
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
public MessageFormat(final int justify,
final int minWidth,
final int maxWidth)
{
super (justify, minWidth, maxWidth);
} // end of MessageFormat(int, int, int)
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// SubFormat Abstract Method Implementation.
//
@Override
public void format(final LogRecord record,
final PrintWriter pw)
{
final ResourceBundle bundle =
record.getResourceBundle();
final String rawMessage = record.getMessage();
String localizedMessage;
if (rawMessage == null || rawMessage.length() == 0)
{
localizedMessage = "";
}
else if (bundle == null)
{
localizedMessage = rawMessage;
}
else
{
try
{
localizedMessage =
bundle.getString(rawMessage);
}
catch (Exception jex)
{
localizedMessage = rawMessage;
}
}
pw.print(justify(localizedMessage));
return;
} // end of format(LogRecord, PrintWriter)
//
// end of SubFormat Abstract Method Implementation.
//-------------------------------------------------------
//-----------------------------------------------------------
// Member data.
//
} // end of class MessageFormat
// Appends the throwable's message to the buffer.
private final class ThrowableMessageFormat
extends SubFormat
{
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
public ThrowableMessageFormat(final int justify,
final int minWidth,
final int maxWidth)
{
super (justify, minWidth, maxWidth);
} // end of ThrowableMessageFormat(int, int, int)
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// SubFormat Abstract Method Implementation.
//
@Override
public void format(final LogRecord record,
final PrintWriter pw)
{
final Throwable t = record.getThrown();
String message = "";
if (t != null)
{
message = t.getMessage();
}
pw.print(justify(message));
return;
} // end of format(LogRecord, PrintWriter)
//
// end of SubFormat Abstract Method Implementation.
//-------------------------------------------------------
//-----------------------------------------------------------
// Member data.
//
} // end of class ThrowableMessageFormat
// Appends the throwable's stack trace to the buffer.
private final class StackTraceFormat
extends SubFormat
{
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
public StackTraceFormat(final int justify,
final int minWidth,
final int maxWidth)
{
super (NO_JUSTIFY, 0, 0);
} // end of StackTraceFormat(int, int, int)
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// SubFormat Abstract Method Implementation.
//
@Override
public void format(final LogRecord record,
final PrintWriter pw)
{
final Throwable t = record.getThrown();
if (t != null)
{
pw.println();
t.printStackTrace(pw);
}
return;
} // end of format(LogRecord, PrintWiter)
//
// end of SubFormat Abstract Method Implementation.
//-------------------------------------------------------
//-----------------------------------------------------------
// Member data.
//
} // end of class StackTraceFormat
// Appends the thread identifier to the buffer.
private final class ThreadIdFormat
extends SubFormat
{
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
public ThreadIdFormat(final int justify,
final int minWidth,
final int maxWidth)
{
super (justify, minWidth, maxWidth);
} // end of ThreadIdFormat(int, int, int)
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// SubFormat Abstract Method Implementation.
//
@Override
public void format(final LogRecord record,
final PrintWriter pw)
{
pw.print(
justify(Integer.toString(record.getThreadID())));
return;
} // end of format(LogRecord, PrintWriter)
//
// end of SubFormat Abstract Method Implementation.
//-------------------------------------------------------
//-----------------------------------------------------------
// Member data.
//
} // end of class ThreadIdFormat
// Appends the sequence number to the buffer.
private final class SequenceFormat
extends SubFormat
{
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
public SequenceFormat(final int justify,
final int minWidth,
final int maxWidth)
{
super (justify, minWidth, maxWidth);
} // end of SequenceFormat(int, int, int)
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// SubFormat Abstract Method Implementation.
//
@Override
public void format(final LogRecord record,
final PrintWriter pw)
{
pw.print(
justify(
Long.toString(record.getSequenceNumber())));
return;
} // end of format(LogRecord, PrintWriter)
//
// end of SubFormat Abstract Method Implementation.
//-------------------------------------------------------
//-----------------------------------------------------------
// Member data.
//
} // end of class SequenceFormat
// Appends the source class name to the buffer.
private final class SourceClassFormat
extends SubFormat
{
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
public SourceClassFormat(final int justify,
final int minWidth,
final int maxWidth)
{
super (justify, minWidth, maxWidth);
} // end of SourceClassFormat(int, int, int)
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// SubFormat Abstract Method Implementation.
//
@Override
public void format(final LogRecord record,
final PrintWriter pw)
{
pw.print(justify(record.getSourceClassName()));
return;
} // end of format(LogRecord, PrintWriter)
//
// end of SubFormat Abstract Method Implementation.
//-------------------------------------------------------
//-----------------------------------------------------------
// Member data.
//
} // end of class SourceClassFormat
// Appends the source method name to the buffer.
private final class SourceMethodFormat
extends SubFormat
{
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
public SourceMethodFormat(final int justify,
final int minWidth,
final int maxWidth)
{
super (justify, minWidth, maxWidth);
} // end of SourceMethodFormat(int, int, int)
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// SubFormat Abstract Method Implementation.
//
@Override
public void format(final LogRecord record,
final PrintWriter pw)
{
pw.print(justify(record.getSourceMethodName()));
return;
} // end of format(LogRecord, PrintWriter)
//
// end of SubFormat Abstract Method Implementation.
//-------------------------------------------------------
//-----------------------------------------------------------
// Member data.
//
} // end of class SourceMethodFormat
} // end of class PatternFormatter
//
// CHANGE LOG
// $Log: PatternFormatter.java,v $
// Revision 1.4 2005/07/22 01:52:33 charlesr
// Moved to Java 5:
// + Added generics.
// + Using Java enums for report frequency.
// + Replaced StringBuffer with StringBuilder.
//
// Revision 1.3 2004/08/15 21:17:43 charlesr
// Correct javadocs.
//
// Revision 1.2 2004/07/23 00:36:02 charlesr
// Added default constructor which uses LogManager to extract
// configuration.
//
// Revision 1.1 2004/02/20 12:12:31 charlesr
// Replaced StringBuffer with StringWriter/PrintWriter.
//
// Revision 1.0 2003/11/20 01:49:23 charlesr
// Initial revision
//