Skip to content
Snippets Groups Projects
ConfigService.cpp 9.94 KiB
Newer Older
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidKernel/ConfigService.h"
#include "MantidKernel/Support.h"
Nick Draper's avatar
Nick Draper committed
#include "MantidKernel/FilterChannel.h"
Roman Tolchenov's avatar
Roman Tolchenov committed
#include "MantidKernel/SignalChannel.h"
#include "Poco/Util/LoggingConfigurator.h"
#include "Poco/Util/SystemConfiguration.h"
#include "Poco/Util/PropertyFileConfiguration.h"
Nick Draper's avatar
Nick Draper committed
#include "Poco/LoggingFactory.h"
#include <sstream>
#include <iostream>
#include <string>
//-------------------------------
// Private member functions
//-------------------------------

  /// Private constructor for singleton class
	ConfigServiceImpl::ConfigServiceImpl() : g_log(Logger::get("ConfigService"))
	  //getting at system details
	  m_pSysConfig = new WrappedObject<Poco::Util::SystemConfiguration>;
	  m_pConf = 0;
Roman Tolchenov's avatar
Roman Tolchenov committed
        
        //Register the FilterChannel with the Poco logging factory
        Poco::LoggingFactory::defaultFactory().registerChannelClass("FilterChannel",new Poco::Instantiator<Poco::FilterChannel, Poco::Channel>);
Nick Draper's avatar
Nick Draper committed

Roman Tolchenov's avatar
Roman Tolchenov committed
        //Register the SignalChannel with the Poco logging factory
        Poco::LoggingFactory::defaultFactory().registerChannelClass("SignalChannel",new Poco::Instantiator<Poco::SignalChannel, Poco::Channel>);
Nick Draper's avatar
Nick Draper committed

    //Determine how we are running mantid
    if( Mantid::Kernel::getPathToExecutable().rfind("python") != std::string::npos )
    {
      m_strBaseDir = Poco::Path::current();
    }
    else
    {
      m_strBaseDir = Mantid::Kernel::getDirectoryOfExecutable();
    }
        
        //attempt to load the default properties file that resides in the directory of the executable
	loadConfig( getBaseDir() + "Mantid.properties");
	//Fill the list of possible relative path keys that may require conversion to absolute paths
	m_vConfigPaths.clear();
	m_vConfigPaths.push_back("plugins.directory");
	m_vConfigPaths.push_back("instrumentDefinition.directory");
	m_vConfigPaths.push_back("pythonscripts.directory");
	m_vConfigPaths.push_back("ManagedWorkspace.FilePath");
	
	convertRelativePaths();

	g_log.debug() << "ConfigService created." << std::endl;
	g_log.debug() << "Configured base directory of application as " << getBaseDir() << std::endl;

  /// Private copy constructor for singleton class
	ConfigServiceImpl::ConfigServiceImpl(const ConfigServiceImpl&) : g_log(Logger::get("ConfigService"))
	{
	}

  /** Private Destructor
   *  Prevents client from calling 'delete' on the pointer handed out by Instance
   */
	ConfigServiceImpl::~ConfigServiceImpl()
Matt Clarke's avatar
Matt Clarke committed
		delete m_pConf;                // potential double delete???
//		g_log.debug() << "ConfigService destroyed." << std::endl;
  /**
   * Searches the stored list for keys that have been loaded from the config file and may contain
   * relative paths. Any it find are converted to absolute paths and stored separately
   */
  void ConfigServiceImpl::convertRelativePaths()
  {
    if( m_vConfigPaths.empty() ) return;


    std::vector<std::string>::const_iterator send = m_vConfigPaths.end();
    for( std::vector<std::string>::const_iterator sitr = m_vConfigPaths.begin(); sitr != send; ++sitr )
    {
      if( !m_pConf->hasProperty(*sitr) ) continue;
      
      std::string value(m_pConf->getString(*sitr));
      if( Poco::Path(value).isRelative() )
      {
	m_mAbsolutePaths.insert(std::make_pair(*sitr, Poco::Path(execdir).resolve(value).toString()));
      }
      
    }

  }

//-------------------------------
// Public member functions
//-------------------------------
  /** Loads the config file provided, any previous configuration is discarded.
   *  If the file contains logging setup instructions then these will be used to setup the logging framework.
   *
   *  @param filename The filename and optionally path of the file to load
   */
	void ConfigServiceImpl::loadConfig(const std::string& filename)
		  m_pConf = new WrappedObject<Poco::Util::PropertyFileConfiguration>(filename);
Matt Clarke's avatar
Matt Clarke committed
		catch (std::exception& e)
		{
			//there was a problem loading the file - it probably is not there
			std::cerr << "Problem loading the logging file " << filename << " " << e.what() << std::endl;
			
			std::string propFile = 
				"logging.loggers.root.level = debug\n"
				"logging.loggers.root.channel.class = SplitterChannel\n"
Nick Draper's avatar
Nick Draper committed
				"logging.loggers.root.channel.channel1 = consoleChannelFilter\n"
				"logging.loggers.root.channel.channel2 = fileChannel\n"
Nick Draper's avatar
Nick Draper committed
				"logging.channels.consoleChannelFilter.class = FilterChannel\n"
				"logging.channels.consoleChannelFilter.channel = ConsoleChannel\n"
				"logging.channels.consoleChannelFilter.level = information\n"
				"logging.channels.consoleChannel.class = ConsoleChannel\n"
				"logging.channels.consoleChannel.formatter = f1\n"
				"logging.channels.fileChannel.class = FileChannel\n"
				"logging.channels.fileChannel.path = mantid.log\n"
				"logging.channels.fileChannel.formatter.class = PatternFormatter\n"
Nick Draper's avatar
Nick Draper committed
				"logging.channels.fileChannel.formatter.pattern = %Y-%m-%d %H:%M:%S,%i [%I] %p %s - %t\n"
				"logging.formatters.f1.class = PatternFormatter\n"
				"logging.formatters.f1.pattern = %s-[%p] %t\n"
				"logging.formatters.f1.times = UTC\n";
		
			std::istringstream istr(propFile);
			m_pConf = new WrappedObject<Poco::Util::PropertyFileConfiguration>(istr);
		}

		try
		{
			//configure the logging framework
			Poco::Util::LoggingConfigurator configurator;
			//BUG? This line crashes the FrameworkManagerTest and ConfigServiceImplTest
Matt Clarke's avatar
Matt Clarke committed
		catch (std::exception& e)
Matt Clarke's avatar
Matt Clarke committed
			std::cerr << "Trouble configuring the logging framework " << e.what()<<std::endl;
  /** Searches for a string within the currently loaded configuaration values and 
   *  returns the value as a string. If the key is one of those that was a possible relative path
   *  then the local store is searched first.
   *
   *  @param keyName The case sensitive name of the property that you need the value of.
Nick Draper's avatar
Nick Draper committed
   *  @returns The string value of the property, or an empty string if the key cannot be found
  std::string ConfigServiceImpl::getString(const std::string& keyName)
  {
    std::map<std::string, std::string>::const_iterator mitr = m_mAbsolutePaths.find(keyName);
    if( mitr != m_mAbsolutePaths.end() ) 
    {
      return (*mitr).second;
    }
Nick Draper's avatar
Nick Draper committed
    std::string retVal;
    try
    {
      retVal = m_pConf->getString(keyName);
    }
    catch(Poco::NotFoundException& ex)
    {
      g_log.debug()<<"Unable to find " << keyName << " in the properties file" << std::endl;
Nick Draper's avatar
Nick Draper committed
      retVal = "";
    }
		return retVal;
  /** Searches for a string within the currently loaded configuaration values and 
   *  attempts to convert the values to the template type supplied.
   *
   *  @param keyName The case sensitive name of the property that you need the value of.
   *  @param out     The value if found
   *  @returns A success flag - 0 on failure, 1 on success
   */
	int ConfigServiceImpl::getValue(const std::string& keyName, T& out)
	{
		std::string strValue = getString(keyName);
  /** Searches for the string within the environment variables and returns the 
   *  value as a string.
   *
   *  @param keyName The name of the environment variable that you need the value of.
   *  @returns The string value of the property
   */
	std::string ConfigServiceImpl::getEnvironment(const std::string& keyName)	
	{
		return m_pSysConfig->getString("system.env." + keyName);
	}
	
  /** Gets the name of the host operating system
   *
   *  @returns The name pf the OS version
   */
	std::string ConfigServiceImpl::getOSName()
	{
		return m_pSysConfig->getString("system.osName");
	}

  /** Gets the name of the computer running Mantid
   *
   *  @returns The  name of the computer
   */
	std::string ConfigServiceImpl::getOSArchitecture()
	{
		return m_pSysConfig->getString("system.osArchitecture");
	}
	
  /** Gets the name of the operating system Architecture
   *
   * @returns The operating system architecture
   */
	std::string ConfigServiceImpl::getComputerName()
	{
		return m_pSysConfig->getString("system.nodeName");
	}

Nick Draper's avatar
Nick Draper committed
  /** Gets the name of the operating system version
   *
   * @returns The operating system version
   */
	std::string ConfigServiceImpl::getOSVersion()
	{
		return m_pSysConfig->getString("system.osVersion");
	}
	
Nick Draper's avatar
Nick Draper committed
  /** Gets the absolute path of the current directory containing the dll
   *
   * @returns The absolute path of the current directory containing the dll
   */
	std::string ConfigServiceImpl::getCurrentDir()
	{
		return m_pSysConfig->getString("system.currentDir");
	}
Nick Draper's avatar
Nick Draper committed
  /** Gets the absolute path of the temp directory 
   *
   * @returns The absolute path of the temp directory 
   */
	std::string ConfigServiceImpl::getTempDir()
	{
		return m_pSysConfig->getString("system.tempDir");
	}
Nick Draper's avatar
Nick Draper committed

  /**
      * Gets the directory that we consider to be the bse directory. Basically, this is the 
      * executable directory when running normally or the current directory on startup when
      * running through Python on the command line
      * @returns The directory to consider as the base directory, including a trailing slash
      */
  std::string ConfigServiceImpl::getBaseDir()
	{
		return m_strBaseDir;
	}
	
/// \cond TEMPLATE 

	template DLLExport int ConfigServiceImpl::getValue(const std::string&,double&);
	template DLLExport int ConfigServiceImpl::getValue(const std::string&,std::string&);
	template DLLExport int ConfigServiceImpl::getValue(const std::string&,int&);
Matt Clarke's avatar
Matt Clarke committed
/// \endcond TEMPLATE