diff --git a/src/java/com/samskivert/util/JDK14Logger.java b/src/java/com/samskivert/util/JDK14Logger.java new file mode 100644 index 00000000..3cd4e1c7 --- /dev/null +++ b/src/java/com/samskivert/util/JDK14Logger.java @@ -0,0 +1,97 @@ +// +// $Id$ +// +// samskivert library - useful routines for java programs +// Copyright (C) 2001-2008 Michael Bayne +// +// 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 + +package com.samskivert.util; + +import java.util.logging.Level; + +/** + * A factory for creating JDK14 logger implementations. Automatically configures a formatter to + * display log messages on a single line unless the following system property is set: + *
com.samskivert.util.JDK14Logger.noFormatter=true
+ */ +public class JDK14Logger implements Logger.Factory +{ + // from interface Logger.Factory + public void init () + { + try { + if (!Boolean.getBoolean("com.samskivert.util.JDK14Logger.noFormatter")) { + OneLineLogFormatter.configureDefaultHandler(); + } + } catch (SecurityException se) { + // running in sandbox; no custom logging; no problem! + } + } + + // from interface Logger.Factory + public Logger getLogger (String name) + { + return new Impl(java.util.logging.Logger.getLogger(name)); + } + + // from interface Logger.Factory + public Logger getLogger (Class clazz) + { + return getLogger(clazz.getName()); + } + + protected static class Impl extends Logger + { + public Impl (java.util.logging.Logger impl) + { + _impl = impl; + } + + @Override // from Logger + public void debug (Object message, Object... args) + { + if (_impl.isLoggable(Level.FINE)) { + _impl.log(Level.FINE, format(message, args), getException(message, args)); + } + } + + @Override // from Logger + public void info (Object message, Object... args) + { + if (_impl.isLoggable(Level.INFO)) { + _impl.log(Level.INFO, format(message, args), getException(message, args)); + } + } + + @Override // from Logger + public void warning (Object message, Object... args) + { + if (_impl.isLoggable(Level.WARNING)) { + _impl.log(Level.WARNING, format(message, args), getException(message, args)); + } + } + + @Override // from Logger + public void error (Object message, Object... args) + { + if (_impl.isLoggable(Level.SEVERE)) { + _impl.log(Level.SEVERE, format(message, args), getException(message, args)); + } + } + + protected java.util.logging.Logger _impl; + } +} diff --git a/src/java/com/samskivert/util/Logger.java b/src/java/com/samskivert/util/Logger.java new file mode 100644 index 00000000..602f01c4 --- /dev/null +++ b/src/java/com/samskivert/util/Logger.java @@ -0,0 +1,181 @@ +// +// $Id$ +// +// samskivert library - useful routines for java programs +// Copyright (C) 2001-2008 Michael Bayne +// +// 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 + +package com.samskivert.util; + +/** + * Provides logging services to this library and others which depend on this library in such a way + * that they can be used in a larger project and easily be made to log to the logging framework in + * use by that project. + * + *

The default implementation uses log4j if it is available and falls back to the Java logging + * services if not. A specific (or custom) logging implementation can be configured like so: + *

-Dcom.samskivert.util.Logger=com.samskivert.util.Log4Logger
+ * + *

One additional enhancement is the use of varargs log methods to allow for some handy + * automatic formatting. The methods take a log message and list of zero or more additional + * parameters. Those parameters should be key/value pairs which will be logged like so: + *

message [key=value, key=value, key=value]
+ * + *

The final parameter can optionally be a Throwable, which will be supplied to the underlying + * log system as an exception to accompany the log message. + */ +public abstract class Logger +{ + /** + * Obtains a logger with the specified name. + */ + public static Logger getLogger (String name) + { + return _factory.getLogger(name); + } + + /** + * Obtains a logger with a name equal to the supplied class's name. + */ + public static Logger getLogger (Class clazz) + { + return _factory.getLogger(clazz); + } + + /** + * Logs a debug message. + * + * @param message the message to be logged. + * @param args a list of key/value pairs and an optional final Throwable. + */ + public abstract void debug (Object message, Object... args); + + /** + * Logs an info message. + * + * @param message the message to be logged. + * @param args a list of key/value pairs and an optional final Throwable. + */ + public abstract void info (Object message, Object... args); + + /** + * Logs a warning message. + * + * @param message the message to be logged. + * @param args a list of key/value pairs and an optional final Throwable. + */ + public abstract void warning (Object message, Object... args); + + /** + * Logs an error message. + * + * @param message the message to be logged. + * @param args a list of key/value pairs and an optional final Throwable. + */ + public abstract void error (Object message, Object... args); + + /** + * Format messages and arguments. For use by logger implementations. + */ + protected String format (Object message, Object[] args) + { + StringBuilder buf = new StringBuilder(); + buf.append(message); + if (args != null && args.length > 1) { + buf.append(" ["); + for (int ii = 0, nn = args.length/2; ii < nn; ii++) { + if (ii > 0) { + buf.append(", "); + } + buf.append(args[2*ii]).append("="); + try { + StringUtil.toString(buf, args[2*ii+1]); + } catch (Throwable t) { + buf.append(""); + } + } + buf.append("]"); + } + return buf.toString(); + } + + /** + * Extracts the exception from the message and arguments (if there is one). For use by logger + * implementations. + */ + protected Throwable getException (Object message, Object[] args) + { + if (message instanceof Throwable) { + return (Throwable)message; + } else if (args.length % 2 == 1 && args[args.length-1] instanceof Throwable) { + return (Throwable)args[args.length-1]; + } else { + return null; + } + } + + /** + * Called at static initialization time. Selects and initializes our logging backend. + */ + protected static void initLogger () + { + // if a custom class was specified as a system property, use that + _factory = createConfiguredFactory(); + + // TODO: create and try a log4j logger + + // lastly, fall back to the Java logging system + if (_factory == null) { + _factory = new JDK14Logger(); + } + + // and finally initialize our factory + _factory.init(); + } + + /** + * A helper function for {@link #initLogger}. + */ + protected static Factory createConfiguredFactory () + { + String implClass = System.getProperty("com.samskivert.util.Log"); + if (!StringUtil.isBlank(implClass)) { + try { + return (Factory)Class.forName(implClass).newInstance(); + } catch (Throwable t) { + System.err.println("Unable to instantiate logging implementation: " + implClass); + t.printStackTrace(System.err); + } + } + return null; + } + + /** + * Used to create logger instances. + */ + protected static interface Factory + { + public void init (); + public Logger getLogger (String name); + public Logger getLogger (Class clazz); + } + + protected static Factory _factory; + + static { + initLogger(); + } +}