23#include <Poco/AutoPtr.h>
24#include <Poco/Channel.h>
25#include <Poco/DOM/DOMParser.h>
26#include <Poco/DOM/Document.h>
27#include <Poco/DOM/Element.h>
28#include <Poco/DOM/Node.h>
29#include <Poco/DOM/NodeList.h>
30#include <Poco/Environment.h>
31#include <Poco/Exception.h>
32#include <Poco/Instantiator.h>
33#include <Poco/Logger.h>
34#include <Poco/LoggingFactory.h>
35#include <Poco/LoggingRegistry.h>
38#include <Poco/PipeStream.h>
39#include <Poco/Platform.h>
40#include <Poco/Process.h>
41#include <Poco/StreamCopier.h>
42#include <Poco/String.h>
44#include <Poco/Util/LoggingConfigurator.h>
45#include <Poco/Util/PropertyFileConfiguration.h>
46#include <Poco/Util/SystemConfiguration.h>
47#include <Poco/Version.h>
49#include <boost/algorithm/string/join.hpp>
50#include <boost/algorithm/string/trim.hpp>
67#include <mach-o/dyld.h>
68#include <sys/sysctl.h>
87Logger
g_log(
"ConfigService");
89const std::string PATH_DELIMITERS =
";,";
97std::vector<std::string> splitPath(
const std::string &path) {
98 std::vector<std::string> splitted;
100 if (path.find_first_of(PATH_DELIMITERS) == std::string::npos) {
101 splitted.emplace_back(path);
108 splitted.emplace_back(*itr);
115const std::string LOG_LEVEL_KEY(
"logging.loggers.root.level");
125 : m_pConf(nullptr), m_pSysConfig(new
Poco::Util::SystemConfiguration()), m_changed_keys(), m_strBaseDir(
""),
126 m_propertyString(
""), m_properties_file_name(
"Mantid.properties"),
127 m_user_properties_file_name(
"Mantid.user.properties"), m_dataSearchDirs(), m_instrumentDirs(), m_proxyInfo(),
128 m_isProxySet(false) {
130 Poco::LoggingFactory::defaultFactory().registerChannelClass(
131 "StdoutChannel",
new Poco::Instantiator<Poco::StdoutChannel, Poco::Channel>);
154 std::string propertiesFilesList;
164 if (Poco::Environment::has(
"MANTIDPROPERTIES")) {
169 updateConfig(Poco::Environment::get(
"MANTIDPROPERTIES"),
true,
true);
170 propertiesFilesList +=
", " + Poco::Environment::get(
"MANTIDPROPERTIES");
182 << Types::Core::DateAndTime::getCurrentTime().toFormattedString(
"%Y-%m-%dT%H:%MZ") <<
"\n";
183 g_log.
information() <<
"Properties file(s) loaded: " << propertiesFilesList <<
'\n';
187 std::filesystem::path path = std::filesystem::path(appDataDir) /
"instrument";
191 std::filesystem::create_directories(path);
192 }
catch (
const std::filesystem::filesystem_error &fe) {
193 g_log.
error() <<
"Cannot create the local instrument cache directory [" << path.string()
194 <<
"]. Mantid will not be able to update instrument definitions.\n"
195 << fe.what() <<
'\n';
199 std::filesystem::create_directories(vtpDir);
200 }
catch (
const std::filesystem::filesystem_error &fe) {
201 g_log.
error() <<
"Cannot create the local instrument geometry cache directory [" << vtpDir.string()
202 <<
"]. Mantid will be slower at viewing complex instruments.\n"
203 << fe.what() <<
'\n';
239 std::filesystem::path filepath;
242 m_strBaseDir = std::filesystem::current_path().string() +
"/";
244 if (std::filesystem::exists(filepath))
251 if (std::filesystem::exists(filepath))
255 if (Poco::Environment::has(
"MANTIDPATH")) {
263 m_strBaseDir = Poco::Environment::get(
"MANTIDPATH") +
"\\";
265 m_strBaseDir = Poco::Environment::get(
"MANTIDPATH") +
"/";
268 if (std::filesystem::exists(filepath))
276 m_strBaseDir = execPath.parent_path().parent_path().parent_path().string() +
"/";
282std::string checkForBadConfigOptions(
const std::string &filename,
const std::string &propertiesString) {
283 std::stringstream stream(propertiesString);
284 std::stringstream resultPropertiesString;
287 while (std::getline(stream, line)) {
296 }
else if (line.find(
"FilterChannel") != std::string::npos) {
302 const auto end = line.find(
"=");
304 if (end != std::string::npos) {
309 g_log.
warning() <<
"\" in " << filename <<
" on line " << line_num << std::endl;
312 resultPropertiesString <<
'#';
315 resultPropertiesString << line <<
'\n';
317 return resultPropertiesString.str();
341 bool good =
readFile(filename, temp);
344 if ((!good) || (temp.empty())) {
354 temp = checkForBadConfigOptions(filename, temp);
362 }
catch (std::exception &e) {
364 g_log.
error() <<
"Problem loading the configuration file " << filename <<
" " << e.what() <<
'\n';
365 g_log.
error() <<
"Mantid is unable to start.\n" << std::endl;
371 m_pConf =
new Poco::Util::PropertyFileConfiguration(istr);
381 std::ifstream propFile(filename.c_str(), std::ios::in);
382 bool good = propFile.good();
392 getline(propFile, contents,
'`');
403 Poco::Util::LoggingConfigurator configurator;
404#if POCO_VERSION > 0x01090400
405 configurator.configure(
m_pConf);
407 configurator.configure(
m_pConf.get());
409 }
catch (std::exception &e) {
410 std::cerr <<
"Trouble configuring the logging framework " << e.what() <<
'\n';
426 std::string converted;
428 if (dir.find_first_of(PATH_DELIMITERS) != std::string::npos) {
429 auto splitted = splitPath(dir);
430 auto iend = splitted.cend();
431 for (
auto itr = splitted.begin(); itr != iend;) {
433 if (absolute.empty()) {
436 converted += absolute;
454 bool is_relative(
false);
456 std::filesystem::path testPath(dir);
457 is_relative = testPath.is_relative();
463 if (is_relative && !dir.empty() && (dir[0] ==
'/' || dir[0] ==
'\\')) {
467 }
catch (
const std::exception &) {
468 g_log.
warning() <<
"Malformed path detected in the \"" << key <<
"\" variable, skipping \"" << dir <<
"\"\n";
473 std::filesystem::path basePath(propFileDir);
474 std::filesystem::path fullPath = basePath / dir;
475 converted = fullPath.string();
479 std::filesystem::path convertedPath(converted);
480 if (!convertedPath.extension().empty()) {
481 converted = convertedPath.string();
484 converted = convertedPath.string();
485 if (converted.back() !=
'/' && converted.back() !=
'\\') {
492 boost::replace_all(converted,
"\\",
"/");
502 std::string paths =
getString(
"datasearch.directories",
true);
519 std::string correctedPath = path;
520 replace(correctedPath.begin(), correctedPath.end(),
'\\',
'/');
522 using std::placeholders::_1;
524 std::bind(std::equal_to<std::string>(), _1, correctedPath));
536 filestr <<
"# This file can be used to override any properties for this "
538 filestr <<
"# Any properties found in this file will override any that are "
539 "found in the Mantid.Properties file\n";
540 filestr <<
"# As this file will not be replaced with further installations "
541 "of Mantid it is a safe place to put \n";
542 filestr <<
"# properties that suit your particular installation.\n";
544 filestr <<
"# See here for a list of possible options:\n";
546 "http://docs.mantidproject.org/nightly/concepts/PropertiesFile.html"
549 filestr <<
"## GENERAL\n";
551 filestr <<
"## Set the maximum number of cores used to run algorithms over\n";
552 filestr <<
"#MultiThreaded.MaxCores=4\n\n";
554 filestr <<
"## FACILITY AND INSTRUMENT\n";
556 filestr <<
"## Sets the default facility\n";
557 filestr <<
"## e.g.: ISIS, SNS, ILL\n";
558 filestr <<
"default.facility=\n\n";
559 filestr <<
"## Sets the default instrument\n";
560 filestr <<
"## e.g. IRIS, HET, NIMROD\n";
561 filestr <<
"default.instrument=\n\n";
563 filestr <<
"## Sets the Q.convention\n";
564 filestr <<
"## Set to Crystallography for kf-ki instead of default "
565 "Inelastic which is ki-kf\n";
566 filestr <<
"#Q.convention=Crystallography\n";
568 filestr <<
"## DIRECTORIES\n";
570 filestr <<
"## Sets a list of directories (separated by semi colons) to "
572 filestr <<
"#datasearch.directories=../data;../isis/data\n\n";
573 filestr <<
"## Set a list (separated by semi colons) of directories to "
574 "look for additional Python scripts\n";
575 filestr <<
"#pythonscripts.directories=../scripts;../docs/MyScripts\n\n";
576 filestr <<
"## Uncomment to enable archive search - ICat and Orbiter\n";
577 filestr <<
"#datasearch.searcharchive=On\n\n";
578 filestr <<
"## Sets default save directory\n";
579 filestr <<
"#defaultsave.directory=../data\n\n";
581 filestr <<
"## LOGGING\n";
583 filestr <<
"## Uncomment to change logging level\n";
584 filestr <<
"## Default is information\n";
585 filestr <<
"## Valid values are: error, warning, notice, information, debug\n";
586 filestr <<
"#logging.loggers.root.level=information\n\n";
588 filestr <<
"## MantidWorkbench\n";
590 filestr <<
"## Hides categories from the algorithm list in MantidWorkbench\n";
591 filestr <<
"#algorithms.catagories.hidden=Muons,Inelastic\n\n";
592 filestr <<
"## Show invisible workspaces\n";
593 filestr <<
"#MantidOptions.InvisibleWorkspaces=0\n";
594 filestr <<
"## Re-use plot instances for different plot types\n";
595 filestr <<
"#MantidOptions.ReusePlotInstances=Off\n\n";
596 filestr <<
"## Uncomment to disable use of OpenGL to render unwrapped "
597 "instrument views\n";
598 filestr <<
"#MantidOptions.InstrumentView.UseOpenGL=Off\n\n";
599 filestr <<
"## Muon GUI settings\n";
600 filestr <<
"#muon.GUI = \n";
603 }
catch (std::runtime_error &ex) {
620 }
catch (
const std::exception &) {
625 const bool append =
false;
626 const bool updateCaches =
true;
660 std::string updated_file;
662 std::ifstream reader(filename.c_str(), std::ios::in);
664 throw std::runtime_error(
"Error opening user properties file. Cannot save "
665 "updated configuration.");
668 std::string file_line, output;
669 bool line_continuing(
false);
670 while (std::getline(reader, file_line)) {
671 if (!file_line.empty()) {
672 char last = *(file_line.end() - 1);
676 if (!line_continuing)
678 line_continuing =
true;
679 output += file_line +
"\n";
681 }
else if (line_continuing) {
683 line_continuing =
false;
689 updated_file +=
"\n";
697 std::string::size_type pos = output.find(
'=');
698 if (pos == std::string::npos) {
701 key = output.substr(0, pos);
704 Poco::trimInPlace(key);
707 std::string::size_type comment = key.find(
'#');
712 updated_file += output;
720 Poco::replaceInPlace(
value,
"\\",
"\\\\");
721 updated_file.append(key).append(
"=").append(
value);
725 updated_file +=
"\n";
731 updated_file +=
"\n";
733 for (
auto key_itr =
m_changed_keys.begin(); key_itr != key_end;) {
739 updated_file += *key_itr +
"=";
741 Poco::replaceInPlace(
value,
"\\",
"\\\\");
742 updated_file +=
value;
743 if (++key_itr != key_end) {
744 updated_file +=
"\n";
751 std::ofstream writer(filename.c_str(), std::ios_base::trunc);
754 g_log.
error() <<
"Error writing new user properties file. Cannot save "
755 "current configuration.\n";
756 throw std::runtime_error(
"Error writing new user properties file. Cannot "
757 "save current configuration.");
760 writer.write(updated_file.c_str(), updated_file.size());
777 if (
m_pConf->hasProperty(keyName)) {
786 g_log.
debug() <<
"Unable to find " << keyName <<
" in the properties file" <<
'\n';
800 std::vector<std::string> rawKeys;
801 m_pConf->keys(keyName, rawKeys);
809 std::vector<std::string> rootKeys =
getKeys(root);
811 if (rootKeys.empty())
812 allKeys.emplace_back(root);
814 for (
auto &rootKey : rootKeys) {
815 std::string searchString;
817 searchString.append(rootKey);
819 searchString.append(root).append(
".").append(rootKey);
835 std::vector<std::string> allKeys;
862std::string expandEnvironmentInFilepath(
const std::string &target) {
return Poco::Path::expand(target); }
875 std::filesystem::path filepath(expandEnvironmentInFilepath(target));
877 if (std::filesystem::exists(filepath) && std::filesystem::is_regular_file(filepath)) {
883 std::string ext = filepath.extension().string();
884 std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
885 return (ext ==
".exe" || ext ==
".bat" || ext ==
".cmd" || ext ==
".com");
888 auto perms = std::filesystem::status(filepath).permissions();
889 return (perms & std::filesystem::perms::owner_exec) != std::filesystem::perms::none ||
890 (perms & std::filesystem::perms::group_exec) != std::filesystem::perms::none ||
891 (perms & std::filesystem::perms::others_exec) != std::filesystem::perms::none;
895 }
catch (
const std::exception &) {
913 const std::vector<std::string> &programArguments)
const {
915 std::string expTarget = expandEnvironmentInFilepath(programFilePath);
916 Poco::Process::launch(expTarget, programArguments);
917 }
catch (Poco::SystemException &e) {
918 throw std::runtime_error(e.what());
938 if (key ==
"datasearch.directories") {
940 }
else if (key ==
"instrumentDefinition.directory") {
942 }
else if (key ==
"defaultsave.directory") {
944 }
else if (key ==
"logging.channels.consoleChannel.class") {
947 }
else if (key == LOG_LEVEL_KEY) {
963 std::string strValue =
getString(keyName);
971 return std::optional<T>(output);
982 auto returnedValue = getValue<std::string>(keyName);
983 if (!returnedValue.has_value()) {
987 auto &configVal = returnedValue.value();
989 std::transform(configVal.begin(), configVal.end(), configVal.begin(), ::tolower);
991 boost::trim(configVal);
993 bool trueString = configVal ==
"true";
994 bool valueOne = configVal ==
"1";
995 bool onOffString = configVal ==
"on";
998 return trueString || valueOne || onOffString;
1007 return "Mantid.local.properties";
1009 return "/etc/mantid.local.properties";
1027 return m_pSysConfig->getString(
"system.env." + keyName);
1041 auto osArch =
m_pSysConfig->getString(
"system.osArchitecture");
1043 if (osArch ==
"x86_64") {
1047 size_t size =
sizeof(ret);
1048 if (sysctlbyname(
"sysctl.proc_translated", &ret, &size,
nullptr, 0) != -1 && ret == 1) {
1049 osArch =
"arm64_(x86_64)";
1050 g_log.
warning(
"You are running an Intel build of Mantid on Apple silicon, which will be significantly slower and "
1051 "use more power. For best performance, install the Arm version of Mantid. This version is "
1052 "available here: https://downloads.mantidproject.org");
1055 g_log.
warning(
"Mantid v6.14 is the last version that will support Intel macOS.");
1077 if (!std::filesystem::exists(filename)) {
1082 std::ifstream file(filename);
1088 size_t start = orig.find(key);
1089 if (start == std::string::npos) {
1090 return std::string();
1092 start += key.size();
1094 size_t stop = orig.find(
'\n', start);
1095 if (stop == std::string::npos) {
1096 return std::string();
1108 std::string description;
1111 static const std::string OS_RELEASE(
"/etc/os-release");
1113 static const std::string PRETTY_NAME(
"PRETTY_NAME=");
1116 std::ifstream handle(OS_RELEASE.c_str(), std::ios::in);
1120 while (std::getline(handle, line)) {
1121 if (line.find(PRETTY_NAME) != std::string::npos) {
1122 if (line.length() > PRETTY_NAME.length() + 1) {
1123 size_t length = line.length() - PRETTY_NAME.length() - 2;
1124 description = line.substr(PRETTY_NAME.length() + 1, length);
1132 if (!description.empty()) {
1138 static const std::string REDHAT_RELEASE(
"/etc/redhat-release");
1139 if (
canRead(REDHAT_RELEASE)) {
1141 std::ifstream handle(REDHAT_RELEASE.c_str(), std::ios::in);
1145 while (std::getline(handle, line)) {
1146 if (!line.empty()) {
1147 description = std::move(line);
1154 if (!description.empty()) {
1161 std::vector<std::string> args;
1166 args.emplace_back(
"os");
1167 args.emplace_back(
"get");
1168 args.emplace_back(
"Caption");
1169 args.emplace_back(
"/value");
1172#if defined __APPLE__ || defined _WIN32
1174 Poco::Pipe outPipe, errorPipe;
1175 Poco::ProcessHandle ph = Poco::Process::launch(cmd, args,
nullptr, &outPipe, &errorPipe);
1176 const int rc = ph.wait();
1179 Poco::PipeInputStream pipeStream(outPipe);
1180 std::stringstream stringStream;
1181 Poco::StreamCopier::copyStream(pipeStream, stringStream);
1182 const std::string result = stringStream.str();
1187 description = product_name +
" " + product_vers;
1194 std::stringstream messageStream;
1195 messageStream <<
"command \"" << cmd <<
"\" failed with code: " << rc;
1198 }
catch (Poco::SystemException &e) {
1199 g_log.
debug(
"command \"" + cmd +
"\" failed");
1208 std::string username;
1213 if (!username.empty()) {
1216 }
catch (
const Poco::NotFoundException &e) {
1222 username =
m_pSysConfig->getString(
"system.env.USERNAME");
1223 if (!username.empty()) {
1226 }
catch (
const Poco::NotFoundException &e) {
1231 return std::string();
1258 const std::string applicationName =
"mantid";
1259#if POCO_OS == POCO_OS_WINDOWS_NT
1260 const std::string vendorName =
"mantidproject";
1261 wchar_t *w_appdata = _wgetenv(L
"APPDATA");
1262 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
1263 std::string appdata = converter.to_bytes(w_appdata);
1264 std::filesystem::path path(appdata);
1266 path /= applicationName;
1267 return path.string();
1269 const char *home = std::getenv(
"HOME");
1271 throw std::runtime_error(
"HOME environment variable not set - seen in ConfigService.getAppDataDir()");
1273 std::filesystem::path path(home);
1274 path /= (
"." + applicationName);
1275 return path.string();
1286 return execPath.parent_path().string() +
"/";
1295 std::string execpath;
1296 const size_t LEN(1024);
1300 unsigned int bytes = GetModuleFileName(NULL, pBuf, LEN);
1301#elif defined __linux__
1303 sprintf(szTmp,
"/proc/%d/exe", getpid());
1304 ssize_t bytes = readlink(szTmp, pBuf, LEN);
1305#elif defined __APPLE__
1308 _NSGetExecutablePath(pBuf, &bytes);
1309 const int success = _NSGetExecutablePath(pBuf, &bytes);
1314 if (bytes > 0 && bytes < 1024) {
1316 execpath = std::string(pBuf);
1329 char buff[MAX_PATH];
1330 GetFullPathName(path.c_str(), MAX_PATH, buff, NULL);
1331 std::string fullName(buff);
1332 size_t i = fullName.find(
':');
1335 if (i == std::string::npos)
1338 fullName.erase(i + 1);
1340 UINT type = GetDriveType(fullName.c_str());
1341 return DRIVE_REMOTE == type;
1342#elif defined __linux__
1356 std::ifstream mntfile(
"/proc/mounts");
1357 std::string txtread(
"");
1358 while (getline(mntfile, txtread)) {
1359 std::istringstream strm(txtread);
1360 std::string devname(
""), mntpoint(
""), fstype(
"");
1361 strm >> devname >> mntpoint >> fstype;
1365 std::transform(fstype.begin(), fstype.end(), fstype.begin(), toupper);
1367 if (fstype !=
"NFS" && fstype !=
"SMB")
1376 std::string::size_type idx = mntpoint.find(
"\\0");
1377 if (idx != std::string::npos) {
1378 std::string oct = mntpoint.substr(idx + 1, 3);
1381 strm.setf(std::ios::oct, std::ios::basefield);
1383 if (printch != -1) {
1384 mntpoint = mntpoint.substr(0, idx) +
static_cast<char>(printch) + mntpoint.substr(idx + 4);
1387 if (path.find(mntpoint) == 0)
1420 std::filesystem::path datadir(
m_pSysConfig->getString(
"system.homeDir"));
1421 datadir /=
".mantid";
1423 std::filesystem::create_directory(datadir);
1424 return datadir.string() +
"/";
1439 std::string searchPaths = boost::join(searchDirs,
";");
1449 setString(
"datasearch.directories", searchDirs);
1461 std::filesystem::path subDirPath;
1463 subDirPath = std::filesystem::path(subdir);
1464 }
catch (
const std::exception &) {
1469 if (!subDirPath.is_relative()) {
1475 std::filesystem::path newDirPath;
1477 newDirPath = std::filesystem::path(path) / subDirPath;
1479 if (std::find(newDataDirs.begin(), newDataDirs.end(), newDirPath.string()) == newDataDirs.end())
1480 newDataDirs.emplace_back(newDirPath.string());
1481 }
catch (
const std::exception &) {
1498 std::filesystem::path dirPath;
1500 dirPath = std::filesystem::path(path);
1502 std::string pathStr = dirPath.string();
1503 if (pathStr.back() !=
'/' && pathStr.back() !=
'\\') {
1508 newSearchString.append(
";" + path);
1509 setString(
"datasearch.directories", newSearchString);
1511 }
catch (
const std::exception &) {
1541 std::string directoryName =
getString(
"instrumentDefinition.vtp.directory");
1543 if (directoryName.empty()) {
1545 path /=
"instrument";
1546 path /=
"geometryCache";
1547 directoryName = path.string();
1549 return directoryName;
1565 path /=
"instrument";
1566 const std::string appdatadir = path.string();
1574 std::string directoryName =
getString(
"instrumentDefinition.directory",
true);
1575 if (directoryName.empty()) {
1580 directoryName = (basePath /
".." /
"instrument").lexically_normal().string();
1593 std::vector<std::string> &directoryList) {
1595 if (std::filesystem::is_directory(directoryName)) {
1596 directoryList.emplace_back(directoryName);
1602 }
catch (
const std::filesystem::filesystem_error &) {
1605 }
catch (
const std::exception &) {
1612 std::vector<std::string> returnPaths;
1615 if (!fName.empty()) {
1616 if (std::filesystem::exists(fName)) {
1617 returnPaths.emplace_back(fName);
1626 const std::string updateInstrStr = this->
getString(
"UpdateInstrumentDefinitions.OnStartup");
1628 auto instrDir = directoryNames.begin();
1634 if (!(updateInstrStr ==
"1" || updateInstrStr ==
"on" || updateInstrStr ==
"On") && directoryNames.size() > 1) {
1639 for (; instrDir != directoryNames.end(); ++instrDir) {
1640 std::filesystem::path p(*instrDir);
1641 p /=
"Facilities.xml";
1642 std::string filename = p.string();
1644 if (std::filesystem::exists(filename))
1645 returnPaths.emplace_back(filename);
1648 if (returnPaths.size() > 0) {
1653 std::string directoryNamesList = boost::algorithm::join(directoryNames,
", ");
1654 throw std::runtime_error(
"Failed to find \"Facilities.xml\". Searched in " + directoryNamesList);
1673 size_t attemptIndex = 0;
1674 bool success =
false;
1675 while ((!success) && (attemptIndex < fileNames.size())) {
1676 const auto &fileName = fileNames[attemptIndex];
1679 Poco::AutoPtr<Poco::XML::Document> pDoc;
1681 Poco::XML::DOMParser pParser;
1682 pDoc = pParser.parse(fileName);
1688 Poco::XML::Element *pRootElem = pDoc->documentElement();
1689 if (!pRootElem->hasChildNodes()) {
1690 throw std::runtime_error(
"No root element in Facilities.xml file");
1693 const Poco::AutoPtr<Poco::XML::NodeList> pNL_facility = pRootElem->getElementsByTagName(
"facility");
1694 const size_t n = pNL_facility->length();
1696 for (
unsigned long i = 0; i <
n; ++i) {
1697 const auto *elem =
dynamic_cast<Poco::XML::Element *
>(pNL_facility->item(i));
1704 throw std::runtime_error(
"The facility definition file " + fileName +
" defines no facilities");
1709 }
catch (std::runtime_error &ex) {
1711 g_log.
error() <<
"Failed to load the facilities.xml file at " << fileName <<
"\nIt might be corrupt. "
1712 << ex.what() <<
"\nWill try to load another version.\n";
1715 if (attemptIndex == fileNames.size()) {
1716 const std::string errorMessage =
"No more Facilities.xml files can be found, Mantid will not be "
1717 "able to start, Sorry. Try reinstalling Mantid.";
1723 throw std::runtime_error(errorMessage);
1749 if (!defaultFacility.empty()) {
1751 g_log.
debug() <<
"Looking for " << instrumentName <<
" at " << defaultFacility <<
".\n";
1762 g_log.
debug() <<
"Looking for " << instrumentName <<
" at " << (*facility).name() <<
".\n";
1763 return (*facility).instrument(instrumentName);
1770 const std::string errMsg =
"Failed to find an instrument with this name in any facility: '" + instrumentName +
"' -";
1771 g_log.
debug(
"Instrument " + instrumentName +
" not found");
1784 auto names = std::vector<std::string>(
m_facilities.size());
1786 [](
const FacilityInfo *facility) { return facility->name(); });
1795 std::string defFacility =
getString(
"default.facility");
1796 if (defFacility.empty()) {
1809 if (facilityName.empty())
1813 [&facilityName](
const auto f) { return f->name() == facilityName; });
1835 g_log.
error(
"Failed to set default facility to be " + facilityName +
". Facility not found");
1838 assert(foundFacility);
1839 setString(
"default.facility", facilityName);
1841 const auto &associatedInsts = foundFacility->
instruments();
1842 if (associatedInsts.empty()) {
1843 throw std::invalid_argument(
"The selected facility has no instruments associated with it");
1873 auto proxyHost = getValue<std::string>(
"proxy.host");
1874 auto proxyPort = getValue<int>(
"proxy.port");
1876 if (proxyHost.has_value() && proxyPort.has_value()) {
1891 const int options)
const {
1893 g_log.
debug() <<
"getFullPath(" << fName <<
")\n";
1895 std::filesystem::path filepath(fName);
1896 if (filepath.is_absolute())
1901 std::filesystem::path fullPath = std::filesystem::current_path() / fName;
1902 if (std::filesystem::exists(fullPath) && (!ignoreDirs || !std::filesystem::is_directory(fullPath)))
1903 return fullPath.string();
1904 }
catch (
const std::exception &) {
1909 directoryNames.insert(directoryNames.end(), instrDirectories.begin(), instrDirectories.end());
1910 for (
const auto &searchPath : directoryNames) {
1911 g_log.
debug() <<
"Searching for " << fName <<
" in " << searchPath <<
"\n";
1917 if (fName.find(
"*") != std::string::npos) {
1919 std::filesystem::path path = std::filesystem::path(searchPath) / fName;
1920 std::set<std::string> files;
1922 if (!files.empty()) {
1923 std::filesystem::path matchPath(*files.begin());
1924 if (ignoreDirs && std::filesystem::is_directory(matchPath)) {
1927 return *files.begin();
1931 std::filesystem::path path = std::filesystem::path(searchPath) / fName;
1932 if (std::filesystem::exists(path) && !(ignoreDirs && std::filesystem::is_directory(path))) {
1933 return path.string();
double value
The value of the point.
#define DLLExport
Definitions of the DLLImport compiler directives for MSVC.
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
This is the class for the notification that is to be sent when a value has been changed in config ser...
const std::vector< std::string > & getInstrumentDirectories() const
Get instrument search directories.
std::string m_propertyString
The configuration properties in string format.
void setBaseDirectory()
Setup the base directory.
const std::string getVTPFileDirectory()
get the vtp file directory
const std::string m_properties_file_name
The filename of the Mantid properties file.
std::set< std::string > m_configPaths
List of config paths that may be relative.
void setInstrumentDirectories(const std::vector< std::string > &directories)
Sets instrument directories.
ConfigServiceImpl()
Private constructor for singleton class.
const FacilityInfo & getFacility() const
Get the default facility.
std::string getDirectoryOfExecutable() const
Get the directory containing the program executable.
bool addDirectoryifExists(const std::string &directoryName, std::vector< std::string > &directoryList)
Verifies the directory exists and add it to the back of the directory list if valid.
void cacheInstrumentPaths()
Create the storage of the instrument directories.
void reset()
Reset to "factory" settings. Removes current user properties.
std::string getLocalFilename() const
Return the local properties filename.
std::string getAppDataDir()
Returns the system's appdata directory.
std::string getPropertiesDir() const
Returns the directory where the Mantid.properties file is found.
std::string getOSVersion()
Returns the OS version.
std::string getOSVersionReadable()
Returns a human readable version of the OS version.
virtual ~ConfigServiceImpl()
Private Destructor Prevents client from calling 'delete' on the pointer handed out by Instance.
std::string getFullPath(const std::string &filename, const bool ignoreDirs, const int options) const
std::string getPathToExecutable() const
Get the full path to the executing program (i.e.
void loadConfig(const std::string &filename, const bool append=false)
Loads a config file.
void configureLogging()
Configures the Poco logging and starts it up.
std::string getUserPropertiesDir() const
Returns a directory to use to write out Mantid information.
bool isExecutable(const std::string &target) const
Checks to see whether the target passed is an executable file.
void saveConfig(const std::string &filename) const
Save the configuration to the user file.
std::string getLogLevel()
const std::vector< std::string > & getDataSearchDirs() const
Get the list of search paths.
bool isInDataSearchList(const std::string &path) const
Returns true if the path is in the data search list.
const std::vector< std::string > getFacilityFilenames(const std::string &fName)
Determine the name of the facilities file to use.
void removeObserver(const Poco::AbstractObserver &observer) const
Remove an observer.
std::string m_strBaseDir
The directory that is considered to be the base directory.
Kernel::ProxyInfo & getProxy(const std::string &url)
Gets the proxy for the system.
std::string makeAbsolute(const std::string &dir, const std::string &key) const
Make a relative path or a list of relative paths into an absolute one.
const InstrumentInfo & getInstrument(const std::string &instrumentName="") const
Look for an instrument.
std::set< std::string > m_changed_keys
A set of property keys that have been changed.
void updateConfig(const std::string &filename, const bool append=false, const bool update_caches=true)
Wipe out the current configuration and load a new one.
void createUserPropertiesFile() const
Writes out a fresh user properties file.
std::vector< std::string > m_dataSearchDirs
Store a list of data search paths.
void updateFacilities(const std::string &fName="")
Load facility information from instrumentDir/Facilities.xml file.
const std::vector< FacilityInfo * > getFacilities() const
Get the list of facilities.
std::string getEnvironment(const std::string &keyName)
Searches for the given environment variable and returns it as a string.
void appendDataSearchDir(const std::string &path)
Adds the passed path to the end of the list of data search paths.
std::string getCurrentDir()
Returns the current directory.
void getKeysRecursive(const std::string &root, std::vector< std::string > &allKeys) const
Returns a list of all keys under a given root key.
void setLogLevel(int logLevel, bool quiet=false)
Sets the log level priority for all log channels.
std::optional< T > getValue(const std::string &keyName)
Searches for a string within the currently loaded configuration values and attempts to convert the va...
void setDataSearchDirs(const std::vector< std::string > &searchDirs)
Set a list of search paths via a vector.
std::string getString(const std::string &keyName, bool pathAbsolute=true) const
Searches for a configuration property.
const std::string getInstrumentDirectory() const
Get instrument search directory.
void addObserver(const Poco::AbstractObserver &observer) const
Add an observer for a notification.
std::string getUsername()
Returns the username.
std::string getOSName()
Returns the OS name.
void setString(const std::string &key, const std::string &value)
Sets a configuration property.
void clearFacilities()
Empty the list of facilities, deleting the FacilityInfo objects in the process.
std::string getComputerName()
Returns the computer name.
std::string getOSArchitecture()
Returns the architecture.
std::string getUserFilename() const
Return the user properties filename.
Poco::AutoPtr< Poco::Util::SystemConfiguration > m_pSysConfig
the POCO system Config Object
bool m_isProxySet
whether the proxy has been populated yet
bool isNetworkDrive(const std::string &path)
Check if the path is on a network drive.
bool readFile(const std::string &filename, std::string &contents) const
Read a file and place its contents into the given string.
Poco::NotificationCenter m_notificationCenter
Handles distribution of Poco signals.
Kernel::ProxyInfo m_proxyInfo
local cache of proxy details
void setFacility(const std::string &facilityName)
Set the default facility.
void remove(const std::string &rootName)
Removes the value from a selected keyName.
void cacheDataSearchPaths()
Create the storage of the data search directories.
std::string getTempDir()
Returns the system's temp directory.
const std::string m_user_properties_file_name
The filename of the Mantid user properties file.
void appendDataSearchSubDir(const std::string &subdir)
Appends subdirectory to each of the specified data search directories.
std::vector< std::string > keys() const
Returns a list of all full keys in the config.
Poco::AutoPtr< Poco::Util::PropertyFileConfiguration > m_pConf
the POCO file config object
const std::vector< std::string > getFacilityNames() const
Get the list of facility names.
std::vector< FacilityInfo * > m_facilities
The list of available facilities.
void launchProcess(const std::string &programFilePath, const std::vector< std::string > &programArguments) const
Launches a process i.e opening a program.
std::vector< std::string > getKeys(const std::string &keyName) const
Searches for a key in the configuration property.
std::vector< std::string > m_instrumentDirs
Store a list of instrument directory paths.
bool hasProperty(const std::string &rootName) const
Checks to see whether a key has a value assigned to it.
Records the filename and the description of failure.
Exception for when an item is not found in a collection.
A class that holds information about a facility.
const std::vector< InstrumentInfo > & instruments() const
Returns a list of instruments of this facility.
const std::string & name() const
Return the name of the facility.
const InstrumentInfo & instrument(std::string iName="") const
Returns instruments with given name.
static void glob(const std::string &pathPattern, std::set< std::string > &files, int options=0)
Creates a set of files that match the given pathPattern.
A class that holds information about an instrument.
void debug(const std::string &msg)
Logs at debug level.
static void setLevelForAll(const int level)
Sets the log level for all Loggers created so far, including the root logger.
static void shutdown()
Shuts down the logging framework and releases all Loggers.
void error(const std::string &msg)
Logs at error level.
std::string getLevelName() const
void warning(const std::string &msg)
Logs at warning level.
Poco::Message::Priority Priority
void log(const std::string &message, const Priority &priority)
Log a message at a given priority.
int getLevel() const
Returns the Logger's log level.
void information(const std::string &msg)
Logs at information level.
static const std::array< std::string, 9 > PriorityNames
static const char * version()
The full version number.
static std::string doi()
The DOI for this release of Mantid.
static std::string paperCitation()
The citation for the Mantid paper.
static const char * revision()
The abbreviated SHA-1 of the last commit.
NetworkProxy : Network proxy utility for getting network proxy information.
ProxyInfo getHttpProxy(const std::string &targetURLString)
Get http proxy information.
ProxyInfo : Container for carrying around network proxy information.
Iterator begin()
Iterator referring to first element in the container.
@ TOK_IGNORE_EMPTY
ignore empty tokens
@ TOK_TRIM
remove leading and trailing whitespace from tokens
Iterator end()
Iterator referring to the past-the-end element in the container.
Logger g_log("DateAndTime")
MANTID_KERNEL_DLL std::string strip(const std::string &A)
strip pre/post spaces
DLLExport std::string join(ITERATOR_TYPE begin, ITERATOR_TYPE end, const std::string &separator, typename std::enable_if<!(std::is_same< typename std::iterator_traits< ITERATOR_TYPE >::iterator_category, std::random_access_iterator_tag >::value)>::type *=nullptr)
Join a set or vector of (something that turns into a string) together into one string,...
int convert(const std::string &A, T &out)
Convert a string into a number.
std::string getValueFromStdOut(const std::string &orig, const std::string &key)
bool canRead(const std::string &filename)
Mantid::Kernel::StringTokenizer tokenizer
Helper class which provides the Collimation Length for SANS instruments.
MANTID_KERNEL_DLL std::string welcomeMessage()
Returns the welcome message for Mantid.