| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "CacheXmlParser.hpp" |
| |
| #include <chrono> |
| |
| #include <geode/PoolFactory.hpp> |
| #include <geode/PoolManager.hpp> |
| #include <geode/internal/chrono/duration.hpp> |
| |
| #include "AutoDelete.hpp" |
| #include "CacheImpl.hpp" |
| #include "CacheRegionHelper.hpp" |
| #include "util/string.hpp" |
| |
| #if defined(_WIN32) |
| #include <windows.h> |
| #else |
| #include <dlfcn.h> |
| #endif |
| |
| namespace apache { |
| namespace geode { |
| namespace client { |
| |
| namespace impl { |
| void* getFactoryFunc(const std::string& lib, const std::string& funcName); |
| } // namespace impl |
| |
| namespace { |
| |
| using apache::geode::client::impl::getFactoryFunc; |
| |
| std::vector<std::pair<std::string, int>> parseEndPoints( |
| const std::string& str) { |
| std::vector<std::pair<std::string, int>> endPoints; |
| std::string::size_type start = 0; |
| std::string::size_type pos = str.find_first_of(','); |
| while (std::string::npos != pos) { |
| const std::string endPoint(str.substr(start, pos - start)); |
| const std::string::size_type split = endPoint.find_last_of(':'); |
| if (std::string::npos == split) { |
| endPoints.push_back(std::pair<std::string, int>(endPoint, 0)); |
| } else { |
| int port = 0; |
| try { |
| port = std::stoi(endPoint.substr(split + 1)); |
| } catch (...) { |
| // NOP |
| } |
| endPoints.push_back( |
| std::pair<std::string, int>(endPoint.substr(0, split), port)); |
| } |
| start = pos + 1; |
| pos = str.find_first_of(',', start); |
| } |
| return endPoints; |
| } |
| } // namespace |
| |
| /////////////////XML Parser Callback functions//////////////////////// |
| |
| extern "C" void startElementSAX2Function(void* ctx, const xmlChar* name, |
| const xmlChar** atts) { |
| CacheXmlParser* parser = (CacheXmlParser*)ctx; |
| if (!parser) { |
| Log::error("CacheXmlParser::startElementSAX2Function:Parser is nullptr"); |
| return; |
| } |
| |
| if ((!parser->isCacheXmlException()) && |
| (!parser->isIllegalStateException()) && |
| (!parser->isAnyOtherException())) { |
| try { |
| auto uname = |
| reinterpret_cast<const char*>(const_cast<unsigned char*>(name)); |
| if (std::strcmp(uname, parser->CACHE) == 0) { |
| parser->startCache(ctx, atts); |
| } else if (strcmp(uname, parser->CLIENT_CACHE) == 0) { |
| parser->startCache(ctx, atts); |
| } else if (strcmp(uname, parser->PDX) == 0) { |
| parser->startPdx(atts); |
| } else if (strcmp(uname, parser->REGION) == 0) { |
| parser->incNesting(); |
| parser->startRegion(atts, parser->isRootLevel()); |
| } else if (strcmp(uname, parser->ROOT_REGION) == 0) { |
| parser->incNesting(); |
| parser->startRegion(atts, parser->isRootLevel()); |
| } else if (strcmp(uname, parser->REGION_ATTRIBUTES) == 0) { |
| parser->startRegionAttributes(atts); |
| } else if (strcmp(uname, parser->REGION_TIME_TO_LIVE) == 0) { |
| } else if (strcmp(uname, parser->REGION_IDLE_TIME) == 0) { |
| } else if (strcmp(uname, parser->ENTRY_TIME_TO_LIVE) == 0) { |
| } else if (strcmp(uname, parser->ENTRY_IDLE_TIME) == 0) { |
| } else if (strcmp(uname, parser->EXPIRATION_ATTRIBUTES) == 0) { |
| parser->startExpirationAttributes(atts); |
| } else if (strcmp(uname, parser->CACHE_LOADER) == 0) { |
| parser->startCacheLoader(atts); |
| } else if (strcmp(uname, parser->CACHE_WRITER) == 0) { |
| parser->startCacheWriter(atts); |
| } else if (strcmp(uname, parser->CACHE_LISTENER) == 0) { |
| parser->startCacheListener(atts); |
| } else if (strcmp(uname, parser->PARTITION_RESOLVER) == 0) { |
| parser->startPartitionResolver(atts); |
| } else if (strcmp(uname, parser->PERSISTENCE_MANAGER) == 0) { |
| parser->startPersistenceManager(atts); |
| } else if (strcmp(uname, parser->PROPERTIES) == 0) { |
| } else if (strcmp(uname, parser->PROPERTY) == 0) { |
| parser->startPersistenceProperties(atts); |
| } else if (strcmp(uname, parser->POOL) == 0) { |
| parser->startPool(atts); |
| } else if (strcmp(uname, parser->LOCATOR) == 0) { |
| parser->startLocator(atts); |
| } else if (strcmp(uname, parser->SERVER) == 0) { |
| parser->startServer(atts); |
| } else { |
| throw CacheXmlException("XML:Unknown XML element \"" + |
| std::string(uname) + "\""); |
| } |
| } catch (const CacheXmlException& e) { |
| parser->setCacheXmlException(); |
| std::string s = e.what(); |
| parser->setError(s); |
| } catch (const IllegalStateException& ex) { |
| parser->setIllegalStateException(); |
| std::string s = ex.what(); |
| parser->setError(s); |
| } catch (const Exception& ex) { |
| parser->setAnyOtherException(); |
| std::string s = ex.what(); |
| parser->setError(s); |
| } |
| } // flag |
| } |
| |
| extern "C" void endElementSAX2Function(void* ctx, const xmlChar* name) { |
| CacheXmlParser* parser = (CacheXmlParser*)ctx; |
| if (!parser) { |
| Log::error( |
| "Error occured while xml parsing: " |
| "CacheXmlParser:startElementSAX2Function:Parser is nullptr"); |
| return; |
| } |
| |
| if ((!parser->isCacheXmlException()) && |
| (!parser->isIllegalStateException()) && |
| (!parser->isAnyOtherException())) { |
| try { |
| auto uname = |
| reinterpret_cast<const char*>(const_cast<unsigned char*>(name)); |
| if (strcmp(uname, parser->CACHE) == 0) { |
| parser->endCache(); |
| } else if (strcmp(uname, parser->CLIENT_CACHE) == 0) { |
| parser->endCache(); |
| } else if (strcmp(uname, parser->PDX) == 0) { |
| parser->endPdx(); |
| } else if (strcmp(uname, parser->REGION) == 0) { |
| parser->endRegion(parser->isRootLevel()); |
| parser->decNesting(); |
| } else if (strcmp(uname, parser->ROOT_REGION) == 0) { |
| parser->endRegion(parser->isRootLevel()); |
| parser->decNesting(); |
| } else if (strcmp(uname, parser->REGION_ATTRIBUTES) == 0) { |
| parser->endRegionAttributes(); |
| } else if (strcmp(uname, parser->REGION_TIME_TO_LIVE) == 0) { |
| parser->endRegionTimeToLive(); |
| } else if (strcmp(uname, parser->REGION_IDLE_TIME) == 0) { |
| parser->endRegionIdleTime(); |
| } else if (strcmp(uname, parser->ENTRY_TIME_TO_LIVE) == 0) { |
| parser->endEntryTimeToLive(); |
| } else if (strcmp(uname, parser->ENTRY_IDLE_TIME) == 0) { |
| parser->endEntryIdleTime(); |
| } else if (strcmp(uname, parser->EXPIRATION_ATTRIBUTES) == 0) { |
| } else if (strcmp(uname, parser->CACHE_LOADER) == 0) { |
| } else if (strcmp(uname, parser->CACHE_WRITER) == 0) { |
| } else if (strcmp(uname, parser->CACHE_LISTENER) == 0) { |
| } else if (strcmp(uname, parser->PARTITION_RESOLVER) == 0) { |
| } else if (strcmp(uname, parser->PERSISTENCE_MANAGER) == 0) { |
| parser->endPersistenceManager(); |
| } else if (strcmp(uname, parser->PROPERTIES) == 0) { |
| } else if (strcmp(uname, parser->PROPERTY) == 0) { |
| } else if (strcmp(uname, parser->POOL) == 0) { |
| parser->endPool(); |
| } else if (strcmp(uname, parser->LOCATOR) == 0) { |
| // parser->endLocator(); |
| } else if (strcmp(uname, parser->SERVER) == 0) { |
| // parser->endServer(); |
| } else { |
| throw CacheXmlException("XML:Unknown XML element \"" + |
| std::string(uname) + "\""); |
| } |
| } catch (CacheXmlException& e) { |
| parser->setCacheXmlException(); |
| std::string s = e.what(); |
| parser->setError(s); |
| } catch (IllegalStateException& ex) { |
| parser->setIllegalStateException(); |
| std::string s = ex.what(); |
| parser->setError(s); |
| } catch (Exception& ex) { |
| parser->setAnyOtherException(); |
| std::string s = ex.what(); |
| parser->setError(s); |
| } |
| } // flag |
| } |
| |
| /** |
| * warningDebug: |
| * @ctxt: An XML parser context |
| * @msg: the message to display/transmit |
| * @...: extra parameters for the message display |
| * |
| * Display and format a warning messages, gives file, line, position and |
| * extra parameters. |
| */ |
| extern "C" void warningDebug(void*, const char* msg, ...) { |
| char logmsg[2048]; |
| va_list args; |
| va_start(args, msg); |
| vsprintf(logmsg, msg, args); |
| va_end(args); |
| LOGWARN("SAX.warning during XML declarative client initialization: %s", |
| logmsg); |
| } |
| |
| /** |
| * fatalErrorDebug: |
| * @ctxt: An XML parser context |
| * @msg: the message to display/transmit |
| * @...: extra parameters for the message display |
| * |
| * Display and format a fatalError messages, gives file, line, position and |
| * extra parameters. |
| */ |
| extern "C" void fatalErrorDebug(void* ctx, const char* msg, ...) { |
| char buf[1024]; |
| va_list args; |
| |
| va_start(args, msg); |
| CacheXmlParser* parser = (CacheXmlParser*)ctx; |
| vsprintf(buf, msg, args); |
| std::string stringMsg(buf); |
| parser->setParserMessage(parser->getParserMessage() + stringMsg); |
| va_end(args); |
| } |
| |
| /////////////End of XML Parser Cackllback functions/////////////// |
| |
| ///////////////static variables of the class//////////////////////// |
| |
| LibraryCacheLoaderFn CacheXmlParser::managedCacheLoaderFn = nullptr; |
| LibraryCacheListenerFn CacheXmlParser::managedCacheListenerFn = nullptr; |
| LibraryPartitionResolverFn CacheXmlParser::managedPartitionResolverFn = nullptr; |
| LibraryCacheWriterFn CacheXmlParser::managedCacheWriterFn = nullptr; |
| LibraryPersistenceManagerFn CacheXmlParser::managedPersistenceManagerFn = |
| nullptr; |
| |
| ////////////////////////////////////////////////////////////////// |
| |
| CacheXmlParser::CacheXmlParser(Cache* cache) |
| : m_cacheCreation(nullptr), |
| m_nestedRegions(0), |
| m_config(nullptr), |
| m_parserMessage(""), |
| m_flagCacheXmlException(false), |
| m_flagIllegalStateException(false), |
| m_flagAnyOtherException(false), |
| m_flagExpirationAttribute(false), |
| m_poolFactory(nullptr), |
| m_cache(cache) { |
| static xmlSAXHandler saxHandler = { |
| nullptr, /* internalSubset */ |
| nullptr, /* isStandalone */ |
| nullptr, /* hasInternalSubset */ |
| nullptr, /* hasExternalSubset */ |
| nullptr, /* resolveEntity */ |
| nullptr, /* getEntity */ |
| nullptr, /* entityDecl */ |
| nullptr, /* notationDecl */ |
| nullptr, /* attributeDecl */ |
| nullptr, /* elementDecl */ |
| nullptr, /* unparsedEntityDecl */ |
| nullptr, /* setDocumentLocator */ |
| nullptr, /* startDocument */ |
| nullptr, /* endDocument */ |
| startElementSAX2Function, /* startElement */ |
| endElementSAX2Function, /* endElement */ |
| nullptr, /* reference */ |
| nullptr, /* characters */ |
| nullptr, /* ignorableWhitespace */ |
| nullptr, /* processingInstruction */ |
| nullptr, // commentDebug, /* comment */ |
| warningDebug, /* xmlParserWarning */ |
| fatalErrorDebug, /* xmlParserError */ |
| nullptr, /* xmlParserError */ |
| nullptr, /* getParameterEntity */ |
| nullptr, /* cdataBlock; */ |
| nullptr, /* externalSubset; */ |
| XML_SAX2_MAGIC, |
| nullptr, |
| nullptr, /* startElementNs */ |
| nullptr, /* endElementNs */ |
| nullptr /* xmlStructuredErrorFunc */ |
| }; |
| |
| m_saxHandler = saxHandler; |
| |
| namedRegions = CacheImpl::getRegionShortcut(); |
| } |
| |
| void CacheXmlParser::parseFile(const char* filename) { |
| int res = 0; |
| |
| res = xmlSAXUserParseFile(&this->m_saxHandler, this, filename); |
| |
| if (res == -1) { |
| throw CacheXmlException("Xml file " + std::string(filename) + " not found"); |
| } |
| handleParserErrors(res); |
| } |
| |
| void CacheXmlParser::parseMemory(const char* buffer, int size) { |
| int res = 0; |
| res = xmlSAXUserParseMemory(&this->m_saxHandler, this, buffer, size); |
| |
| if (res == -1) { |
| throw CacheXmlException("Unable to read buffer."); |
| } |
| handleParserErrors(res); |
| } |
| |
| void CacheXmlParser::handleParserErrors(int res) { |
| if (res != 0) // xml file is not well-formed |
| { |
| Log::error("Error code returned by xml parser is : " + std::to_string(res)); |
| throw CacheXmlException("Xml file is not well formed. Error _stack: \n" + |
| std::string(this->m_parserMessage)); |
| } |
| std::string temp = this->getError(); |
| if (temp.empty()) { |
| Log::info("Xml file parsed successfully"); |
| } else { |
| // well formed, but not according to our specs(dtd errors thrown manually) |
| if (this->m_flagCacheXmlException) { |
| throw CacheXmlException(temp); |
| } else if (this->m_flagIllegalStateException) { |
| throw IllegalStateException(temp); |
| } else if (this->m_flagAnyOtherException) { |
| throw UnknownException(temp); |
| } |
| this->setError(""); |
| } |
| } |
| |
| ////////////////////// Static Methods ////////////////////// |
| |
| /** |
| * Parses XML data and from it creates an instance of |
| * <code>CacheXmlParser</code> that can be used to create |
| * the {@link Cache}, etc. |
| * |
| * @param cacheXml |
| * The xml file |
| * |
| * @throws CacheXmlException |
| * Something went wrong while parsing the XML |
| * @throws OutOfMemoryException |
| * @throws CacheXmlException |
| * If xml file is not well-formed or |
| * Something went wrong while parsing the XML |
| * @throws IllegalStateException |
| * If xml file is well-flrmed but not valid |
| * @throws UnknownException otherwise |
| */ |
| CacheXmlParser* CacheXmlParser::parse(const char* cacheXml, Cache* cache) { |
| CacheXmlParser* handler; |
| _GEODE_NEW(handler, CacheXmlParser(cache)); |
| // use RAII to delete the handler object in case of exceptions |
| DeleteObject<CacheXmlParser> delHandler(handler); |
| |
| { |
| handler->parseFile(cacheXml); |
| delHandler.noDelete(); |
| return handler; |
| } |
| } |
| |
| void CacheXmlParser::setAttributes(Cache*) {} |
| |
| /** |
| * Creates cache artifacts ({@link Cache}s, etc.) based upon the XML |
| * parsed by this parser. |
| * |
| * @param cache |
| * The cachewhcih is to be populated |
| * @throws OutOfMemoryException if the memory allocation failed |
| * @throws NotConnectedException if the cache is not connected |
| * @throws InvalidArgumentException if the attributePtr is nullptr. |
| * or if RegionAttributes is null or if regionName is null, |
| * the empty string, or contains a '/' |
| * @throws RegionExistsException |
| * @throws CacheClosedException if the cache is closed |
| * at the time of region creation |
| * @throws UnknownException otherwise |
| * |
| */ |
| void CacheXmlParser::create(Cache* cache) { |
| // use DeleteObject class to delete m_cacheCreation in case of exceptions |
| DeleteObject<CacheXmlCreation> delCacheCreation(m_cacheCreation); |
| |
| if (cache == nullptr) { |
| throw IllegalArgumentException( |
| "XML:No cache specified for performing configuration"); |
| } |
| if (!m_cacheCreation) { |
| throw CacheXmlException("XML: Element <cache> was not provided in the xml"); |
| } |
| m_cacheCreation->create(cache); |
| delCacheCreation.noDelete(); |
| Log::info("Declarative configuration of cache completed successfully"); |
| } |
| |
| void CacheXmlParser::startCache(void*, const xmlChar** atts) { |
| if (atts) { |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| if (value.empty()) { |
| throw CacheXmlException("XML: No value provided for attribute: " + |
| name); |
| } |
| |
| if (ENDPOINTS == name) { |
| if (m_poolFactory) { |
| for (auto&& endPoint : parseEndPoints(value)) { |
| m_poolFactory->addServer(endPoint.first, endPoint.second); |
| } |
| } |
| } else if (REDUNDANCY_LEVEL == name) { |
| m_poolFactory->setSubscriptionRedundancy(std::stoi(value)); |
| } |
| } |
| } |
| _GEODE_NEW(m_cacheCreation, CacheXmlCreation()); |
| } |
| |
| void CacheXmlParser::startPdx(const xmlChar** atts) { |
| if (!atts) { |
| return; |
| } |
| |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| if (value.empty()) { |
| throw CacheXmlException("XML: No value provided for attribute: " + name); |
| } |
| |
| if (IGNORE_UNREAD_FIELDS == name) { |
| bool flag = false; |
| std::transform(value.begin(), value.end(), value.begin(), ::tolower); |
| if ("false" == value) { |
| flag = false; |
| } else if ("true" == value) { |
| flag = true; |
| } else { |
| throw CacheXmlException( |
| "XML: " + value + |
| " is not a valid value for the attribute <ignore-unread-fields>"); |
| } |
| m_cacheCreation->setPdxIgnoreUnreadField(flag); |
| } else if (READ_SERIALIZED == name) { |
| bool flag = false; |
| std::transform(value.begin(), value.end(), value.begin(), ::tolower); |
| if ("false" == value) { |
| flag = false; |
| } else if ("true" == value) { |
| flag = true; |
| } else { |
| throw CacheXmlException( |
| "XML: " + value + |
| " is not a valid value for the attribute <ignore-unread-fields>"); |
| } |
| m_cacheCreation->setPdxReadSerialized(flag); |
| } else { |
| throw CacheXmlException("XML:Unrecognized pdx attribute " + name); |
| } |
| } |
| } |
| |
| void CacheXmlParser::endPdx() {} |
| |
| void CacheXmlParser::startLocator(const xmlChar** atts) { |
| if (!atts) { |
| throw CacheXmlException( |
| "XML:No attributes provided for <locator>. A locator requires a host " |
| "and port"); |
| } |
| m_poolFactory = std::static_pointer_cast<PoolFactory>(_stack.top()); |
| |
| std::string host; |
| std::string port; |
| int attrsCount = 0; |
| |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| if (value.empty()) { |
| throw CacheXmlException("XML: No value provided for attribute: " + name); |
| } |
| |
| if (HOST == name) { |
| host = std::move(value); |
| } else if (PORT == name) { |
| port = std::move(value); |
| } else { |
| throw CacheXmlException("XML:Unrecognized locator attribute"); |
| } |
| |
| ++attrsCount; |
| } |
| |
| if (attrsCount < 2) { |
| throw CacheXmlException( |
| "XML:Not enough attributes provided for a <locator> - host and port " |
| "required"); |
| } |
| |
| m_poolFactory->addLocator(host, std::stoi(port)); |
| } |
| |
| void CacheXmlParser::startServer(const xmlChar** atts) { |
| if (!atts) { |
| throw CacheXmlException( |
| "XML:No attributes provided for <server>. A server requires a host and " |
| "port"); |
| } |
| auto factory = std::static_pointer_cast<PoolFactory>(_stack.top()); |
| |
| std::string host; |
| std::string port; |
| int attrsCount = 0; |
| |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| if (value.empty()) { |
| throw CacheXmlException("XML: No value provided for attribute: " + name); |
| } |
| |
| if (HOST == name) { |
| host = std::move(value); |
| } else if (PORT == name) { |
| port = std::move(value); |
| } else { |
| throw CacheXmlException("XML:Unrecognized server attribute"); |
| } |
| |
| ++attrsCount; |
| } |
| |
| if (attrsCount < 2) { |
| throw CacheXmlException( |
| "XML:Not enough attributes provided for a <server> - host and port " |
| "required"); |
| } |
| |
| factory->addServer(host, std::stoi(port)); |
| } |
| |
| void CacheXmlParser::startPool(const xmlChar** atts) { |
| if (!atts) { |
| throw CacheXmlException( |
| "XML:No attributes provided for <pool>. A pool cannot be created " |
| "without a name"); |
| } |
| auto factory = |
| std::make_shared<PoolFactory>(m_cache->getPoolManager().createFactory()); |
| |
| std::string poolName; |
| |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| if (value.empty()) { |
| throw CacheXmlException("XML: No value provided for attribute: " + name); |
| } |
| |
| if (NAME == name) { |
| poolName = std::move(value); |
| } else { |
| setPoolInfo(factory.get(), name.c_str(), value.c_str()); |
| } |
| } |
| |
| if (poolName.empty()) { |
| throw CacheXmlException( |
| "XML:No attributes provided for a <pool> - at least the name is " |
| "required"); |
| } |
| |
| auto poolxml = std::make_shared<PoolXmlCreation>(poolName, factory); |
| |
| _stack.push(poolxml); |
| _stack.push(factory); |
| } |
| |
| void CacheXmlParser::endPool() { |
| _stack.pop(); // remove factory |
| auto poolxml = std::static_pointer_cast<PoolXmlCreation>(_stack.top()); |
| _stack.pop(); // remove pool |
| m_cacheCreation->addPool(poolxml); |
| } |
| |
| void CacheXmlParser::setPoolInfo(PoolFactory* factory, const char* name, |
| const char* value) { |
| using apache::geode::client::equal_ignore_case; |
| using apache::geode::internal::chrono::duration::from_string; |
| |
| if (strcmp(name, FREE_CONNECTION_TIMEOUT) == 0) { |
| factory->setFreeConnectionTimeout( |
| from_string<std::chrono::milliseconds>(std::string(value))); |
| } else if (strcmp(name, MULTIUSER_SECURE_MODE) == 0) { |
| if (equal_ignore_case(value, "true")) { |
| factory->setMultiuserAuthentication(true); |
| } else { |
| factory->setMultiuserAuthentication(false); |
| } |
| } else if (strcmp(name, IDLE_TIMEOUT) == 0) { |
| factory->setIdleTimeout( |
| from_string<std::chrono::milliseconds>(std::string(value))); |
| } else if (strcmp(name, LOAD_CONDITIONING_INTERVAL) == 0) { |
| factory->setLoadConditioningInterval( |
| from_string<std::chrono::milliseconds>(std::string(value))); |
| } else if (strcmp(name, MAX_CONNECTIONS) == 0) { |
| factory->setMaxConnections(atoi(value)); |
| } else if (strcmp(name, MIN_CONNECTIONS) == 0) { |
| factory->setMinConnections(atoi(value)); |
| } else if (strcmp(name, PING_INTERVAL) == 0) { |
| factory->setPingInterval( |
| from_string<std::chrono::milliseconds>(std::string(value))); |
| } else if (strcmp(name, UPDATE_LOCATOR_LIST_INTERVAL) == 0) { |
| factory->setUpdateLocatorListInterval( |
| from_string<std::chrono::milliseconds>(std::string(value))); |
| } else if (strcmp(name, READ_TIMEOUT) == 0) { |
| factory->setReadTimeout( |
| from_string<std::chrono::milliseconds>(std::string(value))); |
| } else if (strcmp(name, RETRY_ATTEMPTS) == 0) { |
| factory->setRetryAttempts(atoi(value)); |
| } else if (strcmp(name, SERVER_GROUP) == 0) { |
| factory->setServerGroup(value); |
| } else if (strcmp(name, SOCKET_BUFFER_SIZE) == 0) { |
| factory->setSocketBufferSize(atoi(value)); |
| } else if (strcmp(name, STATISTIC_INTERVAL) == 0) { |
| factory->setStatisticInterval( |
| from_string<std::chrono::milliseconds>(std::string(value))); |
| } else if (strcmp(name, SUBSCRIPTION_ACK_INTERVAL) == 0) { |
| factory->setSubscriptionAckInterval( |
| from_string<std::chrono::milliseconds>(std::string(value))); |
| } else if (strcmp(name, SUBSCRIPTION_ENABLED) == 0) { |
| if (equal_ignore_case(value, "true")) { |
| factory->setSubscriptionEnabled(true); |
| } else { |
| factory->setSubscriptionEnabled(false); |
| } |
| } else if (strcmp(name, SUBSCRIPTION_MTT) == 0) { |
| factory->setSubscriptionMessageTrackingTimeout( |
| from_string<std::chrono::milliseconds>(std::string(value))); |
| } else if (strcmp(name, SUBSCRIPTION_REDUNDANCY) == 0) { |
| factory->setSubscriptionRedundancy(atoi(value)); |
| } else if (strcmp(name, THREAD_LOCAL_CONNECTIONS) == 0) { |
| if (equal_ignore_case(value, "true")) { |
| factory->setThreadLocalConnections(true); |
| } else { |
| factory->setThreadLocalConnections(false); |
| } |
| } else if (strcmp(name, PR_SINGLE_HOP_ENABLED) == 0) { |
| if (equal_ignore_case(value, "true")) { |
| factory->setPRSingleHopEnabled(true); |
| } else { |
| factory->setPRSingleHopEnabled(false); |
| } |
| } else { |
| throw CacheXmlException("XML:Unrecognized pool attribute " + |
| std::string(name)); |
| } |
| } |
| |
| /** |
| * When a <code>region</code> element is first encountered, we |
| * create a {@link RegionCreation} and push it on the _stack. |
| * An {@link RegionAttributesFactory }is also created and puhed on _stack. |
| */ |
| void CacheXmlParser::startRegion(const xmlChar** atts, bool isRoot) { |
| int attrsCount = 0; |
| if (!atts) { |
| throw CacheXmlException( |
| "XML:No attributes provided for <region>. A region cannot be created " |
| "without a name"); |
| } |
| while (atts[attrsCount]) ++attrsCount; |
| if (attrsCount < 2 || attrsCount > 4) { |
| throw CacheXmlException( |
| "XML:Incorrect number of attributes provided for a <region>"); |
| } |
| |
| std::string regionName; |
| std::string refid; |
| |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| |
| if ("name" == name) { |
| regionName = value; |
| } else if ("refid" == name) { |
| refid = value; |
| } else { |
| throw CacheXmlException("XML:<region> does not contain the attribute :" + |
| name); |
| } |
| } |
| |
| if (regionName.empty()) { |
| throw CacheXmlException( |
| "XML:The attribute name of <region> should be specified and cannot be " |
| "empty"); |
| } |
| |
| auto region = std::make_shared<RegionXmlCreation>(regionName, isRoot); |
| if (!region) { |
| throw UnknownException("CacheXmlParser::startRegion:Out of memeory"); |
| } |
| |
| _stack.push(region); |
| |
| RegionAttributesFactory regionAttributesFactory; |
| if (!refid.empty()) { |
| if (namedRegions.find(refid) != namedRegions.end()) { |
| regionAttributesFactory = RegionAttributesFactory(namedRegions[refid]); |
| } else { |
| throw CacheXmlException("XML:referenced named attribute '" + refid + |
| "' does not exist."); |
| } |
| } |
| |
| region->setAttributes(regionAttributesFactory.create()); |
| } |
| |
| void CacheXmlParser::startSubregion(const xmlChar** atts) { |
| startRegion(atts, false); |
| } |
| |
| void CacheXmlParser::startRootRegion(const xmlChar** atts) { |
| startRegion(atts, true); |
| } |
| |
| void CacheXmlParser::startRegionAttributes(const xmlChar** atts) { |
| bool isDistributed = false; |
| bool isTCR = false; |
| std::shared_ptr<RegionAttributesFactory> regionAttributesFactory = nullptr; |
| if (atts) { |
| int attrsCount = 0; |
| while (atts[attrsCount]) ++attrsCount; |
| if (attrsCount > 24) // Remember to change this when the number changes |
| { |
| throw CacheXmlException( |
| "XML:Number of attributes provided for <region-attributes> are more"); |
| } |
| |
| std::string refid; |
| |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| |
| if (value.empty()) { |
| throw CacheXmlException( |
| "XML:In the <region-attributes> element attribute " + name + |
| " can be set to empty string. It should either have a " |
| "value or the attribute should be removed. In the latter case " |
| "the default value will be set"); |
| } |
| |
| if (ID == name) { |
| auto region = std::static_pointer_cast<RegionXmlCreation>(_stack.top()); |
| region->setAttrId(value); |
| } else if (REFID == name) { |
| refid = std::move(value); |
| } |
| } |
| |
| if (refid.empty()) { |
| auto region = std::static_pointer_cast<RegionXmlCreation>(_stack.top()); |
| regionAttributesFactory = |
| std::make_shared<RegionAttributesFactory>(region->getAttributes()); |
| } else { |
| if (namedRegions.find(refid) != namedRegions.end()) { |
| regionAttributesFactory = |
| std::make_shared<RegionAttributesFactory>(namedRegions[refid]); |
| } else { |
| throw CacheXmlException("XML:referenced named attribute '" + refid + |
| "' does not exist."); |
| } |
| } |
| |
| if (!regionAttributesFactory) { |
| throw UnknownException( |
| "CacheXmlParser::startRegionAttributes:Out of memeory"); |
| } |
| |
| _stack.push(regionAttributesFactory); |
| |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| |
| if (ID == name || REFID == name) { |
| continue; |
| } else if (CLIENT_NOTIFICATION_ENABLED == name) { |
| bool flag = false; |
| std::transform(value.begin(), value.end(), value.begin(), ::tolower); |
| if ("false" == value) { |
| flag = false; |
| } else if ("true" == value) { |
| flag = true; |
| } else { |
| throw CacheXmlException( |
| "XML: " + value + |
| " is not a valid name for the attribute <client-notification>"); |
| } |
| if (m_poolFactory) { |
| m_poolFactory->setSubscriptionEnabled(flag); |
| } |
| } else if (INITIAL_CAPACITY == name) { |
| regionAttributesFactory->setInitialCapacity(std::stoi(value)); |
| } else if (CONCURRENCY_LEVEL == name) { |
| regionAttributesFactory->setConcurrencyLevel(std::stoi(value)); |
| } else if (LOAD_FACTOR == name) { |
| regionAttributesFactory->setLoadFactor(std::stof(value)); |
| } else if (CACHING_ENABLED == name) { |
| bool flag = false; |
| std::transform(value.begin(), value.end(), value.begin(), ::tolower); |
| if ("false" == value) { |
| flag = false; |
| } else if ("true" == value) { |
| flag = true; |
| } else { |
| throw CacheXmlException( |
| "XML: " + value + |
| " is not a valid name for the attribute <caching-enabled>"); |
| } |
| regionAttributesFactory->setCachingEnabled(flag); |
| } else if (LRU_ENTRIES_LIMIT == name) { |
| regionAttributesFactory->setLruEntriesLimit(std::stoi(value)); |
| } else if (DISK_POLICY == name) { |
| auto diskPolicy = apache::geode::client::DiskPolicyType::NONE; |
| if (OVERFLOWS == value) { |
| diskPolicy = apache::geode::client::DiskPolicyType::OVERFLOWS; |
| } else if (PERSIST == value) { |
| throw IllegalStateException("Persistence feature is not supported"); |
| } else if (NONE == value) { |
| diskPolicy = apache::geode::client::DiskPolicyType::NONE; |
| } else { |
| throw CacheXmlException( |
| "XML: " + value + |
| " is not a valid name for the attribute <disk-policy>"); |
| } |
| regionAttributesFactory->setDiskPolicy(diskPolicy); |
| } else if (ENDPOINTS == name) { |
| if (m_poolFactory) { |
| for (auto&& endPoint : parseEndPoints(name)) { |
| m_poolFactory->addServer(endPoint.first, endPoint.second); |
| } |
| } |
| isTCR = true; |
| } else if (POOL_NAME == name) { |
| regionAttributesFactory->setPoolName(value); |
| isTCR = true; |
| } else if (CLONING_ENABLED == name) { |
| bool flag = false; |
| std::transform(value.begin(), value.end(), value.begin(), ::tolower); |
| if ("false" == value) { |
| flag = false; |
| } else if ("true" == value) { |
| flag = true; |
| } else { |
| throw CacheXmlException( |
| "XML: " + value + |
| " is not a valid value for the attribute <cloning-enabled>"); |
| } |
| regionAttributesFactory->setCloningEnabled(flag); |
| isTCR = true; |
| } else if (CONCURRENCY_CHECKS_ENABLED == name) { |
| bool flag = false; |
| std::transform(value.begin(), value.end(), value.begin(), ::tolower); |
| if ("false" == value) { |
| flag = false; |
| } else if ("true" == value) { |
| flag = true; |
| } else { |
| throw CacheXmlException("XML: " + value + |
| " is not a valid value for the attribute " |
| "<concurrency-checks-enabled>"); |
| } |
| regionAttributesFactory->setConcurrencyChecksEnabled(flag); |
| } |
| } // for loop |
| } // atts is nullptr |
| else { |
| auto region = std::static_pointer_cast<RegionXmlCreation>(_stack.top()); |
| regionAttributesFactory = |
| std::make_shared<RegionAttributesFactory>(region->getAttributes()); |
| _stack.push(regionAttributesFactory); |
| } |
| |
| if (isDistributed && isTCR) { |
| /* we don't allow DR+TCR at current stage according to sudhir */ |
| throw CacheXmlException( |
| "XML:endpoints cannot be defined for distributed region.\n"); |
| } |
| } |
| |
| void CacheXmlParser::endRegionAttributes() { |
| auto regionAttributesFactory = |
| std::static_pointer_cast<RegionAttributesFactory>(_stack.top()); |
| _stack.pop(); |
| if (!regionAttributesFactory) { |
| throw UnknownException( |
| "CacheXmlParser::endRegion:RegionAttributesFactory is null"); |
| } |
| |
| auto regionAttributes = regionAttributesFactory->create(); |
| |
| auto regionPtr = std::static_pointer_cast<RegionXmlCreation>(_stack.top()); |
| if (!regionPtr) { |
| throw UnknownException("CacheXmlParser::endRegion:Region is null"); |
| } |
| |
| std::string id = regionPtr->getAttrId(); |
| if (id != "") { |
| namedRegions[id] = regionAttributes; |
| } |
| |
| regionPtr->setAttributes(regionAttributes); |
| } |
| |
| /** |
| * When a <code>expiration-attributes</code> element is first |
| * encountered, we create an {@link ExpirationAttibutes} object from |
| * the element's attributes and push it on the _stack. |
| */ |
| void CacheXmlParser::startExpirationAttributes(const xmlChar** atts) { |
| using apache::geode::internal::chrono::duration::from_string; |
| |
| if (!atts) { |
| throw CacheXmlException( |
| "XML:No attributes provided for <expiration-attributes> "); |
| } |
| m_flagExpirationAttribute = true; |
| size_t attrsCount = 0; |
| while (atts[attrsCount]) ++attrsCount; |
| if (attrsCount > 4) { |
| throw CacheXmlException( |
| "XML:Incorrect number of attributes provided for " |
| "<expirartion-attributes>"); |
| } |
| std::string timeOut; |
| ExpirationAction expire = ExpirationAction::INVALID_ACTION; |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| if (TIMEOUT == name) { |
| if (value.empty()) { |
| throw CacheXmlException( |
| "XML:Value for attribute <timeout> needs to be specified"); |
| } |
| timeOut = value; |
| } else if (ACTION == name) { |
| if (value.empty()) { |
| throw CacheXmlException( |
| "XML:The attribute <action> of <expiration-attributes> cannot be " |
| "set to empty string. It should either have a value or the " |
| "attribute should be removed. In the latter case the default value " |
| "will be set"); |
| } else if (INVALIDATE == value) { |
| expire = ExpirationAction::INVALIDATE; |
| } else if (DESTROY == value) { |
| expire = ExpirationAction::DESTROY; |
| } else if (LOCAL_INVALIDATE == value) { |
| expire = ExpirationAction::LOCAL_INVALIDATE; |
| } else if (LOCAL_DESTROY == value) { |
| expire = ExpirationAction::LOCAL_DESTROY; |
| } else { |
| throw CacheXmlException( |
| "XML: " + value + |
| " is not a valid value for the attribute <action>"); |
| } |
| } else { |
| throw CacheXmlException( |
| "XML:Incorrect attribute name specified in " |
| "<expiration-attributes>: " + |
| value); |
| } |
| } |
| if (timeOut.empty()) { |
| throw CacheXmlException( |
| "XML:The attribute <timeout> not specified in " |
| "<expiration-attributes>."); |
| } |
| auto timeOutSeconds = from_string<std::chrono::seconds>(timeOut); |
| |
| auto expireAttr = |
| std::make_shared<ExpirationAttributes>(timeOutSeconds, expire); |
| if (!expireAttr) { |
| throw UnknownException( |
| "CacheXmlParser::startExpirationAttributes:Out of memory"); |
| } |
| expireAttr->setAction(expire); |
| |
| _stack.push(expireAttr); |
| } |
| void CacheXmlParser::startPersistenceManager(const xmlChar** atts) { |
| int attrsCount = 0; |
| if (!atts) { |
| throw CacheXmlException( |
| "XML:No attributes provided for <persistence-manager>"); |
| } |
| while (atts[attrsCount]) ++attrsCount; |
| if (attrsCount > 4) { |
| throw CacheXmlException( |
| "XML:Incorrect number of attributes provided for " |
| "<persistence-manager>"); |
| } |
| std::string libraryName; |
| std::string libraryFunctionName; |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| if (value.empty()) { |
| throw CacheXmlException("XML:Value for attribute <" + name + |
| "> needs to be specified in the " |
| "<persistence-manager>"); |
| } |
| |
| if (LIBRARY_NAME == name) { |
| libraryName = std::move(value); |
| } else if (LIBRARY_FUNCTION_NAME == name) { |
| libraryFunctionName = std::move(value); |
| } else { |
| throw CacheXmlException( |
| "XML:Incorrect attribute name specified in <persistence-manager>: " + |
| value); |
| } |
| } |
| if (libraryFunctionName.empty()) { |
| throw CacheXmlException( |
| "XML:Library function name not specified in the <persistence-manager>"); |
| } |
| |
| try { |
| if (managedPersistenceManagerFn && |
| libraryFunctionName.find('.') != std::string::npos) { |
| // this is a managed library |
| (*managedPersistenceManagerFn)(libraryName.c_str(), |
| libraryFunctionName.c_str()); |
| } else { |
| getFactoryFunc(libraryName, libraryFunctionName); |
| } |
| } catch (IllegalArgumentException& ex) { |
| throw CacheXmlException(ex.what()); |
| } |
| |
| _stack.emplace(std::make_shared<std::string>(std::move(libraryName))); |
| _stack.emplace(std::make_shared<std::string>(std::move(libraryFunctionName))); |
| } |
| |
| void CacheXmlParser::startPersistenceProperties(const xmlChar** atts) { |
| if (!atts) { |
| throw CacheXmlException("XML:No attributes provided for <property>"); |
| } |
| int attrsCount = 0; |
| while (atts[attrsCount]) ++attrsCount; |
| if (attrsCount > 4) { |
| throw CacheXmlException( |
| "XML:Incorrect number of attributes provided for <property>"); |
| } else { |
| if (m_config == nullptr) { |
| m_config = Properties::create(); |
| } |
| } |
| std::string propName; |
| std::string propValue; |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| |
| if (value.empty()) { |
| throw CacheXmlException("XML:Value for attribute <" + name + |
| "> needs to be specified in the " |
| "<property>"); |
| } |
| |
| if ("name" == name) { |
| propName = value; |
| } else if ("value" == name) { |
| propValue = value; |
| } else { |
| throw CacheXmlException( |
| "XML:Incorrect attribute name specified in <property>: " + name); |
| } |
| } |
| if (propName.empty()) { |
| throw CacheXmlException( |
| "XML:attribute <name> needs to be specified in the <property>"); |
| } |
| if (propValue.empty()) { |
| throw CacheXmlException( |
| "XML:attribute <value> needs to be specified in the <property>"); |
| } |
| m_config->insert(propName, propValue); |
| } |
| |
| void CacheXmlParser::startCacheLoader(const xmlChar** atts) { |
| std::string libraryName; |
| std::string libraryFunctionName; |
| int attrsCount = 0; |
| if (!atts) { |
| throw CacheXmlException("XML:No attributes provided for <cache-loader>"); |
| } |
| while (atts[attrsCount]) ++attrsCount; |
| if (attrsCount > 4) { |
| throw CacheXmlException( |
| "XML:Incorrect number of attributes provided for <cache-loader>"); |
| } |
| |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| |
| if (value.empty()) { |
| throw CacheXmlException("XML:Value for attribute <" + name + |
| "> needs to be specified in the " |
| "<cache-loader>"); |
| } |
| |
| if (LIBRARY_NAME == name) { |
| libraryName = std::move(value); |
| } else if (LIBRARY_FUNCTION_NAME == name) { |
| libraryFunctionName = std::move(value); |
| } else { |
| throw CacheXmlException( |
| "XML:Incorrect attribute name specified in <cache-loader> : " + name); |
| } |
| } |
| if (libraryFunctionName.empty()) { |
| throw CacheXmlException( |
| "XML:<library-function-name> not specified in <cache-loader>"); |
| } |
| |
| try { |
| if (managedCacheLoaderFn && |
| libraryFunctionName.find('.') != std::string::npos) { |
| // this is a managed library |
| (*managedCacheLoaderFn)(libraryName.c_str(), libraryFunctionName.c_str()); |
| } else { |
| getFactoryFunc(libraryName, libraryFunctionName); |
| } |
| } catch (IllegalArgumentException& ex) { |
| throw CacheXmlException(ex.what()); |
| } |
| |
| auto regionAttributesFactory = |
| std::static_pointer_cast<RegionAttributesFactory>(_stack.top()); |
| regionAttributesFactory->setCacheLoader(libraryName, libraryFunctionName); |
| } |
| |
| void CacheXmlParser::startCacheListener(const xmlChar** atts) { |
| std::string libraryName; |
| std::string libraryFunctionName; |
| int attrsCount = 0; |
| if (!atts) { |
| throw CacheXmlException("XML:No attributes provided for <cache-listener>"); |
| } |
| while (atts[attrsCount]) ++attrsCount; |
| if (attrsCount > 4) { |
| throw CacheXmlException( |
| "XML:Incorrect number of attributes provided for <cache-listener>"); |
| } |
| |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| |
| if (value.empty()) { |
| throw CacheXmlException("XML:Value for attribute <" + name + |
| "> needs to be specified in the " |
| "<cache-listener>"); |
| } |
| |
| if (LIBRARY_NAME == name) { |
| libraryName = std::move(value); |
| } else if (LIBRARY_FUNCTION_NAME == name) { |
| libraryFunctionName = std::move(value); |
| } else { |
| throw CacheXmlException( |
| "XML:Incorrect attribute name specified in <cache-listener> : " + |
| name); |
| } |
| } |
| if (libraryFunctionName.empty()) { |
| throw CacheXmlException( |
| "XML:Library function name not specified in <cache-listener>"); |
| } |
| |
| try { |
| if (managedCacheListenerFn && |
| libraryFunctionName.find('.') != std::string::npos) { |
| // this is a managed library |
| (*managedCacheListenerFn)(libraryName.c_str(), |
| libraryFunctionName.c_str()); |
| } else { |
| getFactoryFunc(libraryName, libraryFunctionName); |
| } |
| } catch (IllegalArgumentException& ex) { |
| throw CacheXmlException(ex.what()); |
| } |
| |
| auto regionAttributesFactory = |
| std::static_pointer_cast<RegionAttributesFactory>(_stack.top()); |
| regionAttributesFactory->setCacheListener(libraryName, libraryFunctionName); |
| } |
| |
| void CacheXmlParser::startPartitionResolver(const xmlChar** atts) { |
| if (!atts) { |
| throw CacheXmlException( |
| "XML:No attributes provided for <partition-resolver> "); |
| } |
| |
| int attrsCount = 0; |
| while (atts[attrsCount]) ++attrsCount; |
| if (attrsCount > 4) { |
| throw CacheXmlException( |
| "XML:Incorrect number of attributes provided for " |
| "<partition-resolver>"); |
| } |
| |
| std::string libraryName; |
| std::string libraryFunctionName; |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| |
| if (value.empty()) { |
| throw CacheXmlException("XML:Value for attribute <" + name + |
| "> needs to be specified in the " |
| "<cache-listener>"); |
| } |
| |
| if (LIBRARY_NAME == name) { |
| libraryName = std::move(value); |
| } else if (LIBRARY_FUNCTION_NAME == name) { |
| libraryFunctionName = std::move(value); |
| } else { |
| throw CacheXmlException( |
| "XML:Incorrect attribute name specified in <partition-resolver>: " + |
| value); |
| } |
| } |
| if (libraryFunctionName.empty()) { |
| throw CacheXmlException( |
| "XML:Library function name not specified in <partition-resolver> "); |
| } |
| |
| try { |
| if (managedPartitionResolverFn != nullptr && |
| libraryFunctionName.find('.') != std::string::npos) { |
| // this is a managed library |
| (*managedPartitionResolverFn)(libraryName.c_str(), |
| libraryFunctionName.c_str()); |
| } else { |
| getFactoryFunc(libraryName, libraryFunctionName); |
| } |
| } catch (IllegalArgumentException& ex) { |
| throw CacheXmlException(ex.what()); |
| } |
| |
| auto regionAttributesFactory = |
| std::static_pointer_cast<RegionAttributesFactory>(_stack.top()); |
| regionAttributesFactory->setPartitionResolver(libraryName, |
| libraryFunctionName); |
| } |
| |
| void CacheXmlParser::startCacheWriter(const xmlChar** atts) { |
| if (!atts) { |
| throw CacheXmlException("XML:No attributes provided for <cache-writer>"); |
| } |
| |
| int attrsCount = 0; |
| while (atts[attrsCount] != nullptr) ++attrsCount; |
| if (attrsCount > 4) { |
| throw CacheXmlException( |
| "XML:Incorrect number of attributes provided for <cache-writer>"); |
| } |
| |
| std::string libraryName; |
| std::string libraryFunctionName; |
| |
| for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) { |
| auto name = std::string(reinterpret_cast<const char*>(atts[i])); |
| auto value = std::string(reinterpret_cast<const char*>(atts[i + 1])); |
| |
| if (value.empty()) { |
| throw CacheXmlException("XML:Value for attribute <" + name + |
| "> needs to be specified in the <cache-writer>"); |
| } |
| |
| if (LIBRARY_NAME == name) { |
| libraryName = std::move(value); |
| } else if (LIBRARY_FUNCTION_NAME == name) { |
| libraryFunctionName = std::move(value); |
| } else { |
| throw CacheXmlException( |
| "XML:Incorrect attribute name specified in <cache-writer>: " + value); |
| } |
| } |
| if (libraryFunctionName.empty()) { |
| throw CacheXmlException( |
| "XML:Library function name not specified in the <cache-writer>"); |
| } |
| |
| try { |
| if (managedCacheWriterFn && |
| libraryFunctionName.find('.') != std::string::npos) { |
| // this is a managed library |
| (*managedCacheWriterFn)(libraryName.c_str(), libraryFunctionName.c_str()); |
| } else { |
| getFactoryFunc(libraryName, libraryFunctionName); |
| } |
| } catch (IllegalArgumentException& ex) { |
| throw CacheXmlException(ex.what()); |
| } |
| |
| auto regionAttributesFactory = |
| std::static_pointer_cast<RegionAttributesFactory>(_stack.top()); |
| regionAttributesFactory->setCacheWriter(libraryName, libraryFunctionName); |
| } |
| |
| /** |
| * After popping the current <code>RegionXmlCreation</code> off the |
| * _stack, if the element on top of the _stack is a |
| * <code>RegionXmlCreation</code>, then it is the parent region. |
| */ |
| void CacheXmlParser::endRegion(bool isRoot) { |
| auto regionPtr = std::static_pointer_cast<RegionXmlCreation>(_stack.top()); |
| _stack.pop(); |
| if (isRoot) { |
| if (!_stack.empty()) { |
| throw CacheXmlException("Xml file has incorrectly nested region tags"); |
| } |
| if (!m_cacheCreation) { |
| throw CacheXmlException( |
| "XML: Element <cache> was not provided in the xml"); |
| } |
| |
| m_cacheCreation->addRootRegion(regionPtr); |
| } else { |
| if (_stack.empty()) { |
| throw CacheXmlException("Xml file has incorrectly nested region tags"); |
| } |
| auto parent = std::static_pointer_cast<RegionXmlCreation>(_stack.top()); |
| parent->addSubregion(regionPtr); |
| } |
| } |
| |
| void CacheXmlParser::endSubregion() { endRegion(false); } |
| |
| void CacheXmlParser::endRootRegion() { endRegion(true); } |
| |
| /** |
| * When a <code>cache</code> element is finished |
| */ |
| void CacheXmlParser::endCache() {} |
| |
| /** |
| * When a <code>region-time-to-live</code> element is finished, the |
| * {@link ExpirationAttributes} are on top of the _stack followed by |
| * the {@link RegionAttributesFactory} to which the expiration |
| * attributes are assigned. |
| */ |
| void CacheXmlParser::endRegionTimeToLive() { |
| if (!m_flagExpirationAttribute) { |
| throw CacheXmlException( |
| "XML: <region-time-to-live> cannot be without a " |
| "<expiration-attributes>"); |
| } |
| |
| auto expireAttr = |
| std::static_pointer_cast<ExpirationAttributes>(_stack.top()); |
| _stack.pop(); |
| |
| auto regionAttributesFactory = |
| std::static_pointer_cast<RegionAttributesFactory>(_stack.top()); |
| regionAttributesFactory->setRegionTimeToLive(expireAttr->getAction(), |
| expireAttr->getTimeout()); |
| m_flagExpirationAttribute = false; |
| } |
| |
| /** |
| * When a <code>region-idle-time</code> element is finished, the |
| * {@link ExpirationAttributes} are on top of the _stack followed by |
| * the {@link RegionAttributesFactory} to which the expiration |
| * attributes are assigned. |
| */ |
| void CacheXmlParser::endRegionIdleTime() { |
| if (!m_flagExpirationAttribute) { |
| throw CacheXmlException( |
| "XML: <region-idle-time> cannot be without <expiration-attributes>"); |
| } |
| auto expireAttr = |
| std::static_pointer_cast<ExpirationAttributes>(_stack.top()); |
| _stack.pop(); |
| auto regionAttributesFactory = |
| std::static_pointer_cast<RegionAttributesFactory>(_stack.top()); |
| |
| regionAttributesFactory->setRegionIdleTimeout(expireAttr->getAction(), |
| expireAttr->getTimeout()); |
| m_flagExpirationAttribute = false; |
| } |
| |
| /** |
| * When a <code>entry-time-to-live</code> element is finished, the |
| * {@link ExpirationAttributes} are on top of the _stack followed by |
| * the {@link RegionAttributesFactory} to which the expiration |
| * attributes are assigned. |
| */ |
| void CacheXmlParser::endEntryTimeToLive() { |
| if (!m_flagExpirationAttribute) { |
| throw CacheXmlException( |
| "XML: <entry-time-to-live> cannot be without <expiration-attributes>"); |
| } |
| auto expireAttr = |
| std::static_pointer_cast<ExpirationAttributes>(_stack.top()); |
| _stack.pop(); |
| auto regionAttributesFactory = |
| std::static_pointer_cast<RegionAttributesFactory>(_stack.top()); |
| |
| regionAttributesFactory->setEntryTimeToLive(expireAttr->getAction(), |
| expireAttr->getTimeout()); |
| m_flagExpirationAttribute = false; |
| } |
| |
| /** |
| * When a <code>entry-idle-time</code> element is finished, the |
| * {@link ExpirationAttributes} are on top of the _stack followed by |
| * the {@link RegionAttributesFactory} to which the expiration |
| * attributes are assigned. |
| */ |
| void CacheXmlParser::endEntryIdleTime() { |
| if (!m_flagExpirationAttribute) { |
| throw CacheXmlException( |
| "XML: <entry-idle-time> cannot be without <expiration-attributes>"); |
| } |
| auto expireAttr = |
| std::static_pointer_cast<ExpirationAttributes>(_stack.top()); |
| _stack.pop(); |
| auto regionAttributesFactory = |
| std::static_pointer_cast<RegionAttributesFactory>(_stack.top()); |
| // TODO GEODE-3136: consider string parser here. |
| regionAttributesFactory->setEntryIdleTimeout(expireAttr->getAction(), |
| expireAttr->getTimeout()); |
| m_flagExpirationAttribute = false; |
| } |
| |
| /** |
| * When persistence-manager attributes is finished, it will set the attribute |
| * factory. |
| */ |
| void CacheXmlParser::endPersistenceManager() { |
| std::shared_ptr<std::string> libraryFunctionName = |
| std::static_pointer_cast<std::string>(_stack.top()); |
| _stack.pop(); |
| std::shared_ptr<std::string> libraryName = |
| std::static_pointer_cast<std::string>(_stack.top()); |
| _stack.pop(); |
| auto regionAttributesFactory = |
| std::static_pointer_cast<RegionAttributesFactory>(_stack.top()); |
| if (m_config != nullptr) { |
| regionAttributesFactory->setPersistenceManager( |
| libraryName->c_str(), libraryFunctionName->c_str(), m_config); |
| m_config = nullptr; |
| } else { |
| regionAttributesFactory->setPersistenceManager( |
| libraryName->c_str(), libraryFunctionName->c_str()); |
| } |
| } |
| |
| CacheXmlParser::~CacheXmlParser() { _GEODE_SAFE_DELETE(m_cacheCreation); } |
| |
| void CacheXmlParser::setError(const std::string& err) { m_error = err; } |
| |
| const std::string& CacheXmlParser::getError() const { return m_error; } |
| |
| } // namespace client |
| } // namespace geode |
| } // namespace apache |