00001
00002
00003
00004
00005
00006
00007
00008 #include "PortabilityImpl.hh"
00009
00010 #ifdef LOG4CPP_HAVE_UNISTD_H
00011 #include <unistd.h>
00012 #endif
00013 #ifdef LOG4CPP_HAVE_IO_H
00014 # include <io.h>
00015 #endif
00016 #include <iostream>
00017
00018 #include <string>
00019 #include <fstream>
00020
00021 #include <log4cpp/Category.hh>
00022
00023
00024 #include <log4cpp/Appender.hh>
00025 #include <log4cpp/OstreamAppender.hh>
00026 #include <log4cpp/FileAppender.hh>
00027 #include <log4cpp/RollingFileAppender.hh>
00028 #include <log4cpp/AbortAppender.hh>
00029 #ifdef WIN32
00030 #include <log4cpp/Win32DebugAppender.hh>
00031 #include <log4cpp/NTEventLogAppender.hh>
00032 #endif
00033 #include <log4cpp/RemoteSyslogAppender.hh>
00034 #ifdef LOG4CPP_HAVE_LIBIDSA
00035 #include <log4cpp/IdsaAppender.hh>
00036 #endif // LOG4CPP_HAVE_LIBIDSA
00037 #ifdef LOG4CPP_HAVE_SYSLOG
00038 #include <log4cpp/SyslogAppender.hh>
00039 #endif
00040
00041
00042 #include <log4cpp/Layout.hh>
00043 #include <log4cpp/BasicLayout.hh>
00044 #include <log4cpp/SimpleLayout.hh>
00045 #include <log4cpp/PatternLayout.hh>
00046
00047 #include <log4cpp/Priority.hh>
00048 #include <log4cpp/NDC.hh>
00049
00050 #include <list>
00051 #include <vector>
00052 #include <iterator>
00053
00054 #include "PropertyConfiguratorImpl.hh"
00055 #include "StringUtil.hh"
00056
00057 namespace log4cpp {
00058
00059 PropertyConfiguratorImpl::PropertyConfiguratorImpl() {
00060 }
00061
00062 PropertyConfiguratorImpl::~PropertyConfiguratorImpl() {
00063 }
00064
00065 void PropertyConfiguratorImpl::doConfigure(const std::string& initFileName) throw (ConfigureFailure) {
00066 std::ifstream initFile(initFileName.c_str());
00067
00068 if (!initFile) {
00069 throw ConfigureFailure(std::string("File ") + initFileName + " does not exist");
00070 }
00071
00072 doConfigure(initFile);
00073 }
00074
00075
00076 void PropertyConfiguratorImpl::doConfigure(std::istream& in) throw (ConfigureFailure) {
00077
00078 _properties.load(in);
00079
00080 instantiateAllAppenders();
00081
00082 std::vector<std::string> catList;
00083 getCategories(catList);
00084
00085
00086 for(std::vector<std::string>::const_iterator iter = catList.begin();
00087 iter != catList.end(); ++iter) {
00088 configureCategory(*iter);
00089 }
00090 }
00091
00092 void PropertyConfiguratorImpl::instantiateAllAppenders() throw(ConfigureFailure) {
00093 std::string currentAppender;
00094
00095 std::string prefix("appender");
00096 Properties::const_iterator from = _properties.lower_bound(prefix + '.');
00097 Properties::const_iterator to = _properties.lower_bound(prefix + '/');
00098 for(Properties::const_iterator i = from; i != to; ++i) {
00099 const std::string& key = (*i).first;
00100 const std::string& value = (*i).second;
00101 std::list<std::string> propNameParts;
00102 std::back_insert_iterator<std::list<std::string> > pnpIt(propNameParts);
00103 StringUtil::split(pnpIt, key, '.');
00104 std::list<std::string>::const_iterator i2 = propNameParts.begin();
00105 std::list<std::string>::const_iterator iEnd = propNameParts.end();
00106 if (++i2 == iEnd) {
00107 throw ConfigureFailure(std::string("missing appender name"));
00108 }
00109
00110 const std::string appenderName = *i2++;
00111
00112
00113
00114
00115
00116 if (appenderName == currentAppender) {
00117
00118 } else {
00119 if (i2 == iEnd) {
00120
00121 currentAppender = appenderName;
00122 _allAppenders[currentAppender] =
00123 instantiateAppender(currentAppender);
00124 } else {
00125 throw ConfigureFailure(std::string("partial appender definition : ") + key);
00126 }
00127 }
00128 }
00129 }
00130
00131 void PropertyConfiguratorImpl::configureCategory(const std::string& categoryName) throw (ConfigureFailure) {
00132
00133 std::string tempCatName =
00134 (categoryName == "rootCategory") ? categoryName : "category." + categoryName;
00135
00136 Properties::iterator iter = _properties.find(tempCatName);
00137
00138 if (iter == _properties.end())
00139 throw ConfigureFailure(std::string("Unable to find category: ") + tempCatName);
00140
00141
00142 Category& category = (categoryName == "rootCategory") ?
00143 Category::getRoot() : Category::getInstance(categoryName);
00144
00145
00146 std::list<std::string> tokens;
00147 std::back_insert_iterator<std::list<std::string> > tokIt(tokens);
00148 StringUtil::split(tokIt, (*iter).second, ',');
00149 std::list<std::string>::const_iterator i = tokens.begin();
00150 std::list<std::string>::const_iterator iEnd = tokens.end();
00151
00152 Priority::Value priority = Priority::NOTSET;
00153 if (i != iEnd) {
00154 std::string priorityName = StringUtil::trim(*i++);
00155 try {
00156 if (priorityName != "") {
00157 priority = Priority::getPriorityValue(priorityName);
00158 }
00159 } catch(std::invalid_argument& e) {
00160 throw ConfigureFailure(std::string(e.what()) +
00161 " for category '" + categoryName + "'");
00162 }
00163 }
00164
00165 category.setPriority(priority);
00166
00167 bool additive = _properties.getBool("additivity." + categoryName, true);
00168 category.setAdditivity(additive);
00169
00170 category.removeAllAppenders();
00171 for(; i != iEnd; ++i) {
00172 std::string appenderName = StringUtil::trim(*i);
00173 AppenderMap::const_iterator appIt =
00174 _allAppenders.find(appenderName);
00175 if (appIt == _allAppenders.end()) {
00176
00177 throw ConfigureFailure(std::string("Appender '") +
00178 appenderName + "' not found for category '" + categoryName + "'");
00179 } else {
00180
00181
00182 category.addAppender(*((*appIt).second));
00183 }
00184 }
00185 }
00186
00187 Appender* PropertyConfiguratorImpl::instantiateAppender(const std::string& appenderName) {
00188 Appender* appender = NULL;
00189 std::string appenderPrefix = std::string("appender.") + appenderName;
00190
00191
00192 Properties::iterator key = _properties.find(appenderPrefix);
00193 if (key == _properties.end())
00194 throw ConfigureFailure(std::string("Appender '") + appenderName + "' not defined");
00195
00196 std::string::size_type length = (*key).second.find_last_of(".");
00197 std::string appenderType = (length == std::string::npos) ?
00198 (*key).second : (*key).second.substr(length+1);
00199
00200
00201 if (appenderType == "ConsoleAppender") {
00202 appender = new OstreamAppender(appenderName, &std::cout);
00203 }
00204 else if (appenderType == "FileAppender") {
00205 std::string fileName = _properties.getString(appenderPrefix + ".fileName", "foobar");
00206 bool append = _properties.getBool(appenderPrefix + ".append", true);
00207 appender = new FileAppender(appenderName, fileName, append);
00208 }
00209 else if (appenderType == "RollingFileAppender") {
00210 std::string fileName = _properties.getString(appenderPrefix + ".fileName", "foobar");
00211 size_t maxFileSize = _properties.getInt(appenderPrefix + ".maxFileSize", 10*1024*1024);
00212 int maxBackupIndex = _properties.getInt(appenderPrefix + ".maxBackupIndex", 1);
00213 bool append = _properties.getBool(appenderPrefix + ".append", true);
00214 appender = new RollingFileAppender(appenderName, fileName, maxFileSize, maxBackupIndex,
00215 append);
00216 }
00217 else if (appenderType == "SyslogAppender") {
00218 std::string syslogName = _properties.getString(appenderPrefix + ".syslogName", "syslog");
00219 std::string syslogHost = _properties.getString(appenderPrefix + ".syslogHost", "localhost");
00220 int facility = _properties.getInt(appenderPrefix + ".facility", -1) * 8;
00221 int portNumber = _properties.getInt(appenderPrefix + ".portNumber", -1);
00222 appender = new RemoteSyslogAppender(appenderName, syslogName,
00223 syslogHost, facility, portNumber);
00224 }
00225 #ifdef LOG4CPP_HAVE_SYSLOG
00226 else if (appenderType == "LocalSyslogAppender") {
00227 std::string syslogName = _properties.getString(appenderPrefix + ".syslogName", "syslog");
00228 int facility = _properties.getInt(appenderPrefix + ".facility", -1) * 8;
00229 appender = new SyslogAppender(appenderName, syslogName, facility);
00230 }
00231 #endif // LOG4CPP_HAVE_SYSLOG
00232 else if (appenderType == "AbortAppender") {
00233 appender = new AbortAppender(appenderName);
00234 }
00235 #ifdef LOG4CPP_HAVE_LIBIDSA
00236 else if (appenderType == "IdsaAppender") {
00237
00238 std::string idsaName = _properties.getString(appenderPrefix + ".idsaName", "foobar");
00239
00240 appender = new IdsaAppender(appenderName, idsaname);
00241 }
00242 #endif // LOG4CPP_HAVE_LIBIDSA
00243
00244 #ifdef WIN32
00245
00246 else if (appenderType == "Win32DebugAppender") {
00247 appender = new Win32DebugAppender(appenderName);
00248 }
00249
00250 else if (appenderType == "NTEventLogAppender") {
00251 std::string source = _properties.getString(appenderPrefix + ".source", "foobar");
00252 appender = new NTEventLogAppender(appenderName, source);
00253 }
00254 #endif // WIN32
00255 else {
00256 throw ConfigureFailure(std::string("Appender '") + appenderName +
00257 "' has unknown type '" + appenderType + "'");
00258 }
00259
00260 if (appender->requiresLayout()) {
00261 setLayout(appender, appenderName);
00262 }
00263
00264
00265 std::string thresholdName = _properties.getString(appenderPrefix + ".threshold", "");
00266 try {
00267 if (thresholdName != "") {
00268 appender->setThreshold(Priority::getPriorityValue(thresholdName));
00269 }
00270 } catch(std::invalid_argument& e) {
00271 throw ConfigureFailure(std::string(e.what()) +
00272 " for threshold of appender '" + appenderName + "'");
00273 }
00274
00275 return appender;
00276 }
00277
00278 void PropertyConfiguratorImpl::setLayout(Appender* appender, const std::string& appenderName) {
00279
00280 std::string tempString;
00281 Properties::iterator key =
00282 _properties.find(std::string("appender.") + appenderName + ".layout");
00283
00284 if (key == _properties.end())
00285 throw ConfigureFailure(std::string("Missing layout property for appender '") +
00286 appenderName + "'");
00287
00288 std::string::size_type length = (*key).second.find_last_of(".");
00289 std::string layoutType = (length == std::string::npos) ?
00290 (*key).second : (*key).second.substr(length+1);
00291
00292 Layout* layout;
00293
00294 if (layoutType == "BasicLayout") {
00295 layout = new BasicLayout();
00296 }
00297 else if (layoutType == "SimpleLayout") {
00298 layout = new SimpleLayout();
00299 }
00300 else if (layoutType == "PatternLayout") {
00301
00302 PatternLayout* patternLayout = new PatternLayout();
00303
00304 key = _properties.find(std::string("appender.") + appenderName + ".layout.ConversionPattern");
00305 if (key == _properties.end()) {
00306
00307 } else {
00308
00309 patternLayout->setConversionPattern((*key).second);
00310 }
00311
00312 layout = patternLayout;
00313 }
00314 else {
00315 throw ConfigureFailure(std::string("Unknown layout type '" + layoutType +
00316 "' for appender '") + appenderName + "'");
00317 }
00318
00319 appender->setLayout(layout);
00320 }
00321
00328 void PropertyConfiguratorImpl::getCategories(std::vector<std::string>& categories) const {
00329 categories.clear();
00330
00331
00332 categories.push_back(std::string("rootCategory"));
00333
00334
00335 std::string prefix("category");
00336 Properties::const_iterator from = _properties.lower_bound(prefix + '.');
00337 Properties::const_iterator to = _properties.lower_bound(prefix + (char)('.' + 1));
00338 for (Properties::const_iterator iter = from; iter != to; iter++) {
00339 categories.push_back((*iter).first.substr(prefix.size() + 1));
00340 }
00341 }
00342 }