2005/5/9

     
 

LogManager.cpp

artefaktur
// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*- 
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
// 
// 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the 
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
//                         ACDK
// 
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
// 
// $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/util/logging/LogManager.cpp,v 1.30 2005/05/02 23:07:20 kommer Exp $
#include <acdk.h>
#include <acdk/lang/System.h>
#include <acdk/lang/Integer.h>
#include "LogManager.h"
#include "Logger.h"
#include "ConsoleConsumer.h"
#include "SimpleFormatter.h"
#include "Win32DbgConsumer.h"
#include "FileConsumer.h"
#include <acdk/util/THashMap.h>
#include <acdk/util/HashMap.h>
#include <acdk/lang/sys/core_system.h>

namespace acdk {
namespace util {
namespace logging {

  



  //static 
int LogManager::MinLevel = None;
int LogManager::Threshold = Warn;
bool LogManager::TresholdSet = false;


//#define USE_TYPED_HASHMAP
/*
#if ACDK_CHECK_GCC_VERSION(3, 0) && defined(USE_TYPED_HASHMAP)
# undef USE_TYPED_HASHMAP
#endif
*/

#if defined(USE_TYPED_HASHMAP)

typedef ::acdk::util::THashMap<RString, RLogger> StringToLoggerHashMap; 
typedef StringToLoggerHashMap::RefType RStringToLoggerHashMap;
ACDK_DECL_HASHMAP(String, RString, LogConsumer, RLogConsumer);

//static 
/// @internal
INOUTP(RStringToLogConsumerHashMap)
LogManager_getConsumerMap()
{
  ACDK_STATIC_INSTANCE0(StringToLogConsumerHashMap, consumer);
  return consumer;
}

/// @internal
//static 
INOUTP(RStringToLoggerHashMap)
LogManager_getLoggerMap()
{
  ACDK_STATIC_INSTANCE0(StringToLoggerHashMap, loggermap);
  return loggermap;
}
#else
/FONT>

INOUTP(RHashMap)
LogManager_getConsumerMap()
{
  ACDK_STATIC_INSTANCE0(HashMap, consumer);
  return consumer;
}


//static 
INOUTP(RHashMap)
LogManager_getLoggerMap()
{
  ACDK_STATIC_INSTANCE0(HashMap, loggermap);
  return loggermap;
}

#endif
/FONT>

//static 
INOUTP(RLogger)
LogManager::getRootLogger()
{

  ACDK_STATIC_INSTANCE2(Logger, const char*, "Root", int, None, rootLogger);
  if (rootLogger.isCreated())
    return rootLogger;
  if (sys::core_system::getState() == sys::AfterMain)
    return rootLogger;

  init_configure(rootLogger);
  return rootLogger;
}

//static 
INOUTP(RLogger) 
LogManager::getNullLogger()
{
  ACDK_STATIC_INSTANCE2(Logger, RString, RString("NullLogger"), int, None, nullLogger);
  return nullLogger;
}

namespace {

  /// @internal
OUTP(RFormatter) 
getStdFormater()
{
  static RFormatter format;
  return format;
}
} // anon namespace
//static 
OUTP(RFormatter) 
LogManager::getStandardFormatter()
{
  OUTP(RFormatter) frm = getStdFormater();
  if (frm == Nil)
    frm = new StdFormatter();
  return frm;
}

//static 
void 
LogManager::setStandardFormatter(INP(RFormatter) formatter)
{
  getStdFormater() = formatter;
}


//static 
void 
LogManager::init_configure(INOUT(RLogger) rootLogger)
{
  
  rootLogger = new Logger("Root", None);

  RProperties props = (RProperties)System::getProperties()->clone(); // clone it, because cfg may modify Property and make iterator invalid
  
  if (TresholdSet == false && props->getProperty("acdk.util.logging.threshold", Nil) != Nil)
    LogManager::Threshold = Level::parseLevel(props->getProperty("acdk.util.logging.threshold"));
  
  //acdk.util.logging.consumer.*
  RIterator it = props->propertyNames();
#if defined(USE_TYPED_HASHMAP)
  RStringToLogConsumerHashMap consumerMap = LogManager_getConsumerMap();
#else
/FONT>
  RHashMap consumerMap = LogManager_getConsumerMap();
#endif
/FONT>
  HashMap newConsumerMap;
  while (it->hasNext() == true)
  {
    RString n = (RString)it->next();
    if (n->startsWith("acdk.util.logging.consumer.") == true) 
    {
      RString consname = n->substr(strlen("acdk.util.logging.consumer."));
      RLogConsumer cons = (RLogConsumer)Class::forName(props->getProperty(n))->newInstance();
      cons->configure("acdk.util.logging.consumer_cfg." + consname, props);
#if defined(USE_TYPED_HASHMAP)
      consumerMap->put(consname, cons);
#else
/FONT>
      consumerMap->put((acdk::lang::Object)consname, (acdk::lang::Object)cons);
#endif
/FONT>
    }
  }
#if defined(USE_TYPED_HASHMAP)
  RStringToLoggerHashMap loggerMap = LogManager_getLoggerMap();
#else
/FONT>
  RHashMap loggerMap = LogManager_getLoggerMap();
#endif
/FONT>
  {
    RIterator it = props->propertyNames();
    while (it->hasNext() == true)
    {
      acdk::lang::Object o = it->next();
      if (instanceof(o, String) == false)
        continue;
      RString n = (RString)o;
      if (n->startsWith("acdk.util.logging.logger.") == false) 
        continue;
      RString loggername = n->substr(strlen("acdk.util.logging.logger."));
      int minlevel = Level::parseLevel(props->getProperty(n));
      RLogger logger = new Logger(loggername, minlevel);
      loggerMap->put(&loggername, &logger);
      if (MinLevel > minlevel)
        MinLevel = minlevel;
    }
  }  
  {
#if defined(USE_TYPED_HASHMAP)
    RStringIterator keys = loggerMap->keySet()->iterator();
#else
/FONT>
    RIterator keys = loggerMap->keySet()->iterator();
#endif
/FONT>
    while (keys->hasNext() == true)
    {
      RString k = (RString)keys->next();
      RLogger logger = (RLogger)loggerMap->get(&k);
      RString baskey = "acdk.util.logging.logger_cfg." + k + ".consumer";
      for (int i = 1; (k = props->getProperty(baskey + i, Nil)) != Nil; ++i)
      {
        RLogConsumer cons = (RLogConsumer)consumerMap->get(&k);
        if (cons != Nil)
          logger->addConsumer(cons);
      }
    }
  }
  RString rootname = "root";
  if (loggerMap->get(&rootname) != Nil)
    rootLogger =  (RLogger)loggerMap->get(&rootname);
  else
    rootLogger = new Logger("Root", None);
}

//static 
RLogger 
LogManager::getLogger(IN(RString) name)
{
  getRootLogger();
  RLogger logger = (RLogger)LogManager_getLoggerMap()->get(&name);
  if (logger != Nil)
    return logger;
  int idx = name->lastIndexOf('.');
  if (idx == -1)
    return getRootLogger();
  return getLogger(name->substr(0, idx));
}

//static 
RLogger 
LogManager::getCreateLogger(IN(RString) name)
{
  getRootLogger();
  RLogger logger = (RLogger)LogManager_getLoggerMap()->get(&name);
  if (logger != Nil)
    return logger;
  logger = new Logger(name);
  LogManager_getLoggerMap()->put(&logger->getName(), &logger);
  return logger;
}

//static 
void 
LogManager::registerLogger(IN(RLogger) logger)
{
  getRootLogger(); // force initialization
  LogManager_getLoggerMap()->put(&logger->getName(), &logger);
}

//static 
void 
LogManager::deregisterLogger(IN(RLogger) logger)
{
  LogManager_getLoggerMap()->remove(&logger->getName());
}

//static 
RStringArray 
LogManager::parseCommandLine(IN(RStringArray) args)
{
  RStringArray erg = new StringArray(0);
  RLogger log = getRootLogger();
  int loglevel = Threshold;
  for (int i = 0; i < args->length(); ++i)
  {
    RString s = args[i];
    /*if (s->startsWith("-log") == false)
    {
      erg->append(s);
    } 
    else
    {*/
    if (s->equals("-loglevel") == true)
    {
      ++i;
      
      int nll = Level::parseLevel(args[i]);
      if (nll < Threshold)
        Threshold = nll;
      loglevel = nll;
      TresholdSet = true;
    }
    else if (s->equals("-logcat") == true)
    {
      ++i;
      RString logCat = args[i];
      log = getCreateLogger(logCat);
    }
    else if (s->equals("-logto") == true)
    {
      ++i;
      RString target = args[i];
      
      if (target->equals("out") == true)
      {
        log->addConsumer(new ConsoleConsumer(new SimpleFormatter(), loglevel, None, false));
      }
      else if (target->equals("err") == true)
      {
        log->addConsumer(new ConsoleConsumer(new SimpleFormatter(), loglevel, None, true));
      }
      else if (target->equals("dbg") == true)
      {
        log->addConsumer(new Win32DbgConsumer());
      }
      else
      {
        log->addConsumer(new FileConsumer(target, new StdFormatter()));
      }
    }

    else
    {
      erg->append(s);
    }
    //}
  }
  return erg;
}

} // namespace logging
} // namespace util
} // namespace acdk