/******************************************************************************* * Copyright (c) 2009 MATERNA Information & Communications. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html. For further * project-related information visit http://www.ws4d.org. The most recent * version of the JMEDS framework can be obtained from * http://sourceforge.net/projects/ws4d-javame. ******************************************************************************/ package org.ws4d.java.util; import java.io.OutputStream; import java.io.PrintStream; import java.util.Calendar; import java.util.Enumeration; import java.util.Vector; import org.ws4d.java.DPWSFramework; /** * Debug class provides logging mechanism and control over the output messages.<br /> * Use this instead of System.out.println().<br /> * <br /> * To change the debug level and the message output, use setDebugLevel(int * level).<br /> * <br /> * e.g.<br /> * <code>setDebugLevel(Debug.DEBUG_LEVEL_WARNING);</code><br /> * <br /> * DEBUG_LEVEL_DEBUG = highest output level, every message shown.<br /> * DEBUG_LEVEL_INFO = show information, log, warn and error messages only.<br /> * DEBUG_LEVEL_LOG = show log, warn and error messages only.<br /> * DEBUG_LEVEL_WARN = show warn and error messages only.<br /> * DEBUG_LEVEL_ERROR = show error messages only.<br /> * DEBUG_LEVEL_NO_LOGGING = show nothing.<br /> */ public final class Log { /** * Should be used to show all debug messages. */ public static final int DEBUG_LAYER_ALL = Integer.MAX_VALUE; /** * Should be used to show general framework debug messages. */ public static final int DEBUG_LAYER_FRAMEWORK = 4; /** * Should be used to show application layer (device+service) debug messages */ public static final int DEBUG_LAYER_APPLICATION = 2; /** * Should be used to show communication layer (DPWS) debug messages. */ public static final int DEBUG_LAYER_COMMUNICATION = 1; /** Sets highest output level, every message shown. */ public static final int DEBUG_LEVEL_DEBUG = 4; /** Sets level to show information, warn and error messages only. */ public static final int DEBUG_LEVEL_INFO = 3; /** Sets level to show warn and error messages only. */ public static final int DEBUG_LEVEL_WARN = 2; /** Sets level to show error messages only. */ public static final int DEBUG_LEVEL_ERROR = 1; /** Sets level to show error messages only. */ public static final int DEBUG_LEVEL_NO_LOGGING = 0; /** Prefix setup * */ private static final String PREFIX_DEBUG = "DEBUG"; private static final String PREFIX_INFO = "INFO "; private static final String PREFIX_WARN = "WARN "; private static final String PREFIX_ERROR = "ERROR"; /** Disables/Enables time stamp. */ private static boolean showTimestamp = false; /** Default debug level for this object. */ private static int logLevel = DEBUG_LEVEL_DEBUG; private static int defaultLayers = DEBUG_LAYER_ALL; private static int activeLayers = defaultLayers; /** Notification list for debug subscribers. */ private static Vector subscribers = new Vector(); private static PrintStream out = System.out; private static PrintStream err = System.err; private static boolean logStackTrace = true; /** * Sets time stamp on or off. * * @param set <code>true</code> if Debug should show time stamps, * <code>false</code> if not. */ public static void setShowTimestamp(boolean set) { showTimestamp = set; } /** * Sets logging of stack traces on or off. * * @param logStackTrace <code>true</code> if Debug should log stack traces, * <code>false</code> if not. */ public static void setLogStackTrace(boolean logStackTrace) { Log.logStackTrace = logStackTrace; } /** * Sets the internal debug level for this logger. * * @param level the debug level to set. */ public static void setLogLevel(int level) { setLogLevel(level, defaultLayers); } /** * Sets the internal debug level for this logger. * <p> * The set layers could be a single layer or a combination of them * </p> * * @param level the debug level to set. * @param layers the layers which debug messages should be shown for. * @see #DEBUG_LAYER_ALL * @see #DEBUG_LAYER_APPLICATION * @see #DEBUG_LAYER_COMMUNICATION * @see #DEBUG_LAYER_FRAMEWORK */ public static void setLogLevel(int level, int layers) { logLevel = level; activeLayers = layers; } /** * Gets the internal debug level for this logger. * * @return the debug level. */ public static int getLogLevel() { return logLevel; } /** * Checks whether the current log level is at least * {@link #DEBUG_LEVEL_DEBUG}. * * @return whether the current log level is at least * {@link #DEBUG_LEVEL_DEBUG} or not */ public static boolean isDebug() { return logLevel >= DEBUG_LEVEL_DEBUG; } /** * Checks whether the current log level is at least * {@link #DEBUG_LEVEL_INFO}. * * @return whether the current log level is at least * {@link #DEBUG_LEVEL_INFO} or not */ public static boolean isInfo() { return logLevel >= DEBUG_LEVEL_INFO; } /** * Checks whether the current log level is at least * {@link #DEBUG_LEVEL_WARN}. * * @return whether the current log level is at least * {@link #DEBUG_LEVEL_WARN} or not */ public static boolean isWarn() { return logLevel >= DEBUG_LEVEL_WARN; } /** * Checks whether the current log level is at least * {@link #DEBUG_LEVEL_ERROR}. * * @return whether the current log level is at least * {@link #DEBUG_LEVEL_ERROR} or not */ public static boolean isError() { return logLevel >= DEBUG_LEVEL_ERROR; } /** * Generates time stamp (hour:minute:second.millisecond). * * @return time stamp generated time stamp. */ protected static String showTimestamp() { if (!showTimestamp) return ""; Calendar cal = Calendar.getInstance(); int tmp = cal.get(Calendar.HOUR_OF_DAY); String h = (tmp < 10 ? "0" : "") + String.valueOf(tmp); tmp = cal.get(Calendar.MINUTE); String m = (tmp < 10 ? "0" : "") + String.valueOf(tmp); tmp = cal.get(Calendar.SECOND); String s = (tmp < 10 ? "0" : "") + String.valueOf(tmp); tmp = cal.get(Calendar.MILLISECOND); String ms = (tmp < 10 ? "00" : (tmp < 100 ? "0" : "")) + String.valueOf(tmp); return "|" + h + ":" + m + ":" + s + "." + ms; } /** * Logs a debug message.<br /> * Use this for debugging messages.<br /> * The message is logged only when the current debug level is >= * DEBUG_LEVEL_DEBUG. * * @param msg the message to log. */ public static void debug(String msg) { debug(msg, DEBUG_LAYER_ALL); } /** * Logs a debug message.<br /> * Use this for debugging messages.<br /> * The message is logged only when the current debug level is >= * DEBUG_LEVEL_DEBUG. * * @param msg the message to log. */ public static void debug(String msg, int layer) { if ((layer & activeLayers) == activeLayers || (layer & activeLayers) == layer) { msgout(DEBUG_LEVEL_DEBUG, "[" + PREFIX_DEBUG + showTimestamp() + "] " + msg); } } /** * Logs an info message.<br /> * Use this for informational messages.<br /> * The message is logged only when the current debug level is >= * DEBUG_LEVEL_INFO. * * @param msg the message to log. */ public static void info(String msg) { msgout(DEBUG_LEVEL_INFO, "[" + PREFIX_INFO + showTimestamp() + "] " + msg); } /** * Logs an error message.<br /> * Use this for messages regarding critical errors.<br /> * The message is logged only when the current debug level is >= * DEBUG_LEVEL_ERROR. * * @param msg the message to log. */ public static void error(String msg) { msgout(DEBUG_LEVEL_ERROR, "[" + PREFIX_ERROR + showTimestamp() + "] " + msg); } /** * Logs a warning message.<br /> * Use this for messages about malfunctions which are not so severe to be * treated as errors.<br /> * The message is logged only when the current debug level is >= * DEBUG_LEVEL_WARN. * * @param msg the message to log. */ public static void warn(String msg) { msgout(DEBUG_LEVEL_WARN, "[" + PREFIX_WARN + showTimestamp() + "] " + msg); } /** * Prints messages on System.out depending on debug level. * * @param level in the range from 1..5, or use one of the predefined * constants. * @param msg the message to log. */ protected static void msgout(int level, String msg) { if (level <= logLevel) { if (level == DEBUG_LEVEL_ERROR || level == DEBUG_LEVEL_WARN) { err.println(msg); err.flush(); } else { out.println(msg); out.flush(); } notifySubscribers(msg); } } /** * Prints stack trace, if debug level is "Error" or higher and logging of * stack traces is on. Will be printed to error output if possible. Within * CLDC environment log will be printed to System.err. * * @param t the throwable. */ public static void printStackTrace(Throwable t) { if (logLevel != DEBUG_LEVEL_NO_LOGGING && logStackTrace) { Toolkit toolkit = DPWSFramework.getToolkit(); if (toolkit != null) { toolkit.printStackTrace(err, t); } else { // fall back to common interface t.printStackTrace(); } } } /** * Returns the Java VM stack trace if possible. * <p> * Can return <code>null</code> if the platform does not support access to * the stack trace! * </p> * * @param t stack trace * @return stack trace as array of <code>String</code>. */ public static String[] getStackTrace(Throwable t) { Toolkit toolkit = DPWSFramework.getToolkit(); if (toolkit != null) { return toolkit.getStackTrace(t); } else { // fall back to common interface return null; } } /** * Notifies all subscribers. * * @param message the debug message. */ private static void notifySubscribers(String message) { for (Enumeration subEnum = subscribers.elements(); subEnum.hasMoreElements();) { ((LogSubscriber) subEnum.nextElement()).notify(message); } } /** * Subscribes to notification list for receiving debug messages. This is * especially useful when you want to stay informed about new debug messages * on devices without a console output (like CLDC/MIDP devices). * * @param ds an object wants to subscribe for debug messages. * @see org.ws4d.java.util.LogSubscriber */ public static void subscribe(LogSubscriber ds) { subscribers.addElement(ds); } /** * Unsubscribes from notification list. * * @param ds an object wants to unsubscribe form debug messages * @see org.ws4d.java.util.LogSubscriber */ public static void unsubscribe(LogSubscriber ds) { subscribers.removeElement(ds); } public static void setNormalOutput(OutputStream newout) { out = new PrintStream(newout); } public static void setErrorOutput(OutputStream newout) { err = new PrintStream(newout); } }