add log4cplus
This commit is contained in:
957
libs/log4cplus/src/patternlayout.cxx
Normal file
957
libs/log4cplus/src/patternlayout.cxx
Normal file
@ -0,0 +1,957 @@
|
||||
// Module: Log4CPLUS
|
||||
// File: patternlayout.cxx
|
||||
// Created: 6/2001
|
||||
// Author: Tad E. Smith
|
||||
//
|
||||
//
|
||||
// Copyright 2001-2010 Tad E. Smith
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include <log4cplus/layout.h>
|
||||
#include <log4cplus/helpers/loglog.h>
|
||||
#include <log4cplus/helpers/timehelper.h>
|
||||
#include <log4cplus/helpers/stringhelper.h>
|
||||
#include <log4cplus/helpers/socket.h>
|
||||
#include <log4cplus/spi/loggingevent.h>
|
||||
|
||||
#ifdef LOG4CPLUS_HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <exception>
|
||||
|
||||
#ifdef LOG4CPLUS_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef LOG4CPLUS_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static
|
||||
#if defined (_WIN32)
|
||||
DWORD
|
||||
get_process_id ()
|
||||
{
|
||||
return GetCurrentProcessId ();
|
||||
}
|
||||
|
||||
#elif defined (LOG4CPLUS_HAVE_GETPID)
|
||||
pid_t
|
||||
get_process_id ()
|
||||
{
|
||||
return getpid ();
|
||||
}
|
||||
|
||||
#else
|
||||
int
|
||||
get_process_id ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static
|
||||
log4cplus::tstring
|
||||
get_basename (const log4cplus::tstring& filename)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
log4cplus::tchar const dir_sep(LOG4CPLUS_TEXT('\\'));
|
||||
#else
|
||||
log4cplus::tchar const dir_sep(LOG4CPLUS_TEXT('/'));
|
||||
#endif
|
||||
|
||||
log4cplus::tstring::size_type pos = filename.rfind(dir_sep);
|
||||
if (pos != log4cplus::tstring::npos)
|
||||
return filename.substr(pos+1);
|
||||
else
|
||||
return filename;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace log4cplus;
|
||||
using namespace log4cplus::helpers;
|
||||
using namespace log4cplus::spi;
|
||||
|
||||
|
||||
#define ESCAPE_CHAR LOG4CPLUS_TEXT('%')
|
||||
|
||||
|
||||
namespace log4cplus {
|
||||
namespace pattern {
|
||||
|
||||
/**
|
||||
* This is used by PatternConverter class to inform them how to format
|
||||
* their output.
|
||||
*/
|
||||
struct FormattingInfo {
|
||||
int minLen;
|
||||
size_t maxLen;
|
||||
bool leftAlign;
|
||||
FormattingInfo() { reset(); }
|
||||
|
||||
void reset();
|
||||
void dump(log4cplus::helpers::LogLog&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This is the base class of all "Converter" classes that format a
|
||||
* field of InternalLoggingEvent objects. In fact, the PatternLayout
|
||||
* class simply uses an array of PatternConverter objects to format
|
||||
* and append a logging event.
|
||||
*/
|
||||
class PatternConverter : protected log4cplus::helpers::LogLogUser {
|
||||
public:
|
||||
PatternConverter(const FormattingInfo& info);
|
||||
virtual ~PatternConverter() {}
|
||||
void formatAndAppend(log4cplus::tostream& output,
|
||||
const InternalLoggingEvent& event);
|
||||
|
||||
protected:
|
||||
virtual log4cplus::tstring convert(const InternalLoggingEvent& event) = 0;
|
||||
|
||||
private:
|
||||
int minLen;
|
||||
size_t maxLen;
|
||||
bool leftAlign;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This PatternConverter returns a constant string.
|
||||
*/
|
||||
class LiteralPatternConverter : public PatternConverter {
|
||||
public:
|
||||
LiteralPatternConverter(const log4cplus::tstring& str);
|
||||
virtual log4cplus::tstring convert(const InternalLoggingEvent&) {
|
||||
return str;
|
||||
}
|
||||
|
||||
private:
|
||||
log4cplus::tstring str;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This PatternConverter is used to format most of the "simple" fields
|
||||
* found in the InternalLoggingEvent object.
|
||||
*/
|
||||
class BasicPatternConverter : public PatternConverter {
|
||||
public:
|
||||
enum Type { THREAD_CONVERTER,
|
||||
PROCESS_CONVERTER,
|
||||
LOGLEVEL_CONVERTER,
|
||||
NDC_CONVERTER,
|
||||
MESSAGE_CONVERTER,
|
||||
NEWLINE_CONVERTER,
|
||||
BASENAME_CONVERTER,
|
||||
FILE_CONVERTER,
|
||||
LINE_CONVERTER,
|
||||
FULL_LOCATION_CONVERTER };
|
||||
BasicPatternConverter(const FormattingInfo& info, Type type);
|
||||
virtual log4cplus::tstring convert(const InternalLoggingEvent& event);
|
||||
|
||||
private:
|
||||
// Disable copy
|
||||
BasicPatternConverter(const BasicPatternConverter&);
|
||||
BasicPatternConverter& operator=(BasicPatternConverter&);
|
||||
|
||||
LogLevelManager& llmCache;
|
||||
Type type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This PatternConverter is used to format the Logger field found in
|
||||
* the InternalLoggingEvent object.
|
||||
*/
|
||||
class LoggerPatternConverter : public PatternConverter {
|
||||
public:
|
||||
LoggerPatternConverter(const FormattingInfo& info, int precision);
|
||||
virtual log4cplus::tstring convert(const InternalLoggingEvent& event);
|
||||
|
||||
private:
|
||||
int precision;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This PatternConverter is used to format the timestamp field found in
|
||||
* the InternalLoggingEvent object. It will be formatted according to
|
||||
* the specified "pattern".
|
||||
*/
|
||||
class DatePatternConverter : public PatternConverter {
|
||||
public:
|
||||
DatePatternConverter(const FormattingInfo& info,
|
||||
const log4cplus::tstring& pattern,
|
||||
bool use_gmtime);
|
||||
virtual log4cplus::tstring convert(const InternalLoggingEvent& event);
|
||||
|
||||
private:
|
||||
bool use_gmtime;
|
||||
log4cplus::tstring format;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This PatternConverter is used to format the hostname field.
|
||||
*/
|
||||
class HostnamePatternConverter : public PatternConverter {
|
||||
public:
|
||||
HostnamePatternConverter(const FormattingInfo& info, bool fqdn);
|
||||
virtual log4cplus::tstring convert(const InternalLoggingEvent& event);
|
||||
|
||||
private:
|
||||
log4cplus::tstring hostname_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This PatternConverter is used to format the NDC field found in
|
||||
* the InternalLoggingEvent object, optionally limited to
|
||||
* \c precision levels (using space to separate levels).
|
||||
*/
|
||||
class NDCPatternConverter : public PatternConverter {
|
||||
public:
|
||||
NDCPatternConverter(const FormattingInfo& info, int precision);
|
||||
virtual log4cplus::tstring convert(const InternalLoggingEvent& event);
|
||||
|
||||
private:
|
||||
int precision;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This class parses a "pattern" string into an array of
|
||||
* PatternConverter objects.
|
||||
* <p>
|
||||
* @see PatternLayout for the formatting of the "pattern" string.
|
||||
*/
|
||||
class PatternParser : protected log4cplus::helpers::LogLogUser {
|
||||
public:
|
||||
PatternParser(const log4cplus::tstring& pattern, unsigned ndcMaxDepth);
|
||||
std::vector<PatternConverter*> parse();
|
||||
|
||||
private:
|
||||
// Types
|
||||
enum ParserState { LITERAL_STATE,
|
||||
CONVERTER_STATE,
|
||||
DOT_STATE,
|
||||
MIN_STATE,
|
||||
MAX_STATE };
|
||||
|
||||
// Methods
|
||||
log4cplus::tstring extractOption();
|
||||
int extractPrecisionOption();
|
||||
void finalizeConverter(log4cplus::tchar c);
|
||||
|
||||
// Data
|
||||
log4cplus::tstring pattern;
|
||||
FormattingInfo formattingInfo;
|
||||
std::vector<PatternConverter*> list;
|
||||
ParserState state;
|
||||
tstring::size_type pos;
|
||||
log4cplus::tstring currentLiteral;
|
||||
unsigned ndcMaxDepth;
|
||||
};
|
||||
}
|
||||
}
|
||||
using namespace log4cplus::pattern;
|
||||
typedef std::vector<log4cplus::pattern::PatternConverter*> PatternConverterList;
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// PatternConverter methods:
|
||||
////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
log4cplus::pattern::FormattingInfo::reset() {
|
||||
minLen = -1;
|
||||
maxLen = 0x7FFFFFFF;
|
||||
leftAlign = false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
log4cplus::pattern::FormattingInfo::dump(log4cplus::helpers::LogLog& loglog) {
|
||||
log4cplus::tostringstream buf;
|
||||
buf << LOG4CPLUS_TEXT("min=") << minLen
|
||||
<< LOG4CPLUS_TEXT(", max=") << maxLen
|
||||
<< LOG4CPLUS_TEXT(", leftAlign=")
|
||||
<< (leftAlign ? LOG4CPLUS_TEXT("true") : LOG4CPLUS_TEXT("false"));
|
||||
loglog.debug(buf.str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// PatternConverter methods:
|
||||
////////////////////////////////////////////////
|
||||
|
||||
log4cplus::pattern::PatternConverter::PatternConverter(const FormattingInfo& i)
|
||||
{
|
||||
minLen = i.minLen;
|
||||
maxLen = i.maxLen;
|
||||
leftAlign = i.leftAlign;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
log4cplus::pattern::PatternConverter::formatAndAppend
|
||||
(log4cplus::tostream& output, const InternalLoggingEvent& event)
|
||||
{
|
||||
log4cplus::tstring s = convert(event);
|
||||
size_t len = s.length();
|
||||
|
||||
if(len > maxLen) {
|
||||
output << s.substr(len - maxLen);
|
||||
}
|
||||
else if(static_cast<int>(len) < minLen) {
|
||||
if(leftAlign) {
|
||||
output << s;
|
||||
output << log4cplus::tstring(minLen - len, LOG4CPLUS_TEXT(' '));
|
||||
}
|
||||
else {
|
||||
output << log4cplus::tstring(minLen - len, LOG4CPLUS_TEXT(' '));
|
||||
output << s;
|
||||
}
|
||||
}
|
||||
else {
|
||||
output << s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// LiteralPatternConverter methods:
|
||||
////////////////////////////////////////////////
|
||||
|
||||
log4cplus::pattern::LiteralPatternConverter::LiteralPatternConverter
|
||||
(const log4cplus::tstring& str_)
|
||||
: PatternConverter(FormattingInfo()),
|
||||
str(str_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// BasicPatternConverter methods:
|
||||
////////////////////////////////////////////////
|
||||
|
||||
log4cplus::pattern::BasicPatternConverter::BasicPatternConverter
|
||||
(const FormattingInfo& info, Type type_)
|
||||
: PatternConverter(info),
|
||||
llmCache(getLogLevelManager()),
|
||||
type(type_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
log4cplus::tstring
|
||||
log4cplus::pattern::BasicPatternConverter::convert
|
||||
(const InternalLoggingEvent& event)
|
||||
{
|
||||
switch(type) {
|
||||
case LOGLEVEL_CONVERTER: return llmCache.toString(event.getLogLevel());
|
||||
case NDC_CONVERTER: return event.getNDC();
|
||||
case MESSAGE_CONVERTER: return event.getMessage();
|
||||
case NEWLINE_CONVERTER: return LOG4CPLUS_TEXT("\n");
|
||||
case BASENAME_CONVERTER: return get_basename(event.getFile());
|
||||
case FILE_CONVERTER: return event.getFile();
|
||||
case THREAD_CONVERTER: return event.getThread();
|
||||
case PROCESS_CONVERTER: return convertIntegerToString(get_process_id ());
|
||||
|
||||
case LINE_CONVERTER:
|
||||
{
|
||||
int line = event.getLine();
|
||||
if(line != -1) {
|
||||
return convertIntegerToString(line);
|
||||
}
|
||||
else {
|
||||
return log4cplus::tstring();
|
||||
}
|
||||
}
|
||||
|
||||
case FULL_LOCATION_CONVERTER:
|
||||
{
|
||||
tstring const & filename = event.getFile();
|
||||
if(! filename.empty ()) {
|
||||
return filename
|
||||
+ LOG4CPLUS_TEXT(":")
|
||||
+ convertIntegerToString(event.getLine());
|
||||
}
|
||||
else {
|
||||
return LOG4CPLUS_TEXT(":");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return LOG4CPLUS_TEXT("INTERNAL LOG4CPLUS ERROR");
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// LoggerPatternConverter methods:
|
||||
////////////////////////////////////////////////
|
||||
|
||||
log4cplus::pattern::LoggerPatternConverter::LoggerPatternConverter
|
||||
(const FormattingInfo& info, int precision_)
|
||||
: PatternConverter(info),
|
||||
precision(precision_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
log4cplus::tstring
|
||||
log4cplus::pattern::LoggerPatternConverter::convert
|
||||
(const InternalLoggingEvent& event)
|
||||
{
|
||||
const log4cplus::tstring& name = event.getLoggerName();
|
||||
if (precision <= 0) {
|
||||
return name;
|
||||
}
|
||||
else {
|
||||
size_t len = name.length();
|
||||
|
||||
// We substract 1 from 'len' when assigning to 'end' to avoid out of
|
||||
// bounds exception in return r.substring(end+1, len). This can happen
|
||||
// if precision is 1 and the logger name ends with a dot.
|
||||
tstring::size_type end = len - 1;
|
||||
for(int i=precision; i>0; --i) {
|
||||
end = name.rfind(LOG4CPLUS_TEXT('.'), end - 1);
|
||||
if(end == tstring::npos) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
return name.substr(end + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// DatePatternConverter methods:
|
||||
////////////////////////////////////////////////
|
||||
|
||||
|
||||
log4cplus::pattern::DatePatternConverter::DatePatternConverter
|
||||
(const FormattingInfo& info,
|
||||
const log4cplus::tstring& pattern,
|
||||
bool use_gmtime_)
|
||||
: PatternConverter(info),
|
||||
use_gmtime(use_gmtime_),
|
||||
format(pattern)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
log4cplus::tstring
|
||||
log4cplus::pattern::DatePatternConverter::convert
|
||||
(const InternalLoggingEvent& event)
|
||||
{
|
||||
return event.getTimestamp().getFormattedTime(format, use_gmtime);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// HostnamePatternConverter methods:
|
||||
////////////////////////////////////////////////
|
||||
|
||||
log4cplus::pattern::HostnamePatternConverter::HostnamePatternConverter (
|
||||
const FormattingInfo& info, bool fqdn)
|
||||
: PatternConverter(info)
|
||||
, hostname_ (helpers::getHostname (fqdn))
|
||||
{ }
|
||||
|
||||
|
||||
log4cplus::tstring
|
||||
log4cplus::pattern::HostnamePatternConverter::convert (
|
||||
const InternalLoggingEvent &)
|
||||
{
|
||||
return hostname_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// NDCPatternConverter methods:
|
||||
////////////////////////////////////////////////
|
||||
|
||||
log4cplus::pattern::NDCPatternConverter::NDCPatternConverter (
|
||||
const FormattingInfo& info, int precision_)
|
||||
: PatternConverter(info)
|
||||
, precision(precision_)
|
||||
{ }
|
||||
|
||||
|
||||
log4cplus::tstring
|
||||
log4cplus::pattern::NDCPatternConverter::convert (
|
||||
const InternalLoggingEvent& event)
|
||||
{
|
||||
const log4cplus::tstring& text = event.getNDC();
|
||||
if (precision <= 0)
|
||||
return text;
|
||||
else
|
||||
{
|
||||
tstring::size_type p = text.find(LOG4CPLUS_TEXT(' '));
|
||||
for (int i = 1; i < precision && p != tstring::npos; ++i)
|
||||
p = text.find(LOG4CPLUS_TEXT(' '), p + 1);
|
||||
|
||||
return text.substr(0, p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// PatternParser methods:
|
||||
////////////////////////////////////////////////
|
||||
|
||||
log4cplus::pattern::PatternParser::PatternParser(
|
||||
const log4cplus::tstring& pattern_, unsigned ndcMaxDepth_)
|
||||
: pattern(pattern_)
|
||||
, state(LITERAL_STATE)
|
||||
, pos(0)
|
||||
, ndcMaxDepth (ndcMaxDepth_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
log4cplus::tstring
|
||||
log4cplus::pattern::PatternParser::extractOption()
|
||||
{
|
||||
if ( (pos < pattern.length())
|
||||
&& (pattern[pos] == LOG4CPLUS_TEXT('{')))
|
||||
{
|
||||
tstring::size_type end = pattern.find_first_of(LOG4CPLUS_TEXT('}'), pos);
|
||||
if (end != tstring::npos) {
|
||||
log4cplus::tstring r = pattern.substr(pos + 1, end - pos - 1);
|
||||
pos = end + 1;
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
log4cplus::tostringstream buf;
|
||||
buf << LOG4CPLUS_TEXT("No matching '}' found in conversion pattern string \"")
|
||||
<< pattern
|
||||
<< LOG4CPLUS_TEXT("\"");
|
||||
getLogLog().error(buf.str());
|
||||
pos = pattern.length();
|
||||
}
|
||||
}
|
||||
|
||||
return LOG4CPLUS_TEXT("");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
log4cplus::pattern::PatternParser::extractPrecisionOption()
|
||||
{
|
||||
log4cplus::tstring opt = extractOption();
|
||||
int r = 0;
|
||||
if(! opt.empty ()) {
|
||||
r = std::atoi(LOG4CPLUS_TSTRING_TO_STRING(opt).c_str());
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PatternConverterList
|
||||
log4cplus::pattern::PatternParser::parse()
|
||||
{
|
||||
tchar c;
|
||||
pos = 0;
|
||||
while(pos < pattern.length()) {
|
||||
c = pattern[pos++];
|
||||
switch (state) {
|
||||
case LITERAL_STATE :
|
||||
// In literal state, the last char is always a literal.
|
||||
if(pos == pattern.length()) {
|
||||
currentLiteral += c;
|
||||
continue;
|
||||
}
|
||||
if(c == ESCAPE_CHAR) {
|
||||
// peek at the next char.
|
||||
switch (pattern[pos]) {
|
||||
case ESCAPE_CHAR:
|
||||
currentLiteral += c;
|
||||
pos++; // move pointer
|
||||
break;
|
||||
default:
|
||||
if(! currentLiteral.empty ()) {
|
||||
list.push_back
|
||||
(new LiteralPatternConverter(currentLiteral));
|
||||
//getLogLog().debug("Parsed LITERAL converter: \""
|
||||
// +currentLiteral+"\".");
|
||||
}
|
||||
currentLiteral.resize(0);
|
||||
currentLiteral += c; // append %
|
||||
state = CONVERTER_STATE;
|
||||
formattingInfo.reset();
|
||||
}
|
||||
}
|
||||
else {
|
||||
currentLiteral += c;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONVERTER_STATE:
|
||||
currentLiteral += c;
|
||||
switch (c) {
|
||||
case LOG4CPLUS_TEXT('-'):
|
||||
formattingInfo.leftAlign = true;
|
||||
break;
|
||||
case LOG4CPLUS_TEXT('.'):
|
||||
state = DOT_STATE;
|
||||
break;
|
||||
default:
|
||||
if(c >= LOG4CPLUS_TEXT('0') && c <= LOG4CPLUS_TEXT('9')) {
|
||||
formattingInfo.minLen = c - LOG4CPLUS_TEXT('0');
|
||||
state = MIN_STATE;
|
||||
}
|
||||
else {
|
||||
finalizeConverter(c);
|
||||
}
|
||||
} // switch
|
||||
break;
|
||||
|
||||
case MIN_STATE:
|
||||
currentLiteral += c;
|
||||
if (c >= LOG4CPLUS_TEXT('0') && c <= LOG4CPLUS_TEXT('9')) {
|
||||
formattingInfo.minLen = formattingInfo.minLen * 10 + (c - LOG4CPLUS_TEXT('0'));
|
||||
}
|
||||
else if(c == LOG4CPLUS_TEXT('.')) {
|
||||
state = DOT_STATE;
|
||||
}
|
||||
else {
|
||||
finalizeConverter(c);
|
||||
}
|
||||
break;
|
||||
|
||||
case DOT_STATE:
|
||||
currentLiteral += c;
|
||||
if(c >= LOG4CPLUS_TEXT('0') && c <= LOG4CPLUS_TEXT('9')) {
|
||||
formattingInfo.maxLen = c - LOG4CPLUS_TEXT('0');
|
||||
state = MAX_STATE;
|
||||
}
|
||||
else {
|
||||
log4cplus::tostringstream buf;
|
||||
buf << LOG4CPLUS_TEXT("Error occured in position ")
|
||||
<< pos
|
||||
<< LOG4CPLUS_TEXT(".\n Was expecting digit, instead got char \"")
|
||||
<< c
|
||||
<< LOG4CPLUS_TEXT("\".");
|
||||
getLogLog().error(buf.str());
|
||||
state = LITERAL_STATE;
|
||||
}
|
||||
break;
|
||||
|
||||
case MAX_STATE:
|
||||
currentLiteral += c;
|
||||
if (c >= LOG4CPLUS_TEXT('0') && c <= LOG4CPLUS_TEXT('9'))
|
||||
formattingInfo.maxLen = formattingInfo.maxLen * 10 + (c - LOG4CPLUS_TEXT('0'));
|
||||
else {
|
||||
finalizeConverter(c);
|
||||
state = LITERAL_STATE;
|
||||
}
|
||||
break;
|
||||
} // end switch
|
||||
} // end while
|
||||
|
||||
if(! currentLiteral.empty ()) {
|
||||
list.push_back(new LiteralPatternConverter(currentLiteral));
|
||||
//getLogLog().debug("Parsed LITERAL converter: \""+currentLiteral+"\".");
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
log4cplus::pattern::PatternParser::finalizeConverter(log4cplus::tchar c)
|
||||
{
|
||||
PatternConverter* pc = 0;
|
||||
switch (c) {
|
||||
case LOG4CPLUS_TEXT('b'):
|
||||
pc = new BasicPatternConverter
|
||||
(formattingInfo,
|
||||
BasicPatternConverter::BASENAME_CONVERTER);
|
||||
//getLogLog().debug("BASENAME converter.");
|
||||
//formattingInfo.dump(getLogLog());
|
||||
break;
|
||||
|
||||
case LOG4CPLUS_TEXT('c'):
|
||||
pc = new LoggerPatternConverter(formattingInfo,
|
||||
extractPrecisionOption());
|
||||
getLogLog().debug( LOG4CPLUS_TEXT("LOGGER converter.") );
|
||||
formattingInfo.dump(getLogLog());
|
||||
break;
|
||||
|
||||
case LOG4CPLUS_TEXT('d'):
|
||||
case LOG4CPLUS_TEXT('D'):
|
||||
{
|
||||
log4cplus::tstring dOpt = extractOption();
|
||||
if(dOpt.empty ()) {
|
||||
dOpt = LOG4CPLUS_TEXT("%Y-%m-%d %H:%M:%S");
|
||||
}
|
||||
bool use_gmtime = c == LOG4CPLUS_TEXT('d');
|
||||
pc = new DatePatternConverter(formattingInfo, dOpt, use_gmtime);
|
||||
//if(use_gmtime) {
|
||||
// getLogLog().debug("GMT DATE converter.");
|
||||
//}
|
||||
//else {
|
||||
// getLogLog().debug("LOCAL DATE converter.");
|
||||
//}
|
||||
//formattingInfo.dump(getLogLog());
|
||||
}
|
||||
break;
|
||||
|
||||
case LOG4CPLUS_TEXT('F'):
|
||||
pc = new BasicPatternConverter
|
||||
(formattingInfo,
|
||||
BasicPatternConverter::FILE_CONVERTER);
|
||||
//getLogLog().debug("FILE NAME converter.");
|
||||
//formattingInfo.dump(getLogLog());
|
||||
break;
|
||||
|
||||
case LOG4CPLUS_TEXT('h'):
|
||||
case LOG4CPLUS_TEXT('H'):
|
||||
{
|
||||
bool fqdn = (c == LOG4CPLUS_TEXT('H'));
|
||||
pc = new HostnamePatternConverter(formattingInfo, fqdn);
|
||||
// getLogLog().debug( LOG4CPLUS_TEXT("HOSTNAME converter.") );
|
||||
// formattingInfo.dump(getLogLog());
|
||||
}
|
||||
break;
|
||||
|
||||
case LOG4CPLUS_TEXT('i'):
|
||||
pc = new BasicPatternConverter
|
||||
(formattingInfo,
|
||||
BasicPatternConverter::PROCESS_CONVERTER);
|
||||
//getLogLog().debug("PROCESS_CONVERTER converter.");
|
||||
//formattingInfo.dump(getLogLog());
|
||||
break;
|
||||
|
||||
case LOG4CPLUS_TEXT('l'):
|
||||
pc = new BasicPatternConverter
|
||||
(formattingInfo,
|
||||
BasicPatternConverter::FULL_LOCATION_CONVERTER);
|
||||
//getLogLog().debug("FULL LOCATION converter.");
|
||||
//formattingInfo.dump(getLogLog());
|
||||
break;
|
||||
|
||||
case LOG4CPLUS_TEXT('L'):
|
||||
pc = new BasicPatternConverter
|
||||
(formattingInfo,
|
||||
BasicPatternConverter::LINE_CONVERTER);
|
||||
//getLogLog().debug("LINE NUMBER converter.");
|
||||
//formattingInfo.dump(getLogLog());
|
||||
break;
|
||||
|
||||
case LOG4CPLUS_TEXT('m'):
|
||||
pc = new BasicPatternConverter
|
||||
(formattingInfo,
|
||||
BasicPatternConverter::MESSAGE_CONVERTER);
|
||||
//getLogLog().debug("MESSAGE converter.");
|
||||
//formattingInfo.dump(getLogLog());
|
||||
break;
|
||||
|
||||
// 'M' is METHOD converter in log4j.
|
||||
// Not implemented.
|
||||
case LOG4CPLUS_TEXT('M'):
|
||||
goto not_implemented;
|
||||
|
||||
case LOG4CPLUS_TEXT('n'):
|
||||
pc = new BasicPatternConverter
|
||||
(formattingInfo,
|
||||
BasicPatternConverter::NEWLINE_CONVERTER);
|
||||
//getLogLog().debug("MESSAGE converter.");
|
||||
//formattingInfo.dump(getLogLog());
|
||||
break;
|
||||
|
||||
case LOG4CPLUS_TEXT('p'):
|
||||
pc = new BasicPatternConverter
|
||||
(formattingInfo,
|
||||
BasicPatternConverter::LOGLEVEL_CONVERTER);
|
||||
//getLogLog().debug("LOGLEVEL converter.");
|
||||
//formattingInfo.dump(getLogLog());
|
||||
break;
|
||||
|
||||
// 'r' is RELATIVE time converter in log4j.
|
||||
// Not implemented.
|
||||
case LOG4CPLUS_TEXT('r'):
|
||||
goto not_implemented;
|
||||
|
||||
case LOG4CPLUS_TEXT('t'):
|
||||
pc = new BasicPatternConverter
|
||||
(formattingInfo,
|
||||
BasicPatternConverter::THREAD_CONVERTER);
|
||||
//getLogLog().debug("THREAD converter.");
|
||||
//formattingInfo.dump(getLogLog());
|
||||
break;
|
||||
|
||||
case LOG4CPLUS_TEXT('x'):
|
||||
pc = new NDCPatternConverter (formattingInfo, ndcMaxDepth);
|
||||
//getLogLog().debug("NDC converter.");
|
||||
break;
|
||||
|
||||
// 'X' is MDC in log4j.
|
||||
// Not implemented.
|
||||
case LOG4CPLUS_TEXT('X'):
|
||||
goto not_implemented;
|
||||
|
||||
not_implemented:;
|
||||
default:
|
||||
log4cplus::tostringstream buf;
|
||||
buf << LOG4CPLUS_TEXT("Unexpected char [")
|
||||
<< c
|
||||
<< LOG4CPLUS_TEXT("] at position ")
|
||||
<< pos
|
||||
<< LOG4CPLUS_TEXT(" in conversion patterrn.");
|
||||
getLogLog().error(buf.str());
|
||||
pc = new LiteralPatternConverter(currentLiteral);
|
||||
}
|
||||
|
||||
currentLiteral.resize(0);
|
||||
list.push_back(pc);
|
||||
state = LITERAL_STATE;
|
||||
formattingInfo.reset();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// PatternLayout methods:
|
||||
////////////////////////////////////////////////
|
||||
|
||||
PatternLayout::PatternLayout(const log4cplus::tstring& pattern_)
|
||||
{
|
||||
init(pattern_, 0);
|
||||
}
|
||||
|
||||
|
||||
PatternLayout::PatternLayout(const log4cplus::helpers::Properties& properties)
|
||||
{
|
||||
unsigned ndcMaxDepth
|
||||
= std::atoi (LOG4CPLUS_TSTRING_TO_STRING (
|
||||
properties.getProperty (
|
||||
LOG4CPLUS_TEXT ("NDCMaxDepth"),
|
||||
LOG4CPLUS_TEXT ("0"))).c_str ());
|
||||
|
||||
bool hasPattern = properties.exists( LOG4CPLUS_TEXT("Pattern") );
|
||||
bool hasConversionPattern = properties.exists( LOG4CPLUS_TEXT("ConversionPattern") );
|
||||
|
||||
if(hasPattern) {
|
||||
getLogLog().warn( LOG4CPLUS_TEXT("PatternLayout- the \"Pattern\" property has been deprecated. Use \"ConversionPattern\" instead."));
|
||||
}
|
||||
|
||||
if(hasConversionPattern) {
|
||||
init(properties.getProperty( LOG4CPLUS_TEXT("ConversionPattern") ),
|
||||
ndcMaxDepth);
|
||||
}
|
||||
else if(hasPattern) {
|
||||
init(properties.getProperty( LOG4CPLUS_TEXT("Pattern") ), ndcMaxDepth);
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error("ConversionPattern not specified in properties");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PatternLayout::init(const log4cplus::tstring& pattern_, unsigned ndcMaxDepth)
|
||||
{
|
||||
this->pattern = pattern_;
|
||||
this->parsedPattern = PatternParser(pattern, ndcMaxDepth).parse();
|
||||
|
||||
// Let's validate that our parser didn't give us any NULLs. If it did,
|
||||
// we will convert them to a valid PatternConverter that does nothing so
|
||||
// at least we don't core.
|
||||
for(PatternConverterList::iterator it=parsedPattern.begin();
|
||||
it!=parsedPattern.end();
|
||||
++it)
|
||||
{
|
||||
if( (*it) == 0 ) {
|
||||
getLogLog().error(LOG4CPLUS_TEXT("Parsed Pattern created a NULL PatternConverter"));
|
||||
(*it) = new LiteralPatternConverter( LOG4CPLUS_TEXT("") );
|
||||
}
|
||||
}
|
||||
if(parsedPattern.empty ()) {
|
||||
getLogLog().warn(LOG4CPLUS_TEXT("PatternLayout pattern is empty. Using default..."));
|
||||
parsedPattern.push_back
|
||||
(new BasicPatternConverter(FormattingInfo(),
|
||||
BasicPatternConverter::MESSAGE_CONVERTER));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PatternLayout::~PatternLayout()
|
||||
{
|
||||
for(PatternConverterList::iterator it=parsedPattern.begin();
|
||||
it!=parsedPattern.end();
|
||||
++it)
|
||||
{
|
||||
delete (*it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
PatternLayout::formatAndAppend(log4cplus::tostream& output,
|
||||
const InternalLoggingEvent& event)
|
||||
{
|
||||
for(PatternConverterList::iterator it=parsedPattern.begin();
|
||||
it!=parsedPattern.end();
|
||||
++it)
|
||||
{
|
||||
(*it)->formatAndAppend(output, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user