/*
* 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 gov.nist.javax.sip.stack;
import gov.nist.core.ServerLogger;
import gov.nist.core.StackLogger;
import gov.nist.javax.sip.LogRecord;
import gov.nist.javax.sip.header.CallID;
import gov.nist.javax.sip.message.SIPMessage;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import javax.sip.SipStack;
import javax.sip.header.TimeStampHeader;
// BEGIN android-deleted
// import org.apache.log4j.Level;
// import org.apache.log4j.Logger;
// END android-deleted
/**
* Log file wrapper class. Log messages into the message trace file and also write the log into
* the debug file if needed. This class keeps an XML formatted trace around for later access via
* RMI. The trace can be viewed with a trace viewer (see tools.traceviewerapp).
*
* @version 1.2 $Revision: 1.39 $ $Date: 2009/11/11 14:00:58 $
*
* @author M. Ranganathan <br/>
*
*
*/
public class ServerLog implements ServerLogger {
private boolean logContent;
protected StackLogger stackLogger;
/**
* Name of the log file in which the trace is written out (default is null)
*/
private String logFileName;
/**
* Print writer that is used to write out the log file.
*/
private PrintWriter printWriter;
/**
* Set auxililary information to log with this trace.
*/
private String auxInfo;
private String description;
private String stackIpAddress;
private SIPTransactionStack sipStack;
private Properties configurationProperties;
public ServerLog() {
// Debug log file. Whatever gets logged by us also makes its way into debug log.
}
private void setProperties(Properties configurationProperties) {
this.configurationProperties = configurationProperties;
// Set a descriptive name for the message trace logger.
this.description = configurationProperties.getProperty("javax.sip.STACK_NAME");
this.stackIpAddress = configurationProperties.getProperty("javax.sip.IP_ADDRESS");
this.logFileName = configurationProperties.getProperty("gov.nist.javax.sip.SERVER_LOG");
String logLevel = configurationProperties.getProperty("gov.nist.javax.sip.TRACE_LEVEL");
String logContent = configurationProperties
.getProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT");
this.logContent = (logContent != null && logContent.equals("true"));
if (logLevel != null) {
if (logLevel.equals("LOG4J")) {
// if TRACE_LEVEL property is specified as
// "LOG4J" then, set the traceLevel based on
// the log4j effective log level.
// check whether a Log4j logger name has been
// specified. if not, use the stack name as the default
// logger name.
// BEGIN android-deleted
/*
Logger logger = Logger.getLogger(configurationProperties.getProperty(
"gov.nist.javax.sip.LOG4J_LOGGER_NAME", this.description));
Level level = logger.getEffectiveLevel();
if (level == Level.OFF) {
this.setTraceLevel(0);
} else if (level.isGreaterOrEqual(Level.DEBUG)) {
this.setTraceLevel(TRACE_DEBUG);
} else if (level.isGreaterOrEqual(Level.INFO)) {
this.setTraceLevel(TRACE_MESSAGES);
} else if (level.isGreaterOrEqual(Level.WARN)) {
this.setTraceLevel(TRACE_EXCEPTION);
}
*/
// END android-deleted
} else {
try {
int ll;
if (logLevel.equals("DEBUG")) {
ll = TRACE_DEBUG;
} else if (logLevel.equals("INFO")) {
ll = TRACE_MESSAGES;
} else if (logLevel.equals("ERROR")) {
ll = TRACE_EXCEPTION;
} else if (logLevel.equals("NONE") || logLevel.equals("OFF")) {
ll = TRACE_NONE;
} else {
ll = Integer.parseInt(logLevel);
}
this.setTraceLevel(ll);
} catch (NumberFormatException ex) {
System.out.println("ServerLog: WARNING Bad integer " + logLevel);
System.out.println("logging dislabled ");
this.setTraceLevel(0);
}
}
}
checkLogFile();
}
public void setStackIpAddress(String ipAddress) {
this.stackIpAddress = ipAddress;
}
// public static boolean isWebTesterCatchException=false;
// public static String webTesterLogFile=null;
/**
* default trace level
*/
protected int traceLevel = TRACE_MESSAGES;
public synchronized void closeLogFile() {
if (printWriter != null) {
printWriter.close();
printWriter = null;
}
}
public void checkLogFile() {
if (logFileName == null || traceLevel < TRACE_MESSAGES) {
// Dont create a log file if tracing is
// disabled.
return;
}
try {
File logFile = new File(logFileName);
if (!logFile.exists()) {
logFile.createNewFile();
printWriter = null;
}
// Append buffer to the end of the file unless otherwise specified
// by the user.
if (printWriter == null) {
boolean overwrite = Boolean.valueOf(
configurationProperties.getProperty(
"gov.nist.javax.sip.SERVER_LOG_OVERWRITE"));
FileWriter fw = new FileWriter(logFileName, !overwrite);
printWriter = new PrintWriter(fw, true);
printWriter.println("<!-- "
+ "Use the Trace Viewer in src/tools/tracesviewer to"
+ " view this trace \n"
+ "Here are the stack configuration properties \n"
+ "javax.sip.IP_ADDRESS= "
+ configurationProperties.getProperty("javax.sip.IP_ADDRESS") + "\n"
+ "javax.sip.STACK_NAME= "
+ configurationProperties.getProperty("javax.sip.STACK_NAME") + "\n"
+ "javax.sip.ROUTER_PATH= "
+ configurationProperties.getProperty("javax.sip.ROUTER_PATH") + "\n"
+ "javax.sip.OUTBOUND_PROXY= "
+ configurationProperties.getProperty("javax.sip.OUTBOUND_PROXY") + "\n"
+ "-->");
printWriter.println("<description\n logDescription=\"" + description
+ "\"\n name=\""
+ configurationProperties.getProperty("javax.sip.STACK_NAME")
+ "\"\n auxInfo=\"" + auxInfo + "\"/>\n ");
if (auxInfo != null) {
if (sipStack.isLoggingEnabled()) {
stackLogger
.logDebug("Here are the stack configuration properties \n"
+ "javax.sip.IP_ADDRESS= "
+ configurationProperties
.getProperty("javax.sip.IP_ADDRESS")
+ "\n"
+ "javax.sip.ROUTER_PATH= "
+ configurationProperties
.getProperty("javax.sip.ROUTER_PATH")
+ "\n"
+ "javax.sip.OUTBOUND_PROXY= "
+ configurationProperties
.getProperty("javax.sip.OUTBOUND_PROXY")
+ "\n"
+ "gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS= "
+ configurationProperties
.getProperty("gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS")
+ "\n"
+ "gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS= "
+ configurationProperties
.getProperty("gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS")
+ "\n"
+ "gov.nist.javax.sip.REENTRANT_LISTENER= "
+ configurationProperties
.getProperty("gov.nist.javax.sip.REENTRANT_LISTENER")
+ "gov.nist.javax.sip.THREAD_POOL_SIZE= "
+ configurationProperties
.getProperty("gov.nist.javax.sip.THREAD_POOL_SIZE")
+ "\n");
stackLogger.logDebug(" ]]> ");
stackLogger.logDebug("</debug>");
stackLogger.logDebug("<description\n logDescription=\"" + description
+ "\"\n name=\"" + stackIpAddress + "\"\n auxInfo=\"" + auxInfo
+ "\"/>\n ");
stackLogger.logDebug("<debug>");
stackLogger.logDebug("<![CDATA[ ");
}
} else {
if (sipStack.isLoggingEnabled()) {
stackLogger.logDebug("Here are the stack configuration properties \n"
+ configurationProperties + "\n");
stackLogger.logDebug(" ]]>");
stackLogger.logDebug("</debug>");
stackLogger.logDebug("<description\n logDescription=\"" + description
+ "\"\n name=\"" + stackIpAddress + "\" />\n");
stackLogger.logDebug("<debug>");
stackLogger.logDebug("<![CDATA[ ");
}
}
}
} catch (IOException ex) {
}
}
/**
* Global check for whether to log or not. To minimize the time return false here.
*
* @return true -- if logging is globally enabled and false otherwise.
*
*/
public boolean needsLogging() {
return logFileName != null;
}
/**
* Set the log file name
*
* @param name is the name of the log file to set.
*/
public void setLogFileName(String name) {
logFileName = name;
}
/**
* return the name of the log file.
*/
public String getLogFileName() {
return logFileName;
}
/**
* Log a message into the log file.
*
* @param message message to log into the log file.
*/
private void logMessage(String message) {
// String tname = Thread.currentThread().getName();
checkLogFile();
String logInfo = message;
if (printWriter != null) {
printWriter.println(logInfo);
}
if (sipStack.isLoggingEnabled()) {
stackLogger.logInfo(logInfo);
}
}
private void logMessage(String message, String from, String to, boolean sender,
String callId, String firstLine, String status, String tid, long time,
long timestampVal) {
LogRecord log = this.sipStack.logRecordFactory.createLogRecord(message, from, to, time,
sender, firstLine, tid, callId, timestampVal);
if (log != null)
logMessage(log.toString());
}
/**
* Log a message into the log directory.
*
* @param message a SIPMessage to log
* @param from from header of the message to log into the log directory
* @param to to header of the message to log into the log directory
* @param sender is the server the sender
* @param time is the time to associate with the message.
*/
public void logMessage(SIPMessage message, String from, String to, boolean sender, long time) {
checkLogFile();
if (message.getFirstLine() == null)
return;
CallID cid = (CallID) message.getCallId();
String callId = null;
if (cid != null)
callId = cid.getCallId();
String firstLine = message.getFirstLine().trim();
String inputText = (logContent ? message.encode() : message.encodeMessage());
String tid = message.getTransactionId();
TimeStampHeader tsHdr = (TimeStampHeader) message.getHeader(TimeStampHeader.NAME);
long tsval = tsHdr == null ? 0 : tsHdr.getTime();
logMessage(inputText, from, to, sender, callId, firstLine, null, tid, time, tsval);
}
/**
* Log a message into the log directory.
*
* @param message a SIPMessage to log
* @param from from header of the message to log into the log directory
* @param to to header of the message to log into the log directory
* @param status the status to log.
* @param sender is the server the sender or receiver (true if sender).
* @param time is the reception time.
*/
public void logMessage(SIPMessage message, String from, String to, String status,
boolean sender, long time) {
checkLogFile();
CallID cid = (CallID) message.getCallId();
String callId = null;
if (cid != null)
callId = cid.getCallId();
String firstLine = message.getFirstLine().trim();
String encoded = (logContent ? message.encode() : message.encodeMessage());
String tid = message.getTransactionId();
TimeStampHeader tshdr = (TimeStampHeader) message.getHeader(TimeStampHeader.NAME);
long tsval = tshdr == null ? 0 : tshdr.getTime();
logMessage(encoded, from, to, sender, callId, firstLine, status, tid, time, tsval);
}
/**
* Log a message into the log directory. Time stamp associated with the message is the current
* time.
*
* @param message a SIPMessage to log
* @param from from header of the message to log into the log directory
* @param to to header of the message to log into the log directory
* @param status the status to log.
* @param sender is the server the sender or receiver (true if sender).
*/
public void logMessage(SIPMessage message, String from, String to, String status,
boolean sender) {
logMessage(message, from, to, status, sender, System.currentTimeMillis());
}
/**
* Log an exception stack trace.
*
* @param ex Exception to log into the log file
*/
public void logException(Exception ex) {
if (traceLevel >= TRACE_EXCEPTION) {
checkLogFile();
ex.printStackTrace();
if (printWriter != null)
ex.printStackTrace(printWriter);
}
}
/**
* Set the trace level for the stack.
*
* @param level -- the trace level to set. The following trace levels are supported:
* <ul>
* <li> 0 -- no tracing </li>
*
* <li> 16 -- trace messages only </li>
*
* <li> 32 Full tracing including debug messages. </li>
*
* </ul>
*/
public void setTraceLevel(int level) {
traceLevel = level;
}
/**
* Get the trace level for the stack.
*
* @return the trace level
*/
public int getTraceLevel() {
return traceLevel;
}
/**
* Set aux information. Auxiliary information may be associated with the log file. This is
* useful for remote logs.
*
* @param auxInfo -- auxiliary information.
*/
public void setAuxInfo(String auxInfo) {
this.auxInfo = auxInfo;
}
public void setSipStack(SipStack sipStack) {
if(sipStack instanceof SIPTransactionStack) {
this.sipStack = (SIPTransactionStack)sipStack;
this.stackLogger = this.sipStack.getStackLogger();
}
else
throw new IllegalArgumentException("sipStack must be a SIPTransactionStack");
}
public void setStackProperties(Properties stackProperties) {
setProperties(stackProperties);
}
public void setLevel(int jsipLoggingLevel) {
}
}