All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gjt.sp.util.Log Maven / Gradle / Ivy

Go to download

This project aims to build a command line tool that can create HTML view with syntax highlighted source code. It uses Jedit syntax highlighting engine and support all languages that are supported in JEdit. Which are currently: ActionScript, Ada 95, ANTLR, Apache HTTPD, APDL, AppleScript, ASP, Aspect-J, Assembly, AWK, B formal method, Batch, BBj, BCEL, BibTeX, C, C++, C#, CHILL, CIL, COBOL, ColdFusion, CSS, CVS Commit, D, DOxygen, DSSSL, Eiffel, EmbPerl, Erlang, Factor, Fortran, Foxpro, FreeMarker, Fortran, Gettext, Groovy, Haskell, HTML, Icon, IDL, Inform, INI, Inno Setup, Informix 4GL, Interlis, Io, Java, JavaScript, JCL, JHTML, JMK, JSP, Latex, Lilypond, Lisp, LOTOS, Lua, Makefile, Maple, ML, Modula-3, MoinMoin, MQSC, NetRexx, NQC, NSIS2, Objective C, ObjectRexx, Occam, Omnimark, Parrot, Pascal, Patch, Perl, PHP, Pike, PL-SQL, PL/I, Pop11, PostScript, Povray, PowerDynamo, Progress 4GL, Prolog, Properties, PSP, PV-WAVE, Pyrex, Python, REBOL, Redcode, Relax-NG, RelationalView, Rest, Rib, RPM spec, RTF, Ruby, Ruby-HTML, RView, S+, S#, SAS, Scheme, SDL/PL, SGML, Shell Script, SHTML, Smalltalk, SMI MIB, SQR, Squidconf, SVN Commit, Swig, TCL, TeX, Texinfo, TPL, Transact-SQL, UnrealScript, VBScript, Velocity, Verilog, VHDL, XML, XSL, ZPT

The newest version!
/*
 * Log.java - A class for logging events
 * :tabSize=8:indentSize=8:noTabs=false:
 * :folding=explicit:collapseFolds=1:
 *
 * Copyright (C) 1999, 2003 Slava Pestov
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package org.gjt.sp.util;

//{{{ Imports
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Writer;

import java.text.DateFormat;

import java.util.*;

import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;

import javax.swing.ListModel;
import javax.swing.SwingUtilities;

import static java.text.DateFormat.MEDIUM;
//}}}

/**
 * This class provides methods for logging events. In terms of functionality,
 * it is somewhere in between 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 throwables; //}}} //{{{ Class initializer static { LOCK = new Object(); level = WARNING; realOut = System.out; realErr = System.err; log = new String[MAXLINES]; lineSep = System.getProperty("line.separator"); listModel = new LogListModel(); timeFormat = DateFormat.getTimeInstance(MEDIUM); throwables = Collections.synchronizedList(new ArrayList(MAX_THROWABLES)); } //}}} //{{{ createPrintStream() method private static PrintStream createPrintStream(final int urgency, final Object source) { return new LogPrintStream(urgency, source); } //}}} //{{{ _logException() method private static void _logException(final int urgency, final Object source, final Throwable message) { PrintStream out = createPrintStream(urgency,source); if (urgency >= level) { synchronized (throwables) { if (throwables.size() == MAX_THROWABLES) { throwables.remove(0); } throwables.add(message); } } synchronized(LOCK) { message.printStackTrace(out); } } //}}} //{{{ _log() method private static void _log(int urgency, String source, String message) { String fullMessage = timeFormat.format(new Date()) + " ["+Thread.currentThread().getName()+"] [" + urgencyToString(urgency) + "] " + source + ": " + message; try { log[logLineCount] = fullMessage; if(++logLineCount >= log.length) { wrap = true; logLineCount = 0; } if(stream != null) { stream.write(fullMessage); stream.write(lineSep); } } catch(Exception e) { e.printStackTrace(realErr); } if(urgency >= level) { if(urgency == ERROR) realErr.println(fullMessage); else realOut.println(fullMessage); } } //}}} //{{{ urgencyToString() method private static String urgencyToString(int urgency) { switch(urgency) { case DEBUG: return "debug"; case MESSAGE: return "message"; case NOTICE: return "notice"; case WARNING: return "warning"; case ERROR: return "error"; } throw new IllegalArgumentException("Invalid urgency: " + urgency); } //}}} //}}} //{{{ LogListModel class static class LogListModel implements ListModel { final List listeners = new ArrayList(); //{{{ fireIntervalAdded() method private void fireIntervalAdded(int index1, int index2) { for(int i = 0; i < listeners.size(); i++) { ListDataListener listener = listeners.get(i); listener.intervalAdded(new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, index1,index2)); } } //}}} //{{{ fireIntervalRemoved() method private void fireIntervalRemoved(int index1, int index2) { for(int i = 0; i < listeners.size(); i++) { ListDataListener listener = listeners.get(i); listener.intervalRemoved(new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, index1,index2)); } } //}}} //{{{ addListDataListener() method public void addListDataListener(ListDataListener listener) { listeners.add(listener); } //}}} //{{{ removeListDataListener() method public void removeListDataListener(ListDataListener listener) { listeners.remove(listener); } //}}} //{{{ getElementAt() method public Object getElementAt(int index) { if(wrap) { if(index < MAXLINES - logLineCount) return log[index + logLineCount]; else return log[index - MAXLINES + logLineCount]; } else return log[index]; } //}}} //{{{ getSize() method public int getSize() { if(wrap) return MAXLINES; else return logLineCount; } //}}} //{{{ update() method void update(final int lineCount, final boolean oldWrap) { if(lineCount == 0 || listeners.isEmpty()) return; SwingUtilities.invokeLater(new Runnable() { public void run() { if(wrap) { if(oldWrap) fireIntervalRemoved(0,lineCount - 1); else { fireIntervalRemoved(0, logLineCount); } fireIntervalAdded( MAXLINES - lineCount + 1, MAXLINES); } else { fireIntervalAdded( logLineCount - lineCount + 1, logLineCount); } } }); } //}}} } //}}} //{{{ LogPrintStream class /** * A print stream that uses the "Log" class to output the messages, * and has special treatment for the printf() function. Using this * stream has one caveat: printing messages that don't have a line * break at the end will have one added automatically... */ private static class LogPrintStream extends PrintStream { private final ByteArrayOutputStream buffer; private final OutputStream orig; //{{{ LogPrintStream constructor LogPrintStream(int urgency, Object source) { super(new LogOutputStream(urgency, source)); buffer = new ByteArrayOutputStream(); orig = out; } //}}} //{{{ printf() method /** * This is a hack to allow "printf" to not print weird * stuff to the output. Since "printf" doesn't seem to * print the whole message in one shot, our output * stream above would break a line of log into several * lines; so we buffer the result of the printf call and * print the whole thing in one shot. A similar hack * would be needed for the "other" printf method, but * I'll settle for the common case only. */ public PrintStream printf(String format, Object... args) { synchronized (orig) { buffer.reset(); out = buffer; super.printf(format, args); try { byte[] data = buffer.toByteArray(); orig.write(data, 0, data.length); out = orig; } catch (IOException ioe) { // don't do anything? } finally { buffer.reset(); } } return this; } //}}} } //}}} //{{{ LogOutputStream class private static class LogOutputStream extends OutputStream { private final int urgency; private final Object source; //{{{ LogOutputStream constructor LogOutputStream(int urgency, Object source) { this.urgency = urgency; this.source = source; } //}}} //{{{ write() method public synchronized void write(int b) { byte[] barray = { (byte)b }; write(barray,0,1); } //}}} //{{{ write() method public synchronized void write(byte[] b, int off, int len) { String str = new String(b,off,len); log(urgency,source,str); } //}}} } //}}} }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy