System.out.println()
and
* full-blown logging packages such as log4j.* * All events are logged to an in-memory buffer and optionally a stream, * and those with a high urgency (warnings and errors) are also printed * to standard output.
* * Logging of exception tracebacks is supported.
* * This class can also optionally redirect standard output and error to the log. * * @author Slava Pestov * @version $Id: Log.java 12789 2008-06-04 21:23:10Z kpouer $ */ public class Log { //{{{ Constants /** * The maximum number of log messages that will be kept in memory. * @since jEdit 2.6pre5 */ public static final int MAXLINES = 500; /** * Debugging message urgency. Should be used for messages only * useful when debugging a problem. * @since jEdit 2.2pre2 */ public static final int DEBUG = 1; /** * Message urgency. Should be used for messages which give more * detail than notices. * @since jEdit 2.2pre2 */ public static final int MESSAGE = 3; /** * Notice urgency. Should be used for messages that directly * affect the user. * @since jEdit 2.2pre2 */ public static final int NOTICE = 5; /** * Warning urgency. Should be used for messages that warrant * attention. * @since jEdit 2.2pre2 */ public static final int WARNING = 7; /** * Error urgency. Should be used for messages that signal a * failure. * @since jEdit 2.2pre2 */ public static final int ERROR = 9; //}}} //{{{ init() method /** * Initializes the log. * @param stdio If true, standard output and error will be * sent to the log * @param level Messages with this log level or higher will * be printed to the system console * @since jEdit 3.2pre4 */ public static void init(boolean stdio, int level) { if(stdio) { if(System.out == realOut && System.err == realErr) { System.setOut(createPrintStream(NOTICE,null)); System.setErr(createPrintStream(ERROR,null)); } } Log.level = level; // Log some stuff log(MESSAGE,Log.class,"When reporting bugs, please" + " include the following information:"); String[] props = { "java.version", "java.vm.version", "java.runtime.version", "java.vendor", "java.compiler", "os.name", "os.version", "os.arch", "user.home", "java.home", "java.class.path", }; for(int i = 0; i < props.length; i++) { log(MESSAGE,Log.class, props[i] + '=' + System.getProperty(props[i])); } } //}}} //{{{ setLogWriter() method /** * Writes all currently logged messages to this stream if there was no * stream set previously, and sets the stream to write future log * messages to. * @param stream The writer * @since jEdit 3.2pre4 */ public static void setLogWriter(Writer stream) { if(Log.stream == null && stream != null) { try { if(wrap) { for(int i = logLineCount; i < log.length; i++) { stream.write(log[i]); stream.write(lineSep); } } for(int i = 0; i < logLineCount; i++) { stream.write(log[i]); stream.write(lineSep); } stream.flush(); } catch(Exception e) { // do nothing, who cares } } Log.stream = stream; } //}}} //{{{ flushStream() method /** * Flushes the log stream. * @since jEdit 2.6pre5 */ public static void flushStream() { if(stream != null) { try { stream.flush(); } catch(IOException io) { io.printStackTrace(realErr); } } } //}}} //{{{ closeStream() method /** * Closes the log stream. Should be done before your program exits. * @since jEdit 2.6pre5 */ public static void closeStream() { if(stream != null) { try { stream.close(); stream = null; } catch(IOException io) { io.printStackTrace(realErr); } } } //}}} //{{{ getLogListModel() method /** * Returns the list model for viewing the log contents. * @since jEdit 4.2pre1 */ public static ListModel getLogListModel() { return listModel; } //}}} //{{{ log() method /** * Logs an exception with a message. * * If an exception is the cause of a call to {@link #log}, then * the exception should be explicitly provided so that it can * be presented to the (debugging) user in a useful manner * (not just the exception message, but also the exception stack trace) * * @since jEdit 4.3pre5 */ public static void log(int urgency, Object source, Object message, Throwable exception) { // We can do nicer here, but this is a start... log(urgency,source,message); log(urgency,source,exception); } //}}} //{{{ log() method /** * Logs a message. This method is thread-safe.
* * The following code sends a typical debugging message to the activity * log: *
Log.log(Log.DEBUG,this,"counter = " + counter);* The corresponding activity log entry might read as follows: *
[debug] JavaParser: counter = 15* * @param urgency The urgency; can be one of *
Log.DEBUG
, Log.MESSAGE
,
* Log.NOTICE
, Log.WARNING
, or
* Log.ERROR
.
* @param source The source of the message, either an object or a
* class instance. When writing log messages from macros, set
* this parameter to BeanShell.class
to make macro
* errors easier to spot in the activity log.
* @param message The message. This can either be a string or
* an exception
*
* @since jEdit 2.2pre2
*/
public static void log(int urgency, Object source, Object message)
{
String _source;
if(source == null)
{
_source = Thread.currentThread().getName();
if(_source == null)
{
_source = Thread.currentThread().getClass().getName();
}
}
else if(source instanceof Class)
_source = ((Class)source).getName();
else
_source = source.getClass().getName();
int index = _source.lastIndexOf('.');
if(index != -1)
_source = _source.substring(index+1);
if(message instanceof Throwable)
{
_logException(urgency,source,(Throwable)message);
}
else
{
String _message = String.valueOf(message);
// If multiple threads log stuff, we don't want
// the output to get mixed up
synchronized(LOCK)
{
StringTokenizer st = new StringTokenizer(
_message,"\r\n");
int lineCount = 0;
boolean oldWrap = wrap;
while(st.hasMoreTokens())
{
lineCount++;
_log(urgency,_source,st.nextToken()
.replace('\t',' '));
}
listModel.update(lineCount,oldWrap);
}
}
} //}}}
//{{{ Private members
//{{{ Instance variables
private static final Object LOCK;
private static final String[] log;
private static int logLineCount;
private static boolean wrap;
private static int level;
private static Writer stream;
private static final String lineSep;
private static final PrintStream realOut;
private static final PrintStream realErr;
private static final LogListModel listModel;
private static final DateFormat timeFormat;
private static final int MAX_THROWABLES = 10;
public static final List