/* JUG Java Uuid Generator * * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta@iki.fi * * Licensed under the License specified in the file LICENSE which is * included with the source code. * You may not use this file except in compliance with the License. * * 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.safehaus.uuid; import java.io.*; /** * This is the simple logging interface used by JUG package. It is meant * to provide a minimal but sufficient functionality for JUG to report * problems (warnings, errors), in a way that it can be sufficiently * customized (redirected, suppressed; even redefined), without forcing * overhead of a real * full-featured logging sub-system (like log4j or java.util.logging). * By being customizable, it is still possible to connect JUG logging into * such a real logging framework (log4j, java.util.logging) when being * used in a system that already uses such a framework. *<p> * To keep things as light-weight as possible, we won't bother defining * separate interface or abstract class -- this class defines both API * and the default implementation. It can thus be extended to override * functionality to provide thigs like bridging to "real" logging systems. * For simple configuration (suppress all, redirect to another stream) * default implementation should be sufficient, however. *<p> * Note: package <code>org.safehaus.uuid.ext</code> does contain * simple wrappers to connect JUG logging to log4j and java.util.logging: * * @see org.safehaus.uuid.ext.Log4jLogger * @see org.safehaus.uuid.ext.JavaUtilLogger */ public class Logger { /* ////////////////////////////////////////////////// // Constants ////////////////////////////////////////////////// */ public final static int LOG_ALL = 0; public final static int LOG_INFO_AND_ABOVE = 1; public final static int LOG_WARNING_AND_ABOVE = 2; public final static int LOG_ERROR_AND_ABOVE = 3; public final static int LOG_NOTHING = 4; /* ////////////////////////////////////////////////// // Static objects ////////////////////////////////////////////////// */ /** * By default we'll use this default implementation; however, * it can be easily changed. */ private static Logger sInstance = new Logger(); /* ////////////////////////////////////////////////// // Default impl. configuration ////////////////////////////////////////////////// */ /** * Threshold to use for outputting varius log statements. *<p> * Default is to low only warnings and errors */ protected int mLogLevel = LOG_ALL; /** * Output object to use, if defined; initialized to * <code>System.err</code>. */ protected PrintStream mOutput1 = System.err; /** * Override output used to explicitly specify where to pass diagnostic * output, instead of System.err. Used if <code>mOutput1</code> * is null; */ protected PrintWriter mOutput2 = null; /* ///////////////////////////////////////////////////////////// // Life-cycle ///////////////////////////////////////////////////////////// */ protected Logger() { } /** * Method that can be used to completely re-define the logging * functionality JUG uses. When called, JUG will start using the * new instance; if instance passed is null, will basically suppress * all logging. * * @param inst Logger instance to use for all logging JUG does; can be * null, but if so, essentially disables all logging. */ public synchronized static void setLogger(Logger inst) { sInstance = inst; } /* ///////////////////////////////////////////////////////////// // Actual simple logging API // (static dispatchers to instance methods) ///////////////////////////////////////////////////////////// */ // // // Configuration /** * Method to set the minimum level of messages that will get logged * using currently specific logger instace. For example, if * {@link #LOG_WARNING_AND_ABOVE} is passed as the argument, warnings * and errors will be logged, but informational (INFO) messages will * not. *<p> * Note: exact functionality invoked depends on the logger instance: * sub-classes of this class may need to do mapping to some other * logging sub-system (log4j and JUL logging, for example, use their * own severity levels that while generally reasonably easy to map, * are nonetheless not one-to-one which the simple logger). */ public static void setLogLevel(int level) { Logger l = sInstance; if (l != null) { l.doSetLogLevel(level); } } /** * Method that will re-direct output of the logger using the specified * {@link PrintStream}. Null is allowed, and signifies that all the * output should be suppressed. *<p> * Note: exact functionality invoked depends on the logger instance. */ public static void setOutput(PrintStream str) { Logger l = sInstance; if (l != null) { l.doSetOutput(str); } } /** * Method that will re-direct output of the logger using the specified * {@link Writer}. Null is allowed, and signifies that all the * output should be suppressed. */ public static void setOutput(Writer w) { Logger l = sInstance; if (l != null) { l.doSetOutput(w); } } // // // Logging methods public static void logInfo(String msg) { Logger l = sInstance; if (l != null) { l.doLogInfo(msg); } } public static void logWarning(String msg) { Logger l = sInstance; if (l != null) { l.doLogWarning(msg); } } public static void logError(String msg) { Logger l = sInstance; if (l != null) { l.doLogError(msg); } } /* ///////////////////////////////////////////////////////////// // Overridable implementation/instance methods ///////////////////////////////////////////////////////////// */ // // // Config protected void doSetLogLevel(int ll) { /* No need to sync for atomic value that's not used * for synced or critical things */ mLogLevel = ll; } protected void doSetOutput(PrintStream str) { synchronized (this) { mOutput1 = str; mOutput2 = null; } } protected void doSetOutput(Writer w) { synchronized (this) { mOutput1 = null; mOutput2 = (w instanceof PrintWriter) ? (PrintWriter) w : new PrintWriter(w); } } // // // Logging methods protected void doLogInfo(String msg) { if (mLogLevel <= LOG_INFO_AND_ABOVE && isEnabled()) { synchronized (this) { doWrite("INFO: "+msg); } } } protected void doLogWarning(String msg) { if (mLogLevel <= LOG_WARNING_AND_ABOVE && isEnabled()) { synchronized (this) { doWrite("WARNING: "+msg); } } } protected void doLogError(String msg) { if (mLogLevel <= LOG_ERROR_AND_ABOVE && isEnabled()) { synchronized (this) { doWrite("ERROR: "+msg); } } } /* ///////////////////////////////////////////////////////////// // Internal methods ///////////////////////////////////////////////////////////// */ protected void doWrite(String msg) { if (mOutput1 != null) { mOutput1.println(msg); } else if (mOutput2 != null) { mOutput2.println(msg); } } /** * Internal method used to quickly check if the Logger's output * is suppressed or not. *<p> * Note: not synchronized since it's read-only method that's return * value can not be used for reliable syncing. */ protected boolean isEnabled() { return (mOutput1 != null) || (mOutput2 != null); } }