package com.perforce.api;
import java.io.*;
import java.util.*;
import java.text.*;
/*
* Copyright (c) 2001, Perforce Software, All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Utility class used for debugging. The level of debugging determines the
* amount of debugging information that is generated. The process using this
* class for debugging should ensure that it
* {@link #setDebugLevel(int) sets the debugging level} appropriately.
*
* @author <a href="mailto:david@markley.cc">David Markley</a>
* @version $Date: 2001/11/05 $ $Revision: #1 $
*/
public final class Debug {
/** No debug messages are displayed. */
public final static int NONE = 0;
/** Only error messages are displayed. */
public final static int ERROR = 1;
/** Error and warning messages are displayed. */
public final static int WARNING = 2;
/** Error, warning, and notice messages are displayed. */
public final static int NOTICE = 3;
/** Error, warning, notice, and verbose messages are displayed. */
public final static int VERBOSE = 99;
/** Debugging output is discarded entirely. */
public final static int LOG_NONE = 0;
/**
* Debugging output is sent to standard out and to the
* {@link EventLog EventLog}.
*/
public final static int LOG_SPLIT = 1;
/** Debugging output is sent only to the {@link EventLog EventLog}. */
public final static int LOG_ONLY = 3;
private static int level = NONE;
private static EventLog elog = null;
private static int log_level = LOG_ONLY;
private static boolean show_thread = false;
/**
* Returns the name associated with the specified level.
*
* @see #setDebugLevel(int)
*/
public static String getLevelName(int level) {
if(NONE >= level) {
return "NONE";
} else if(ERROR >= level) {
return "ERROR";
} else if(WARNING >= level) {
return "WARNING";
} else if(NOTICE >= level) {
return "NOTICE";
}
return "VERBOSE";
}
/**
* Sets the debug level for the application. If this is 0, no debug
* information is generated.
*
* @see #NONE
* @see #ERROR
* @see #WARNING
* @see #NOTICE
* @see #VERBOSE
* @param l
* The level of debugging to use.
*/
public static void setDebugLevel(int l) {
level = l;
}
/**
* Returns the current debug level.
*
* @see #setDebugLevel(int)
*/
public static int getDebugLevel() {
return level;
}
/**
* If set <code>true</code>, the thread number is included in all
* debugging output.
*/
public static void setShowThread(boolean show) {
show_thread = show;
}
/**
* Returns the state of showing threads in degugging output.
*/
public static boolean getShowThread() {
return show_thread;
}
/**
* Sets the <code>EventLog</code> that debugging output should be sent to.
*
* @param elog
* <code>EventLog</code> to use.
*/
public static void setEventLog(EventLog elog) {
Debug.elog = elog;
}
/**
* Returns the current <code>EventLog</code> in use.
*/
public static EventLog getEventLog() {
return elog;
}
/**
* Sets the logging level. This determines where the debugging output will
* be sent. Valid values are "none", "only", or "split". The default is
* "only". The default value will be set, if the <code>String</code> does
* not match.
*/
public static void setLogLevel(String level) {
if(level.equalsIgnoreCase("split")) {
setLogLevel(Debug.LOG_SPLIT);
} else if(level.equalsIgnoreCase("only")) {
setLogLevel(Debug.LOG_ONLY);
} else {
setLogLevel(Debug.LOG_NONE);
}
}
/**
* Sets the logging level from the supplied <code>Properties</code>. This
* looks for the "p4.log_level" property with the value of either "none",
* "split", or "only".
*/
public static void setProperties(Properties props) {
String log = props.getProperty("p4.log_level", "none");
if(log.equalsIgnoreCase("split")) {
Debug.log_level = Debug.LOG_SPLIT;
} else if(log.equalsIgnoreCase("only")) {
Debug.log_level = Debug.LOG_ONLY;
} else {
Debug.log_level = Debug.LOG_NONE;
}
}
/**
* Sets the logging level. This determines where the debugging output will
* be sent. Valid values are: {@link #LOG_SPLIT LOG_SPLIT},
* {@link #LOG_ONLY LOG_ONLY}, and {@link #LOG_NONE LOG_NONE}. The default
* is {@link #LOG_ONLY LOG_ONLY}.
* <p>
* If the log level is set to {@link #LOG_NONE LOG_NONE}, then the debug
* level is automatically set to {@link #NONE NONE}.
*/
public static void setLogLevel(int log_level) {
Debug.log_level = log_level;
if(Debug.LOG_NONE == Debug.log_level)
Debug.level = Debug.NONE;
}
/**
* Returns the current logging level.
*/
public static int getLogLevel() {
return Debug.log_level;
}
/**
* Sends the message to the <code>EventLog</code>
*
* @see EventLog
*/
private static void errLog(String msg, String level) {
if(null == elog)
return;
elog.log(getThreadName() + msg, level);
}
/**
* @return The current Thread Name if show_thread is true
*/
private static String getThreadName() {
return show_thread ? Thread.currentThread().getName() + ": " : "";
}
/**
* Displays an error message for debugging. If the debugging level is set
* below ERROR, then no message is displayed.
*
* @param msg
* The debugging error message.
*/
public static void error(String msg) {
if(ERROR > level)
return;
System.out.println(getThreadName() + "ERROR: " + msg);
System.out.flush();
if(LOG_SPLIT <= log_level) {
errLog(msg, "ERROR");
}
}
/**
* Displays a warning message for debugging. If the debugging level is set
* below WARNING, then no message is displayed.
*
* @param msg
* The debugging warning message.
*/
public static void warn(String msg) {
if(WARNING > level)
return;
if(LOG_SPLIT >= log_level) {
System.out.println(getThreadName() + "WARNING: " + msg);
System.out.flush();
}
if(LOG_SPLIT <= log_level) {
errLog(msg, "WARNING");
}
}
/**
* Displays a notice message for debugging. If the debugging level is set
* below NOTICE, then no message is displayed.
*
* @param msg
* The debugging notice message.
*/
public static void notify(String msg) {
if(NOTICE > level)
return;
if(LOG_SPLIT >= log_level) {
System.out.println(getThreadName() + msg);
System.out.flush();
}
if(LOG_SPLIT <= log_level) {
errLog(msg, "NOTIFY");
}
}
/**
* Displays a notice message for debugging. If the debugging level is set
* below NOTICE, then no message is displayed.
*
* @param msg
* The debugging notice message.
* @param arry
* Array containing useful debug information.
*/
public static void notify(String msg, String[] arry) {
if(NOTICE > level)
return;
StringBuffer sb = new StringBuffer();
for(int i = 0; i < arry.length; i++) {
sb.append(arry[i]);
sb.append(' ');
}
if(LOG_SPLIT >= log_level) {
System.out.println(getThreadName() + msg + sb);
System.out.flush();
}
if(LOG_SPLIT <= log_level) {
errLog(msg + sb, "NOTIFY");
}
}
/**
* Displays a verbose message for debugging. If the debugging level is set
* below VERBOSE, then no message is displayed.
*
* @param msg
* The debugging notice message.
*/
public static void verbose(String msg) {
if(VERBOSE > level)
return;
if(LOG_SPLIT >= log_level) {
System.out.println(getThreadName() + msg);
System.out.flush();
}
if(LOG_SPLIT <= log_level) {
errLog(msg, "VERBOSE");
}
}
/**
* Displays a verbose message for debugging. If the debugging level is set
* below VERBOSE, then no message is displayed.
*
* @param msg
* The debugging notice message.
* @param arry
* Array containing useful debug information.
*/
public static void verbose(String msg, String[] arry) {
if(VERBOSE > level)
return;
StringBuffer sb = new StringBuffer();
for(int i = 0; i < arry.length; i++) {
sb.append(arry[i]);
sb.append(' ');
}
if(LOG_SPLIT >= log_level) {
System.out.println(getThreadName() + msg + sb);
System.out.flush();
}
if(LOG_SPLIT <= log_level) {
errLog(msg + sb, "VERBOSE");
}
}
/**
* Writes the message associated with the <code>Throwable</code> to the
* debugging output.
*
* @param level
* Debugging level to associate with the message.
* @param t
* Throwable that contains the message.
*/
public static void out(int level, Throwable t) {
out("{0}", level, t);
}
/**
* Writes the formatted message associated with the <code>Throwable</code>
* to the debugging output. The message will be placed in the string
* generated wherever the '{0}' attribute is placed.
*
* @see java.text.MessageFormat
* @param format
* Format to use for the debugging output.
* @param level
* Debugging level to associate with the message.
* @param t
* Throwable that contains the message.
*/
public static void out(String format, int level, Throwable t) {
if(level > Debug.level)
return;
try {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
pw.close();
Object[] args = { sw.toString() };
String msg = MessageFormat.format(format, args);
if(LOG_SPLIT >= log_level) {
System.out.println(getThreadName() + msg);
System.out.flush();
}
if(LOG_SPLIT <= log_level) {
errLog(msg, Debug.getLevelName(level));
}
} catch(Exception ex) {
System.err.println(t);
System.err.flush();
}
}
/**
* Writes the message to the debugging output.
*
* @param level
* Debugging level to associate with the message.
* @param msg
* Debugging message.
*/
public static void out(int level, String msg) {
if(level > Debug.level)
return;
if(LOG_SPLIT >= log_level) {
System.out.println(getThreadName() + msg);
System.out.flush();
}
if(LOG_SPLIT <= log_level) {
errLog(msg, Debug.getLevelName(level));
}
}
/**
* Writes the message and associated array of Strings to the debugging
* output. The message will be followed by all the elements in the
* <code>arry</code>.
*
* @param level
* Debugging level to associate with the message.
* @param msg
* Debugging message.
* @param arry
* Array of strings to be sent to the debugging output.
*/
public static void out(int level, String msg, String[] arry) {
if(level > Debug.level)
return;
StringBuffer sb = new StringBuffer();
for(int i = 0; i < arry.length; i++) {
sb.append(arry[i]);
sb.append(' ');
}
if(LOG_SPLIT >= log_level) {
System.out.println(getThreadName() + msg + sb);
System.out.flush();
}
if(LOG_SPLIT <= log_level) {
errLog(msg + sb, Debug.getLevelName(level));
}
}
}