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


log4cpp
Author(s): Stephen Roderick, Bastiaan Bakker, Cedric Le Goater, Steve Ostlind, Marcel Harkema, Walter Stroebel, Glenn Scott and Tony Cheung
autogenerated on Sun Aug 14 2016 03:18:26