JSONEnumService::JSONEnumService(std::string configuration) { // Check whether the file exists. struct stat s; if ((stat(configuration.c_str(), &s) != 0) && (errno == ENOENT)) { TRC_STATUS("No ENUM configuration (file %s does not exist)", configuration.c_str()); CL_SPROUT_ENUM_FILE_MISSING.log(configuration.c_str()); return; } TRC_STATUS("Loading ENUM configuration from %s", configuration.c_str()); // Read from the file std::ifstream fs(configuration.c_str()); std::string enum_str((std::istreambuf_iterator<char>(fs)), std::istreambuf_iterator<char>()); if (enum_str == "") { // LCOV_EXCL_START TRC_ERROR("Failed to read ENUM configuration data from %s", configuration.c_str()); CL_SPROUT_ENUM_FILE_EMPTY.log(configuration.c_str()); return; // LCOV_EXCL_STOP } // Now parse the document rapidjson::Document doc; doc.Parse<0>(enum_str.c_str()); if (doc.HasParseError()) { TRC_ERROR("Failed to read ENUM configuration data: %s\nError: %s", enum_str.c_str(), rapidjson::GetParseError_En(doc.GetParseError())); CL_SPROUT_ENUM_FILE_INVALID.log(configuration.c_str()); return; } try { JSON_ASSERT_CONTAINS(doc, "number_blocks"); JSON_ASSERT_ARRAY(doc["number_blocks"]); const rapidjson::Value& nb_arr = doc["number_blocks"]; for (rapidjson::Value::ConstValueIterator nb_it = nb_arr.Begin(); nb_it != nb_arr.End(); ++nb_it) { try { std::string prefix; JSON_GET_STRING_MEMBER(*nb_it, "prefix", prefix); std::string regex; JSON_GET_STRING_MEMBER(*nb_it, "regex", regex); // Entry is well-formed, so add it. TRC_DEBUG("Found valid number prefix block %s", prefix.c_str()); NumberPrefix *pfix = new NumberPrefix; pfix->prefix = prefix; if (parse_regex_replace(regex, pfix->match, pfix->replace)) { _number_prefixes.push_back(pfix); TRC_STATUS(" Adding number prefix %s, regex=%s", pfix->prefix.c_str(), regex.c_str()); } else { TRC_WARNING("Badly formed regular expression in ENUM number block %s", regex.c_str()); delete pfix; } } catch (JsonFormatError err) { // Badly formed number block. TRC_WARNING("Badly formed ENUM number block (hit error at %s:%d)", err._file, err._line); CL_SPROUT_ENUM_FILE_INVALID.log(configuration.c_str()); } } } catch (JsonFormatError err) { TRC_ERROR("Badly formed ENUM configuration data - missing number_blocks object"); CL_SPROUT_ENUM_FILE_INVALID.log(configuration.c_str()); } }
void JSONEnumService::update_enum() { // Check whether the file exists. struct stat s; if ((stat(_configuration.c_str(), &s) != 0) && (errno == ENOENT)) { TRC_STATUS("No ENUM configuration (file %s does not exist)", _configuration.c_str()); CL_SPROUT_ENUM_FILE_MISSING.log(_configuration.c_str()); return; } TRC_STATUS("Loading ENUM configuration from %s", _configuration.c_str()); // Read from the file std::ifstream fs(_configuration.c_str()); std::string enum_str((std::istreambuf_iterator<char>(fs)), std::istreambuf_iterator<char>()); if (enum_str == "") { // LCOV_EXCL_START TRC_ERROR("Failed to read ENUM configuration data from %s", _configuration.c_str()); CL_SPROUT_ENUM_FILE_EMPTY.log(_configuration.c_str()); return; // LCOV_EXCL_STOP } // Now parse the document rapidjson::Document doc; doc.Parse<0>(enum_str.c_str()); if (doc.HasParseError()) { TRC_ERROR("Failed to read ENUM configuration data: %s\nError: %s", enum_str.c_str(), rapidjson::GetParseError_En(doc.GetParseError())); CL_SPROUT_ENUM_FILE_INVALID.log(_configuration.c_str()); return; } try { std::vector<NumberPrefix> new_number_prefixes; std::map<std::string, NumberPrefix> new_prefix_regex_map; JSON_ASSERT_CONTAINS(doc, "number_blocks"); JSON_ASSERT_ARRAY(doc["number_blocks"]); const rapidjson::Value& nb_arr = doc["number_blocks"]; for (rapidjson::Value::ConstValueIterator nb_it = nb_arr.Begin(); nb_it != nb_arr.End(); ++nb_it) { try { std::string prefix; JSON_GET_STRING_MEMBER(*nb_it, "prefix", prefix); std::string regex; JSON_GET_STRING_MEMBER(*nb_it, "regex", regex); // Entry is well-formed, so strip off visual separators and add it. TRC_DEBUG("Found valid number prefix block %s", prefix.c_str()); NumberPrefix pfix; prefix = PJUtils::remove_visual_separators(prefix); pfix.prefix = prefix; if (parse_regex_replace(regex, pfix.match, pfix.replace)) { // Create an array in order of entries in json file, and a map // (automatically sorted in order of key length) so we can later // match numbers to the most specific prefixes new_number_prefixes.push_back(pfix); new_prefix_regex_map.insert(std::make_pair(prefix, pfix)); TRC_STATUS(" Adding number prefix %s, regex=%s", pfix.prefix.c_str(), regex.c_str()); } else { TRC_WARNING("Badly formed regular expression in ENUM number block %s", regex.c_str()); } } catch (JsonFormatError err) { // Badly formed number block. TRC_WARNING("Badly formed ENUM number block (hit error at %s:%d)", err._file, err._line); CL_SPROUT_ENUM_FILE_INVALID.log(_configuration.c_str()); } } // Take a write lock on the mutex in RAII style boost::lock_guard<boost::shared_mutex> write_lock(_number_prefixes_rw_lock); _number_prefixes = new_number_prefixes; _prefix_regex_map = new_prefix_regex_map; } catch (JsonFormatError err) { TRC_ERROR("Badly formed ENUM configuration data - missing number_blocks object"); CL_SPROUT_ENUM_FILE_INVALID.log(_configuration.c_str()); } }