blob: fdc6a2642ae9447f9c5985eeba6bf539ab49fa3e [file] [log] [blame]
/*
* 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