From a116aeb2cf5a84fa03f9814c3884561149029267 Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Sun, 13 Jan 2013 00:49:43 +0100 Subject: Refactored to PIMPL pattern --- CMakeLists.txt | 8 +- src/uscxml/Factory.cpp | 43 ++--- src/uscxml/Factory.h | 128 ++++++++++++--- src/uscxml/Interpreter.cpp | 177 ++++++++++----------- src/uscxml/Interpreter.h | 29 ++-- src/uscxml/URL.cpp | 52 +++--- src/uscxml/URL.h | 47 +++++- .../datamodel/ecmascript/v8/V8DataModel.cpp | 6 +- .../plugins/datamodel/ecmascript/v8/V8DataModel.h | 6 +- .../plugins/datamodel/prolog/swi/SWIDataModel.cpp | 4 +- .../plugins/datamodel/prolog/swi/SWIDataModel.h | 6 +- .../invoker/graphics/openscenegraph/OSGInvoker.cpp | 8 +- .../invoker/graphics/openscenegraph/OSGInvoker.h | 10 +- .../plugins/invoker/heartbeat/HeartbeatInvoker.cpp | 10 +- .../plugins/invoker/heartbeat/HeartbeatInvoker.h | 10 +- src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp | 19 +-- src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h | 11 +- .../plugins/invoker/umundo/UmundoInvoker.cpp | 22 +-- src/uscxml/plugins/invoker/umundo/UmundoInvoker.h | 10 +- .../basichttp/libevent/EventIOProcessor.cpp | 8 +- .../basichttp/libevent/EventIOProcessor.h | 6 +- test/CMakeLists.txt | 5 + test/src/test-url.cpp | 42 +++++ 23 files changed, 403 insertions(+), 264 deletions(-) create mode 100644 test/src/test-url.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c7d0ca2..0c24682 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -557,10 +557,11 @@ elseif(WIN32) endif() find_package(OpenSceneGraph COMPONENTS osgViewer osgGA osgText osgFX osgManipulator osgDB osgUtil OpenThreads) -if (OPENSCENEGRAPH_FOUND) - set(CAN_BUILD_OPENSCENEGRAPH_INVOKER ON) +find_package(OpenGL) +if (OPENSCENEGRAPH_FOUND AND OPENGL_FOUND) include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS}) + include_directories(${OPENGL_INCLUDE_DIR}) file(GLOB_RECURSE OPENSCENEGRAPH_INVOKER src/uscxml/plugins/invoker/graphics/openscenegraph/*.cpp src/uscxml/plugins/invoker/graphics/openscenegraph/*.h) @@ -571,11 +572,12 @@ if (OPENSCENEGRAPH_FOUND) ${OPENSCENEGRAPH_INVOKER}) target_link_libraries(invoker_openscenegraph ${OPENSCENEGRAPH_LIBRARIES} + ${OPENGL_LIBRARIES} uscxml) set_target_properties(invoker_openscenegraph PROPERTIES FOLDER "Plugin Invoker") else() list (APPEND USCXML_FILES ${OPENSCENEGRAPH_INVOKER}) - list (APPEND USCXML_OPT_LIBS ${OPENSCENEGRAPH_LIBRARIES}) + list (APPEND USCXML_OPT_LIBS ${OPENSCENEGRAPH_LIBRARIES} ${OPENGL_LIBRARIES}) endif() endif() diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp index 3cac6b1..478d282 100644 --- a/src/uscxml/Factory.cpp +++ b/src/uscxml/Factory.cpp @@ -127,7 +127,7 @@ Factory::~Factory() { #endif } -void Factory::registerIOProcessor(IOProcessor* ioProcessor) { +void Factory::registerIOProcessor(IOProcessorImpl* ioProcessor) { std::set names = ioProcessor->getNames(); std::set::iterator nameIter = names.begin(); if (nameIter != names.end()) { @@ -140,7 +140,7 @@ void Factory::registerIOProcessor(IOProcessor* ioProcessor) { } } -void Factory::registerDataModel(DataModel* dataModel) { +void Factory::registerDataModel(DataModelImpl* dataModel) { std::set names = dataModel->getNames(); std::set::iterator nameIter = names.begin(); if (nameIter != names.end()) { @@ -153,7 +153,7 @@ void Factory::registerDataModel(DataModel* dataModel) { } } -void Factory::registerInvoker(Invoker* invoker) { +void Factory::registerInvoker(InvokerImpl* invoker) { std::set names = invoker->getNames(); std::set::iterator nameIter = names.begin(); if (nameIter != names.end()) { @@ -166,55 +166,42 @@ void Factory::registerInvoker(Invoker* invoker) { } } -void Factory::registerExecutableContent(const std::string tag, ExecutableContent* executableContent) { - _executableContent[tag] = executableContent; -} - -Invoker* Factory::getInvoker(const std::string type, Interpreter* interpreter) { +boost::shared_ptr Factory::createInvoker(const std::string& type, Interpreter* interpreter) { Factory* factory = getInstance(); if (factory->_invokerAliases.find(type) == factory->_invokerAliases.end()) - return NULL; + return boost::shared_ptr(); std::string canonicalName = factory->_invokerAliases[type]; if (factory->_invokers.find(canonicalName) == factory->_invokers.end()) - return NULL; + return boost::shared_ptr(); - return factory->_invokers[canonicalName]->create(interpreter); + return boost::shared_ptr(factory->_invokers[canonicalName]->create(interpreter)); } -DataModel* Factory::getDataModel(const std::string type, Interpreter* interpreter) { +boost::shared_ptr Factory::createDataModel(const std::string& type, Interpreter* interpreter) { Factory* factory = getInstance(); if (factory->_dataModelAliases.find(type) == factory->_dataModelAliases.end()) - return NULL; + return boost::shared_ptr(); std::string canonicalName = factory->_dataModelAliases[type]; if (factory->_dataModels.find(canonicalName) == factory->_dataModels.end()) - return NULL; + return boost::shared_ptr(); - return factory->_dataModels[canonicalName]->create(interpreter); + return boost::shared_ptr(factory->_dataModels[canonicalName]->create(interpreter)); } -IOProcessor* Factory::getIOProcessor(const std::string type, Interpreter* interpreter) { +boost::shared_ptr Factory::createIOProcessor(const std::string& type, Interpreter* interpreter) { Factory* factory = getInstance(); if (factory->_ioProcessorAliases.find(type) == factory->_ioProcessorAliases.end()) - return NULL; + return boost::shared_ptr(); std::string canonicalName = factory->_ioProcessorAliases[type]; if (factory->_ioProcessors.find(canonicalName) == factory->_ioProcessors.end()) - return NULL; + return boost::shared_ptr(); - return factory->_ioProcessors[canonicalName]->create(interpreter); + return boost::shared_ptr(factory->_ioProcessors[canonicalName]->create(interpreter)); } -#if 0 -ExecutableContent* Factory::getExecutableContent(const std::string tag, Interpreter* interpreter) { - Factory* factory = getInstance(); - if (factory->_executableContent.find(tag) != factory->_executableContent.end()) { - return factory->_executableContent[tag]->create(interpreter); - } - return NULL; -} -#endif Factory* Factory::getInstance() { if (_instance == NULL) { diff --git a/src/uscxml/Factory.h b/src/uscxml/Factory.h index 16b26da..09bab7b 100644 --- a/src/uscxml/Factory.h +++ b/src/uscxml/Factory.h @@ -9,6 +9,7 @@ #include #include +#include namespace uscxml { @@ -33,12 +34,12 @@ public: ExecutableContent() {}; virtual ExecutableContent* create(Interpreter* interpreter) = 0; }; - -class IOProcessor { + +class IOProcessorImpl { public: - IOProcessor() {}; - virtual ~IOProcessor() {}; - virtual IOProcessor* create(Interpreter* interpreter) = 0; + IOProcessorImpl() {}; + virtual ~IOProcessorImpl() {}; + virtual IOProcessorImpl* create(Interpreter* interpreter) = 0; virtual std::set getNames() = 0; virtual void setInterpreter(Interpreter* interpreter) { @@ -46,7 +47,7 @@ public: } virtual Data getDataModelVariables() = 0; - virtual void send(SendRequest& req) = 0; + virtual void send(const SendRequest& req) = 0; virtual void runOnMainThread() {}; @@ -54,24 +55,69 @@ protected: Interpreter* _interpreter; }; -class Invoker : public IOProcessor { +class IOProcessor { +public: + IOProcessor() : _impl() {} + IOProcessor(boost::shared_ptr const impl) : _impl(impl) { } + IOProcessor(const IOProcessor& other) : _impl(other._impl) { } + virtual ~IOProcessor() {}; + + operator bool() const { return _impl;} + bool operator< (const IOProcessor& other) const { return _impl < other._impl; } + bool operator==(const IOProcessor& other) const { return _impl == other._impl; } + bool operator!=(const IOProcessor& other) const { return _impl != other._impl; } + IOProcessor& operator= (const IOProcessor& other) { _impl = other._impl; return *this; } + + virtual Data getDataModelVariables() const { return _impl->getDataModelVariables(); }; + virtual void send(const SendRequest& req) { return _impl->send(req); }; + virtual void runOnMainThread() { return _impl->runOnMainThread(); } + +protected: + boost::shared_ptr _impl; +}; + +class InvokerImpl : public IOProcessorImpl { public: - virtual void invoke(InvokeRequest& req) = 0; - virtual void sendToParent(SendRequest& req) = 0; - virtual Invoker* create(Interpreter* interpreter) = 0; + virtual void invoke(const InvokeRequest& req) = 0; + virtual void sendToParent(const SendRequest& req) = 0; + virtual InvokerImpl* create(Interpreter* interpreter) = 0; }; -class DataModel { +class Invoker : public IOProcessor { public: - virtual ~DataModel() {} - virtual DataModel* create(Interpreter* interpreter) = 0; + Invoker() : _impl() {} + Invoker(boost::shared_ptr const impl) : IOProcessor(impl), _impl(impl) { } + Invoker(const Invoker& other) : IOProcessor(other._impl), _impl(other._impl) { } + virtual ~Invoker() {}; + + operator bool() const { return _impl;} + bool operator< (const Invoker& other) const { return _impl < other._impl; } + bool operator==(const Invoker& other) const { return _impl == other._impl; } + bool operator!=(const Invoker& other) const { return _impl != other._impl; } + Invoker& operator= (const Invoker& other) { + _impl = other._impl; + IOProcessor::_impl = _impl; + return *this; + } + + virtual void invoke(InvokeRequest& req) { _impl->invoke(req); } + virtual void sendToParent(SendRequest& req) { _impl->sendToParent(req); } + +protected: + boost::shared_ptr _impl; +}; + +class DataModelImpl { +public: + virtual ~DataModelImpl() {} + virtual DataModelImpl* create(Interpreter* interpreter) = 0; virtual std::set getNames() = 0; virtual bool validate(const std::string& location, const std::string& schema) = 0; virtual void setEvent(const Event& event) = 0; virtual Data getStringAsData(const std::string& content) = 0; - virtual void registerIOProcessor(const std::string& name, IOProcessor* ioprocessor) = 0; + virtual void registerIOProcessor(const std::string& name, const IOProcessor& ioprocessor) = 0; // foreach virtual uint32_t getLength(const std::string& expr) = 0; @@ -85,27 +131,57 @@ public: virtual void assign(const std::string& location, const Data& data) = 0; }; +class DataModel { +public: + DataModel() : _impl() {} + DataModel(boost::shared_ptr const impl) : _impl(impl) { } + DataModel(const DataModel& other) : _impl(other._impl) { } + virtual ~DataModel() {}; + + operator bool() const { return _impl;} + bool operator< (const DataModel& other) const { return _impl < other._impl; } + bool operator==(const DataModel& other) const { return _impl == other._impl; } + bool operator!=(const DataModel& other) const { return _impl != other._impl; } + DataModel& operator= (const DataModel& other) { _impl = other._impl; return *this; } + + virtual bool validate(const std::string& location, const std::string& schema) { return _impl->validate(location, schema); } + virtual void setEvent(const Event& event) { return _impl->setEvent(event); } + virtual Data getStringAsData(const std::string& content) { return _impl->getStringAsData(content); } + + virtual uint32_t getLength(const std::string& expr) { return _impl->getLength(expr); } + virtual void pushContext() { return _impl->pushContext(); } + virtual void popContext() { return _impl->popContext(); } + + virtual void registerIOProcessor(const std::string& name, const IOProcessor& ioprocessor) { _impl->registerIOProcessor(name, ioprocessor); } + + virtual void eval(const std::string& expr) { return _impl->eval(expr); } + virtual std::string evalAsString(const std::string& expr) { return _impl->evalAsString(expr); } + virtual bool evalAsBool(const std::string& expr) { return _impl->evalAsBool(expr); } + virtual void assign(const std::string& location, const std::string& expr) { return _impl->assign(location, expr); } + virtual void assign(const std::string& location, const Data& data) { return _impl->assign(location, data); } + +protected: + boost::shared_ptr _impl; +}; + class Factory { public: - void registerIOProcessor(IOProcessor* ioProcessor); - void registerDataModel(DataModel* dataModel); - void registerInvoker(Invoker* invoker); - void registerExecutableContent(const std::string tag, ExecutableContent* executableContent); + void registerIOProcessor(IOProcessorImpl* ioProcessor); + void registerDataModel(DataModelImpl* dataModel); + void registerInvoker(InvokerImpl* invoker); - static DataModel* getDataModel(const std::string type, Interpreter* interpreter); - static IOProcessor* getIOProcessor(const std::string type, Interpreter* interpreter); - static ExecutableContent* getExecutableContent(const std::string tag, Interpreter* interpreter); - static Invoker* getInvoker(const std::string type, Interpreter* interpreter); + static boost::shared_ptr createDataModel(const std::string& type, Interpreter* interpreter); + static boost::shared_ptr createIOProcessor(const std::string& type, Interpreter* interpreter); + static boost::shared_ptr createInvoker(const std::string& type, Interpreter* interpreter); static Factory* getInstance(); - std::map _dataModels; + std::map _dataModels; std::map _dataModelAliases; - std::map _ioProcessors; + std::map _ioProcessors; std::map _ioProcessorAliases; - std::map _invokers; + std::map _invokers; std::map _invokerAliases; - std::map _executableContent; static std::string pluginPath; diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 453bdd5..5681ff9 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -52,16 +52,23 @@ Interpreter* Interpreter::fromXML(const std::string& xml) { } Interpreter* Interpreter::fromURI(const std::string& uri) { - Arabica::SAX::InputSource inputSource(uri); + URL absUrl(uri); + if (!absUrl.isAbsolute()) { + if (!absUrl.toAbsoluteCwd()) { + LOG(ERROR) << "Given URL is not absolute or does not have file schema"; + return NULL; + } + } + Arabica::SAX::InputSource inputSource(absUrl.asString()); Interpreter* interpreter = fromInputSource(inputSource); // try to establish URI root for relative src attributes in document if (interpreter) - interpreter->_baseURI = toBaseURI(Arabica::io::URI(uri)); + interpreter->_baseURI = toBaseURI(absUrl); return interpreter; } -Arabica::io::URI Interpreter::toBaseURI(const Arabica::io::URI& uri) { +URL Interpreter::toBaseURI(const URL& uri) { std::stringstream ssBaseURI; if (uri.scheme().size() > 0) { ssBaseURI << uri.scheme() << "://"; @@ -75,30 +82,20 @@ Arabica::io::URI Interpreter::toBaseURI(const Arabica::io::URI& uri) { } if (uri.path().size() > 0) { std::string uriPath = uri.path(); - uriPath = uriPath.substr(0, uriPath.find_last_of("/\\")); + uriPath = uriPath.substr(0, uriPath.find_last_of("/\\") + 1); ssBaseURI << uriPath; } - return Arabica::io::URI(ssBaseURI.str()); + return URL(ssBaseURI.str()); } -bool Interpreter::makeAbsolute(Arabica::io::URI& uri) { - if (uri.is_absolute()) +bool Interpreter::toAbsoluteURI(URL& uri) { + if (uri.isAbsolute()) return true; - if (_baseURI.as_string().size() > 0) { - std::stringstream ssAbsoluteURI; - if (_baseURI.scheme().size() > 0) - ssAbsoluteURI << _baseURI.scheme() << "://"; - if (_baseURI.host().size() > 0) { - ssAbsoluteURI << _baseURI.host(); - if (!boost::iequals(_baseURI.port(), "0")) - ssAbsoluteURI << ":" << _baseURI.port(); - } - if (_baseURI.path().size() > 0) { - ssAbsoluteURI << _baseURI.path() << "/" << uri.path(); - } - uri = Arabica::io::URI(ssAbsoluteURI.str()); - return true; + if (_baseURI.asString().size() > 0) { + if (uri.toAbsolute(_baseURI)); + return true; + return false; } return false; } @@ -114,13 +111,13 @@ Interpreter* Interpreter::fromInputSource(Arabica::SAX::InputSource Arabica::SAX::CatchErrorHandler errorHandler; interpreter->setErrorHandler(errorHandler); if(!interpreter->parse(source) || !interpreter->Arabica::SAX2DOM::Parser::getDocument().hasChildNodes()) { - LOG(INFO) << "could not parse input:"; if(errorHandler.errorsReported()) { + LOG(ERROR) << "could not parse input:"; LOG(ERROR) << errorHandler.errors() << std::endl; } else { Arabica::SAX::InputSourceResolver resolver(source, Arabica::default_string_adaptor()); if (!resolver.resolve()) { - LOG(ERROR) << "no such file"; + LOG(ERROR) << source.getSystemId() << ": no such file"; } } return NULL; @@ -134,8 +131,6 @@ Interpreter* Interpreter::fromInputSource(Arabica::SAX::InputSource void Interpreter::init() { _lastRunOnMainThread = 0; _thread = NULL; - _dataModel = NULL; - _invoker = NULL; _running = false; _sendQueue = new DelayedEventQueue(); _sendQueue->start(); @@ -163,18 +158,12 @@ void Interpreter::init() { } Interpreter::~Interpreter() { - std::map::iterator ioProcessorIter = _ioProcessors.begin(); - while(ioProcessorIter != _ioProcessors.end()) { - delete ioProcessorIter->second; - ioProcessorIter++; - } if (_thread) { _running = false; _externalQueue.push(Event()); _thread->join(); delete(_thread); } - delete _dataModel; delete _sendQueue; } @@ -200,15 +189,15 @@ bool Interpreter::runOnMainThread(int fps, bool blocking) { _lastRunOnMainThread = tthread::timeStamp(); - std::map::iterator ioProcessorIter = _ioProcessors.begin(); + std::map::iterator ioProcessorIter = _ioProcessors.begin(); while(ioProcessorIter != _ioProcessors.end()) { - ioProcessorIter->second->runOnMainThread(); + ioProcessorIter->second.runOnMainThread(); ioProcessorIter++; } - std::map::iterator invokerIter = _invokers.begin(); + std::map::iterator invokerIter = _invokers.begin(); while(invokerIter != _invokers.end()) { - invokerIter->second->runOnMainThread(); + invokerIter->second.runOnMainThread(); invokerIter++; } @@ -229,8 +218,8 @@ void Interpreter::interpret() { _sessionId = getUUID(); if(HAS_ATTR(_scxml, "datamodel")) { - _dataModel = Factory::getDataModel(ATTR(_scxml, "datamodel"), this); - if(_dataModel == NULL) { + _dataModel = Factory::createDataModel(ATTR(_scxml, "datamodel"), this); + if(!_dataModel) { LOG(ERROR) << "No datamodel for " << ATTR(_scxml, "datamodel") << " registered"; return; } @@ -298,19 +287,19 @@ void Interpreter::initializeData(const Arabica::DOM::Node& data) { if (HAS_ATTR(data, "expr")) { std::string value = ATTR(data, "expr"); - _dataModel->assign(ATTR(data, "id"), value); + _dataModel.assign(ATTR(data, "id"), value); } else if (HAS_ATTR(data, "src")) { Arabica::SAX::InputSourceResolver resolver(Arabica::SAX::InputSource(ATTR(data, "src")), Arabica::default_string_adaptor()); std::string value = std::string(std::istreambuf_iterator(*resolver.resolve()), std::istreambuf_iterator()); - _dataModel->assign(ATTR(data, "id"), value); + _dataModel.assign(ATTR(data, "id"), value); } else if (data.hasChildNodes()) { // search for the text node with the actual script NodeList dataChilds = data.getChildNodes(); for (int i = 0; i < dataChilds.getLength(); i++) { if (dataChilds.item(i).getNodeType() == Node_base::TEXT_NODE) { Data value = Data(dataChilds.item(i).getNodeValue()); - _dataModel->assign(ATTR(data, "id"), value); + _dataModel.assign(ATTR(data, "id"), value); break; } } @@ -408,7 +397,7 @@ void Interpreter::mainEventLoop() { std::cout << "Received internal event " << internalEvent.name << std::endl; #endif if (_dataModel) - _dataModel->setEvent(internalEvent); + _dataModel.setEvent(internalEvent); enabledTransitions = selectTransitions(internalEvent.name); } } @@ -446,7 +435,7 @@ void Interpreter::mainEventLoop() { if (_dataModel) try { - _dataModel->setEvent(externalEvent); + _dataModel.setEvent(externalEvent); } catch (Event e) { LOG(ERROR) << "Syntax error while setting external event:" << std::endl << e << std::endl; } @@ -502,10 +491,10 @@ void Interpreter::internalDoneSend(const Arabica::DOM::Node& state) } std::string paramValue; if (HAS_ATTR(doneChilds.item(i), "expr") && _dataModel) { - std::string location = _dataModel->evalAsString(ATTR(doneChilds.item(i), "expr")); - paramValue = _dataModel->evalAsString(location); + std::string location = _dataModel.evalAsString(ATTR(doneChilds.item(i), "expr")); + paramValue = _dataModel.evalAsString(location); } else if(HAS_ATTR(doneChilds.item(i), "location") && _dataModel) { - paramValue = _dataModel->evalAsString(ATTR(doneChilds.item(i), "location")); + paramValue = _dataModel.evalAsString(ATTR(doneChilds.item(i), "location")); } else { LOG(ERROR) << "param element is missing expr or location or no datamodel is specified"; continue; @@ -515,7 +504,7 @@ void Interpreter::internalDoneSend(const Arabica::DOM::Node& state) if (boost::iequals(TAGNAME(doneChilds.item(i)), "content")) { if (HAS_ATTR(doneChilds.item(i), "expr")) { if (_dataModel) { - event.compound["content"] = Data(_dataModel->evalAsString(ATTR(doneChilds.item(i), "expr")), Data::VERBATIM); + event.compound["content"] = Data(_dataModel.evalAsString(ATTR(doneChilds.item(i), "expr")), Data::VERBATIM); } else { LOG(ERROR) << "content element has expr attribute but no datamodel is specified."; } @@ -539,19 +528,19 @@ void Interpreter::send(const Arabica::DOM::Node& element) { try { // event if (HAS_ATTR(element, "eventexpr") && _dataModel) { - sendReq.name = _dataModel->evalAsString(ATTR(element, "eventexpr")); + sendReq.name = _dataModel.evalAsString(ATTR(element, "eventexpr")); } else if (HAS_ATTR(element, "event")) { sendReq.name = ATTR(element, "event"); } // target if (HAS_ATTR(element, "targetexpr") && _dataModel) { - sendReq.target = _dataModel->evalAsString(ATTR(element, "targetexpr")); + sendReq.target = _dataModel.evalAsString(ATTR(element, "targetexpr")); } else if (HAS_ATTR(element, "target")) { sendReq.target = ATTR(element, "target"); } // type if (HAS_ATTR(element, "typeexpr") && _dataModel) { - sendReq.type = _dataModel->evalAsString(ATTR(element, "typeexpr")); + sendReq.type = _dataModel.evalAsString(ATTR(element, "typeexpr")); } else if (HAS_ATTR(element, "type")) { sendReq.type = ATTR(element, "type"); } else { @@ -559,7 +548,7 @@ void Interpreter::send(const Arabica::DOM::Node& element) { } // id if (HAS_ATTR(element, "idlocation") && _dataModel) { - sendReq.sendid = _dataModel->evalAsString(ATTR(element, "idlocation")); + sendReq.sendid = _dataModel.evalAsString(ATTR(element, "idlocation")); } else if (HAS_ATTR(element, "id")) { sendReq.sendid = ATTR(element, "id"); } else { @@ -588,7 +577,7 @@ void Interpreter::send(const Arabica::DOM::Node& element) { std::string delay; sendReq.delayMs = 0; if (HAS_ATTR(element, "delayexpr") && _dataModel) { - delay = _dataModel->evalAsString(ATTR(element, "delayexpr")); + delay = _dataModel.evalAsString(ATTR(element, "delayexpr")); } else if (HAS_ATTR(element, "delay")) { delay = ATTR(element, "delay"); } @@ -610,7 +599,7 @@ void Interpreter::send(const Arabica::DOM::Node& element) { if (HAS_ATTR(element, "namelist")) { std::vector names = tokenizeIdRefs(ATTR(element, "namelist")); for (int i = 0; i < names.size(); i++) { - sendReq.namelist[names[i]] = _dataModel->evalAsString(names[i]); + sendReq.namelist[names[i]] = _dataModel.evalAsString(names[i]); } } @@ -623,9 +612,9 @@ void Interpreter::send(const Arabica::DOM::Node& element) { } std::string paramValue; if (HAS_ATTR(params[i], "expr") && _dataModel) { - paramValue = _dataModel->evalAsString(ATTR(params[i], "expr")); + paramValue = _dataModel.evalAsString(ATTR(params[i], "expr")); } else if(HAS_ATTR(params[i], "location") && _dataModel) { - paramValue = _dataModel->evalAsString(ATTR(params[i], "location")); + paramValue = _dataModel.evalAsString(ATTR(params[i], "location")); } else { LOG(ERROR) << "param element is missing expr or location or no datamodel is specified"; continue; @@ -640,7 +629,7 @@ void Interpreter::send(const Arabica::DOM::Node& element) { if (contents.size() > 0) { if (HAS_ATTR(contents[0], "expr")) { if (_dataModel) { - sendReq.content = _dataModel->evalAsString(ATTR(contents[0], "expr")); + sendReq.content = _dataModel.evalAsString(ATTR(contents[0], "expr")); } else { LOG(ERROR) << "content element has expr attribute but no datamodel is specified."; } @@ -672,8 +661,8 @@ void Interpreter::delayedSend(void* userdata, std::string eventName) { if (boost::iequals(sendReq.target, "#_parent")) { // send to parent scxml session - if (INSTANCE->_invoker != NULL) { - INSTANCE->_invoker->sendToParent(sendReq); + if (INSTANCE->_invoker) { + INSTANCE->_invoker.sendToParent(sendReq); } else { LOG(ERROR) << "Can not send to parent, we were not invoked" << std::endl; } @@ -681,16 +670,16 @@ void Interpreter::delayedSend(void* userdata, std::string eventName) { // send to invoker std::string invokeId = sendReq.target.substr(2, sendReq.target.length() - 2); if (INSTANCE->_invokers.find(invokeId) != INSTANCE->_invokers.end()) { - INSTANCE->_invokers[invokeId]->send(sendReq); + INSTANCE->_invokers[invokeId].send(sendReq); } else { LOG(ERROR) << "Can not send to invoked component '" << invokeId << "', no such invokeId" << std::endl; } } else if (sendReq.target.length() == 0) { INSTANCE->receive(sendReq); } else { - IOProcessor* ioProc = INSTANCE->getIOProcessor(sendReq.type); - if (ioProc != NULL) { - ioProc->send(sendReq); + IOProcessor ioProc = INSTANCE->getIOProcessor(sendReq.type); + if (ioProc) { + ioProc.send(sendReq); } } assert(INSTANCE->_sendIds.find(sendReq.sendid) != INSTANCE->_sendIds.end()); @@ -704,7 +693,7 @@ void Interpreter::invoke(const Arabica::DOM::Node& element) { try { // type if (HAS_ATTR(element, "typeexpr") && _dataModel) { - invokeReq.type = _dataModel->evalAsString(ATTR(element, "typeexpr")); + invokeReq.type = _dataModel.evalAsString(ATTR(element, "typeexpr")); } else if (HAS_ATTR(element, "type")) { invokeReq.type = ATTR(element, "type"); } else { @@ -714,22 +703,22 @@ void Interpreter::invoke(const Arabica::DOM::Node& element) { // src std::string source; if (HAS_ATTR(element, "srcexpr") && _dataModel) { - source = _dataModel->evalAsString(ATTR(element, "srcexpr")); + source = _dataModel.evalAsString(ATTR(element, "srcexpr")); } else if (HAS_ATTR(element, "src")) { source = ATTR(element, "src"); } if (source.length() > 0) { - Arabica::io::URI srcURI(source); - if (!makeAbsolute(srcURI)) { + URL srcURI(source); + if (!toAbsoluteURI(srcURI)) { LOG(ERROR) << "invoke element has relative src URI with no baseURI set."; return; } - invokeReq.src = srcURI.as_string(); + invokeReq.src = srcURI.asString(); } // id if (HAS_ATTR(element, "idlocation") && _dataModel) { - invokeReq.invokeid = _dataModel->evalAsString(ATTR(element, "idlocation")); + invokeReq.invokeid = _dataModel.evalAsString(ATTR(element, "idlocation")); } else if (HAS_ATTR(element, "id")) { invokeReq.invokeid = ATTR(element, "id"); } else { @@ -760,12 +749,12 @@ void Interpreter::invoke(const Arabica::DOM::Node& element) { std::string paramValue; if (HAS_ATTR(params[i], "expr")) { if (_dataModel) { - paramValue = _dataModel->evalAsString(ATTR(params[i], "expr")); + paramValue = _dataModel.evalAsString(ATTR(params[i], "expr")); } else { paramValue = ATTR(params[i], "expr"); } } else if(HAS_ATTR(params[i], "location") && _dataModel) { - paramValue = _dataModel->evalAsString(ATTR(params[i], "location")); + paramValue = _dataModel.evalAsString(ATTR(params[i], "location")); } else { LOG(ERROR) << "param element is missing expr or location or no datamodel is specified"; continue; @@ -783,11 +772,11 @@ void Interpreter::invoke(const Arabica::DOM::Node& element) { invokeReq.content = contents[0].getNodeValue(); } - Invoker* invoker = Factory::getInvoker(invokeReq.type, this); - if (invoker != NULL) { + Invoker invoker(Factory::createInvoker(invokeReq.type, this)); + if (invoker) { _invokers[invokeReq.invokeid] = invoker; LOG(INFO) << "Added invoker " << invokeReq.type << " at " << invokeReq.invokeid; - invoker->invoke(invokeReq); + invoker.invoke(invokeReq); } else { LOG(ERROR) << "No invoker known for type " << invokeReq.type; } @@ -800,7 +789,7 @@ void Interpreter::invoke(const Arabica::DOM::Node& element) { void Interpreter::cancelInvoke(const Arabica::DOM::Node& element) { std::string invokeId; if (HAS_ATTR(element, "idlocation") && _dataModel) { - invokeId = _dataModel->evalAsString(ATTR(element, "idlocation")); + invokeId = _dataModel.evalAsString(ATTR(element, "idlocation")); } else if (HAS_ATTR(element, "id")) { invokeId = ATTR(element, "id"); } else { @@ -808,7 +797,6 @@ void Interpreter::cancelInvoke(const Arabica::DOM::Node& element) { } if (_invokers.find(invokeId) != _invokers.end()) { LOG(INFO) << "Removed invoker at " << invokeId; - delete (_invokers[invokeId]); _invokers.erase(invokeId); } else { LOG(ERROR) << "Cannot cancel invoke for id " << invokeId << ": no soch invokation"; @@ -930,7 +918,7 @@ LOOP: bool Interpreter::hasConditionMatch(const Arabica::DOM::Node& conditional) { try { if (_dataModel && HAS_ATTR(conditional, "cond")) - return _dataModel->evalAsBool(ATTR(conditional, "cond")); + return _dataModel.evalAsBool(ATTR(conditional, "cond")); } catch (Event e) { LOG(ERROR) << "Syntax error in cond attribute of " << TAGNAME(conditional) << " element:" << std::endl << e << std::endl; return false; @@ -1073,25 +1061,25 @@ ELSIF_ELEM_MATCH: std::string array = ATTR(content, "array"); std::string item = ATTR(content, "item"); std::string index = (HAS_ATTR(content, "index") ? ATTR(content, "index") : ""); - uint32_t iterations = _dataModel->getLength(array); - _dataModel->pushContext(); // copy old and enter new context + uint32_t iterations = _dataModel.getLength(array); + _dataModel.pushContext(); // copy old and enter new context for (uint32_t iteration = 0; iteration < iterations; iteration++) { { // assign array element to item std::stringstream ss; ss << array << "[" << iteration << "]"; - _dataModel->assign(item, ss.str()); + _dataModel.assign(item, ss.str()); } if (index.length() > 0) { // assign iteration element to index std::stringstream ss; ss << iteration; - _dataModel->assign(index,ss.str()); + _dataModel.assign(index,ss.str()); } if (content.hasChildNodes()) executeContent(content.getChildNodes()); } - _dataModel->popContext(); // leave stacked context + _dataModel.popContext(); // leave stacked context } else { LOG(ERROR) << "Expected array and item attributes with foreach element!" << std::endl; } @@ -1102,7 +1090,7 @@ ELSIF_ELEM_MATCH: if (logElem.hasAttribute("expr")) { if (_dataModel) { try { - std::cout << _dataModel->evalAsString(logElem.getAttribute("expr")) << std::endl; + std::cout << _dataModel.evalAsString(logElem.getAttribute("expr")) << std::endl; } catch (Event e) { LOG(ERROR) << "Syntax error in expr attribute of log element:" << std::endl << e << std::endl; } @@ -1114,7 +1102,7 @@ ELSIF_ELEM_MATCH: // --- ASSIGN -------------------------- if (_dataModel && HAS_ATTR(content, "location") && HAS_ATTR(content, "expr")) { try { - _dataModel->assign(ATTR(content, "location"), ATTR(content, "expr")); + _dataModel.assign(ATTR(content, "location"), ATTR(content, "expr")); } catch (Event e) { LOG(ERROR) << "Syntax error in attributes of assign element:" << std::endl << e << std::endl; } @@ -1124,24 +1112,23 @@ ELSIF_ELEM_MATCH: if (_dataModel) { std::string location = (HAS_ATTR(content, "location") ? ATTR(content, "location") : ""); std::string schema = (HAS_ATTR(content, "schema") ? ATTR(content, "schema") : ""); - _dataModel->validate(location, schema); + _dataModel.validate(location, schema); } } else if (boost::iequals(TAGNAME(content), "script")) { // --- SCRIPT -------------------------- if (_dataModel) { if (HAS_ATTR(content, "src")) { - Arabica::io::URI url(ATTR(content, "src")); - if (!makeAbsolute(url)) { + URL scriptUrl(ATTR(content, "src")); + if (!toAbsoluteURI(scriptUrl)) { LOG(ERROR) << "script element has relative URI " << ATTR(content, "src") << " with no base URI set for interpreter"; return; } std::stringstream srcContent; - URL scriptUrl(url.as_string()); srcContent << scriptUrl; try { - _dataModel->eval(srcContent.str()); + _dataModel.eval(srcContent.str()); } catch (Event e) { LOG(ERROR) << "Syntax error while executing script element from '" << ATTR(content, "src") << "':" << std::endl << e << std::endl; } @@ -1150,7 +1137,7 @@ ELSIF_ELEM_MATCH: // search for the text node with the actual script if (content.getFirstChild().getNodeType() == Node_base::TEXT_NODE) { try { - _dataModel->eval(content.getFirstChild().getNodeValue()); + _dataModel.eval(content.getFirstChild().getNodeValue()); } catch (Event e) { LOG(ERROR) << "Syntax error while executing script element" << std::endl << e << std::endl; } @@ -1166,7 +1153,7 @@ ELSIF_ELEM_MATCH: std::string sendId; try { if (HAS_ATTR(content, "sendidexpr")) { - sendId = _dataModel->evalAsString(ATTR(content, "sendidexpr")); + sendId = _dataModel.evalAsString(ATTR(content, "sendidexpr")); } else if(HAS_ATTR(content, "sendid")) { sendId = ATTR(content, "sendid"); } else { @@ -1806,12 +1793,12 @@ bool Interpreter::isCompound(const Arabica::DOM::Node& state) { } void Interpreter::setupIOProcessors() { - std::map::iterator ioProcIter = Factory::getInstance()->_ioProcessors.begin(); + std::map::iterator ioProcIter = Factory::getInstance()->_ioProcessors.begin(); while(ioProcIter != Factory::getInstance()->_ioProcessors.end()) { - _ioProcessors[ioProcIter->first] = Factory::getIOProcessor(ioProcIter->first, this); + _ioProcessors[ioProcIter->first] = Factory::createIOProcessor(ioProcIter->first, this); if (_dataModel) { try { - _dataModel->registerIOProcessor(ioProcIter->first, _ioProcessors[ioProcIter->first]); + _dataModel.registerIOProcessor(ioProcIter->first, _ioProcessors[ioProcIter->first]); } catch (Event e) { LOG(ERROR) << "Syntax error when setting _ioprocessors:" << std::endl << e << std::endl; } @@ -1822,10 +1809,10 @@ void Interpreter::setupIOProcessors() { } } -IOProcessor* Interpreter::getIOProcessor(const std::string& type) { +IOProcessor Interpreter::getIOProcessor(const std::string& type) { if (_ioProcessors.find(type) == _ioProcessors.end()) { LOG(ERROR) << "No ioProcessor known for type " << type; - return NULL; + return IOProcessor(); } return _ioProcessors[type]; } @@ -1842,7 +1829,7 @@ bool Interpreter::validate() { bool validationErrors = false; if (!_document) { - LOG(ERROR) << "Document " << _baseURI.as_string() << " was not parsed successfully" << std::endl; + LOG(ERROR) << "Document " << _baseURI.asString() << " was not parsed successfully" << std::endl; return false; } diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index edfdfd2..33204b5 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -2,6 +2,7 @@ #define RUNTIME_H_SQ1MBKGN #include "uscxml/Common.h" +#include "uscxml/URL.h" #include #include @@ -76,20 +77,19 @@ public: bool validate(); void setBaseURI(std::string baseURI) { - _baseURI = Arabica::io::URI(baseURI); + _baseURI = URL(baseURI); } - std::string getBaseURI() { - return _baseURI.as_string(); + URL getBaseURI() { + return _baseURI; } - bool makeAbsolute(Arabica::io::URI& uri); - DataModel* getDataModel() { + DataModel getDataModel() { return _dataModel; } - Invoker* getInvoker() { + Invoker getInvoker() { return _invoker; } - void setInvoker(Invoker* invoker) { + void setInvoker(const Invoker& invoker) { _invoker = invoker; } std::string getNSPrefix() { @@ -162,7 +162,7 @@ protected: tthread::mutex _mutex; tthread::condition_variable _stabilized; - Arabica::io::URI _baseURI; + URL _baseURI; Arabica::DOM::Document _document; Arabica::DOM::Element _scxml; Arabica::XPath::XPath _xpath; @@ -174,15 +174,16 @@ protected: Arabica::XPath::NodeSet _configuration; Arabica::XPath::NodeSet _statesToInvoke; - DataModel* _dataModel; + DataModel _dataModel; std::map > _historyValue; std::list _internalQueue; uscxml::concurrency::BlockingQueue _externalQueue; DelayedEventQueue* _sendQueue; - Invoker* _invoker; + Invoker _invoker; - static Arabica::io::URI toBaseURI(const Arabica::io::URI& uri); + static URL toBaseURI(const URL& url); + bool toAbsoluteURI(URL& uri); void microstep(const Arabica::XPath::NodeSet& enabledTransitions); void exitStates(const Arabica::XPath::NodeSet& enabledTransitions); @@ -227,12 +228,12 @@ protected: std::string _name; std::string _sessionId; - IOProcessor* getIOProcessor(const std::string& type); + IOProcessor getIOProcessor(const std::string& type); // IOProcessor* getIOProcessorForId(const std::string& sendId); - std::map _ioProcessors; + std::map _ioProcessors; std::map > _sendIds; - std::map _invokers; + std::map _invokers; /// We need to remember to adapt them when the DOM is operated upon std::map > _cachedStates; diff --git a/src/uscxml/URL.cpp b/src/uscxml/URL.cpp index 592c0c6..59fca34 100644 --- a/src/uscxml/URL.cpp +++ b/src/uscxml/URL.cpp @@ -19,6 +19,14 @@ #include "uscxml/config.h" +#include /* defines FILENAME_MAX */ +#ifdef WIN32 +#include +#define getcwd _getcwd +#else +#include +#endif + #include // mkstemp #ifdef HAS_UNISTD_H #include // mkstemp legacy @@ -26,38 +34,30 @@ namespace uscxml { -URL::~URL() { +URLImpl::~URLImpl() { if (_localFile.length() > 0) remove(_localFile.c_str()); } - -const bool URL::toAbsolute(const std::string& baseUrl) { + +const bool URLImpl::toAbsoluteCwd() { + char currPath[FILENAME_MAX]; + if (!getcwd(currPath, sizeof(currPath))) { + return false; + } + currPath[sizeof(currPath) - 1] = '\0'; /* not really required */ + return toAbsolute(std::string("file://" + std::string(currPath) + "/")); +} + +const bool URLImpl::toAbsolute(const std::string& baseUrl) { if (_uri.is_absolute()) return true; - - Arabica::io::URI baseUri(baseUrl); - if (!baseUri.is_absolute()) + _uri = Arabica::io::URI(baseUrl, _uri.as_string()); + if (!_uri.is_absolute()) return false; - - std::stringstream ssAbsoluteURI; - if (baseUri.scheme().size() > 0) - ssAbsoluteURI << baseUri.scheme() << "://"; - if (baseUri.host().size() > 0) { - ssAbsoluteURI << baseUri.host(); - if (!boost::iequals(baseUri.port(), "0")) - ssAbsoluteURI << ":" << baseUri.port(); - } - if (baseUri.path().size() > 0) { - ssAbsoluteURI << baseUri.path() << "/" << _uri.path(); - } else { - ssAbsoluteURI << "/" << _uri.path(); - } - _uri = Arabica::io::URI(ssAbsoluteURI.str()); - assert(_uri.is_absolute()); return true; } -const std::string URL::asLocalFile(const std::string& suffix, bool reload) { +const std::string URLImpl::asLocalFile(const std::string& suffix, bool reload) { // this is already a local file if (_uri.scheme().compare("file") == 0) return _uri.path(); @@ -69,7 +69,7 @@ const std::string URL::asLocalFile(const std::string& suffix, bool reload) { remove(_localFile.c_str()); // try hard to find a temporary directory - char* tmpDir = NULL; + const char* tmpDir = NULL; if (tmpDir == NULL) tmpDir = getenv("TMPDIR"); if (tmpDir == NULL) @@ -78,6 +78,8 @@ const std::string URL::asLocalFile(const std::string& suffix, bool reload) { tmpDir = getenv("TEMP"); if (tmpDir == NULL) tmpDir = getenv("USERPROFILE"); + if (tmpDir == NULL) + tmpDir = "/tmp"; char* tmpl = (char*)malloc(strlen(tmpDir) + 11 + suffix.length()); char* writePtr = tmpl; @@ -97,7 +99,7 @@ const std::string URL::asLocalFile(const std::string& suffix, bool reload) { std::ofstream file(tmpl, std::ios_base::out); if(file.is_open()) { - file << *this; + file << URL(this->shared_from_this()); file.close(); } else { _localFile = ""; diff --git a/src/uscxml/URL.h b/src/uscxml/URL.h index 3a87fb1..07921f3 100644 --- a/src/uscxml/URL.h +++ b/src/uscxml/URL.h @@ -8,13 +8,17 @@ // use arabica URL parser #include -namespace uscxml { +#include +#include -class URL { +namespace uscxml { + +class URLImpl : public boost::enable_shared_from_this { public: - URL() {} - URL(const std::string uri) : _uri(uri) {} - virtual ~URL(); + URLImpl() {} + URLImpl(const std::string uri) : _uri(uri) {} + virtual ~URLImpl(); + const bool toAbsoluteCwd(); const bool toAbsolute(const std::string& baseUrl); const std::string asLocalFile(const std::string& suffix, bool reload = false); @@ -28,9 +32,40 @@ public: private: Arabica::io::URI _uri; std::string _localFile; - friend std::ostream & operator<<(std::ostream &stream, const URL& p); }; +class URL { +public: + URL() : _impl() {} + URL(const std::string uri) : _impl(new URLImpl(uri)) {} + URL(boost::shared_ptr const impl) : _impl(impl) { } + URL(const URL& other) : _impl(other._impl) { } + virtual ~URL() {}; + + operator bool() const { return _impl;} + bool operator< (const URL& other) const { return _impl < other._impl; } + bool operator==(const URL& other) const { return _impl == other._impl; } + bool operator!=(const URL& other) const { return _impl != other._impl; } + URL& operator= (const URL& other) { _impl = other._impl; return *this; } + + const bool toAbsoluteCwd() { return _impl->toAbsoluteCwd(); } + const bool toAbsolute(const std::string& baseUrl) { return _impl->toAbsolute(baseUrl); } + const bool toAbsolute(const URL& baseUrl) { return _impl->toAbsolute(baseUrl.asString()); } + const std::string asLocalFile(const std::string& suffix, bool reload = false) { return _impl->asLocalFile(suffix, reload); } + + const bool isAbsolute() const { return _impl->isAbsolute(); } + const std::string scheme() const { return _impl->scheme(); } + const std::string host() const { return _impl->host(); } + const std::string port() const { return _impl->port(); } + const std::string path() const { return _impl->path(); } + const std::string asString() const { return _impl->asString(); } + + friend std::ostream & operator<<(std::ostream &stream, const URL& p); + +protected: + boost::shared_ptr _impl; +}; + enum fcurl_type_e { CFTYPE_NONE=0, CFTYPE_FILE=1, diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp index 3bdf28c..5ab9b3e 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp @@ -23,7 +23,7 @@ V8DataModel::V8DataModel() { // _contexts.push_back(v8::Context::New()); } -DataModel* V8DataModel::create(Interpreter* interpreter) { +DataModelImpl* V8DataModel::create(Interpreter* interpreter) { V8DataModel* dm = new V8DataModel(); dm->_interpreter = interpreter; v8::Locker locker; @@ -62,8 +62,8 @@ DataModel* V8DataModel::create(Interpreter* interpreter) { return dm; } -void V8DataModel::registerIOProcessor(const std::string& name, IOProcessor* ioprocessor) { - assign("_ioprocessors['" + name + "']", ioprocessor->getDataModelVariables()); +void V8DataModel::registerIOProcessor(const std::string& name, const IOProcessor& ioprocessor) { + assign("_ioprocessors['" + name + "']", ioprocessor.getDataModelVariables()); } void V8DataModel::setSessionId(const std::string& sessionId) { diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h index deee58c..e5c1bc8 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h @@ -17,11 +17,11 @@ class V8SCXMLDOM; namespace uscxml { -class V8DataModel : public DataModel { +class V8DataModel : public DataModelImpl { public: V8DataModel(); virtual ~V8DataModel(); - virtual DataModel* create(Interpreter* interpreter); + virtual DataModelImpl* create(Interpreter* interpreter); virtual std::set getNames() { std::set names; @@ -34,7 +34,7 @@ public: virtual void setName(const std::string& name); virtual void setEvent(const Event& event); - virtual void registerIOProcessor(const std::string& name, IOProcessor* ioprocessor); + virtual void registerIOProcessor(const std::string& name, const IOProcessor& ioprocessor); virtual bool validate(const std::string& location, const std::string& schema); diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp index 77f0b66..3e20867 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp @@ -20,7 +20,7 @@ bool connect(pluma::Host& host) { SWIDataModel::SWIDataModel() { } -DataModel* SWIDataModel::create(Interpreter* interpreter) { +DataModelImpl* SWIDataModel::create(Interpreter* interpreter) { SWIDataModel* dm = new SWIDataModel(); dm->_interpreter = interpreter; const char* swiPath = SWI_LIBRARY_PATH; @@ -28,7 +28,7 @@ DataModel* SWIDataModel::create(Interpreter* interpreter) { return dm; } -void SWIDataModel::registerIOProcessor(const std::string& name, IOProcessor* ioprocessor) { +void SWIDataModel::registerIOProcessor(const std::string& name, const IOProcessor& ioprocessor) { std::cout << "SWIDataModel::registerIOProcessor" << std::endl; } diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h index 16dee3c..f5f5247 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h @@ -11,11 +11,11 @@ namespace uscxml { -class SWIDataModel : public DataModel { +class SWIDataModel : public DataModelImpl { public: SWIDataModel(); virtual ~SWIDataModel(); - virtual DataModel* create(Interpreter* interpreter); + virtual DataModelImpl* create(Interpreter* interpreter); virtual std::set getNames() { std::set names; @@ -28,7 +28,7 @@ public: virtual void setName(const std::string& name); virtual void setEvent(const Event& event); - virtual void registerIOProcessor(const std::string& name, IOProcessor* ioprocessor); + virtual void registerIOProcessor(const std::string& name, const IOProcessor& ioprocessor); virtual bool validate(const std::string& location, const std::string& schema); diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp index 7a0e63a..94156c0 100644 --- a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp +++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp @@ -22,7 +22,7 @@ OSGInvoker::OSGInvoker() { OSGInvoker::~OSGInvoker() { }; -Invoker* OSGInvoker::create(Interpreter* interpreter) { +InvokerImpl* OSGInvoker::create(Interpreter* interpreter) { OSGInvoker* invoker = new OSGInvoker(); invoker->_interpreter = interpreter; return invoker; @@ -33,16 +33,16 @@ Data OSGInvoker::getDataModelVariables() { return data; } -void OSGInvoker::send(SendRequest& req) { +void OSGInvoker::send(const SendRequest& req) { } void OSGInvoker::cancel(const std::string sendId) { } -void OSGInvoker::sendToParent(SendRequest& req) { +void OSGInvoker::sendToParent(const SendRequest& req) { } -void OSGInvoker::invoke(InvokeRequest& req) { +void OSGInvoker::invoke(const InvokeRequest& req) { tthread::lock_guard lock(_mutex); // register default event handlers diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h index 90dda31..933ee4a 100644 --- a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h +++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h @@ -16,11 +16,11 @@ namespace uscxml { -class OSGInvoker : public Invoker, public Arabica::DOM::Events::EventListener { +class OSGInvoker : public InvokerImpl, public Arabica::DOM::Events::EventListener { public: OSGInvoker(); virtual ~OSGInvoker(); - virtual Invoker* create(Interpreter* interpreter); + virtual InvokerImpl* create(Interpreter* interpreter); virtual std::set getNames() { std::set names; @@ -31,10 +31,10 @@ public: } virtual Data getDataModelVariables(); - virtual void send(SendRequest& req); + virtual void send(const SendRequest& req); virtual void cancel(const std::string sendId); - virtual void invoke(InvokeRequest& req); - virtual void sendToParent(SendRequest& req); + virtual void invoke(const InvokeRequest& req); + virtual void sendToParent(const SendRequest& req); virtual void handleEvent(Arabica::DOM::Events::Event& event); virtual void runOnMainThread(); diff --git a/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.cpp b/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.cpp index 6bc06d9..eaf5eba 100644 --- a/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.cpp +++ b/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.cpp @@ -21,7 +21,7 @@ HeartbeatInvoker::HeartbeatInvoker() { HeartbeatInvoker::~HeartbeatInvoker() { }; -Invoker* HeartbeatInvoker::create(Interpreter* interpreter) { +InvokerImpl* HeartbeatInvoker::create(Interpreter* interpreter) { HeartbeatInvoker* invoker = new HeartbeatInvoker(); invoker->_interpreter = interpreter; return invoker; @@ -32,23 +32,23 @@ Data HeartbeatInvoker::getDataModelVariables() { return data; } -void HeartbeatInvoker::send(SendRequest& req) { +void HeartbeatInvoker::send(const SendRequest& req) { } void HeartbeatInvoker::cancel(const std::string sendId) { HeartbeatDispatcher::getInstance()->cancelEvent(toStr(this)); } -void HeartbeatInvoker::sendToParent(SendRequest& req) { +void HeartbeatInvoker::sendToParent(const SendRequest& req) { } -void HeartbeatInvoker::invoke(InvokeRequest& req) { +void HeartbeatInvoker::invoke(const InvokeRequest& req) { _invokeId = req.invokeid; _event.invokeid = _invokeId; std::string intervalStr; double interval = 0; unsigned long intervalMs = 0; - InvokeRequest::params_t::iterator paramIter = req.params.begin(); + InvokeRequest::params_t::const_iterator paramIter = req.params.begin(); while(paramIter != req.params.end()) { if (boost::iequals(paramIter->first, "interval")) { intervalStr = paramIter->second; diff --git a/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h b/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h index 9a6cb47..8a90011 100644 --- a/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h +++ b/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h @@ -9,11 +9,11 @@ namespace uscxml { -class HeartbeatInvoker : public Invoker { +class HeartbeatInvoker : public InvokerImpl { public: HeartbeatInvoker(); virtual ~HeartbeatInvoker(); - virtual Invoker* create(Interpreter* interpreter); + virtual InvokerImpl* create(Interpreter* interpreter); virtual std::set getNames() { std::set names; @@ -23,10 +23,10 @@ public: } virtual Data getDataModelVariables(); - virtual void send(SendRequest& req); + virtual void send(const SendRequest& req); virtual void cancel(const std::string sendId); - virtual void invoke(InvokeRequest& req); - virtual void sendToParent(SendRequest& req); + virtual void invoke(const InvokeRequest& req); + virtual void sendToParent(const SendRequest& req); static void dispatch(void* instance, std::string name); diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp index b4ee3eb..c90ef4d 100644 --- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp +++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp @@ -23,7 +23,7 @@ USCXMLInvoker::~USCXMLInvoker() { delete _invokedInterpreter; }; -Invoker* USCXMLInvoker::create(Interpreter* interpreter) { +InvokerImpl* USCXMLInvoker::create(Interpreter* interpreter) { USCXMLInvoker* invoker = new USCXMLInvoker(); invoker->_parentInterpreter = interpreter; return invoker; @@ -34,7 +34,7 @@ Data USCXMLInvoker::getDataModelVariables() { return data; } -void USCXMLInvoker::send(SendRequest& req) { +void USCXMLInvoker::send(const SendRequest& req) { assert(false); } @@ -42,19 +42,20 @@ void USCXMLInvoker::cancel(const std::string sendId) { assert(false); } -void USCXMLInvoker::sendToParent(SendRequest& req) { - req.invokeid = _invokeId; - _parentInterpreter->receive(req); +void USCXMLInvoker::sendToParent(const SendRequest& req) { + SendRequest parentReq = req; + parentReq.invokeid = _invokeId; + _parentInterpreter->receive(parentReq); } -void USCXMLInvoker::invoke(InvokeRequest& req) { +void USCXMLInvoker::invoke(const InvokeRequest& req) { _invokeId = req.invokeid; _invokedInterpreter = Interpreter::fromURI(req.src); - DataModel* dataModel = _invokedInterpreter->getDataModel(); - if (dataModel != NULL) { + DataModel dataModel(_invokedInterpreter->getDataModel()); + if (dataModel) { } - _invokedInterpreter->setInvoker(this); + _invokedInterpreter->setInvoker(boost::static_pointer_cast(shared_from_this())); _invokedInterpreter->start(); } diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h index 907df41..b1579a2 100644 --- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h +++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h @@ -2,6 +2,7 @@ #define USCXMLINVOKER_H_OQFA21IO #include +#include #ifdef BUILD_AS_PLUGINS #include "uscxml/plugins/Plugins.h" @@ -11,11 +12,11 @@ namespace uscxml { class Interpreter; -class USCXMLInvoker : public Invoker { +class USCXMLInvoker : public InvokerImpl, public boost::enable_shared_from_this { public: USCXMLInvoker(); virtual ~USCXMLInvoker(); - virtual Invoker* create(Interpreter* interpreter); + virtual InvokerImpl* create(Interpreter* interpreter); virtual std::set getNames() { std::set names; names.insert("uscxml"); @@ -25,10 +26,10 @@ public: } virtual Data getDataModelVariables(); - virtual void send(SendRequest& req); + virtual void send(const SendRequest& req); virtual void cancel(const std::string sendId); - virtual void invoke(InvokeRequest& req); - virtual void sendToParent(SendRequest& req); + virtual void invoke(const InvokeRequest& req); + virtual void sendToParent(const SendRequest& req); protected: std::string _invokeId; diff --git a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp index 9957bfa..3ddc14a 100644 --- a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp +++ b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp @@ -28,7 +28,7 @@ UmundoInvoker::~UmundoInvoker() { } }; -Invoker* UmundoInvoker::create(Interpreter* interpreter) { +InvokerImpl* UmundoInvoker::create(Interpreter* interpreter) { UmundoInvoker* invoker = new UmundoInvoker(); invoker->_interpreter = interpreter; return invoker; @@ -39,7 +39,7 @@ Data UmundoInvoker::getDataModelVariables() { return data; } -void UmundoInvoker::send(SendRequest& req) { +void UmundoInvoker::send(const SendRequest& req) { umundo::Message* msg = new umundo::Message(); if (req.name.length() > 0) { @@ -50,9 +50,9 @@ void UmundoInvoker::send(SendRequest& req) { if (req.params.find("type") != req.params.end()) { // assume JSON in content to transform to protobuf object - if (req.content.length() > 0 && _interpreter->getDataModel() != NULL) { + if (req.content.length() > 0 && _interpreter->getDataModel()) { std::string type; - std::multimap::iterator typeIter = req.params.find("type"); + std::multimap::const_iterator typeIter = req.params.find("type"); if (typeIter != req.params.end()) type = typeIter->second; const google::protobuf::Message* protoMsg = umundo::PBSerializer::getProto(type); @@ -61,7 +61,7 @@ void UmundoInvoker::send(SendRequest& req) { return; } try { - Data data = _interpreter->getDataModel()->getStringAsData(req.content); + Data data = _interpreter->getDataModel().getStringAsData(req.content); google::protobuf::Message* pbMsg = protoMsg->New(); if (!dataToProtobuf(pbMsg, data)) { LOG(ERROR) << "Cannot create message from JSON - not sending"; @@ -105,11 +105,11 @@ void UmundoInvoker::cancel(const std::string sendId) { assert(false); } -void UmundoInvoker::sendToParent(SendRequest& req) { +void UmundoInvoker::sendToParent(const SendRequest& req) { assert(false); } -void UmundoInvoker::invoke(InvokeRequest& req) { +void UmundoInvoker::invoke(const InvokeRequest& req) { _invokeId = req.invokeid; std::string domain; @@ -133,8 +133,8 @@ void UmundoInvoker::invoke(InvokeRequest& req) { // add type from .proto or .desc files if (req.params.find("type") != req.params.end()) { - std::pair typeRange = req.params.equal_range("types"); - for (InvokeRequest::params_t::iterator it = typeRange.first; it != typeRange.second; it++) { + std::pair typeRange = req.params.equal_range("types"); + for (InvokeRequest::params_t::const_iterator it = typeRange.first; it != typeRange.second; it++) { URL typeURI(it->second); if (typeURI.toAbsolute(_interpreter->getBaseURI())) { std::string filename = typeURI.asLocalFile(".proto"); @@ -147,8 +147,8 @@ void UmundoInvoker::invoke(InvokeRequest& req) { // add directory with .proto or .desc files if (req.params.find("types") != req.params.end()) { - std::pair typeRange = req.params.equal_range("types"); - for (InvokeRequest::params_t::iterator it = typeRange.first; it != typeRange.second; it++) { + std::pair typeRange = req.params.equal_range("types"); + for (InvokeRequest::params_t::const_iterator it = typeRange.first; it != typeRange.second; it++) { URL typeURI(it->second); if (typeURI.toAbsolute(_interpreter->getBaseURI()) && typeURI.scheme().compare("file") == 0) { umundo::PBSerializer::addProto(typeURI.path()); diff --git a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.h b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.h index 09d07bf..1aa37f2 100644 --- a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.h +++ b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.h @@ -16,11 +16,11 @@ namespace uscxml { class Interpreter; -class UmundoInvoker : public Invoker, public umundo::TypedReceiver, public umundo::ResultSet { +class UmundoInvoker : public InvokerImpl, public umundo::TypedReceiver, public umundo::ResultSet { public: UmundoInvoker(); virtual ~UmundoInvoker(); - virtual Invoker* create(Interpreter* interpreter); + virtual InvokerImpl* create(Interpreter* interpreter); virtual std::set getNames() { std::set names; @@ -31,10 +31,10 @@ public: } virtual Data getDataModelVariables(); - virtual void send(SendRequest& req); + virtual void send(const SendRequest& req); virtual void cancel(const std::string sendId); - virtual void invoke(InvokeRequest& req); - virtual void sendToParent(SendRequest& req); + virtual void invoke(const InvokeRequest& req); + virtual void sendToParent(const SendRequest& req); virtual void receive(void* object, umundo::Message* msg); diff --git a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp index a50dcaf..1607e3e 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp +++ b/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp @@ -46,7 +46,7 @@ EventIOProcessor::~EventIOProcessor() { httpServer->unregisterProcessor(this); } -IOProcessor* EventIOProcessor::create(Interpreter* interpreter) { +IOProcessorImpl* EventIOProcessor::create(Interpreter* interpreter) { EventIOProcessor* io = new EventIOProcessor(); io->_interpreter = interpreter; @@ -74,7 +74,7 @@ Data EventIOProcessor::getDataModelVariables() { } -void EventIOProcessor::send(SendRequest& req) { +void EventIOProcessor::send(const SendRequest& req) { // I cant figure out how to copy the reference into the struct :( _sendData[req.sendid].req = req; _sendData[req.sendid].ioProcessor = this; @@ -122,7 +122,7 @@ void EventIOProcessor::send(SendRequest& req) { // event namelist if (req.namelist.size() > 0) { - std::map::iterator namelistIter = req.namelist.begin(); + std::map::const_iterator namelistIter = req.namelist.begin(); while (namelistIter != req.namelist.end()) { evhttp_add_header(evhttp_request_get_output_headers(httpReq), namelistIter->first.c_str(), @@ -133,7 +133,7 @@ void EventIOProcessor::send(SendRequest& req) { // event params if (req.params.size() > 0) { - std::multimap::iterator paramIter = req.params.begin(); + std::multimap::const_iterator paramIter = req.params.begin(); while (paramIter != req.params.end()) { // LOG(INFO) << paramIter->first << " = " << paramIter->second << std::endl; evhttp_add_header(evhttp_request_get_output_headers(httpReq), diff --git a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h b/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h index f0228e9..d3557f4 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h +++ b/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h @@ -19,7 +19,7 @@ namespace uscxml { class EventIOServer; -class EventIOProcessor : public uscxml::IOProcessor { +class EventIOProcessor : public IOProcessorImpl { public: struct SendData { EventIOProcessor* ioProcessor; @@ -28,7 +28,7 @@ public: EventIOProcessor(); virtual ~EventIOProcessor(); - virtual IOProcessor* create(uscxml::Interpreter* interpreter); + virtual IOProcessorImpl* create(uscxml::Interpreter* interpreter); virtual std::set getNames() { std::set names; @@ -37,7 +37,7 @@ public: return names; } - virtual void send(uscxml::SendRequest& req); + virtual void send(const SendRequest& req); Data getDataModelVariables(); void setURL(const std::string& url) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 39a4667..353faa2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -53,3 +53,8 @@ add_executable(test-arabica-events src/test-arabica-events.cpp) target_link_libraries(test-arabica-events uscxml) add_test(test-arabica-events ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-arabica-events ${CMAKE_SOURCE_DIR}/test/samples/arabica/test-arabica-events.xml) set_target_properties(test-arabica-events PROPERTIES FOLDER "Tests") + +add_executable(test-url src/test-url.cpp) +target_link_libraries(test-url uscxml) +add_test(test-url ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-url) +set_target_properties(test-url PROPERTIES FOLDER "Tests") diff --git a/test/src/test-url.cpp b/test/src/test-url.cpp new file mode 100644 index 0000000..e7fbae4 --- /dev/null +++ b/test/src/test-url.cpp @@ -0,0 +1,42 @@ +#include "uscxml/URL.h" +#include +#include + +using namespace uscxml; +using namespace boost; + +int main(int argc, char** argv) { + { + URL url("http://www.heise.de/index.html"); + std::cout << url.asString() << std::endl; + assert(url.isAbsolute()); + assert(iequals(url.scheme(), "http")); + assert(iequals(url.host(), "www.heise.de")); + assert(iequals(url.port(), "80")); + assert(iequals(url.path(), "/index.html")); + assert(iequals(url.asString(), "http://www.heise.de/index.html")); + } + { + URL url("file:Document/Text.foo"); + std::cout << url.asString() << std::endl; + assert(!url.isAbsolute()); + assert(iequals(url.scheme(), "file")); + assert(iequals(url.host(), "")); + assert(iequals(url.port(), "0")); + assert(iequals(url.path(), "Document/Text.foo")); + assert(iequals(url.asString(), "file:Document/Text.foo")); + } + { + URL url("test/index.html"); + assert(iequals(url.scheme(), "")); + url.toAbsoluteCwd(); + assert(iequals(url.scheme(), "file")); + std::cout << url.asString() << std::endl; + } + { + URL url("C:\\Document\\Some Spaces\\index.txt"); + assert(url.isAbsolute()); + assert(iequals(url.scheme(), "file")); + std::cout << url.asString() << std::endl; + } +} \ No newline at end of file -- cgit v0.12