| /* |
| * 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 <chrono> |
| |
| #include <geode/internal/chrono/duration.hpp> |
| #include <geode/PoolManager.hpp> |
| #include <geode/PoolFactory.hpp> |
| |
| #include "CacheXmlParser.hpp" |
| #include "CacheRegionHelper.hpp" |
| #include "AutoDelete.hpp" |
| #include "CacheImpl.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"); |
| } |
| |
| 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 { |
| std::string temp(uname); |
| std::string s = "XML:Unknown XML element \"" + temp + "\""; |
| throw CacheXmlException(s.c_str()); |
| } |
| } 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 { |
| std::string temp(uname); |
| std::string s = "XML:Unknown XML element \"" + temp + "\""; |
| throw CacheXmlException(s.c_str()); |
| } |
| } 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) { |
| std::string temp(filename); |
| std::string tempString = "Xml file " + temp + " not found\n"; |
| throw CacheXmlException(tempString.c_str()); |
| } |
| 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 |
| { |
| char buf[256]; |
| ACE_OS::snprintf(buf, 256, "Error code returned by xml parser is : %d ", |
| res); |
| Log::error(buf); |
| |
| std::string temp = |
| "Xml file is not well formed. Error _stack: \n" + this->m_parserMessage; |
| throw CacheXmlException(temp.c_str()); |
| } |
| std::string temp = this->getError(); |
| if (temp == "") { |
| 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.c_str()); |
| } else if (this->m_flagIllegalStateException) { |
| throw IllegalStateException(temp.c_str()); |
| } else if (this->m_flagAnyOtherException) { |
| throw UnknownException(temp.c_str()); |
| } |
| 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) { |
| std::string s = "XML:No cache specified for performing configuration"; |
| throw IllegalArgumentException(s.c_str()); |
| } |
| 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** attrs) { |
| int attrsCount = 0; |
| if (attrs != nullptr) { |
| const char* attrName; |
| const char* attrValue; |
| while ((attrName = reinterpret_cast<const char*>(attrs[attrsCount++])) != nullptr) { |
| attrValue = reinterpret_cast<const char*>(attrs[attrsCount++]); |
| if (attrValue == nullptr) { |
| std::string exStr = "XML: No value provided for attribute: "; |
| exStr += attrName; |
| throw CacheXmlException(exStr.c_str()); |
| } |
| if (strcmp(attrName, ENDPOINTS) == 0) { |
| if (m_poolFactory) { |
| std::vector<std::pair<std::string, int>> endPoints( |
| parseEndPoints(attrValue)); |
| std::vector<std::pair<std::string, int>>::iterator endPoint; |
| for (endPoint = endPoints.begin(); endPoint != endPoints.end(); |
| endPoint++) { |
| m_poolFactory->addServer(endPoint->first.c_str(), endPoint->second); |
| } |
| } |
| } else if (strcmp(attrName, REDUNDANCY_LEVEL) == 0) { |
| m_poolFactory->setSubscriptionRedundancy(atoi(attrValue)); |
| } |
| } |
| } |
| _GEODE_NEW(m_cacheCreation, CacheXmlCreation()); |
| } |
| |
| void CacheXmlParser::startPdx(const xmlChar** atts) { |
| if (!atts) { |
| return; |
| } |
| |
| int attrsCount = 0; |
| |
| while (atts[attrsCount] != nullptr) { |
| const char* name = reinterpret_cast<const char*>(atts[attrsCount]); |
| ++attrsCount; |
| const char* value = reinterpret_cast<const char*>(atts[attrsCount]); |
| if (strcmp(name, IGNORE_UNREAD_FIELDS) == 0) { |
| bool ignorePdxUnreadfields = false; |
| if (strcmp("true", value) == 0 || strcmp("TRUE", value) == 0) { |
| ignorePdxUnreadfields = true; |
| } else if (strcmp("false", value) == 0 || strcmp("FALSE", value) == 0) { |
| ignorePdxUnreadfields = false; |
| } else { |
| std::string temp(value); |
| std::string s = |
| "XML: " + temp + |
| " is not a valid value for the attribute <ignore-unread-fields>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| m_cacheCreation->setPdxIgnoreUnreadField(ignorePdxUnreadfields); |
| } else if (strcmp(name, READ_SERIALIZED) == 0) { |
| bool readSerialized = false; |
| if (strcmp("true", value) == 0 || strcmp("TRUE", value) == 0) { |
| readSerialized = true; |
| } else if (strcmp("false", value) == 0 || strcmp("FALSE", value) == 0) { |
| readSerialized = false; |
| } else { |
| std::string temp(value); |
| std::string s = |
| "XML: " + temp + |
| " is not a valid value for the attribute <ignore-unread-fields>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| m_cacheCreation->setPdxReadSerialized(readSerialized); |
| } else { |
| throw CacheXmlException("XML:Unrecognized pdx attribute"); |
| } |
| ++attrsCount; |
| } |
| } |
| |
| void CacheXmlParser::endPdx() {} |
| |
| void CacheXmlParser::startLocator(const xmlChar** atts) { |
| int attrsCount = 0; |
| if (!atts) { |
| std::string s = |
| "XML:No attributes provided for <locator>. " |
| "A locator requires a host and port"; |
| throw CacheXmlException(s.c_str()); |
| } |
| m_poolFactory = std::static_pointer_cast<PoolFactory>(_stack.top()); |
| |
| const char* host = nullptr; |
| const char* port = nullptr; |
| |
| while (atts[attrsCount] != nullptr) { |
| const char* name = reinterpret_cast<const char*>(atts[attrsCount]); |
| ++attrsCount; |
| const char* value = reinterpret_cast<const char*>(atts[attrsCount]); |
| if (strcmp(name, HOST) == 0) { |
| host = value; |
| } else if (strcmp(name, PORT) == 0) { |
| port = value; |
| } else { |
| throw CacheXmlException("XML:Unrecognized locator attribute"); |
| } |
| ++attrsCount; |
| } |
| |
| if (attrsCount < 4) { |
| throw CacheXmlException( |
| "XML:Not enough attributes provided for a <locator> - host and port " |
| "required"); |
| } |
| |
| m_poolFactory->addLocator(host, atoi(port)); |
| } |
| |
| void CacheXmlParser::startServer(const xmlChar** atts) { |
| int attrsCount = 0; |
| if (!atts) { |
| std::string s = |
| "XML:No attributes provided for <server>. A server requires a host and " |
| "port"; |
| throw CacheXmlException(s.c_str()); |
| } |
| auto factory = std::static_pointer_cast<PoolFactory>(_stack.top()); |
| |
| const char* host = nullptr; |
| const char* port = nullptr; |
| |
| while (atts[attrsCount] != nullptr) { |
| const char* name = reinterpret_cast<const char*>(atts[attrsCount]); |
| ++attrsCount; |
| const char* value = reinterpret_cast<const char*>(atts[attrsCount]); |
| if (strcmp(name, HOST) == 0) { |
| host = value; |
| } else if (strcmp(name, PORT) == 0) { |
| port = value; |
| } else { |
| throw CacheXmlException("XML:Unrecognized server attribute"); |
| } |
| ++attrsCount; |
| } |
| |
| if (attrsCount < 4) { |
| throw CacheXmlException( |
| "XML:Not enough attributes provided for a <server> - host and port " |
| "required"); |
| } |
| |
| factory->addServer(host, atoi(port)); |
| } |
| |
| void CacheXmlParser::startPool(const xmlChar** atts) { |
| int attrsCount = 0; |
| if (!atts) { |
| std::string s = |
| "XML:No attributes provided for <pool>. " |
| "A pool cannot be created without a name"; |
| throw CacheXmlException(s.c_str()); |
| } |
| auto factory = |
| std::make_shared<PoolFactory>(m_cache->getPoolManager().createFactory()); |
| |
| const char* poolName = nullptr; |
| |
| while (atts[attrsCount] != nullptr) { |
| const char* name = reinterpret_cast<const char*>(atts[attrsCount]); |
| ++attrsCount; |
| const char* value = reinterpret_cast<const char*>(atts[attrsCount]); |
| if (strcmp(name, NAME) == 0) { |
| poolName = value; |
| } else { |
| setPoolInfo(factory.get(), name, value); |
| } |
| ++attrsCount; |
| } |
| |
| if (attrsCount < 2) { |
| std::string s = |
| "XML:No attributes provided for a <pool> - at least the name is " |
| "required"; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| 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::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 (ACE_OS::strcasecmp(value, "true") == 0) { |
| 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 (ACE_OS::strcasecmp(value, "true") == 0) { |
| 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 (ACE_OS::strcasecmp(value, "true") == 0) { |
| factory->setThreadLocalConnections(true); |
| } else { |
| factory->setThreadLocalConnections(false); |
| } |
| } else if (strcmp(name, PR_SINGLE_HOP_ENABLED) == 0) { |
| if (ACE_OS::strcasecmp(value, "true") == 0) { |
| factory->setPRSingleHopEnabled(true); |
| } else { |
| factory->setPRSingleHopEnabled(false); |
| } |
| } else { |
| std::string s = "XML:Unrecognized pool attribute "; |
| s += name; |
| throw CacheXmlException(s.c_str()); |
| } |
| } |
| |
| /** |
| * 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) { |
| std::string s = |
| "XML:No attributes provided for <region>. " |
| "A region cannot be created without a name"; |
| throw CacheXmlException(s.c_str()); |
| } |
| while (atts[attrsCount] != nullptr) ++attrsCount; |
| if (attrsCount < 2 || attrsCount > 4) { |
| std::string s = |
| "XML:Incorrect number of attributes provided for a <region>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| const char* regionName = nullptr; |
| const char* refid = nullptr; |
| |
| for (int i = 0; (atts[i] != nullptr); i++) { |
| if (atts[i] != nullptr) { |
| const char* name = reinterpret_cast<const char*>(const_cast<xmlChar*>(atts[i])); |
| i++; |
| if (atts[i] != nullptr) { |
| const char* value = reinterpret_cast<const char*>(const_cast<xmlChar*>(atts[i])); |
| |
| if (std::strcmp(name, "name") == 0) { |
| regionName = value; |
| } else if (std::strcmp(name, "refid") == 0) { |
| refid = value; |
| } else { |
| std::string temp(name); |
| std::string s = |
| "XML:<region> does not contain the attribute :" + temp + ""; |
| throw CacheXmlException(s.c_str()); |
| } |
| } |
| } |
| } |
| |
| if (regionName == nullptr || strcmp(regionName, "") == 0) // empty string |
| { |
| std::string s = |
| "XML:The attribute name of <region> should be specified and cannot be " |
| "empty "; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| auto region = std::make_shared<RegionXmlCreation>(regionName, isRoot); |
| if (!region) { |
| throw UnknownException("CacheXmlParser::startRegion:Out of memeory"); |
| } |
| |
| _stack.push(region); |
| |
| RegionAttributesFactory* regionAttributesFactory = nullptr; |
| if (refid == nullptr) { |
| regionAttributesFactory = new RegionAttributesFactory(); |
| } else { |
| std::string refidStr(refid); |
| |
| if (namedRegions.find(refidStr) != namedRegions.end()) { |
| regionAttributesFactory = |
| new RegionAttributesFactory(namedRegions[refidStr]); |
| } else { |
| std::string s = |
| "XML:referenced named attribute '" + refidStr + "' does not exist."; |
| throw CacheXmlException(s.c_str()); |
| } |
| } |
| |
| region->setAttributes( |
| regionAttributesFactory->create()); |
| delete regionAttributesFactory; |
| } |
| |
| 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] != nullptr) ++attrsCount; |
| |
| if (attrsCount > 24) // Remember to change this when the number changes |
| { |
| std::string s = |
| "XML:Number of attributes provided for <region-attributes> are more"; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| const char* refid = nullptr; |
| |
| for (int i = 0; (atts[i] != nullptr); i++) { |
| i++; |
| |
| if (atts[i] != nullptr) { |
| const char* value = reinterpret_cast<const char*>(atts[i]); |
| if (strcmp(value, "") == 0) { |
| std::string s = |
| "XML:In the <region-attributes> element no " |
| "attribute 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"; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| const char* prev = reinterpret_cast<const char*>(atts[i - 1]); |
| if (strcmp(prev, ID) == 0) { |
| auto region = |
| std::static_pointer_cast<RegionXmlCreation>(_stack.top()); |
| region->setAttrId(std::string(value)); |
| } else if (strcmp(prev, REFID) == 0) { |
| refid = value; |
| } |
| } |
| } |
| |
| if (refid == nullptr) { |
| auto region = std::static_pointer_cast<RegionXmlCreation>(_stack.top()); |
| regionAttributesFactory = |
| std::make_shared<RegionAttributesFactory>(region->getAttributes()); |
| } else { |
| std::string refidStr(refid); |
| |
| if (namedRegions.find(refidStr) != namedRegions.end()) { |
| regionAttributesFactory = |
| std::make_shared<RegionAttributesFactory>(namedRegions[refidStr]); |
| } else { |
| std::string s = |
| "XML:referenced named attribute '" + refidStr + "' does not exist."; |
| throw CacheXmlException(s.c_str()); |
| } |
| } |
| |
| if (!regionAttributesFactory) { |
| throw UnknownException( |
| "CacheXmlParser::startRegionAttributes:Out of memeory"); |
| } |
| |
| _stack.push(regionAttributesFactory); |
| |
| for (int i = 0; (atts[i] != nullptr); i++) { |
| auto name = reinterpret_cast<const char*>(atts[i]); |
| if (strcmp(ID, name) == 0 || |
| strcmp(REFID, name) == 0) { |
| i++; |
| continue; |
| } else if (strcmp(CLIENT_NOTIFICATION_ENABLED, name) == 0) { |
| i++; |
| auto client_notification_enabled = reinterpret_cast<const char*>(atts[i]); |
| if (strcmp("false", client_notification_enabled) == 0 || |
| strcmp("FALSE", client_notification_enabled) == 0) { |
| if (m_poolFactory) { |
| m_poolFactory->setSubscriptionEnabled(false); |
| } |
| } else if (strcmp("true", client_notification_enabled) == 0 || |
| strcmp("TRUE", client_notification_enabled) == 0) { |
| if (m_poolFactory) { |
| m_poolFactory->setSubscriptionEnabled(true); |
| } |
| } else { |
| std::string temp(client_notification_enabled); |
| std::string s = |
| "XML: " + temp + |
| " is not a valid name for the attribute <client-notification>\n"; |
| throw CacheXmlException(s.c_str()); |
| } |
| } else if (strcmp(INITIAL_CAPACITY, name) == 0) { |
| i++; |
| auto initialCapacity = reinterpret_cast<const char*>(atts[i]); |
| regionAttributesFactory->setInitialCapacity(atoi(initialCapacity)); |
| } else if (strcmp(CONCURRENCY_LEVEL, name) == 0) { |
| i++; |
| auto concurrencyLevel = reinterpret_cast<const char*>(atts[i]); |
| regionAttributesFactory->setConcurrencyLevel(atoi(concurrencyLevel)); |
| } else if (strcmp(LOAD_FACTOR, name) == 0) { |
| i++; |
| auto loadFactor = reinterpret_cast<const char*>(atts[i]); |
| regionAttributesFactory->setLoadFactor( |
| static_cast<float>(atof(loadFactor))); // check whether this works |
| } else if (strcmp(CACHING_ENABLED, name) == 0) { |
| bool flag = false; |
| i++; |
| auto cachingEnabled = reinterpret_cast<const char*>(atts[i]); |
| if (strcmp("true", cachingEnabled) == 0 || |
| strcmp("TRUE", cachingEnabled) == 0) { |
| flag = true; |
| } else if (strcmp("false", cachingEnabled) == 0 || |
| strcmp("FALSE", cachingEnabled) == 0) { |
| flag = false; |
| } else { |
| std::string temp(cachingEnabled); |
| std::string s = |
| "XML: " + temp + |
| " is not a valid name for the attribute <caching-enabled>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| regionAttributesFactory->setCachingEnabled( |
| flag); // check whether this works |
| } else if (strcmp(LRU_ENTRIES_LIMIT, name) == 0) { |
| i++; |
| auto lruentriesLimit = reinterpret_cast<const char*>(atts[i]); |
| int lruentriesLimitInt = atoi(lruentriesLimit); |
| uint32_t temp = static_cast<uint32_t>(lruentriesLimitInt); |
| regionAttributesFactory->setLruEntriesLimit(temp); |
| } else if (strcmp(DISK_POLICY, name) == 0) { |
| i++; |
| auto diskPolicy = reinterpret_cast<const char*>(atts[i]); |
| if (strcmp(OVERFLOWS, diskPolicy) == 0) { |
| regionAttributesFactory->setDiskPolicy( |
| apache::geode::client::DiskPolicyType::OVERFLOWS); |
| } else if (strcmp(PERSIST, diskPolicy) == 0) { |
| throw IllegalStateException(" persistence feature is not supported"); |
| } else if (strcmp(NONE, diskPolicy) == 0) { |
| regionAttributesFactory->setDiskPolicy( |
| apache::geode::client::DiskPolicyType::NONE); |
| } else { |
| std::string temp(diskPolicy); |
| std::string s = |
| "XML: " + temp + |
| " is not a valid name for the attribute <disk-policy>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| } else if (strcmp(ENDPOINTS, name) == 0) { |
| i++; |
| if (m_poolFactory) { |
| std::vector<std::pair<std::string, int>> endPoints( |
| parseEndPoints(name)); |
| std::vector<std::pair<std::string, int>>::iterator endPoint; |
| for (endPoint = endPoints.begin(); endPoint != endPoints.end(); |
| endPoint++) { |
| m_poolFactory->addServer(endPoint->first.c_str(), endPoint->second); |
| } |
| } |
| isTCR = true; |
| } else if (strcmp(POOL_NAME, name) == 0) { |
| i++; |
| auto poolName = reinterpret_cast<const char*>(atts[i]); |
| regionAttributesFactory->setPoolName(poolName); |
| isTCR = true; |
| } else if (strcmp(CLONING_ENABLED, name) == 0) { |
| i++; |
| bool flag = false; |
| auto isClonable = reinterpret_cast<const char*>(atts[i]); |
| |
| if (strcmp("true", isClonable) == 0 || |
| strcmp("TRUE", isClonable) == 0) { |
| flag = true; |
| } else if (strcmp("false", isClonable) == 0 || |
| strcmp("FALSE", isClonable) == 0) { |
| flag = false; |
| } else { |
| std::string temp(isClonable); |
| std::string s = |
| "XML: " + temp + |
| " is not a valid value for the attribute <cloning-enabled>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| regionAttributesFactory->setCloningEnabled(flag); |
| isTCR = true; |
| } else if (strcmp(CONCURRENCY_CHECKS_ENABLED, name) == 0) { |
| bool flag = false; |
| i++; |
| auto concurrencyChecksEnabled = reinterpret_cast<const char*>(atts[i]); |
| if (strcmp("true", concurrencyChecksEnabled) == 0 || |
| strcmp("TRUE", concurrencyChecksEnabled) == 0) { |
| flag = true; |
| } else if (strcmp("false", concurrencyChecksEnabled) == 0 || |
| strcmp("FALSE", concurrencyChecksEnabled) == 0) { |
| flag = false; |
| } else { |
| std::string temp(name); |
| std::string s = "XML: " + temp + |
| " is not a valid value for the attribute " |
| "<concurrency-checks-enabled>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| 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) { |
| std::string s = "XML:No attributes provided for <expiration-attributes> "; |
| throw CacheXmlException(s.c_str()); |
| } |
| m_flagExpirationAttribute = true; |
| int attrsCount = 0; |
| while (atts[attrsCount] != nullptr) ++attrsCount; |
| if (attrsCount > 4) { |
| std::string s = |
| "XML:Incorrect number of attributes provided for " |
| "<expirartion-attributes>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| std::string timeOut; |
| std::chrono::seconds timeOutSeconds; |
| ExpirationAction expire = ExpirationAction::INVALID_ACTION; |
| for (int i = 0; (atts[i] != nullptr); i++) { |
| auto name = reinterpret_cast<const char*>(atts[i]); |
| if (strcmp(TIMEOUT, name) == 0) { |
| i++; |
| timeOut = std::string(reinterpret_cast<const char*>(atts[i])); |
| if (timeOut.empty()) { |
| std::string s = |
| "XML:Value for attribute <timeout> needs to be specified"; |
| throw CacheXmlException(s.c_str()); |
| } |
| timeOutSeconds = from_string<std::chrono::seconds>(timeOut); |
| } else if (strcmp(ACTION, name) == 0) { |
| i++; |
| auto action = reinterpret_cast<const char*>(atts[i]); |
| if (strcmp(action, "") == 0) |
| |
| { |
| std::string s = |
| "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"; |
| throw CacheXmlException(s.c_str()); |
| } else if (strcmp(INVALIDATE, action) == 0) { |
| expire = ExpirationAction::INVALIDATE; |
| } else if (strcmp(DESTROY, action) == 0) { |
| expire = ExpirationAction::DESTROY; |
| } else if (strcmp(LOCAL_INVALIDATE, action) == 0) { |
| expire = ExpirationAction::LOCAL_INVALIDATE; |
| } else if (strcmp(LOCAL_DESTROY, action) == 0) { |
| expire = ExpirationAction::LOCAL_DESTROY; |
| } else { |
| std::string temp(action); |
| std::string s = |
| "XML: " + temp + " is not a valid value for the attribute <action>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| } else { |
| std::string temp(name); |
| std::string s = |
| "XML:Incorrect attribute name specified in " |
| "<expiration-attributes>: " + |
| temp; |
| throw CacheXmlException(s.c_str()); |
| } |
| } |
| if (timeOut.empty()) { |
| std::string s = |
| "XML:The attribute <timeout> not specified in " |
| "<expiration-attributes>."; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| 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) { |
| std::string s = "XML:No attributes provided for <persistence-manager>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| while (atts[attrsCount] != nullptr) ++attrsCount; |
| if (attrsCount > 4) { |
| std::string s = |
| "XML:Incorrect number of attributes provided for " |
| "<persistence-manager>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| char* libraryName = nullptr; |
| char* libraryFunctionName = nullptr; |
| for (int i = 0; (atts[i] != nullptr); i++) { |
| auto name = reinterpret_cast<const char*>(atts[i]); |
| if (std::strcmp(LIBRARY_NAME, name) == 0) { |
| i++; |
| auto value = reinterpret_cast<const char*>(atts[i]); |
| size_t len = strlen(value) + 1; |
| libraryName = new char[len]; |
| |
| if (libraryName == nullptr) { |
| std::string s = "Memory allocation fails"; |
| throw CacheXmlException(s.c_str()); |
| } |
| std::strncpy(libraryName, value, len); |
| |
| if (libraryName == nullptr) { |
| std::string s = |
| "XML:The attribute <library-name> of <persistence-manager> " |
| "cannot " |
| "be set to an empty string. It should either have a value or the " |
| "attribute should be removed. In the latter case the default " |
| "value " |
| "will be set"; |
| throw CacheXmlException(s.c_str()); |
| } |
| } else if (std::strcmp(LIBRARY_FUNCTION_NAME, name) == 0) { |
| i++; |
| auto value = reinterpret_cast<const char*>(atts[i]); |
| size_t len = strlen(value) + 1; |
| libraryFunctionName = new char[len]; |
| |
| if (libraryFunctionName == nullptr) { |
| std::string s = "Memory allocation fails"; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| std::strncpy(libraryFunctionName, value, len); |
| if (libraryFunctionName == nullptr) { |
| throw CacheXmlException("XML:Value for the <library-function-name> needs to be provided"); |
| } |
| } else { |
| std::string temp(name); |
| std::string s = |
| "XML:Incorrect attribute name specified in " |
| "<persistence-manager>: " + |
| temp; |
| throw CacheXmlException(s.c_str()); |
| } |
| } |
| if (libraryFunctionName == nullptr) { |
| std::string s = |
| "XML:Library function name not specified in the " |
| "<persistence-manager>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| try { |
| if (managedPersistenceManagerFn != nullptr && |
| strchr(libraryFunctionName, '.') != nullptr) { |
| // this is a managed library |
| (*managedPersistenceManagerFn)(libraryName, libraryFunctionName); |
| } else { |
| getFactoryFunc(libraryName, libraryFunctionName); |
| } |
| } catch (IllegalArgumentException& ex) { |
| throw CacheXmlException(ex.what()); |
| } |
| |
| _stack.push(std::make_shared<std::string>(std::string(libraryName))); |
| _stack.push(std::make_shared<std::string>(std::string(libraryFunctionName))); |
| } |
| |
| void CacheXmlParser::startPersistenceProperties(const xmlChar** atts) { |
| if (!atts) { |
| std::string s = "XML:No attributes provided for <property> "; |
| throw CacheXmlException(s.c_str()); |
| } |
| int attrsCount = 0; |
| while (atts[attrsCount] != nullptr) ++attrsCount; |
| if (attrsCount > 4) { |
| std::string s = |
| "XML:Incorrect number of attributes provided for <property>"; |
| throw CacheXmlException(s.c_str()); |
| } else { |
| if (m_config == nullptr) { |
| m_config = Properties::create(); |
| } |
| } |
| const char* propName = nullptr; |
| const char* propValue = nullptr; |
| for (int i = 0; (atts[i] != nullptr); i++) { |
| auto name = reinterpret_cast<const char*>(atts[i]); |
| if (std::strcmp("name", name) == 0) { |
| i++; |
| propName = reinterpret_cast<const char*>(atts[i]); |
| if (propName == nullptr || std::strcmp(propName, "") == 0) { |
| throw CacheXmlException("XML:Value for attribute <name> needs to be specified in the " |
| "<property>"); |
| } |
| } else if (strcmp("value", name) == 0) { |
| i++; |
| propValue = reinterpret_cast<const char*>(atts[i]); |
| if (propValue == nullptr || strcmp(propValue, "") == 0) { |
| throw CacheXmlException("XML:Value for attribute <value> needs to be " |
| "specified in the <property>"); |
| } |
| } else { |
| std::string temp(name); |
| std::string s = |
| "XML:Incorrect attribute name specified in <property>: " + temp; |
| throw CacheXmlException(s.c_str()); |
| } |
| } |
| if (propName == nullptr || strcmp(propName, "") == 0) { |
| std::string s = |
| "XML:attribute <name> needs to be specified in the <property>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| if (propValue == nullptr || strcmp(propValue, "") == 0) { |
| std::string s = |
| "XML:attribute <value> needs to be specified in the <property>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| m_config->insert(propName, propValue); |
| } |
| |
| void CacheXmlParser::startCacheLoader(const xmlChar** atts) { |
| const char* libraryName = nullptr; |
| const char* libraryFunctionName = nullptr; |
| int attrsCount = 0; |
| if (!atts) { |
| std::string s = "XML:No attributes provided for <cache-loader>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| while (atts[attrsCount] != nullptr) ++attrsCount; |
| if (attrsCount > 4) { |
| std::string s = |
| "XML:Incorrect number of attributes provided for <cache-loader>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| for (int i = 0; (atts[i] != nullptr); i++) { |
| auto name = reinterpret_cast<const char*>(atts[i]); |
| if (strcmp(LIBRARY_NAME, name) == 0) { |
| i++; |
| libraryName = reinterpret_cast<const char*>(atts[i]); |
| if (libraryName == nullptr || strcmp(libraryName, "") == 0) { |
| throw CacheXmlException("XML:The attribute <library-name> of <cache-loader> cannot be " |
| "set " |
| "to an 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 (strcmp(LIBRARY_FUNCTION_NAME, name) == 0) { |
| i++; |
| libraryFunctionName = reinterpret_cast<const char*>(atts[i]); |
| if (libraryFunctionName == nullptr || |
| strcmp(libraryFunctionName, "") == 0) { |
| throw CacheXmlException("XML:Value for the <library-function-name> needs to be provided"); |
| } |
| } else { |
| std::string temp(name); |
| std::string s = |
| "XML:Incorrect attribute name specified in <cache-loader> : " + temp; |
| throw CacheXmlException(s.c_str()); |
| } |
| } |
| if (libraryFunctionName == nullptr || strcmp(libraryFunctionName, "") == 0) { |
| std::string s = |
| "XML:<library-function-name> not specified in <cache-loader> "; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| try { |
| if (managedCacheLoaderFn != nullptr && |
| strchr(libraryFunctionName, '.') != nullptr) { |
| // this is a managed library |
| (*managedCacheLoaderFn)(libraryName, libraryFunctionName); |
| } 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) { |
| const char* libraryName = nullptr; |
| const char* libraryFunctionName = nullptr; |
| int attrsCount = 0; |
| if (!atts) { |
| std::string s = "XML:No attributes provided for <cache-listener> "; |
| throw CacheXmlException(s.c_str()); |
| } |
| while (atts[attrsCount] != nullptr) ++attrsCount; |
| if (attrsCount > 4) { |
| std::string s = |
| "XML:Incorrect number of attributes provided for <cache-listener>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| for (int i = 0; (atts[i] != nullptr); i++) { |
| auto name = reinterpret_cast<const char*>(atts[i]); |
| if (strcmp(LIBRARY_NAME, name) == 0) { |
| i++; |
| libraryName = reinterpret_cast<const char*>(atts[i]); |
| if (libraryName == nullptr || strcmp(libraryName, "") == 0) { |
| throw CacheXmlException("XML:The attribute <library-name> of the <cache-listener> tag " |
| "cannot be set to an 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 (strcmp(LIBRARY_FUNCTION_NAME, name) == 0) { |
| i++; |
| libraryFunctionName = reinterpret_cast<const char*>(atts[i]); |
| if (libraryFunctionName == nullptr || |
| strcmp(libraryFunctionName, "") == 0) { |
| throw CacheXmlException("XML:Value for <library-function-name> needs to be provided"); |
| } |
| } else { |
| std::string temp(name); |
| std::string s = |
| "XML:Incorrect attribute name specified in <cache-listener> : " + |
| temp; |
| throw CacheXmlException(s.c_str()); |
| } |
| } |
| if (libraryFunctionName == nullptr || strcmp(libraryFunctionName, "") == 0) { |
| std::string s = |
| "XML:Library function name not specified in <cache-listener> "; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| try { |
| if (managedCacheListenerFn != nullptr && |
| strchr(libraryFunctionName, '.') != nullptr) { |
| // this is a managed library |
| (*managedCacheListenerFn)(libraryName, libraryFunctionName); |
| } 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) { |
| const char* libraryName = nullptr; |
| const char* libraryFunctionName = nullptr; |
| int attrsCount = 0; |
| if (!atts) { |
| std::string s = "XML:No attributes provided for <partition-resolver> "; |
| throw CacheXmlException(s.c_str()); |
| } |
| while (atts[attrsCount] != nullptr) ++attrsCount; |
| if (attrsCount > 4) { |
| std::string s = |
| "XML:Incorrect number of attributes provided for " |
| "<partition-resolver>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| for (int i = 0; (atts[i] != nullptr); i++) { |
| auto name = reinterpret_cast<const char*>(atts[i]); |
| if (strcmp(LIBRARY_NAME, name) == 0) { |
| i++; |
| libraryName = reinterpret_cast<const char*>(atts[i]); |
| if (libraryName == nullptr || strcmp(libraryName, "") == 0) { |
| throw CacheXmlException("XML:The attribute <library-name> of the <partition-resolver> " |
| "tag " |
| "cannot be set to an 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 (strcmp(LIBRARY_FUNCTION_NAME, name) == 0) { |
| i++; |
| libraryFunctionName = reinterpret_cast<const char*>(atts[i]); |
| if (libraryFunctionName == nullptr || |
| strcmp(libraryFunctionName, "") == 0) { |
| throw CacheXmlException("XML:Value for <library-function-name> needs to be provided"); |
| } |
| } else { |
| std::string temp(name); |
| std::string s = |
| "XML:Incorrect attribute name specified in <partition-resolver> " |
| ": " + |
| temp; |
| throw CacheXmlException(s.c_str()); |
| } |
| } |
| if (libraryFunctionName == nullptr || strcmp(libraryFunctionName, "") == 0) { |
| throw CacheXmlException("XML:Library function name not specified in <partition-resolver> "); |
| } |
| |
| try { |
| if (managedPartitionResolverFn != nullptr && |
| strchr(libraryFunctionName, '.') != nullptr) { |
| // this is a managed library |
| (*managedPartitionResolverFn)(libraryName, libraryFunctionName); |
| } 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) { |
| const char* libraryName = nullptr; |
| const char* libraryFunctionName = nullptr; |
| int attrsCount = 0; |
| if (!atts) { |
| std::string s = "XML:No attributes provided for <cache-writer>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| while (atts[attrsCount] != nullptr) ++attrsCount; |
| if (attrsCount > 4) { |
| std::string s = |
| "XML:Incorrect number of attributes provided for <cache-writer>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| for (int i = 0; (atts[i] != nullptr); i++) { |
| auto name = reinterpret_cast<const char*>(atts[i]); |
| if (strcmp(LIBRARY_NAME, name) == 0) { |
| i++; |
| libraryName = reinterpret_cast<const char*>(atts[i]); |
| if (libraryName == nullptr || strcmp(libraryName, "") == 0) { |
| throw CacheXmlException("XML:The attribute <library-name> of <cache-writer> cannot be " |
| "set " |
| "to an 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 (strcmp(LIBRARY_FUNCTION_NAME, name) == 0) { |
| i++; |
| libraryFunctionName = reinterpret_cast<const char*>(atts[i]); |
| if (libraryFunctionName == nullptr || |
| strcmp(libraryFunctionName, "") == 0) { |
| throw CacheXmlException("XML:Value for the <library-function-name> needs to be provided"); |
| } |
| } else { |
| std::string temp(name); |
| std::string s = |
| "XML:Incorrect attribute name specified in <cache-writer>: " + temp; |
| throw CacheXmlException(s.c_str()); |
| } |
| } |
| if (strcmp(libraryFunctionName, "") == 0) { |
| throw CacheXmlException("XML:Library function name not specified in the <cache-writer>"); |
| } |
| |
| try { |
| if (managedCacheWriterFn != nullptr && |
| strchr(libraryFunctionName, '.') != nullptr) { |
| // this is a managed library |
| (*managedCacheWriterFn)(libraryName, libraryFunctionName); |
| } 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()) { |
| std::string s = "Xml file has incorrectly nested region tags"; |
| throw CacheXmlException(s.c_str()); |
| } |
| if (!m_cacheCreation) { |
| throw CacheXmlException( |
| "XML: Element <cache> was not provided in the xml"); |
| } |
| |
| m_cacheCreation->addRootRegion(regionPtr); |
| } else { |
| if (_stack.empty()) { |
| std::string s = "Xml file has incorrectly nested region tags"; |
| throw CacheXmlException(s.c_str()); |
| } |
| 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) { |
| std::string s = |
| "XML: <region-time-to-live> cannot be without a " |
| "<expiration-attributes>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| |
| 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) { |
| std::string s = |
| "XML: <region-idle-time> cannot be without <expiration-attributes>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| 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) { |
| std::string s = |
| "XML: <entry-time-to-live> cannot be without " |
| "<expiration-attributes>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| 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) { |
| std::string s = |
| "XML: <entry-idle-time> cannot be without <expiration-attributes>"; |
| throw CacheXmlException(s.c_str()); |
| } |
| 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 |