Newer
Older
/**
* Recursively gets a list of all config options.
*
* This function is needed as Boost Python does not like calling function with
* default arguments.
*
* @return Vector containing all config options
*/
std::vector<std::string> ConfigServiceImpl::keys() const {
std::vector<std::string> allKeys;
getKeysRecursive("", allKeys);
return allKeys;
/** Removes a key from the memory stored properties file and inserts the key
*into the
* changed key list so that when the program calls saveConfig the properties
*file will
Robert Whitley
committed
* be the same and not contain the key no more
*
* @param rootName :: The key that is to be deleted
Robert Whitley
committed
*/
void ConfigServiceImpl::remove(const std::string &rootName) const {
m_pConf->remove(rootName);
Robert Whitley
committed
m_changed_keys.insert(rootName);
}
/** Checks to see whether the given key exists.
*
* @param rootName :: The case sensitive key that you are looking to see if
*exists.
Robert Whitley
committed
* @returns Boolean value denoting whether the exists or not.
*/
bool ConfigServiceImpl::hasProperty(const std::string &rootName) const {
return m_pConf->hasProperty(rootName);
Robert Whitley
committed
}
/** Checks to see whether the given file target is an executable one and it
*exists.
* This method will expand environment variables found in the given file path.
Robert Whitley
committed
*
* @param target :: The path to the file you wish to see whether it's an
*executable.
Robert Whitley
committed
* @returns Boolean value denoting whether the file is an executable or not.
*/
bool ConfigServiceImpl::isExecutable(const std::string &target) const {
try {
std::string expTarget = Poco::Path::expand(target);
Poco::File tempFile = Poco::File(expTarget);
Robert Whitley
committed
return tempFile.canExecute();
Robert Whitley
committed
return false;
} catch (Poco::Exception &) {
Robert Whitley
committed
return false;
}
}
/** Runs a command line string to open a program. The function can take program
*arguments.
Robert Whitley
committed
* i.e it can load in a file to the program on startup.
*
* This method will expand environment variables found in the given file path.
*
Robert Whitley
committed
* @param programFilePath :: The directory where the program is located.
* @param programArguments :: The arguments that the program can take on
*startup. For example,
Robert Whitley
committed
* the file to load up.
*/
void ConfigServiceImpl::launchProcess(
const std::string &programFilePath,
const std::vector<std::string> &programArguments) const {
try {
std::string expTarget = Poco::Path::expand(programFilePath);
Poco::Process::launch(expTarget, programArguments);
} catch (Poco::SystemException &e) {
Robert Whitley
committed
throw std::runtime_error(e.what());
}
}
Campbell, Stuart
committed
/**
* Set a configuration property. An existing key will have its value updated.
Janik Zikovsky
committed
* @param key :: The key to refer to this property
* @param value :: The value of the property
Campbell, Stuart
committed
*/
void ConfigServiceImpl::setString(const std::string &key,
const std::string &value) {
// If the value is unchanged (after any path conversions), there's nothing to
// do.
const std::string old = getString(key);
Janik Zikovsky
committed
Campbell, Stuart
committed
std::map<std::string, bool>::const_iterator itr = m_ConfigPaths.find(key);
Campbell, Stuart
committed
m_AbsolutePaths[key] = makeAbsolute(value, key);
if (key == "datasearch.directories") {
Campbell, Stuart
committed
cacheDataSearchPaths();
} else if (key == "usersearch.directories") {
cacheUserSearchPaths();
} else if (key == "instrumentDefinition.directory") {
cacheInstrumentPaths();
} else if (key == "defaultsave.directory") {
Gigg, Martyn Anthony
committed
appendDataSearchDir(value);
}
Campbell, Stuart
committed
m_pConf->setString(key, value);
Janik Zikovsky
committed
m_notificationCenter.postNotification(new ValueChanged(key, value, old));
m_changed_keys.insert(key);
Campbell, Stuart
committed
}
/** 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.
Janik Zikovsky
committed
* @param out :: The value if found
Campbell, Stuart
committed
* @returns A success flag - 0 on failure, 1 on success
*/
template <typename T>
int ConfigServiceImpl::getValue(const std::string &keyName, T &out) {
Campbell, Stuart
committed
std::string strValue = getString(keyName);
Janik Zikovsky
committed
int result = Mantid::Kernel::Strings::convert(strValue, out);
Campbell, Stuart
committed
return result;
}
/**
* 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 {
return "Mantid.local.properties";
#else
return "/etc/mantid.local.properties";
#endif
}
Campbell, Stuart
committed
/**
* Return the full filename of the user properties file
* @returns A string containing the full path to the user file
Campbell, Stuart
committed
*/
std::string ConfigServiceImpl::getUserFilename() const {
Gigg, Martyn Anthony
committed
return getUserPropertiesDir() + m_user_properties_file_name;
Campbell, Stuart
committed
}
/** 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.
Campbell, Stuart
committed
* @returns The string value of the property
*/
std::string ConfigServiceImpl::getEnvironment(const std::string &keyName) {
Campbell, Stuart
committed
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() {
Campbell, Stuart
committed
return m_pSysConfig->getString("system.osName");
}
/** Gets the name of the computer running Mantid
*
* @returns The name of the computer
*/
std::string ConfigServiceImpl::getOSArchitecture() {
Campbell, Stuart
committed
return m_pSysConfig->getString("system.osArchitecture");
}
/** Gets the name of the operating system Architecture
*
* @returns The operating system architecture
*/
std::string ConfigServiceImpl::getComputerName() {
Campbell, Stuart
committed
return m_pSysConfig->getString("system.nodeName");
}
/** Gets the name of the operating system version
*
* @returns The operating system version
*/
std::string ConfigServiceImpl::getOSVersion() {
Campbell, Stuart
committed
return m_pSysConfig->getString("system.osVersion");
}
/// @returns true if the file exists and can be read
bool canRead(const std::string &filename) {
// check for existence of the file
Poco::File pocoFile(filename);
if (!pocoFile.exists()) {
return false;
}
// just return if it is readable
return pocoFile.canRead();
}
/// @returns the value associated with the key.
std::string getValueFromStdOut(const std::string &orig,
const std::string &key) {
size_t start = orig.find(key);
if (start == std::string::npos) {
return std::string();
}
start += key.size();
size_t stop = orig.find('\n', start);
if (stop == std::string::npos) {
return std::string();
}
return Mantid::Kernel::Strings::strip(orig.substr(start, stop - start - 1));
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
/**
* Gets the name of the operating system version in a human readable form.
*
* @returns The operating system desciption
*/
std::string ConfigServiceImpl::getOSVersionReadable() {
std::string description;
// read os-release
static const std::string OS_RELEASE("/etc/os-release");
if (canRead(OS_RELEASE)) {
static const std::string PRETTY_NAME("PRETTY_NAME=");
// open it to see if it has the magic line
std::ifstream handle(OS_RELEASE.c_str(), std::ios::in);
// go through the file
std::string line;
while (std::getline(handle, line)) {
if (line.find(PRETTY_NAME) != std::string::npos) {
if (line.length() > PRETTY_NAME.length() + 1) {
size_t length = line.length() - PRETTY_NAME.length() - 2;
description = line.substr(PRETTY_NAME.length() + 1, length);
}
break;
}
}
// cleanup
handle.close();
if (!description.empty()) {
return description;
}
}
// read redhat-release
static const std::string REDHAT_RELEASE("/etc/redhat-release");
if (canRead(REDHAT_RELEASE)) {
// open it to see if it has the magic line
std::ifstream handle(REDHAT_RELEASE.c_str(), std::ios::in);
// go through the file
std::string line;
while (std::getline(handle, line)) {
if (!line.empty()) {
description = line;
break;
}
}
// cleanup
handle.close();
if (!description.empty()) {
return description;
}
}
// try system calls
std::string cmd;
std::vector<std::string> args;
#ifdef __APPLE__
cmd = "sw_vers"; // mac
#elif _WIN32
args.emplace_back("os"); // windows
args.emplace_back("get"); // windows
args.emplace_back("Caption"); // windows
args.emplace_back("/value"); // windows
#endif
if (!cmd.empty()) {
try {
Poco::Pipe outPipe, errorPipe;
Poco::ProcessHandle ph =
Poco::Process::launch(cmd, args, nullptr, &outPipe, &errorPipe);
const int rc = ph.wait();
// Only if the command returned successfully.
Poco::PipeInputStream pipeStream(outPipe);
std::stringstream stringStream;
Poco::StreamCopier::copyStream(pipeStream, stringStream);
const std::string result = stringStream.str();
#ifdef __APPLE__
const std::string product_name =
getValueFromStdOut(result, "ProductName:");
const std::string product_vers =
getValueFromStdOut(result, "ProductVersion:");
description = product_name + " " + product_vers;
#elif _WIN32
description = getValueFromStdOut(result, "Caption=");
#else
UNUSED_ARG(result); // only used on mac and windows
} else {
std::stringstream messageStream;
messageStream << "command \"" << cmd << "\" failed with code: " << rc;
g_log.debug(messageStream.str());
}
g_log.debug("command \"" + cmd + "\" failed");
g_log.debug(e.what());
}
}
return description;
}
/// @returns The name of the current user as reported by the environment.
std::string ConfigServiceImpl::getUsername() {
std::string username;
// mac and favorite way to get username on linux
try {
username = m_pSysConfig->getString("system.env.USER");
if (!username.empty()) {
return username;
}
} catch (Poco::NotFoundException &e) {
UNUSED_ARG(e); // let it drop on the floor
}
// windoze and alternate linux username variable
try {
username = m_pSysConfig->getString("system.env.USERNAME");
if (!username.empty()) {
return username;
}
} catch (Poco::NotFoundException &e) {
UNUSED_ARG(e); // let it drop on the floor
// give up and return an empty string
return std::string();
}
Campbell, Stuart
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() {
Campbell, Stuart
committed
return m_pSysConfig->getString("system.currentDir");
}
/** Gets the absolute path of the current directory containing the dll. Const
*version.
*
* @returns The absolute path of the current directory containing the dll
*/
std::string ConfigServiceImpl::getCurrentDir() const {
return m_pSysConfig->getString("system.currentDir");
}
Campbell, Stuart
committed
/** Gets the absolute path of the temp directory
*
* @returns The absolute path of the temp directory
*/
std::string ConfigServiceImpl::getTempDir() {
Campbell, Stuart
committed
return m_pSysConfig->getString("system.tempDir");
}
/** Gets the absolute path of the appdata directory
*
* @returns The absolute path of the appdata directory
*/
std::string ConfigServiceImpl::getAppDataDir() {
const std::string applicationName = "mantid";
#if POCO_OS == POCO_OS_WINDOWS_NT
const std::string vendorName = "mantidproject";
std::string appdata = std::getenv("APPDATA");
Poco::Path path(appdata);
path.makeDirectory();
path.pushDirectory(vendorName);
path.pushDirectory(applicationName);
return path.toString();
Poco::Path path(Poco::Path::home());
path.pushDirectory("." + applicationName);
return path.toString();
#endif
}
Gigg, Martyn Anthony
committed
/**
* Get the directory containing the program executable
* @returns A string containing the path of the directory
Gigg, Martyn Anthony
committed
* containing the executable, including a trailing slash
*/
std::string ConfigServiceImpl::getDirectoryOfExecutable() const {
Gigg, Martyn Anthony
committed
return Poco::Path(getPathToExecutable()).parent().toString();
}
/**
* Get the full path to the executing program (i.e. whatever Mantid is embedded
* @returns A string containing the full path the the executable
*/
std::string ConfigServiceImpl::getPathToExecutable() const {
Gigg, Martyn Anthony
committed
const size_t LEN(1024);
// cppcheck-suppress variableScope
Gigg, Martyn Anthony
committed
char pBuf[LEN];
Gigg, Martyn Anthony
committed
#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;
Gigg, Martyn Anthony
committed
#endif
Gigg, Martyn Anthony
committed
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) {
Gigg, Martyn Anthony
committed
#ifdef _WIN32
// if path is relative get the full one
char buff[MAX_PATH];
GetFullPathName(path.c_str(), MAX_PATH, buff, NULL);
Gigg, Martyn Anthony
committed
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;
Gigg, Martyn Anthony
committed
fullName.erase(i + 1);
fullName += '\\'; // make sure the name has the trailing backslash
Gigg, Martyn Anthony
committed
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 ????)
Gigg, Martyn Anthony
committed
// 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
Gigg, Martyn Anthony
committed
// network locations
std::ifstream mntfile("/proc/mounts");
std::string txtread("");
Gigg, Martyn Anthony
committed
std::istringstream strm(txtread);
std::string devname(""), mntpoint(""), fstype("");
strm >> devname >> mntpoint >> fstype;
Gigg, Martyn Anthony
committed
// 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
Gigg, Martyn Anthony
committed
// representations, for example spaces->040.
std::string::size_type idx = mntpoint.find("\\0");
Gigg, Martyn Anthony
committed
std::string oct = mntpoint.substr(idx + 1, 3);
strm.str(oct);
int printch(-1);
strm.setf(std::ios::oct, std::ios::basefield);
Gigg, Martyn Anthony
committed
strm >> printch;
if (printch != -1) {
mntpoint = mntpoint.substr(0, idx) + static_cast<char>(printch) +
mntpoint.substr(idx + 4);
Gigg, Martyn Anthony
committed
}
// Search for this at the start of the path
if (path.find(mntpoint) == 0)
return true;
}
Gigg, Martyn Anthony
committed
}
return false;
#else
Gigg, Martyn Anthony
committed
// Not yet implemented for the mac
return false;
#endif
}
Campbell, Stuart
committed
/**
* 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
Gigg, Martyn Anthony
committed
* executable if this is not set.
* @returns The directory to consider as the base directory, including a
* trailing slash
Campbell, Stuart
committed
*/
std::string ConfigServiceImpl::getPropertiesDir() const { return m_strBaseDir; }
Campbell, Stuart
committed
/**
* Return the directory that Mantid should use for writing any files it needs so
* that
Gigg, Martyn Anthony
committed
* this is kept separated to user saved files. A trailing slash is appended
Campbell, Stuart
committed
* 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 {
Gigg, Martyn Anthony
committed
#ifdef _WIN32
Campbell, Stuart
committed
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
}
Campbell, Stuart
committed
/**
* Return the list of search paths
* @returns A vector of strings containing the defined search directories
*/
const std::vector<std::string> &ConfigServiceImpl::getDataSearchDirs() const {
Campbell, Stuart
committed
return m_DataSearchDirs;
}
Gigg, Martyn Anthony
committed
/**
* 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) {
Gigg, Martyn Anthony
committed
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 (;).
Gigg, Martyn Anthony
committed
*/
void ConfigServiceImpl::setDataSearchDirs(const std::string &searchDirs) {
Gigg, Martyn Anthony
committed
setString("datasearch.directories", searchDirs);
}
/**
* Appends the passed subdirectory path to the end of each of data
* search dirs and adds these new dirs to data search directories
* @param subdir :: the subdirectory path to add (relative)
*/
void ConfigServiceImpl::appendDataSearchSubDir(const std::string &subdir) {
if (subdir.empty())
return;
Poco::Path subDirPath;
try {
subDirPath = Poco::Path(subdir);
} catch (Poco::PathSyntaxException &) {
return;
}
if (!subDirPath.isDirectory() || !subDirPath.isRelative()) {
auto newDataDirs = m_DataSearchDirs;
for (const auto &path : m_DataSearchDirs) {
Poco::Path newDirPath;
try {
newDirPath.append(subDirPath);
newDataDirs.push_back(newDirPath.toString());
} catch (Poco::PathSyntaxException &) {
continue;
}
}
setDataSearchDirs(newDataDirs);
}
Gigg, Martyn Anthony
committed
/**
* 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) {
if (path.empty())
return;
Gigg, Martyn Anthony
committed
Poco::Path dirPath;
Gigg, Martyn Anthony
committed
dirPath = Poco::Path(path);
dirPath.makeDirectory();
} catch (Poco::PathSyntaxException &) {
Gigg, Martyn Anthony
committed
return;
}
if (!isInDataSearchList(dirPath.toString())) {
Gigg, Martyn Anthony
committed
std::string newSearchString;
std::vector<std::string>::const_iterator it = m_DataSearchDirs.begin();
for (; it != m_DataSearchDirs.end(); ++it) {
Gigg, Martyn Anthony
committed
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;
}
* Sets the search directories for XML instrument definition files (IDFs)
* @param directories An ordered list of paths for instrument searching
*/
void ConfigServiceImpl::setInstrumentDirectories(
const std::vector<std::string> &directories) {
m_InstrumentDirs = directories;
}
/**
* Return the search directories for XML instrument definition files (IDFs)
* @returns An ordered list of paths for instrument searching
*/
const std::vector<std::string> &
ConfigServiceImpl::getInstrumentDirectories() const {
return m_InstrumentDirs;
}
/**
* Return the base search directories for XML instrument definition files (IDFs)
* @returns a last entry of getInstrumentDirectories
*/
const std::string ConfigServiceImpl::getInstrumentDirectory() const {
return m_InstrumentDirs.back();
/**
* Return the search directory for vtp files
* @returns a path
*/
const std::string ConfigServiceImpl::getVTPFileDirectory() {
// Determine the search directory for XML instrument definition files (IDFs)
std::string directoryName = getString("instrumentDefinition.vtpDirectory");
if (directoryName.empty()) {
Poco::Path path(getAppDataDir());
path.makeDirectory();
path.pushDirectory("instrument");
path.pushDirectory("geometryCache");
directoryName = path.toString();
}
return directoryName;
}
/**
* Fills the internal cache of instrument definition directories and creates
* The %appdata%/mantidproject/mantid or $home/.mantid directory.
* - The download directory (win %appdata%/mantidproject/mantid/instrument)
* - The user instrument area /etc/mantid/instrument (not on windows)
* - The install directory/instrument
void ConfigServiceImpl::cacheInstrumentPaths() {
m_InstrumentDirs.clear();
const std::string appdatadir = path.toString();
addDirectoryifExists(appdatadir, m_InstrumentDirs);
#ifndef _WIN32
addDirectoryifExists("/etc/mantid/instrument", m_InstrumentDirs);
#endif
// 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();
}
addDirectoryifExists(directoryName, m_InstrumentDirs);
}
/**
* Verifies the directory exists and add it to the back of the directory list if
* valid
* @param directoryName the directory name to add
* @param directoryList the list to add the directory to
* @returns true if the directory was valid and added to the list
*/
bool ConfigServiceImpl::addDirectoryifExists(
const std::string &directoryName, std::vector<std::string> &directoryList) {
try {
if (Poco::File(directoryName).isDirectory()) {
directoryList.push_back(directoryName);
return true;
g_log.information("Unable to locate directory at: " + directoryName);
return false;
}
} catch (Poco::PathNotFoundException &) {
g_log.information("Unable to locate directory at: " + directoryName);
return false;
} catch (Poco::FileNotFoundException &) {
g_log.information("Unable to locate directory at: " + directoryName);
return false;
Campbell, Stuart
committed
}
std::string ConfigServiceImpl::getFacilityFilename(const std::string &fName) {
// first try the supplied file
if (!fName.empty()) {
const Poco::File fileObj(fName);
if (fileObj.exists()) {
return fName;
}
}
// search all of the instrument directories
const std::vector<std::string> directoryNames = getInstrumentDirectories();
// only use downloaded instruments if configured to download
const std::string updateInstrStr =
this->getString("UpdateInstrumentDefinitions.OnStartup");
auto instrDir = directoryNames.begin();
// If we are not updating the instrument definitions
// update the iterator, this means we will skip the folder in HOME and
// look in the instrument folder in mantid install directory or mantid source
// code directory
if (updateInstrStr != "1" || updateInstrStr != "on" ||
updateInstrStr != "On") {
// look through all the possible files
for (; instrDir != directoryNames.end(); ++instrDir) {
std::string filename = (*instrDir) + "Facilities.xml";
Poco::File fileObj(filename);
// stop when you find the first one
if (fileObj.exists())
return filename;
}
// getting this far means the file was not found
std::string directoryNamesList = boost::algorithm::join(directoryNames, ", ");
throw std::runtime_error("Failed to find \"Facilities.xml\". Searched in " +
directoryNamesList);
}
Campbell, Stuart
committed
/**
* Load facility information from instrumentDir/Facilities.xml file if fName
* parameter is not set.
*
* If any of the steps fail, we cannot sensibly recover, because the
* Facilities.xml file is missing or corrupted.
*
Janik Zikovsky
committed
* @param fName :: An alternative file name for loading facilities information.
* @throws std::runtime_error :: If the file is not found or fails to parse
Campbell, Stuart
committed
*/
void ConfigServiceImpl::updateFacilities(const std::string &fName) {
clearFacilities();
// Try to find the file. If it does not exist we will crash, and cannot read
// the Facilities file
std::string fileName = getFacilityFilename(fName);
// Set up the DOM parser and parse xml file
Poco::AutoPtr<Poco::XML::Document> pDoc;
try {
Poco::XML::DOMParser pParser;
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()) {
throw std::runtime_error("No root element in Facilities.xml file");
}
Campbell, Stuart
committed
Poco::AutoPtr<Poco::XML::NodeList> pNL_facility =
pRootElem->getElementsByTagName("facility");
size_t n = pNL_facility->length();
Roman Tolchenov
committed
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));
Janik Zikovsky
committed
if (m_facilities.empty()) {
throw std::runtime_error("The facility definition file " + fileName +
" defines no facilities");
Roman Tolchenov
committed
}
Campbell, Stuart
committed
}
/// Empty the list of facilities, deleting the FacilityInfo objects in the
/// process
void ConfigServiceImpl::clearFacilities() {
for (auto &facility : m_facilities) {
delete facility;
}
m_facilities.clear();
}
/**
* Returns instruments with given name
* @param instrumentName 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 "
return getFacility(defaultFacility).instrument(instrumentName);
} catch (Exception::NotFoundError &) {
// 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
try {
g_log.debug() << "Looking for " << instrumentName << " at "
<< (*facility).name() << ".\n";
return (*facility).instrument(instrumentName);
} catch (Exception::NotFoundError &) {
// Well the instName doesn't exist for this facility...
// Move along, there's nothing to see here...
}
}
const std::string errMsg =
"Failed to find an instrument with this name in any facility: '" +
instrumentName + "' -";
g_log.debug("Instrument " + instrumentName + " not found");
throw Exception::NotFoundError(errMsg, instrumentName);
/** Gets a vector of the facility Information objects
* @return A vector of FacilityInfo objects
*/
const std::vector<FacilityInfo *> ConfigServiceImpl::getFacilities() const {
return m_facilities;
}
/** Gets a vector of the facility names
* @return A vector of the facility Names
*/
const std::vector<std::string> ConfigServiceImpl::getFacilityNames() const {
auto names = std::vector<std::string>(m_facilities.size());
auto itFacilities = m_facilities.begin();
auto itNames = names.begin();
for (; itFacilities != m_facilities.end(); ++itFacilities, ++itNames) {
*itNames = (**itFacilities).name();
}
return names;
}
/** Get the default facility
* @return the facility information object
Campbell, Stuart
committed
*/
const FacilityInfo &ConfigServiceImpl::getFacility() const {
Campbell, Stuart
committed
std::string defFacility = getString("default.facility");
Campbell, Stuart
committed
defFacility = "ISIS";
Roman Tolchenov
committed
}
Michael Whitty
committed
}
Campbell, Stuart
committed
/**
* Get a facility
* @param facilityName :: Facility name
* @return the facility information object
Janik Zikovsky
committed
* @throw NotFoundException if the facility is not found
Campbell, Stuart
committed
*/
const FacilityInfo &
ConfigServiceImpl::getFacility(const std::string &facilityName) const {
if (facilityName.empty())
return this->getFacility();
for (auto facility : m_facilities) {
if ((*facility).name() == facilityName) {
return *facility;
Roman Tolchenov
committed
}
}
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);
}
}
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);
Campbell, Stuart
committed
}
Checks to see whether the pvplugins.directory variable is set. If it is set,
assume