1 /*----------------------------------------------------------------------------
  2 Name:      Log.cpp
  3 Project:   xmlBlaster.org
  4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
  5 Comment:   Handling the Client data
  6 ----------------------------------------------------------------------------*/
  7 #include <util/Log.h>
  8 #include <iostream>
  9 #include <ctime>   //<time.h>
 10 #include <cstdlib> //<stdlib.h>
 11 #include <util/lexical_cast.h>
 12 #include <util/PropertyDef.h>
 13 
 14 using namespace std;
 15 
 16 namespace org { namespace xmlBlaster {
 17 namespace util {
 18 
 19 const char* const Log::ESC          = "\033[0m";
 20 const char* const Log::BOLD         = "\033[1m";
 21 const char* const Log::RED_BLACK    = "\033[31;40m";
 22 const char* const Log::GREEN_BLACK  = "\033[32;40m";
 23 const char* const Log::YELLOW_BLACK = "\033[33;40m";
 24 const char* const Log::BLUE_BLACK   = "\033[34;40m";
 25 const char* const Log::PINK_BLACK   = "\033[35;40m";
 26 const char* const Log::LTGREEN_BLACK= "\033[36;40m";
 27 const char* const Log::WHITE_BLACK  = "\033[37;40m";
 28 const char* const Log::WHITE_RED    = "\033[37;41m";
 29 const char* const Log::BLACK_RED    = "\033[30;41m";
 30 const char* const Log::BLACK_GREEN  = "\033[40;42m";
 31 const char* const Log::BLACK_PINK   = "\033[40;45m";
 32 const char* const Log::BLACK_LTGREEN= "\033[40;46m";
 33 
 34 
 35 
 36    /**
 37     * Initializes logging and Properties
 38     */
 39    Log::Log(Property& properties, int /*args*/, const char * const /*argc*/[], const string& name) 
 40       : withXtermColor_(true), properties_(properties), name_(name)
 41    {
 42       ME     = "Log";
 43 #     ifdef _WIN32
 44          withXtermColor_ = false;
 45 #     endif
 46       withXtermColor_ = properties.getBoolProperty("xmlBlaster.withXtermColor", withXtermColor_, true);
 47       call_  = true;
 48       time_  = true;
 49       trace_ = true;
 50       dump_  = true;
 51       numWarnInvocations     = 0;
 52       numErrorInvocations    = 0;
 53       currentLogFormat       = "{0} {1} {2}: {3}";
 54       logFormatPropertyRead  = false;
 55       logLevel_ = L_PANIC | L_ERROR | L_WARN | L_INFO;
 56 
 57       timeE   = string(LTGREEN_BLACK) + "TIME " + ESC;
 58       callE   = string(BLACK_LTGREEN) + "CALL " + ESC;
 59       traceE  = string(WHITE_BLACK  ) + "TRACE" + ESC;
 60       plainE  = string(WHITE_BLACK  ) + "     " + ESC;
 61       infoE   = string(GREEN_BLACK  ) + "INFO " + ESC;
 62       warnE   = string(YELLOW_BLACK ) + "WARN " + ESC;
 63       errorE  = string(RED_BLACK    ) + "ERROR" + ESC;
 64       panicE  = string(BLACK_RED    ) + "PANIC" + ESC;
 65       exitE   = string(GREEN_BLACK  ) + "EXIT " + ESC;
 66 
 67       timeX   = "TIME ";
 68       callX   = "CALL ";
 69       traceX  = "TRACE";
 70       plainX  = "     ";
 71       infoX   = "INFO ";
 72       warnX   = "WARN ";
 73       errorX  = "ERROR";
 74       panicX  = "PANIC";
 75       exitX   = "EXIT ";
 76    }
 77 
 78 
 79    Log::~Log() {
 80    }
 81 
 82    void Log::exitLow(int val) {
 83       // gcc 3.x: The functions abort, exit, _Exit and _exit are recognized and presumed not to return,
 84       // but otherwise are not built in.
 85       // _exit is not recognized in strict ISO C mode (`-ansi', `-std=c89' or `-std=c99').
 86       // _Exit is not recognized in strict C89 mode (`-ansi' or `-std=c89').
 87 #     if defined(__ICC)
 88          ::exit(val);
 89 #     elif  __GNUC__==3
 90          ::exit(val);
 91 #     elif  __GNUC__==4
 92          ::exit(val);
 93 #     elif defined(__sun)
 94          ::exit(val);
 95 #     else
 96          ::_exit(val);
 97 #     endif
 98    }
 99 
100    void Log::setWithXtermColor(bool val /* = true */) {
101       withXtermColor_ = val;
102    }
103 
104    void Log::setDefaultLogLevel() {
105       logLevel_ = L_PANIC | L_ERROR | L_WARN | L_INFO;
106       setPreLogLevelCheck();
107    }
108 
109 
110    void Log::setLogLevel(int level) {
111       logLevel_ = level;
112       setPreLogLevelCheck();
113    }
114 
115    void Log::setLogLevel(int argc, const char * const args[]) {
116       if ((properties_.findArgument(argc, args, "-?") > 0) ||
117           (properties_.findArgument(argc, args, "-h") > 0)) {
118          std::cout << usage() << std::endl;
119          return;
120       }
121       initialize();
122    }
123 
124 
125    void Log::removeLogLevel(string logLevel) {
126       int level = logLevelToBit(logLevel);
127       logLevel_ = (logLevel_ & ~level);
128       setPreLogLevelCheck();
129    }
130 
131 
132    void Log::addLogLevel(string logLevel) {
133       int level = logLevelToBit(logLevel);
134       logLevel_ = (logLevel_ | level);
135       setPreLogLevelCheck();
136       //std::cout << "DEBUG: " << "Adding logLevel '" << logLevel << "' level=" << level << " dump=" << dump_ << std::endl;
137    }
138 
139 
140    void Log::setPreLogLevelCheck() {
141       call_ = time_ = trace_ = dump_  = false;
142       if (logLevel_ & L_CALL)  call_  = true;
143       if (logLevel_ & L_TIME ) time_  = true;
144       if (logLevel_ & L_TRACE) trace_ = true;
145       if (logLevel_ & L_DUMP ) dump_  = true;
146    }
147 
148 
149    string Log::bitToLogLevel(int level) const {
150       string sb = "";
151       if (level & L_PANIC) sb += "PANIC";
152       if (level & L_ERROR) sb += " | ERROR";
153       if (level & L_WARN ) sb += " | WARN";
154       if (level & L_INFO ) sb += " | INFO";
155       if (level & L_CALL) sb += " | CALL";
156       if (level & L_TIME ) sb += " | TIME";
157       if (level & L_TRACE) sb += " | TRACE";
158       if (level & L_DUMP ) sb += " | DUMP";
159       return sb;
160    }
161 
162 
163    void Log::panic(const string &instance, const string &text) {
164       if (logLevel_ & L_PANIC) {
165          if (withXtermColor_)
166             log(panicE, L_PANIC, instance, text);
167          else
168             log(panicX, L_PANIC, instance, text);
169          cerr << text << endl;
170          numErrorInvocations++;
171          // displayStatistics();
172          exitLow(1);
173       }
174    }
175 
176 
177    void Log::exit(const string &instance, const string &text) {
178       if (withXtermColor_)
179          log(exitE, L_EXIT, instance, text);
180       else
181          log(exitX, L_EXIT, instance, text);
182       displayStatistics();
183       exitLow(0);
184    }
185 
186 
187    void Log::info(const string &instance, const string &text) {
188       if (logLevel_ & L_INFO) {
189          if (withXtermColor_)
190             log(infoE, L_INFO, instance, text);
191          else
192             log(infoX, L_INFO, instance, text);
193       }
194    }
195 
196 
197    void Log::warn(const string &instance, const string &text) {
198       if(logLevel_ & L_WARN) {
199          numWarnInvocations++;
200          if (withXtermColor_)
201             log(warnE, L_WARN, instance, text);
202          else
203             log(warnX, L_WARN, instance, text);
204       }
205    }
206 
207 
208    void Log::error(const string &instance, const string &text) {
209       if(logLevel_ & L_PANIC) {
210          numErrorInvocations++;
211          if (withXtermColor_)
212             log(errorE, L_ERROR, instance, text);
213          else
214             log(errorX, L_ERROR, instance, text);
215       }
216    }
217 
218 
219    void Log::plain(const string &/*instance*/, const string &text) {
220       log("", L_PLAIN, "", text);
221    }
222 
223 
224    void Log::dump(const string &instance, const string &text) {
225       if((logLevel_ & L_DUMP) != 0) {
226          log("", L_DUMP, instance, text);
227 //          log("", L_DUMP, instance, Memory.getStatistic());
228       }
229    }
230 
231 
232    void Log::trace(const string &instance, const string &text) {
233       if(logLevel_ & L_TRACE) {
234          if (withXtermColor_)
235             log(traceE, L_TRACE, instance, text);
236          else
237             log(traceX, L_TRACE, instance, text);
238       }
239    }
240 
241 
242    void Log::call(const string &instance, const string &text) {
243       if(logLevel_ & L_CALL) {
244          if (withXtermColor_)
245             log(callE, L_CALL, instance, text);
246          else
247             log(callX, L_CALL, instance, text);
248       }
249    }
250 
251 
252    void Log::time(const string &instance, const string &text) {
253          if(logLevel_ & L_TIME) {
254             if (withXtermColor_)
255                log(timeE, L_TIME, instance, text);
256             else
257                log(timeX, L_TIME, instance, text);
258          }
259       }
260 
261    void Log::log(const string &levelStr, int level, const string &instance,
262              const string &text) {
263        if (logFormatPropertyRead == false) {
264           initialize();
265        }
266 
267        string logFormat;
268        if(level & L_DUMP)
269           logFormat = "{3}";
270        else
271           logFormat = currentLogFormat;
272 
273        string logEntry = levelStr + " ";
274        if (level & L_TIME) logEntry += getTime() + ": ";
275        if ((level & L_ERROR) || (level & L_WARN) || (level & L_PANIC))
276           cerr << logEntry << instance << " " << text << endl;
277        else
278           cout << logEntry << instance << " " << text << endl;
279     }
280 
281    std::string Log::usage() const {
282       std::string text = string("");
283       text += string("\nLogging options:");
284       text += string("\n   -trace true         Show code trace.");
285       text += string("\n   -dump true          Dump internal state.");
286       text += string("\n   -call true          Show important method entries");
287       text += string("\n   -time true          Display some performance data.");
288       //text += string("\n  -logFile <fileName> Log to given file instead to console.");
289       return text;
290    }
291 
292 
293    void Log::displayStatistics() {
294       //       Log.info(ME, Memory.getStatistic());
295       if (withXtermColor_) {
296          if (numErrorInvocations>0) {
297             info(ME, string(BLACK_RED) + "There were " + lexical_cast<std::string>(numErrorInvocations) +
298                      " ERRORS and " + lexical_cast<std::string>(numWarnInvocations) + " WARNINGS" + ESC);
299          }
300          else if (numWarnInvocations>0) {
301             info(ME, string(BLACK_PINK) + "There were " + lexical_cast<std::string>(numErrorInvocations) +
302                      " ERRORS and " + lexical_cast<std::string>(numWarnInvocations) + " WARNINGS" + ESC);
303          }
304          else {
305             info(ME, string(BLACK_GREEN) + "No errors/warnings were reported" + ESC);
306          }
307       }
308       else {
309          if (numErrorInvocations>0 || numWarnInvocations>0) {
310             info(ME, string("There were ") + lexical_cast<std::string>(numErrorInvocations) + " ERRORS and " + (lexical_cast<std::string>(numWarnInvocations)) + " WARNINGS");
311          }
312          else
313             info(ME, "No errors/warnings were reported");
314       }
315    }
316 
317 
318    void Log::printStack() {
319       cerr << "sorry, no Stack aviable" << endl;
320    }
321 
322 
323 
324    void Log::initSpecificTrace(const string& trace, const string& traceId)
325    {
326       if (properties_.propertyExists(trace + "[" + name_ + "]")) {
327          if (properties_.getBoolProperty(trace + "[" + name_ + "]", false))
328             addLogLevel(traceId);
329          else removeLogLevel(traceId);
330          return;
331       }
332       if (properties_.propertyExists(trace)) {
333          if (properties_.getBoolProperty(trace, false))
334             addLogLevel(traceId);
335          else removeLogLevel(traceId);
336       }
337    }
338 
339 
340    void Log::initialize() {
341       setPreLogLevelCheck();
342       logFormatPropertyRead = true;
343       // Given flag -info switches off Log.info messages:
344       initSpecificTrace("info", "INFO");
345       initSpecificTrace("warn", "WARN");
346       initSpecificTrace("error", "ERROR");
347       initSpecificTrace("call", "CALL");
348       initSpecificTrace("time", "TIME");
349       initSpecificTrace("trace", "TRACE");
350       initSpecificTrace("dump", "DUMP");
351 
352       if (properties_.getBoolProperty("+call", false))
353          addLogLevel("CALL");
354       if (properties_.getBoolProperty("+time", false))
355          addLogLevel("TIME");
356       if (properties_.getBoolProperty("+trace", false))
357          addLogLevel("TRACE");
358       if (properties_.getBoolProperty("+dump", false))
359          addLogLevel("DUMP");
360 
361       // format: {0}:{1}:{2}:{3}    <timestamp>:<levelStr>:<instance>:<text>
362       currentLogFormat = properties_.getStringProperty("LogFormat",
363                                                        currentLogFormat);
364 
365       //std::cout << "DEBUG: " << "Current logLevel for [" << name_ << "] is " << bitToLogLevel(logLevel_) << std::endl;
366 
367 //      string tmp = properties_.getStringProperty("LogFormat.Date","MEDIUM");
368 //       if (tmp == "SHORT") lookAndFeelDate = java.text.DateFormat.SHORT;
369 //       else if (tmp.equals("MEDIUM"))
370 //          lookAndFeelDate = java.text.DateFormat.MEDIUM;
371 //       else if (tmp.equals("LONG"))
372 //          lookAndFeelDate = java.text.DateFormat.LONG;
373 //       else if (tmp.equals("FULL"))
374 //          lookAndFeelDate = java.text.DateFormat.FULL;
375 //       tmp = properties_.getStringProperty("LogFormat.Time","MEDIUM");
376 //       if (tmp.equals("SHORT"))
377 //          lookAndFeelTime = java.text.DateFormat.SHORT;
378 //       else if (tmp.equals("MEDIUM"))
379 //          lookAndFeelTime = java.text.DateFormat.MEDIUM;
380 //       else if (tmp.equals("LONG"))
381 //          lookAndFeelTime = java.text.DateFormat.LONG;
382 //       else if (tmp.equals("FULL"))
383 //          lookAndFeelTime = java.text.DateFormat.FULL;
384 
385 //      string la = properties_.getStringProperty("LogFormat.Language","");
386 //      string co = properties_.getStringProperty("LogFormat.Country", "");
387 //       if (la != null && co != null) country = new Locale(la, co);
388 
389 //       String fileName = properties_.getProperty("logFile", (String)null);
390 //       if (fileName != null)
391 //          Log.logToFile(fileName);
392    }
393 
394 
395    string Log::getTime() {
396       // adapt it here to the correct time format (locales) ?!
397       time_t theTime;
398       ::time(&theTime);
399       string timeStr = ctime(&theTime), ret;
400       // eliminate new lines (if any)
401       string::size_type pos = timeStr.find("\n");
402       if (pos == string::npos) return timeStr;
403       ret.assign(timeStr, 0, pos);
404       return ret;
405    }
406 
407 }}} // end of namespace


syntax highlighted by Code2HTML, v. 0.9.1