PropertyConfiguratorImpl.cpp
Go to the documentation of this file.
1 /*
2  * PropertyConfiguratorImpl.cpp
3  *
4  * Copyright 2002, Log4cpp Project. All rights reserved.
5  *
6  * See the COPYING file for the terms of usage and distribution.
7  */
8 #include "PortabilityImpl.hh"
9 
10 #ifdef LOG4CPP_HAVE_UNISTD_H
11 #include <unistd.h>
12 #endif
13 #ifdef LOG4CPP_HAVE_IO_H
14 # include <io.h>
15 #endif
16 #include <iostream>
17 
18 #include <string>
19 #include <fstream>
20 
21 #include <log4cpp/Category.hh>
22 
23 // appenders
24 #include <log4cpp/Appender.hh>
26 #include <log4cpp/FileAppender.hh>
30 #include <log4cpp/AbortAppender.hh>
31 #ifdef WIN32
34 #endif
35 #ifndef LOG4CPP_DISABLE_REMOTE_SYSLOG
37 #endif // LOG4CPP_DISABLE_REMOTE_SYSLOG
38 #ifdef LOG4CPP_HAVE_LIBIDSA
39 #include <log4cpp/IdsaAppender.hh>
40 #endif // LOG4CPP_HAVE_LIBIDSA
41 #ifdef LOG4CPP_HAVE_SYSLOG
43 #endif
44 
45 // layouts
46 #include <log4cpp/Layout.hh>
47 #include <log4cpp/BasicLayout.hh>
48 #include <log4cpp/SimpleLayout.hh>
49 #include <log4cpp/PatternLayout.hh>
50 
51 #include <log4cpp/Priority.hh>
52 #include <log4cpp/NDC.hh>
53 
54 #include <list>
55 #include <vector>
56 #include <iterator>
57 
59 #include "StringUtil.hh"
60 
61 namespace log4cpp {
62 
64  }
65 
67  }
68 
69  void PropertyConfiguratorImpl::doConfigure(const std::string& initFileName) throw (ConfigureFailure) {
70  std::ifstream initFile(initFileName.c_str());
71 
72  if (!initFile) {
73  throw ConfigureFailure(std::string("File ") + initFileName + " does not exist");
74  }
75 
76  doConfigure(initFile);
77  }
78 
79 
81  // parse the file to get all of the configuration
82  _properties.load(in);
83 
85  // get categories
86  std::vector<std::string> catList;
87  getCategories(catList);
88 
89  // configure each category
90  for(std::vector<std::string>::const_iterator iter = catList.begin();
91  iter != catList.end(); ++iter) {
92  configureCategory(*iter);
93  }
94  }
95 
97  std::string currentAppender;
98 
99  std::string prefix("appender");
100  Properties::const_iterator from = _properties.lower_bound(prefix + '.');
101  Properties::const_iterator to = _properties.lower_bound(prefix + '/');
102  for(Properties::const_iterator i = from; i != to; ++i) {
103  const std::string& key = (*i).first;
104  const std::string& value = (*i).second;
105  std::list<std::string> propNameParts;
106  std::back_insert_iterator<std::list<std::string> > pnpIt(propNameParts);
107  StringUtil::split(pnpIt, key, '.');
108  std::list<std::string>::const_iterator i2 = propNameParts.begin();
109  std::list<std::string>::const_iterator iEnd = propNameParts.end();
110  if (++i2 == iEnd) {
111  throw ConfigureFailure(std::string("missing appender name"));
112  }
113 
114  const std::string appenderName = *i2++;
115 
116  /* WARNING, approaching lame code section:
117  skipping of the Appenders properties only to get them
118  again in instantiateAppender.
119  */
120  if (appenderName == currentAppender) {
121  // simply skip properties for the current appender
122  } else {
123  if (i2 == iEnd) {
124  // a new appender
125  currentAppender = appenderName;
126  _allAppenders[currentAppender] =
127  instantiateAppender(currentAppender);
128  } else {
129  throw ConfigureFailure(std::string("partial appender definition : ") + key);
130  }
131  }
132  }
133  }
134 
135  void PropertyConfiguratorImpl::configureCategory(const std::string& categoryName) throw (ConfigureFailure) {
136  // start by reading the "rootCategory" key
137  std::string tempCatName =
138  (categoryName == "rootCategory") ? categoryName : "category." + categoryName;
139 
140  Properties::iterator iter = _properties.find(tempCatName);
141 
142  if (iter == _properties.end())
143  throw ConfigureFailure(std::string("Unable to find category: ") + tempCatName);
144 
145  // need to get the root instance of the category
146  Category& category = (categoryName == "rootCategory") ?
147  Category::getRoot() : Category::getInstance(categoryName);
148 
149 
150  std::list<std::string> tokens;
151  std::back_insert_iterator<std::list<std::string> > tokIt(tokens);
152  StringUtil::split(tokIt, (*iter).second, ',');
153  std::list<std::string>::const_iterator i = tokens.begin();
154  std::list<std::string>::const_iterator iEnd = tokens.end();
155 
157  if (i != iEnd) {
158  std::string priorityName = StringUtil::trim(*i++);
159  try {
160  if (priorityName != "") {
161  priority = Priority::getPriorityValue(priorityName);
162  }
163  } catch(std::invalid_argument& e) {
164  throw ConfigureFailure(std::string(e.what()) +
165  " for category '" + categoryName + "'");
166  }
167  }
168 
169  category.setPriority(priority);
170 
171  bool additive = _properties.getBool("additivity." + categoryName, true);
172  category.setAdditivity(additive);
173 
174  category.removeAllAppenders();
175  for(; i != iEnd; ++i) {
176  std::string appenderName = StringUtil::trim(*i);
177  AppenderMap::const_iterator appIt =
178  _allAppenders.find(appenderName);
179  if (appIt == _allAppenders.end()) {
180  // appender not found;
181  throw ConfigureFailure(std::string("Appender '") +
182  appenderName + "' not found for category '" + categoryName + "'");
183  } else {
184  /* pass by reference, i.e. don't transfer ownership
185  */
186  category.addAppender(*((*appIt).second));
187  }
188  }
189  }
190 
191  Appender* PropertyConfiguratorImpl::instantiateAppender(const std::string& appenderName) {
192  Appender* appender = NULL;
193  std::string appenderPrefix = std::string("appender.") + appenderName;
194 
195  // determine the type by the appenderName
196  Properties::iterator key = _properties.find(appenderPrefix);
197  if (key == _properties.end())
198  throw ConfigureFailure(std::string("Appender '") + appenderName + "' not defined");
199 
200  std::string::size_type length = (*key).second.find_last_of(".");
201  std::string appenderType = (length == std::string::npos) ?
202  (*key).second : (*key).second.substr(length+1);
203 
204  // and instantiate the appropriate object
205  if (appenderType == "ConsoleAppender") {
206  appender = new OstreamAppender(appenderName, &std::cout);
207  }
208  else if (appenderType == "FileAppender") {
209  std::string fileName = _properties.getString(appenderPrefix + ".fileName", "foobar");
210  bool append = _properties.getBool(appenderPrefix + ".append", true);
211  appender = new FileAppender(appenderName, fileName, append);
212  }
213  else if (appenderType == "RollingFileAppender") {
214  std::string fileName = _properties.getString(appenderPrefix + ".fileName", "foobar");
215  size_t maxFileSize = _properties.getInt(appenderPrefix + ".maxFileSize", 10*1024*1024);
216  int maxBackupIndex = _properties.getInt(appenderPrefix + ".maxBackupIndex", 1);
217  bool append = _properties.getBool(appenderPrefix + ".append", true);
218  appender = new RollingFileAppender(appenderName, fileName, maxFileSize, maxBackupIndex,
219  append);
220  }
221  else if (appenderType == "GenerationalFileAppender") {
222  std::string fileName = _properties.getString(appenderPrefix + ".fileName", "foobar");
223  bool append = _properties.getBool(appenderPrefix + ".append", true);
224  appender = new GenerationalFileAppender(appenderName, fileName, append);
225  }
226  else if (appenderType == "DailyRollingFileAppender") {
227  std::string fileName = _properties.getString(appenderPrefix + ".fileName", "foobar");
228  unsigned int maxDaysKeep = _properties.getInt(appenderPrefix + ".maxDaysKeep", 0);
229  bool append = _properties.getBool(appenderPrefix + ".append", true);
230  appender = new DailyRollingFileAppender(appenderName, fileName, maxDaysKeep, append);
231  }
232 #ifndef LOG4CPP_DISABLE_REMOTE_SYSLOG
233  else if (appenderType == "SyslogAppender") {
234  std::string syslogName = _properties.getString(appenderPrefix + ".syslogName", "syslog");
235  std::string syslogHost = _properties.getString(appenderPrefix + ".syslogHost", "localhost");
236  int facility = _properties.getInt(appenderPrefix + ".facility", -1) * 8; // * 8 to get LOG_KERN, etc. compatible values.
237  int portNumber = _properties.getInt(appenderPrefix + ".portNumber", -1);
238  appender = new RemoteSyslogAppender(appenderName, syslogName,
239  syslogHost, facility, portNumber);
240  }
241 #endif // LOG4CPP_DISABLE_REMOTE_SYSLOG
242 #ifdef LOG4CPP_HAVE_SYSLOG
243  else if (appenderType == "LocalSyslogAppender") {
244  std::string syslogName = _properties.getString(appenderPrefix + ".syslogName", "syslog");
245  int facility = _properties.getInt(appenderPrefix + ".facility", -1) * 8; // * 8 to get LOG_KERN, etc. compatible values.
246  appender = new SyslogAppender(appenderName, syslogName, facility);
247  }
248 #endif // LOG4CPP_HAVE_SYSLOG
249  else if (appenderType == "AbortAppender") {
250  appender = new AbortAppender(appenderName);
251  }
252 #ifdef LOG4CPP_HAVE_LIBIDSA
253  else if (appenderType == "IdsaAppender") {
254  // default idsa name ???
255  std::string idsaName = _properties.getString(appenderPrefix + ".idsaName", "foobar");
256 
257  appender = new IdsaAppender(appenderName, idsaname);
258  }
259 #endif // LOG4CPP_HAVE_LIBIDSA
260 
261 #ifdef WIN32
262  // win32 debug appender
263  else if (appenderType == "Win32DebugAppender") {
264  appender = new Win32DebugAppender(appenderName);
265  }
266  // win32 NT event log appender
267  else if (appenderType == "NTEventLogAppender") {
268  std::string source = _properties.getString(appenderPrefix + ".source", "foobar");
269  appender = new NTEventLogAppender(appenderName, source);
270  }
271 #endif // WIN32
272  else {
273  throw ConfigureFailure(std::string("Appender '") + appenderName +
274  "' has unknown type '" + appenderType + "'");
275  }
276 
277  if (appender->requiresLayout()) {
278  setLayout(appender, appenderName);
279  }
280 
281  // set threshold
282  std::string thresholdName = _properties.getString(appenderPrefix + ".threshold", "");
283  try {
284  if (thresholdName != "") {
285  appender->setThreshold(Priority::getPriorityValue(thresholdName));
286  }
287  } catch(std::invalid_argument& e) {
288  delete appender; // fix for #3109495
289  throw ConfigureFailure(std::string(e.what()) +
290  " for threshold of appender '" + appenderName + "'");
291  }
292 
293  return appender;
294  }
295 
296  void PropertyConfiguratorImpl::setLayout(Appender* appender, const std::string& appenderName) {
297  // determine the type by appenderName
298  std::string tempString;
299  Properties::iterator key =
300  _properties.find(std::string("appender.") + appenderName + ".layout");
301 
302  if (key == _properties.end())
303  throw ConfigureFailure(std::string("Missing layout property for appender '") +
304  appenderName + "'");
305 
306  std::string::size_type length = (*key).second.find_last_of(".");
307  std::string layoutType = (length == std::string::npos) ?
308  (*key).second : (*key).second.substr(length+1);
309 
310  Layout* layout;
311  // and instantiate the appropriate object
312  if (layoutType == "BasicLayout") {
313  layout = new BasicLayout();
314  }
315  else if (layoutType == "SimpleLayout") {
316  layout = new SimpleLayout();
317  }
318  else if (layoutType == "PatternLayout") {
319  // need to read the properties to configure this one
320  PatternLayout* patternLayout = new PatternLayout();
321 
322  key = _properties.find(std::string("appender.") + appenderName + ".layout.ConversionPattern");
323  if (key == _properties.end()) {
324  // leave default pattern
325  } else {
326  // set pattern
327  patternLayout->setConversionPattern((*key).second);
328  }
329 
330  layout = patternLayout;
331  }
332  else {
333  throw ConfigureFailure(std::string("Unknown layout type '" + layoutType +
334  "' for appender '") + appenderName + "'");
335  }
336 
337  appender->setLayout(layout);
338  }
339 
346  void PropertyConfiguratorImpl::getCategories(std::vector<std::string>& categories) const {
347  categories.clear();
348 
349  // add the root category first
350  categories.push_back(std::string("rootCategory"));
351 
352  // then look for "category."
353  std::string prefix("category");
354  Properties::const_iterator from = _properties.lower_bound(prefix + '.');
355  Properties::const_iterator to = _properties.lower_bound(prefix + (char)('.' + 1));
356  for (Properties::const_iterator iter = from; iter != to; iter++) {
357  categories.push_back((*iter).first.substr(prefix.size() + 1));
358  }
359  }
360 }
void setLayout(Appender *appender, const std::string &name)
void getCategories(std::vector< std::string > &categories) const
virtual void setThreshold(Priority::Value priority)=0
Appender * instantiateAppender(const std::string &name)
virtual void setAdditivity(bool additivity)
Definition: Category.cpp:235
static Category & getInstance(const std::string &name)
Definition: Category.cpp:35
virtual void setConversionPattern(const std::string &conversionPattern)
virtual void doConfigure(const std::string &initFileName)
virtual bool requiresLayout() const =0
virtual void removeAllAppenders()
Definition: Category.cpp:151
static Category & getRoot()
Definition: Category.cpp:23
static std::string trim(const std::string &s)
Definition: StringUtil.cpp:71
virtual void setPriority(Priority::Value priority)
Definition: Category.cpp:71
virtual int getInt(const std::string &property, int defaultValue)
Definition: Properties.cpp:95
virtual void load(std::istream &in)
Definition: Properties.cpp:21
static unsigned int split(std::vector< std::string > &v, const std::string &s, char delimiter, unsigned int maxSegments=INT_MAX)
Definition: StringUtil.cpp:90
virtual std::string getString(const std::string &property, const char *defaultValue)
Definition: Properties.cpp:105
virtual void addAppender(Appender *appender)
Definition: Category.cpp:94
virtual void setLayout(Layout *layout)=0
static Value getPriorityValue(const std::string &priorityName)
Definition: Priority.cpp:44
void configureCategory(const std::string &categoryname)
virtual bool getBool(const std::string &property, bool defaultValue)
Definition: Properties.cpp:100


log4cpp
Author(s): Stephen Roderick, Bastiaan Bakker, Cedric Le Goater, Steve Ostlind, Marcel Harkema, Walter Stroebel, Glenn Scott and Tony Cheung
autogenerated on Sun Jun 23 2019 19:14:17