PropertyConfiguratorImpl.cpp
Go to the documentation of this file.
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 }


log4cpp
Author(s): Stephen Roderick
autogenerated on Mon Oct 6 2014 03:13:14