$search
00001 /* 00002 * PropertyConfiguratorImpl.cpp 00003 * 00004 * Copyright 2002, Log4cpp Project. All rights reserved. 00005 * 00006 * See the COPYING file for the terms of usage and distribution. 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 // appenders 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 // layouts 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 // parse the file to get all of the configuration 00078 _properties.load(in); 00079 00080 instantiateAllAppenders(); 00081 // get categories 00082 std::vector<std::string> catList; 00083 getCategories(catList); 00084 00085 // configure each category 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 /* WARNING, approaching lame code section: 00113 skipping of the Appenders properties only to get them 00114 again in instantiateAppender. 00115 */ 00116 if (appenderName == currentAppender) { 00117 // simply skip properties for the current appender 00118 } else { 00119 if (i2 == iEnd) { 00120 // a new appender 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 // start by reading the "rootCategory" key 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 // need to get the root instance of the category 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 // appender not found; 00177 throw ConfigureFailure(std::string("Appender '") + 00178 appenderName + "' not found for category '" + categoryName + "'"); 00179 } else { 00180 /* pass by reference, i.e. don't transfer ownership 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 // determine the type by the appenderName 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 // and instantiate the appropriate object 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; // * 8 to get LOG_KERN, etc. compatible values. 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; // * 8 to get LOG_KERN, etc. compatible values. 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 // default idsa name ??? 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 // win32 debug appender 00246 else if (appenderType == "Win32DebugAppender") { 00247 appender = new Win32DebugAppender(appenderName); 00248 } 00249 // win32 NT event log appender 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 // set threshold 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 // determine the type by appenderName 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 // and instantiate the appropriate object 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 // need to read the properties to configure this one 00302 PatternLayout* patternLayout = new PatternLayout(); 00303 00304 key = _properties.find(std::string("appender.") + appenderName + ".layout.ConversionPattern"); 00305 if (key == _properties.end()) { 00306 // leave default pattern 00307 } else { 00308 // set pattern 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 // add the root category first 00332 categories.push_back(std::string("rootCategory")); 00333 00334 // then look for "category." 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 }