1 /*
2     LinKNX KNX home automation platform
3     Copyright (C) 2007-2008 Jean-François Meessen <linknx@ouaye.net>
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 
20 #include "logger.h"
21 
22 Logging* Logging::instance_m;
23 
24 #ifdef HAVE_LOG4CPP
25 
26 #include    <log4cpp/BasicConfigurator.hh>
27 #include    <log4cpp/PropertyConfigurator.hh>
28 #include    <log4cpp/OstreamAppender.hh>
29 #include    <log4cpp/FileAppender.hh>
30 #include    <log4cpp/RollingFileAppender.hh>
31 #include    <log4cpp/SimpleLayout.hh>
32 #include    <log4cpp/PatternLayout.hh>
33 
importXml(ticpp::Element * pConfig)34 void Logging::importXml(ticpp::Element* pConfig)
35 {
36     if (!pConfig) {
37         log4cpp::BasicConfigurator::configure();
38     }
39     else {
40         try{
41             conffile_m = pConfig->GetAttribute("config");
42             if (conffile_m.length()) {
43                 log4cpp::PropertyConfigurator::configure(conffile_m); // throw (ConfigureFailure)
44             }
45             else {
46                 output_m = pConfig->GetAttribute("output");
47                 format_m = pConfig->GetAttribute("format");
48                 level_m  = pConfig->GetAttribute("level");
49                 log4cpp::Appender* app = NULL;
50                 if (output_m.length()) {
51                     pConfig->GetAttributeOrDefault("maxfilesize", &maxSize_m, -1);
52                     if (maxSize_m > 0) {
53                         pConfig->GetAttributeOrDefault("maxfileindex", &maxIndex_m, 10);
54                         app = new log4cpp::RollingFileAppender("RollingFileAppender", output_m, maxSize_m * 1024, maxIndex_m);
55                     }
56                     else
57                         app = new log4cpp::FileAppender("FileAppender", output_m);
58                 }
59                 else
60                     app = new log4cpp::OstreamAppender("ConsoleAppender", &std::cout);
61                 if (format_m == "basic")
62                     app->setLayout(new log4cpp::BasicLayout());
63                 else if (format_m == "simple")
64                     app->setLayout(new log4cpp::SimpleLayout());
65                 else {
66                     log4cpp::PatternLayout* patternLayout = new log4cpp::PatternLayout();
67                     if (format_m == "")
68                         patternLayout->setConversionPattern("%d [%5p] %c: %m%n");
69                     else
70                         patternLayout->setConversionPattern(format_m);
71                     app->setLayout(patternLayout);
72                 }
73                 log4cpp::Priority::Value prio = log4cpp::Priority::INFO;
74                 if (level_m != "")
75                     prio = log4cpp::Priority::getPriorityValue(level_m);
76 
77                 log4cpp::Category& root = log4cpp::Category::getRoot();
78                 root.setPriority(prio);
79 
80                 root.removeAllAppenders();
81                 root.addAppender(app);
82             }
83         }
84         catch (log4cpp::ConfigureFailure ex) {
85             throw ticpp::Exception(ex.what());
86         }
87         catch (std::invalid_argument ex) {
88             throw ticpp::Exception(ex.what());
89         }
90     }
91 }
92 
exportXml(ticpp::Element * pConfig)93 void Logging::exportXml(ticpp::Element* pConfig)
94 {
95     if (conffile_m != "")
96     {
97         pConfig->SetAttribute("config", conffile_m);
98     }
99     else
100     {
101         if (output_m != "")
102         {
103             pConfig->SetAttribute("output", output_m);
104             if (maxSize_m != -1)
105             {
106                 pConfig->SetAttribute("maxfilesize", maxSize_m);
107                 pConfig->SetAttribute("maxfileindex", maxIndex_m);
108             }
109         }
110         if (format_m != "")
111             pConfig->SetAttribute("format", format_m);
112         if (level_m != "")
113             pConfig->SetAttribute("level", level_m);
114     }
115 }
116 
117 #else
118 
119 #include    <ctime>
120 
121 int Logger::level_m;
122 bool Logger::timestamp_m;
123 NullStreamBuf Logger::nullStreamBuf_m;
124 std::ostream Logger::nullStream_m(&Logger::nullStreamBuf_m);
125 
importXml(ticpp::Element * pConfig)126 void Logging::importXml(ticpp::Element* pConfig)
127 {
128     if (!pConfig) {
129         Logger::level_m = 20;
130         Logger::timestamp_m = true;
131     }
132     else {
133 //        std::string output = pConfig->GetAttribute("output");
134         format_m = pConfig->GetAttribute("format");
135         level_m  = pConfig->GetAttribute("level");
136         if (level_m == "" || level_m == "INFO")
137             Logger::level_m = 20;
138         else if (level_m == "NOTICE")
139             Logger::level_m = 30;
140         else if (level_m == "WARN")
141             Logger::level_m = 40;
142         else if (level_m == "ERROR")
143             Logger::level_m = 50;
144         else if (level_m == "DEBUG")
145             Logger::level_m = 10;
146 
147         Logger::timestamp_m = (format_m != "simple");
148     }
149 }
150 
exportXml(ticpp::Element * pConfig)151 void Logging::exportXml(ticpp::Element* pConfig)
152 {
153     if (format_m != "")
154         pConfig->SetAttribute("format", format_m);
155     if (level_m != "")
156         pConfig->SetAttribute("level", level_m);
157 }
158 
getLoggerMap()159 Logger::LoggerMap_t* Logger::getLoggerMap() {
160     // This static local is used to avoid problems with
161     // initialization order of static object present in
162     // different compilation units
163     static LoggerMap_t* loggerMap = new LoggerMap_t();
164     return loggerMap;
165 }
166 
getInstance(const char * cat)167 Logger& Logger::getInstance(const char* cat) {
168     LoggerMap_t* map = getLoggerMap();
169     LoggerMap_t::iterator it = map->find(cat);
170     Logger* logger;
171     if (it != map->end())
172         logger = it->second;
173     else {
174         logger = new Logger(cat);
175         map->insert(LoggerPair_t(cat, logger));
176     }
177     return *(logger);
178 }
179 
180 DummyStream DummyStream::dummy;
181 
Logger(const char * cat)182 Logger::Logger(const char* cat) : cat_m(cat) {
183 }
184 
addPrefix(std::ostream & s,const char * level)185 std::ostream& Logger::addPrefix(std::ostream &s, const char* level) {
186     if (timestamp_m) {
187         time_t now;
188         struct tm * timeinfo;
189         char buffer [32];
190 
191         time ( &now );
192         timeinfo = localtime ( &now );
193         strftime (buffer,sizeof(buffer),"%Y-%m-%d %X ",timeinfo);
194         s << buffer;
195     }
196     return s << level << cat_m << ": ";
197 }
198 
errorStream()199 ErrStream Logger::errorStream() {
200 #ifdef LOG_SHOW_ERROR
201     if (level_m <= 50)
202         return addPrefix(std::cerr, "[ERROR] ");
203     else
204         return nullStream_m;
205 #else
206     return DummyStream::dummy;
207 #endif
208 }
209 
warnStream()210 WarnStream Logger::warnStream()  {
211 #ifdef LOG_SHOW_WARN
212     if (level_m <= 40)
213         return addPrefix(std::cerr, "[ WARN] ");
214     else
215         return nullStream_m;
216 #else
217     return DummyStream::dummy;
218 #endif
219 }
220 
infoStream()221 LogStream Logger::infoStream()  {
222 #ifdef LOG_SHOW_INFO
223     if (level_m <= 20)
224         return addPrefix(std::cout, "[ INFO] ");
225     else
226         return nullStream_m;
227 #else
228     return DummyStream::dummy;
229 #endif
230 }
231 
debugStream()232 DbgStream Logger::debugStream() {
233 #ifdef LOG_SHOW_DEBUG
234     if (level_m <= 10)
235         return addPrefix(std::cout, "[DEBUG] ");
236     else
237         return nullStream_m;
238 #else
239     return DummyStream::dummy;
240 #endif
241 }
242 
isDebugEnabled()243 bool Logger::isDebugEnabled() {
244 #ifdef LOG_SHOW_DEBUG
245     return (level_m <= 10);
246 #else
247     return false;
248 #endif
249 }
250 
251 #endif
252 
errorStream(const char * cat)253 ErrStream errorStream(const char* cat) { return Logger::getInstance(cat).errorStream(); };
warnStream(const char * cat)254 WarnStream warnStream(const char* cat) { return Logger::getInstance(cat).warnStream(); };
infoStream(const char * cat)255 LogStream infoStream(const char* cat) { return Logger::getInstance(cat).infoStream(); };
debugStream(const char * cat)256 DbgStream debugStream(const char* cat) { return Logger::getInstance(cat).debugStream(); };
isDebugEnabled(const char * cat)257 bool isDebugEnabled(const char* cat) { return Logger::getInstance(cat).isDebugEnabled(); };
258