android.gov.nist.core.LogWriter Maven / Gradle / Ivy
/*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain. As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY. NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement.
*
*/
/***************************************************************************
* Product of NIST/ITL Advanced Networking Technologies Division (ANTD). *
***************************************************************************/
package android.gov.nist.core;
import java.io.*;
import java.util.Properties;
import org.apache.log4j.Appender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.Priority;
import org.apache.log4j.SimpleLayout;
/**
* A wrapper around log4j that is used for logging debug and errors. You can
* replace this file if you want to change the way in which messages are logged.
*
* @version 1.2
*
* @author M. Ranganathan
* @author M.Andrews
* @author Jeroen van Bemmel
* @author Jean Deruelle
*
*/
public class LogWriter implements StackLogger {
/**
* The logger to which we will write our logging output.
*/
private Logger logger;
/**
* The stack name.
*/
private String stackName;
/**
* Name of the log file in which the trace is written out (default is
* /tmp/sipserverlog.txt)
*/
private String logFileName = null;
/**
* Flag to indicate that logging is enabled.
*/
private volatile boolean needsLogging = false;
private int lineCount;
/**
* trace level
*/
protected int traceLevel = TRACE_NONE;
private String buildTimeStamp;
private Properties configurationProperties;
/**
* log a stack trace. This helps to look at the stack frame.
*/
public void logStackTrace() {
this.logStackTrace(TRACE_DEBUG);
}
public void logStackTrace(int traceLevel) {
if (needsLogging) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
StackTraceElement[] ste = new Exception().getStackTrace();
// Skip the log writer frame and log all the other stack frames.
for (int i = 1; i < ste.length; i++) {
String callFrame = "[" + ste[i].getFileName() + ":"
+ ste[i].getLineNumber() + "]";
pw.print(callFrame);
}
pw.close();
String stackTrace = sw.getBuffer().toString();
Level level = this.getLevel(traceLevel);
Priority priority = this.getLogPriority();
if ( level.isGreaterOrEqual(priority)) {
logger.log(level,stackTrace);
}
}
}
/**
* Get the line count in the log stream.
*
* @return
*/
public int getLineCount() {
return lineCount;
}
/**
* Get the logger.
*
* @return
*/
public Logger getLogger() {
return logger;
}
/**
* This method allows you to add an external appender.
* This is useful for the case when you want to log to
* a different log stream than a file.
*
* @param appender
*/
public void addAppender(Appender appender) {
this.logger.addAppender(appender);
}
/**
* Log an exception.
*
* @param ex
*/
public void logException(Throwable ex) {
if (needsLogging) {
this.getLogger().error(ex.getMessage(), ex);
}
}
/**
* Counts the line number so that the debug log can be correlated to the
* message trace.
*
* @param message --
* message to count the lines for.
*/
private void countLines(String message) {
char[] chars = message.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (chars[i] == '\n')
lineCount++;
}
}
/**
* Prepend the line and file where this message originated from
*
* @param message
* @return re-written message.
*/
private String enhanceMessage(String message) {
StackTraceElement[] stackTrace = new Exception().getStackTrace();
StackTraceElement elem = stackTrace[3];
String className = elem.getClassName();
String methodName = elem.getMethodName();
String fileName = elem.getFileName();
int lineNumber = elem.getLineNumber();
String newMessage = className + "." + methodName + "(" + fileName + ":"
+ lineNumber + ") [" + message + "]";
return newMessage;
}
/**
* Log a message into the log file.
*
* @param message
* message to log into the log file.
*/
public void logDebug(String message) {
if (needsLogging) {
String newMessage = this.enhanceMessage(message);
if ( this.lineCount == 0) {
getLogger().debug("BUILD TIMESTAMP = " + this.buildTimeStamp);
getLogger().debug("Config Propeties = " + this.configurationProperties);
}
countLines(newMessage);
getLogger().debug(newMessage);
}
}
/*
* (non-Javadoc)
* @see android.gov.nist.core.StackLogger#logDebug(java.lang.String, java.lang.Exception)
*/
public void logDebug(String message, Exception ex) {
if (needsLogging) {
String newMessage = this.enhanceMessage(message);
if ( this.lineCount == 0) {
getLogger().debug("BUILD TIMESTAMP = " + this.buildTimeStamp);
getLogger().debug("Config Propeties = " + this.configurationProperties);
}
countLines(newMessage);
getLogger().debug(newMessage, ex);
}
}
/**
* Log a message into the log file.
*
* @param message
* message to log into the log file.
*/
public void logTrace(String message) {
if (needsLogging) {
String newMessage = this.enhanceMessage(message);
if ( this.lineCount == 0) {
getLogger().debug("BUILD TIMESTAMP = " + this.buildTimeStamp);
getLogger().debug("Config Propeties = " + this.configurationProperties);
}
countLines(newMessage);
getLogger().trace(newMessage);
}
}
/**
* Set the trace level for the stack.
*/
private void setTraceLevel(int level) {
traceLevel = level;
}
/**
* Get the trace level for the stack.
*/
public int getTraceLevel() {
return traceLevel;
}
/**
* Log an error message.
*
* @param message --
* error message to log.
*/
public void logFatalError(String message) {
Logger logger = this.getLogger();
String newMsg = this.enhanceMessage(message);
countLines(newMsg);
logger.fatal(newMsg);
}
/**
* Log an error message.
*
* @param message --
* error message to log.
*
*/
public void logError(String message) {
Logger logger = this.getLogger();
String newMsg = this.enhanceMessage(message);
countLines(newMsg);
logger.error(newMsg);
}
public LogWriter() {
}
public void setStackProperties(Properties configurationProperties) {
this.configurationProperties = configurationProperties;
String logLevel = configurationProperties
.getProperty("android.gov.nist.javax.sip.TRACE_LEVEL");
this.logFileName = configurationProperties
.getProperty("android.gov.nist.javax.sip.DEBUG_LOG");
this.stackName = configurationProperties
.getProperty("android.javax.sip.STACK_NAME");
//check whether a Log4j logger name has been
//specified. if not, use the stack name as the default
//logger name.
String category = configurationProperties
.getProperty("android.gov.nist.javax.sip.LOG4J_LOGGER_NAME", this.stackName);
logger = Logger.getLogger(category);
if (logLevel != null) {
if (logLevel.equals("LOG4J")) {
CommonLogger.useLegacyLogger = false;
}
else {
try {
int ll = 0;
if (logLevel.equals("TRACE")) {
ll = TRACE_DEBUG;
Debug.debug = true;
Debug.setStackLogger(this);
} else if (logLevel.equals("DEBUG")) {
ll = TRACE_DEBUG;
} else if ( logLevel.equals("INFO")) {
ll = TRACE_INFO;
} else if (logLevel.equals("ERROR")) {
ll = TRACE_ERROR;
} else if (logLevel.equals("NONE") || logLevel.equals("OFF")) {
ll = TRACE_NONE;
} else {
ll = Integer.parseInt(logLevel);
if ( ll > 32 ) {
Debug.debug = true;
Debug.setStackLogger(this);
}
}
this.setTraceLevel(ll);
this.needsLogging = true;
if (traceLevel == TRACE_DEBUG) {
logger.setLevel(Level.DEBUG);
} else if (traceLevel == TRACE_INFO) {
logger.setLevel(Level.INFO);
} else if (traceLevel == TRACE_ERROR) {
logger.setLevel(Level.ERROR);
} else if (traceLevel == TRACE_NONE) {
logger.setLevel(Level.OFF);
this.needsLogging = false;
}
/*
* If user specifies a logging file as part of the startup
* properties then we try to create the appender.
*/
if (this.needsLogging && this.logFileName != null) {
boolean overwrite = Boolean.valueOf(
configurationProperties.getProperty(
"android.gov.nist.javax.sip.DEBUG_LOG_OVERWRITE"));
FileAppender fa = null;
try {
fa = new FileAppender(new SimpleLayout(),
this.logFileName, !overwrite);
} catch (FileNotFoundException fnf) {
// Likely due to some directoy not existing. Create
// them
File logfile = new File(this.logFileName);
logfile.getParentFile().mkdirs();
logfile.delete();
try {
fa = new FileAppender(new SimpleLayout(),
this.logFileName);
} catch (IOException ioe) {
ioe.printStackTrace(); // give up
}
} catch (IOException ex) {
ex.printStackTrace();
}
if (fa != null)
logger.addAppender(fa);
}
} catch (NumberFormatException ex) {
ex.printStackTrace();
System.err.println("LogWriter: Bad integer " + logLevel);
System.err.println("logging dislabled ");
needsLogging = false;
}
}
} else {
this.needsLogging = false;
}
}
/**
* @return flag to indicate if logging is enabled.
*/
public boolean isLoggingEnabled() {
return this.needsLogging;
}
/**
* Return true/false if loging is enabled at a given level.
*
* @param logLevel
*/
public boolean isLoggingEnabled(int logLevel) {
return this.needsLogging && logLevel <= traceLevel;
}
/**
* Log an error message.
*
* @param message
* @param ex
*/
public void logError(String message, Exception ex) {
Logger logger = this.getLogger();
logger.error(message, ex);
}
/**
* Log a warning mesasge.
*
* @param string
*/
public void logWarning(String string) {
getLogger().warn(string);
}
/**
* Log an info message.
*
* @param string
*/
public void logInfo(String string) {
getLogger().info(string);
}
/**
* Disable logging altogether.
*
*/
public void disableLogging() {
this.needsLogging = false;
}
/**
* Enable logging (globally).
*/
public void enableLogging() {
this.needsLogging = true;
}
public void setBuildTimeStamp(String buildTimeStamp) {
this.buildTimeStamp = buildTimeStamp;
}
public Priority getLogPriority() {
if ( this.traceLevel == TRACE_INFO ) {
return Priority.INFO;
} else if ( this.traceLevel == TRACE_ERROR ) {
return Priority.ERROR;
} else if ( this.traceLevel == TRACE_DEBUG) {
return Priority.DEBUG;
} else if ( this.traceLevel == TRACE_TRACE) {
return Priority.DEBUG;
} else {
return Priority.FATAL;
}
}
public Level getLevel(int traceLevel) {
if ( traceLevel == TRACE_INFO ) {
return Level.INFO;
} else if ( traceLevel == TRACE_ERROR ) {
return Level.ERROR;
} else if ( traceLevel == TRACE_DEBUG) {
return Level.DEBUG;
} else if (traceLevel == TRACE_TRACE) {
return Level.ALL;
} else {
return Level.OFF;
}
}
public String getLoggerName() {
if ( this.logger != null ) {
return logger.getName();
} else {
return null;
}
}
}