Skip to content
Snippets Groups Projects
ConfigService.cpp 48.1 KiB
Newer Older
  else if (key == "usersearch.directories")
  else if (key == "defaultsave.directory")
  {
    //Some recursion here! As this call calls the current function
    appendDataSearchDir(m_AbsolutePaths[key]);
  }
Nick Draper's avatar
Nick Draper committed
  {
    m_notificationCenter.postNotification(new ValueChanged(key, value, old));
Nick Draper's avatar
Nick Draper committed
    m_changed_keys.insert(key);
  }
}

/** 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
 */
template<typename T>
int ConfigServiceImpl::getValue(const std::string& keyName, T& out)
{
  std::string strValue = getString(keyName);
  int result = Mantid::Kernel::Strings::convert(strValue, out);
/**
 * Return the full filename of the local properties file.
 * @returns A string containing the full path to the local file.
 */
std::string ConfigServiceImpl::getLocalFilename() const
{
#ifdef _WIN32
#else
  return "/etc/mantid.local.properties";
#endif
}

/**
 * Return the full filename of the user properties file
 * @returns A string containing the full path to the user file
 */
std::string ConfigServiceImpl::getUserFilename() const
{
  return getUserPropertiesDir() + m_user_properties_file_name;
}

/** 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");
}

/** Gets the name of the operating system version
 *
 * @returns The operating system version
 */
std::string ConfigServiceImpl::getOSVersion()
{
  return m_pSysConfig->getString("system.osVersion");
}

/** 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");
}

/** 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");
}

/**
 * Get the directory containing the program executable
 * @returns A string containing the path of the directory 
 * containing the executable, including a trailing slash
 */
std::string ConfigServiceImpl::getDirectoryOfExecutable()
{
  return Poco::Path(getPathToExecutable()).parent().toString();
}

/**
  * Get the full path to the executing program (i.e. whatever Mantid is embedded in) 
  * @returns A string containing the full path the the executable
  */
std::string ConfigServiceImpl::getPathToExecutable()
{
  std::string execpath("");
  const size_t LEN(1024);
  char pBuf[LEN];
  
#ifdef _WIN32
  unsigned int bytes = GetModuleFileName(NULL, pBuf, LEN);
#elif defined __linux__
  char szTmp[32];
  sprintf(szTmp, "/proc/%d/exe", getpid());
  ssize_t bytes = readlink(szTmp, pBuf, LEN);
#elif defined __APPLE__
  // Two calls to _NSGetExecutablePath required - first to get size of buffer
  uint32_t bytes(0);
  _NSGetExecutablePath(pBuf,&bytes);
  const int success = _NSGetExecutablePath(pBuf,&bytes);
  if (success < 0) bytes = 1025;
#endif

  if( bytes > 0 && bytes < 1024 )
  {
    pBuf[bytes] = '\0';
    execpath = std::string(pBuf);
  }
  return execpath;
}

/**
 * Check if the path is on a network drive
 * @param path :: The path to be checked
 * @return True if the path is on a network drive.
 */
bool ConfigServiceImpl::isNetworkDrive(const std::string & path)
{
#ifdef _WIN32
  // if path is relative get the full one
  char buff[MAX_PATH];
  GetFullPathName(path.c_str(),MAX_PATH,buff,NULL);
  std::string fullName(buff);
  size_t i = fullName.find(':');

  // if the full path doesn't contain a drive letter assume it's on the network
  if (i == std::string::npos) return true;

  fullName.erase(i+1);
  fullName += '\\';  // make sure the name has the trailing backslash
  UINT type = GetDriveType(fullName.c_str());
  return DRIVE_REMOTE == type;
#elif defined __linux__
  // This information is only present in the /proc/mounts file on linux. There are no drives on
  // linux only mount locations therefore the test will have to check the path against
  // entries in /proc/mounts to see if the filesystem type is NFS or SMB (any others ????)
  // Each line corresponds to a particular mounted location
  // 1st column - device name
  // 2nd column - mounted location
  // 3rd column - filesystem type commonly ext2, ext3 for hard drives and NFS or SMB for
  //              network locations

  std::ifstream mntfile("/proc/mounts");
  std::string txtread("");
  while( getline(mntfile, txtread) )
  {
    std::istringstream strm(txtread);
    std::string devname(""), mntpoint(""), fstype("");
    strm >> devname >> mntpoint >> fstype;
    if( !strm ) continue;
    // I can't be sure that the file system type is always lower case
    std::transform(fstype.begin(), fstype.end(), fstype.begin(), toupper);
    // Skip the current line if the file system isn't a network one
    if( fstype != "NFS" && fstype != "SMB" ) continue;
    // Now we have a line containing a network filesystem and just need to check if the path
    // supplied contains the mount location. There is a small complication in that the mount
    // points within the file have certain characters transformed into their octal 
    // representations, for example spaces->040.
    std::string::size_type idx = mntpoint.find("\\0");
    if( idx != std::string::npos ) 
    {
      std::string oct = mntpoint.substr(idx + 1, 3);
      strm.str(oct);
      int printch(-1);
      strm.setf( std::ios::oct, std::ios::basefield );  
      strm >> printch;
      if( printch != -1 )
      { 
        mntpoint = mntpoint.substr(0, idx) + static_cast<char>(printch) + mntpoint.substr(idx + 4);
      }
      // Search for this at the start of the path
      if( path.find(mntpoint) == 0 ) return true;
    }     
  }
  return false;
#else
  // Not yet implemented for the mac
  return false;
#endif
}



 * Gets the directory that we consider to be the directory containing the Mantid.properties file. 
 * Basically, this is the either the directory pointed to by MANTIDPATH or the directory of the current
 * executable if this is not set.
 * @returns The directory to consider as the base directory, including a trailing slash
 */
std::string ConfigServiceImpl::getPropertiesDir() const
 * Return the directory that Mantid should use for writing any files it needs so that
 * this is kept separated to user saved files. A trailing slash is appended
 * so that filenames can more easily be concatenated with this
 * @return the directory that Mantid should use for writing files
 */
std::string ConfigServiceImpl::getUserPropertiesDir() const
  return m_strBaseDir;
#else
  Poco::Path datadir(m_pSysConfig->getString("system.homeDir"));
  datadir.append(".mantid");
  // Create the directory if it doesn't already exist
  Poco::File(datadir).createDirectory();
  return datadir.toString() + "/";
#endif
}
/**
 * Return the list of search paths
 * @returns A vector of strings containing the defined search directories
 */
const std::vector<std::string>& ConfigServiceImpl::getDataSearchDirs() const
{
  return m_DataSearchDirs;
}

/**
 * Set a list of search paths via a vector
 * @param searchDirs :: A list of search directories
 */
void ConfigServiceImpl::setDataSearchDirs(const std::vector<std::string> &searchDirs)
{
  std::string searchPaths = boost::join(searchDirs, ";");
  setDataSearchDirs(searchPaths);
}

/**
 * Set a list of search paths via a string
 * @param searchDirs :: A string containing a list of search directories separated by a semi colon (;).
 */
void ConfigServiceImpl::setDataSearchDirs(const std::string &searchDirs)
{
  setString("datasearch.directories", searchDirs);
}

/**
 *  Adds the passed path to the end of the list of data search paths
 *  the path name must be absolute
 *  @param path :: the absolute path to add
 */
void ConfigServiceImpl::appendDataSearchDir(const std::string & path)
{
  {
    std::string newSearchString;
    std::vector<std::string>::const_iterator it = m_DataSearchDirs.begin();
    for (; it != m_DataSearchDirs.end(); ++it)
    {
      newSearchString.append(*it);
      newSearchString.append(";");
    }
    newSearchString.append(path);
    setString("datasearch.directories", newSearchString);
  }
}

/**
 * Return the list of user search paths
 * @returns A vector of strings containing the defined search directories
 */
const std::vector<std::string>& ConfigServiceImpl::getUserSearchDirs() const
{
  return m_UserSearchDirs;
}

/**
 * Return the search directory for XML instrument definition files (IDFs)
 * @returns Full path of instrument search directory
 */
const std::string ConfigServiceImpl::getInstrumentDirectory() const
{
  // Determine the search directory for XML instrument definition files (IDFs)
  std::string directoryName = getString("instrumentDefinition.directory");
  if (directoryName.empty())
    // This is the assumed deployment directory for IDFs, where we need to be relative to the
    // directory of the executable, not the current working directory.
    directoryName = Poco::Path(getPropertiesDir()).resolve("../instrument").toString();
  if (!Poco::File(directoryName).isDirectory())
    g_log.error("Unable to locate instrument search directory at: " + directoryName);
}

/**
 * Load facility information from instrumentDir/Facilities.xml file if fName parameter
 * is not set
 * @param fName :: An alternative file name for loading facilities information.
 */
void ConfigServiceImpl::updateFacilities(const std::string& fName)
{
  m_facilities.clear();
  std::string instrDir = getString("instrumentDefinition.directory");
  std::string fileName = fName.empty() ? instrDir + "Facilities.xml" : fName;

  // Set up the DOM parser and parse xml file
  Poco::XML::DOMParser pParser;
  Poco::XML::Document* pDoc;
    try
    {
      pDoc = pParser.parse(fileName);
    } catch (...)
    {
      throw Kernel::Exception::FileError("Unable to parse file:", fileName);
    }
    // Get pointer to root element
    Poco::XML::Element* pRootElem = pDoc->documentElement();
    if (!pRootElem->hasChildNodes())
    {
      pDoc->release();
      throw std::runtime_error("No root element in Facilities.xml file");
    }
    Poco::XML::NodeList* pNL_facility = pRootElem->getElementsByTagName("facility");
    unsigned long n = pNL_facility->length();
    for (unsigned long i = 0; i < n; ++i)
    {
      Poco::XML::Element* elem = dynamic_cast<Poco::XML::Element*> (pNL_facility->item(i));
      if (elem)
      {
        m_facilities.push_back(new FacilityInfo(elem));
      }
    }

    if (m_facilities.empty())
      pNL_facility->release();
      pDoc->release();
      throw std::runtime_error("The facility definition file " + fileName + " defines no facilities");
/**
 * Returns instruments with given name
 * @param  iName Instrument name
 * @return the instrument information object
 * @throw NotFoundError if iName was not found
 */
const InstrumentInfo & ConfigServiceImpl::getInstrument(const std::string& instrumentName) const
{

  // Let's first search for the instrument in our default facility
  std::string defaultFacility = ConfigService::Instance().getFacility().name();

  if (!defaultFacility.empty())
  {
    try
    {
      g_log.debug() << "Looking for " << instrumentName << " at " << defaultFacility << "." << std::endl;
      return getFacility(defaultFacility).Instrument(instrumentName);
    {
      // Well the instName doesn't exist for this facility
      // Move along, there's nothing to see here...
    }
  }

  // Now let's look through the other facilities
  std::vector<FacilityInfo*>::const_iterator it = m_facilities.begin();
  for (; it != m_facilities.end(); ++it)
  {
    try
    {
      g_log.debug() << "Looking for " << instrumentName << " at " << (**it).name() << "." << std::endl;
      return (**it).Instrument(instrumentName);
    }
    {
      // Well the instName doesn't exist for this facility...
      // Move along, there's nothing to see here...
    }
  }
  g_log.error("Instrument " + instrumentName + " not found");
  throw Exception::NotFoundError("Instrument", instrumentName);
}

/** Get the default facility
 * @return the facility information object
const FacilityInfo& ConfigServiceImpl::getFacility() const
{
  std::string defFacility = getString("default.facility");
  if (defFacility.empty())
  return getFacility(defFacility);
 * @return the facility information object
 * @throw NotFoundException if the facility is not found
const FacilityInfo& ConfigServiceImpl::getFacility(const std::string& facilityName) const
  if (facilityName.empty())
    return this->getFacility();

  std::vector<FacilityInfo*>::const_iterator it = m_facilities.begin();
  for (; it != m_facilities.end(); ++it)
    if ((**it).name() == facilityName)
  g_log.error("Facility " + facilityName + " not found");
  throw Exception::NotFoundError("Facilities", facilityName);
}

/**
 * Set the default facility
 * @param facilityName the facility name
 * @throw NotFoundException if the facility is not found
 */
void ConfigServiceImpl::setFacility(const std::string &facilityName)
{
  bool found = false;
  // Look through the facilities for a matching one.
  std::vector<FacilityInfo*>::const_iterator it = m_facilities.begin();
  for (; it != m_facilities.end(); ++it)
  {
    if ((**it).name() == facilityName)
    {
      // Found the facility
      found = true;
      // So it's safe to set it as our default
      setString("default.facility", facilityName);
    }
  }
  if (found == false)
  {
    g_log.error("Failed to set default facility to be " + facilityName + ". Facility not found");
    throw Exception::NotFoundError("Facilities", facilityName);
  }

}

/**  Add an observer to a notification
 @param observer :: Reference to the observer to add
 */
void ConfigServiceImpl::addObserver(const Poco::AbstractObserver& observer) const
{
  m_notificationCenter.addObserver(observer);
}

/**  Remove an observer
 @param observer :: Reference to the observer to remove
 */
void ConfigServiceImpl::removeObserver(const Poco::AbstractObserver& observer) const
{
  m_notificationCenter.removeObserver(observer);
}

/// \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&);
Peterson, Peter's avatar
Peterson, Peter committed
template DLLExport int ConfigServiceImpl::getValue(const std::string&, std::size_t&);

} // namespace Kernel
} // namespace Mantid