diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-04-06 21:17:13 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-04-06 21:17:13 (GMT) |
commit | 1e6ba139ac12c688f025745812d381915775b1fb (patch) | |
tree | 1d49070eddd4502ec6aa25a769ab7c47d04a1c30 /src/uscxml | |
parent | 139439f0675ec05e936fd4297086462037cd618e (diff) | |
download | uscxml-1e6ba139ac12c688f025745812d381915775b1fb.zip uscxml-1e6ba139ac12c688f025745812d381915775b1fb.tar.gz uscxml-1e6ba139ac12c688f025745812d381915775b1fb.tar.bz2 |
See detailled log
Added new revised W3C tests
Hide Interpreter via PIMPL
Implemented SCXMLIOProcessor
Diffstat (limited to 'src/uscxml')
49 files changed, 744 insertions, 317 deletions
diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp index 41a3b5a..e927693 100644 --- a/src/uscxml/Factory.cpp +++ b/src/uscxml/Factory.cpp @@ -10,7 +10,8 @@ # include "uscxml/plugins/Plugins.h" #else -# include "uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h" +# include "uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.h" +# include "uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.h" # include "uscxml/plugins/invoker/scxml/USCXMLInvoker.h" # include "uscxml/plugins/invoker/http/HTTPServletInvoker.h" # include "uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h" @@ -165,7 +166,11 @@ Factory::Factory() { registerInvoker(invoker); } { - EventIOProcessor* ioProcessor = new EventIOProcessor(); + BasicHTTPIOProcessor* ioProcessor = new BasicHTTPIOProcessor(); + registerIOProcessor(ioProcessor); + } + { + SCXMLIOProcessor* ioProcessor = new SCXMLIOProcessor(); registerIOProcessor(ioProcessor); } { @@ -240,7 +245,7 @@ void Factory::registerExecutableContent(ExecutableContentImpl* executableContent } -boost::shared_ptr<InvokerImpl> Factory::createInvoker(const std::string& type, Interpreter* interpreter) { +boost::shared_ptr<InvokerImpl> Factory::createInvoker(const std::string& type, InterpreterImpl* interpreter) { Factory* factory = getInstance(); if (factory->_invokerAliases.find(type) == factory->_invokerAliases.end()) { LOG(ERROR) << "No " << type << " Invoker known"; @@ -256,7 +261,7 @@ boost::shared_ptr<InvokerImpl> Factory::createInvoker(const std::string& type, I return boost::static_pointer_cast<InvokerImpl>(factory->_invokers[canonicalName]->create(interpreter)); } -boost::shared_ptr<DataModelImpl> Factory::createDataModel(const std::string& type, Interpreter* interpreter) { +boost::shared_ptr<DataModelImpl> Factory::createDataModel(const std::string& type, InterpreterImpl* interpreter) { Factory* factory = getInstance(); if (factory->_dataModelAliases.find(type) == factory->_dataModelAliases.end()) { LOG(ERROR) << "No " << type << " DataModel known"; @@ -272,7 +277,7 @@ boost::shared_ptr<DataModelImpl> Factory::createDataModel(const std::string& typ return factory->_dataModels[canonicalName]->create(interpreter); } -boost::shared_ptr<IOProcessorImpl> Factory::createIOProcessor(const std::string& type, Interpreter* interpreter) { +boost::shared_ptr<IOProcessorImpl> Factory::createIOProcessor(const std::string& type, InterpreterImpl* interpreter) { Factory* factory = getInstance(); if (factory->_ioProcessorAliases.find(type) == factory->_ioProcessorAliases.end()) { LOG(ERROR) << "No " << type << " IOProcessor known"; @@ -288,7 +293,7 @@ boost::shared_ptr<IOProcessorImpl> Factory::createIOProcessor(const std::string& return factory->_ioProcessors[canonicalName]->create(interpreter); } -boost::shared_ptr<ExecutableContentImpl> Factory::createExecutableContent(const std::string& localName, const std::string& nameSpace, Interpreter* interpreter) { +boost::shared_ptr<ExecutableContentImpl> Factory::createExecutableContent(const std::string& localName, const std::string& nameSpace, InterpreterImpl* interpreter) { Factory* factory = getInstance(); std::string actualNameSpace = (nameSpace.length() == 0 ? "http://www.w3.org/2005/07/scxml" : nameSpace); if (factory->_executableContent.find(std::make_pair(localName, actualNameSpace)) == factory->_executableContent.end()) { diff --git a/src/uscxml/Factory.h b/src/uscxml/Factory.h index 990b035..c396e63 100644 --- a/src/uscxml/Factory.h +++ b/src/uscxml/Factory.h @@ -33,15 +33,15 @@ inline bool isNumeric( const char* pszInput, int nNumberBase) { return (input.find_first_not_of(base.substr(0, nNumberBase)) == std::string::npos); } -class Interpreter; +class InterpreterImpl; class ExecutableContentImpl { public: ExecutableContentImpl() {}; virtual ~ExecutableContentImpl() {}; - virtual boost::shared_ptr<ExecutableContentImpl> create(Interpreter* interpreter) = 0; + virtual boost::shared_ptr<ExecutableContentImpl> create(InterpreterImpl* interpreter) = 0; - virtual void setInterpreter(Interpreter* interpreter) { + virtual void setInterpreter(InterpreterImpl* interpreter) { _interpreter = interpreter; } @@ -52,7 +52,7 @@ public: virtual bool processChildren() = 0; ///< Whether or not the interpreter should process this elements children. protected: - Interpreter* _interpreter; + InterpreterImpl* _interpreter; }; class ExecutableContent { @@ -79,7 +79,7 @@ public: return *this; } - void setInterpreter(Interpreter* interpreter) { + void setInterpreter(InterpreterImpl* interpreter) { _impl->setInterpreter(interpreter); } @@ -107,10 +107,10 @@ class IOProcessorImpl { public: IOProcessorImpl() {}; virtual ~IOProcessorImpl() {}; - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter) = 0; + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter) = 0; virtual std::set<std::string> getNames() = 0; - virtual void setInterpreter(Interpreter* interpreter) { + virtual void setInterpreter(InterpreterImpl* interpreter) { _interpreter = interpreter; } void setInvokeId(const std::string& invokeId) { @@ -128,7 +128,7 @@ public: void returnEvent(Event& event); protected: - Interpreter* _interpreter; + InterpreterImpl* _interpreter; std::string _invokeId; std::string _type; }; @@ -171,7 +171,7 @@ public: return _impl->runOnMainThread(); } - void setInterpreter(Interpreter* interpreter) { + void setInterpreter(InterpreterImpl* interpreter) { _impl->setInterpreter(interpreter); } void setInvokeId(const std::string& invokeId) { @@ -183,13 +183,13 @@ public: protected: boost::shared_ptr<IOProcessorImpl> _impl; - friend class Interpreter; + friend class InterpreterImpl; }; class InvokerImpl : public IOProcessorImpl { public: virtual void invoke(const InvokeRequest& req) = 0; - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter) = 0; + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter) = 0; }; class Invoker : public IOProcessor { @@ -228,7 +228,7 @@ protected: class DataModelImpl { public: virtual ~DataModelImpl() {} - virtual boost::shared_ptr<DataModelImpl> create(Interpreter* interpreter) = 0; + virtual boost::shared_ptr<DataModelImpl> create(InterpreterImpl* interpreter) = 0; virtual std::set<std::string> getNames() = 0; virtual bool validate(const std::string& location, const std::string& schema) = 0; @@ -249,7 +249,7 @@ public: virtual bool isDeclared(const std::string& expr) = 0; protected: - Interpreter* _interpreter; + InterpreterImpl* _interpreter; }; class DataModel { @@ -332,10 +332,10 @@ public: void registerInvoker(InvokerImpl* invoker); void registerExecutableContent(ExecutableContentImpl* executableContent); - static boost::shared_ptr<DataModelImpl> createDataModel(const std::string& type, Interpreter* interpreter); - static boost::shared_ptr<IOProcessorImpl> createIOProcessor(const std::string& type, Interpreter* interpreter); - static boost::shared_ptr<InvokerImpl> createInvoker(const std::string& type, Interpreter* interpreter); - static boost::shared_ptr<ExecutableContentImpl> createExecutableContent(const std::string& localName, const std::string& nameSpace, Interpreter* interpreter); + static boost::shared_ptr<DataModelImpl> createDataModel(const std::string& type, InterpreterImpl* interpreter); + static boost::shared_ptr<IOProcessorImpl> createIOProcessor(const std::string& type, InterpreterImpl* interpreter); + static boost::shared_ptr<InvokerImpl> createInvoker(const std::string& type, InterpreterImpl* interpreter); + static boost::shared_ptr<ExecutableContentImpl> createExecutableContent(const std::string& localName, const std::string& nameSpace, InterpreterImpl* interpreter); static Factory* getInstance(); diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 86f40c1..48410a9 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -40,12 +40,15 @@ namespace uscxml { using namespace Arabica::XPath; using namespace Arabica::DOM; -boost::uuids::random_generator Interpreter::uuidGen; -const std::string Interpreter::getUUID() { +std::map<std::string, boost::weak_ptr<InterpreterImpl> > Interpreter::_instances; +tthread::recursive_mutex Interpreter::_instanceMutex; + +boost::uuids::random_generator InterpreterImpl::uuidGen; +const std::string InterpreterImpl::getUUID() { return boost::lexical_cast<std::string>(uuidGen()); } -Interpreter::Interpreter() { +InterpreterImpl::InterpreterImpl() { _lastRunOnMainThread = 0; _nsURL = "*"; _thread = NULL; @@ -63,13 +66,17 @@ Interpreter::Interpreter() { #endif } -Interpreter* Interpreter::fromDOM(const Arabica::DOM::Document<std::string>& dom) { - Interpreter* interpreter = new InterpreterDraft6(); - interpreter->_document = dom; +Interpreter Interpreter::fromDOM(const Arabica::DOM::Document<std::string>& dom) { + tthread::lock_guard<tthread::recursive_mutex> lock(_instanceMutex); + boost::shared_ptr<InterpreterDraft6> interpreterImpl = boost::shared_ptr<InterpreterDraft6>(new InterpreterDraft6); + Interpreter interpreter(interpreterImpl); + interpreterImpl->_document = dom; + interpreterImpl->init(); + _instances[interpreterImpl->getSessionId()] = interpreterImpl; return interpreter; } -Interpreter* Interpreter::fromXML(const std::string& xml) { +Interpreter Interpreter::fromXML(const std::string& xml) { std::stringstream* ss = new std::stringstream(); (*ss) << xml; // we need an auto_ptr for arabica to assume ownership @@ -79,16 +86,16 @@ Interpreter* Interpreter::fromXML(const std::string& xml) { return fromInputSource(inputSource); } -Interpreter* Interpreter::fromURI(const std::string& uri) { +Interpreter Interpreter::fromURI(const std::string& 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; + return Interpreter(); } } - Interpreter* interpreter = NULL; + Interpreter interpreter; if (boost::iequals(absUrl.scheme(), "file")) { Arabica::SAX::InputSource<std::string> inputSource; @@ -105,21 +112,22 @@ Interpreter* Interpreter::fromURI(const std::string& uri) { ss << absUrl; if (absUrl.downloadFailed()) { LOG(ERROR) << "Downloading SCXML document from " << absUrl << " failed"; - return NULL; + return interpreter; } interpreter = fromXML(ss.str()); } // try to establish URI root for relative src attributes in document if (interpreter) - interpreter->_baseURI = toBaseURI(absUrl); + interpreter._impl->_baseURI = InterpreterImpl::toBaseURI(absUrl); return interpreter; } -Interpreter* Interpreter::fromInputSource(Arabica::SAX::InputSource<std::string>& source) { - Interpreter* interpreter = new InterpreterDraft6(); - - SCXMLParser* parser = new SCXMLParser(interpreter); +Interpreter Interpreter::fromInputSource(Arabica::SAX::InputSource<std::string>& source) { + tthread::lock_guard<tthread::recursive_mutex> lock(_instanceMutex); + boost::shared_ptr<InterpreterDraft6> interpreterImpl = boost::shared_ptr<InterpreterDraft6>(new InterpreterDraft6); + Interpreter interpreter; + SCXMLParser* parser = new SCXMLParser(interpreterImpl.get()); if(!parser->parse(source) || !parser->getDocument().hasChildNodes()) { if(parser->_errorHandler.errorsReported()) { LOG(ERROR) << "could not parse input:"; @@ -130,18 +138,18 @@ Interpreter* Interpreter::fromInputSource(Arabica::SAX::InputSource<std::string> LOG(ERROR) << source.getSystemId() << ": no such file"; } } - delete parser; - delete interpreter; - return NULL; } else { - interpreter->_document = parser->getDocument(); + interpreterImpl->_document = parser->getDocument(); + interpreterImpl->init(); + interpreter = Interpreter(interpreterImpl); + _instances[interpreterImpl->getSessionId()] = interpreterImpl; } // interpreter->init(); delete parser; return interpreter; } -SCXMLParser::SCXMLParser(Interpreter* interpreter) : _interpreter(interpreter) { +SCXMLParser::SCXMLParser(InterpreterImpl* interpreter) : _interpreter(interpreter) { Arabica::SAX::CatchErrorHandler<std::string> errorHandler; setErrorHandler(errorHandler); } @@ -169,7 +177,7 @@ void SCXMLParser::startPrefixMapping(const std::string& prefix, const std::strin } } -void Interpreter::setName(const std::string& name) { +void InterpreterImpl::setName(const std::string& name) { if (!_running) { _name = name; } else { @@ -177,7 +185,7 @@ void Interpreter::setName(const std::string& name) { } } -URL Interpreter::toBaseURI(const URL& uri) { +URL InterpreterImpl::toBaseURI(const URL& uri) { std::stringstream ssBaseURI; if (uri.scheme().size() > 0) { ssBaseURI << uri.scheme() << "://"; @@ -197,7 +205,7 @@ URL Interpreter::toBaseURI(const URL& uri) { return URL(ssBaseURI.str()); } -bool Interpreter::toAbsoluteURI(URL& uri) { +bool InterpreterImpl::toAbsoluteURI(URL& uri) { if (uri.isAbsolute()) return true; @@ -209,7 +217,7 @@ bool Interpreter::toAbsoluteURI(URL& uri) { return false; } -Interpreter::~Interpreter() { +InterpreterImpl::~InterpreterImpl() { tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); if (_thread) { _running = false; @@ -225,16 +233,16 @@ Interpreter::~Interpreter() { // delete _httpServlet; } -void Interpreter::start() { +void InterpreterImpl::start() { _done = false; - _thread = new tthread::thread(Interpreter::run, this); + _thread = new tthread::thread(InterpreterImpl::run, this); } -void Interpreter::run(void* instance) { - ((Interpreter*)instance)->interpret(); +void InterpreterImpl::run(void* instance) { + ((InterpreterImpl*)instance)->interpret(); } -bool Interpreter::runOnMainThread(int fps, bool blocking) { +bool InterpreterImpl::runOnMainThread(int fps, bool blocking) { if (_done) return false; @@ -267,7 +275,7 @@ bool Interpreter::runOnMainThread(int fps, bool blocking) { return (_thread != NULL); } -void Interpreter::init() { +void InterpreterImpl::init() { if (_document) { NodeList<std::string> scxmls = _document.getElementsByTagNameNS(_nsURL, "scxml"); if (scxmls.getLength() > 0) { @@ -281,9 +289,6 @@ void Interpreter::init() { normalize(_scxml); -// if (_capabilities & CAN_GENERIC_HTTP) -// _httpServlet = new InterpreterServlet(this); - _sendQueue = new DelayedEventQueue(); _sendQueue->start(); @@ -296,23 +301,27 @@ void Interpreter::init() { LOG(ERROR) << "Interpreter has no DOM at all!" << std::endl; _done = true; } + + if (_sessionId.length() == 0) + _sessionId = getUUID(); + _isInitialized = true; } /** * Called with a single data element from the topmost datamodel element. */ -void Interpreter::initializeData(const Node<std::string>& data) { +void InterpreterImpl::initializeData(const Node<std::string>& data) { if (!_dataModel) { LOG(ERROR) << "Cannot initialize data when no datamodel is given!"; return; } - + if (!HAS_ATTR(data, "id")) { LOG(ERROR) << "Data element has no id!"; return; } - + /// test 240 - initialize from invoke request if (_invokeReq.params.find(ATTR(data, "id")) != _invokeReq.params.end()) { try { @@ -332,7 +341,7 @@ void Interpreter::initializeData(const Node<std::string>& data) { } return; } - + try { std::string contentToProcess; if (HAS_ATTR(data, "expr")) { @@ -341,13 +350,13 @@ void Interpreter::initializeData(const Node<std::string>& data) { _dataModel.assign(ATTR(data, "id"), value); return; } - + if (HAS_ATTR(data, "src")) { // fetch us some string and proess below URL srcURL(ATTR(data, "src")); if (!srcURL.isAbsolute()) toAbsoluteURI(srcURL); - + std::stringstream ss; if (_cachedURLs.find(srcURL.asString()) != _cachedURLs.end()) { ss << _cachedURLs[srcURL.asString()]; @@ -384,7 +393,7 @@ void Interpreter::initializeData(const Node<std::string>& data) { } contentChild = contentChild.getNextSibling(); } - + if (contentChild && presentAsDom) { Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation(); Document<std::string> dom = domFactory.createDocument(contentChild.getNamespaceURI(), "", 0); @@ -422,7 +431,7 @@ void Interpreter::initializeData(const Node<std::string>& data) { } else { _dataModel.assign(ATTR(data, "id"), "undefined"); } - + } catch (Event e) { LOG(ERROR) << "Syntax error in data element:" << std::endl << e << std::endl; /// test 487 @@ -430,7 +439,9 @@ void Interpreter::initializeData(const Node<std::string>& data) { } } -void Interpreter::normalize(Arabica::DOM::Element<std::string>& scxml) { +void InterpreterImpl::normalize(Arabica::DOM::Element<std::string>& scxml) { + // TODO: Resolve XML includes + // make sure every state has an id and set isFirstEntry to true Arabica::XPath::NodeSet<std::string> states = _xpath.evaluate("//" + _xpathPrefix + "state", _scxml).asNodeSet(); for (int i = 0; i < states.size(); i++) { @@ -488,14 +499,14 @@ void Interpreter::normalize(Arabica::DOM::Element<std::string>& scxml) { std::cout << _scxml <<std::endl; #endif } - -void Interpreter::receiveInternal(const Event& event) { + +void InterpreterImpl::receiveInternal(const Event& event) { std::cout << "receiveInternal: " << event.name << std::endl; _internalQueue.push_back(event); } -void Interpreter::internalDoneSend(const Arabica::DOM::Node<std::string>& state) { +void InterpreterImpl::internalDoneSend(const Arabica::DOM::Node<std::string>& state) { if (!isState(state)) return; @@ -520,7 +531,7 @@ void Interpreter::internalDoneSend(const Arabica::DOM::Node<std::string>& state) } -void Interpreter::processContentElement(const Arabica::DOM::Node<std::string>& content, Arabica::DOM::Document<std::string>& dom, std::string& text) { +void InterpreterImpl::processContentElement(const Arabica::DOM::Node<std::string>& content, Arabica::DOM::Document<std::string>& dom, std::string& text) { try { if (HAS_ATTR(content, "expr")) { if (_dataModel) { @@ -579,7 +590,7 @@ void Interpreter::processContentElement(const Arabica::DOM::Node<std::string>& c } } -void Interpreter::processParamChilds(const Arabica::DOM::Node<std::string>& element, std::multimap<std::string, std::string>& params) { +void InterpreterImpl::processParamChilds(const Arabica::DOM::Node<std::string>& element, std::multimap<std::string, std::string>& params) { NodeSet<std::string> paramElems = filterChildElements(_xmlNSPrefix + "param", element); try { for (int i = 0; i < paramElems.size(); i++) { @@ -611,7 +622,7 @@ void Interpreter::processParamChilds(const Arabica::DOM::Node<std::string>& elem } } -void Interpreter::send(const Arabica::DOM::Node<std::string>& element) { +void InterpreterImpl::send(const Arabica::DOM::Node<std::string>& element) { SendRequest sendReq; // test 331 sendReq.Event::type = Event::EXTERNAL; @@ -752,51 +763,19 @@ void Interpreter::send(const Arabica::DOM::Node<std::string>& element) { assert(_sendIds.find(sendReq.sendid) == _sendIds.end()); _sendIds[sendReq.sendid] = std::make_pair(this, sendReq); if (sendReq.delayMs > 0) { - _sendQueue->addEvent(sendReq.sendid, Interpreter::delayedSend, sendReq.delayMs, &_sendIds[sendReq.sendid]); + _sendQueue->addEvent(sendReq.sendid, InterpreterImpl::delayedSend, sendReq.delayMs, &_sendIds[sendReq.sendid]); } else { delayedSend(&_sendIds[sendReq.sendid], sendReq.name); } } -void Interpreter::delayedSend(void* userdata, std::string eventName) { - std::pair<Interpreter*, SendRequest>* data = (std::pair<Interpreter*, SendRequest>*)(userdata); +void InterpreterImpl::delayedSend(void* userdata, std::string eventName) { + std::pair<InterpreterImpl*, SendRequest>* data = (std::pair<InterpreterImpl*, SendRequest>*)(userdata); - Interpreter* INSTANCE = data->first; + InterpreterImpl* INSTANCE = data->first; SendRequest sendReq = data->second; - // test 253 - if (sendReq.origintype.length() == 0) - sendReq.origintype = "http://www.w3.org/TR/scxml/#SCXMLEventProcessor"; - - // see http://www.w3.org/TR/scxml/#SendTargets - if (boost::iequals(sendReq.target, "#_parent")) { - // send to parent scxml session - if (INSTANCE->_parentQueue != NULL) { -// LOG(ERROR) << "Pushing into parent queue: " << INSTANCE->_parentQueue << std::endl; - INSTANCE->_parentQueue->push(sendReq); - } else { - LOG(ERROR) << "Can not send to parent, we were not invoked" << std::endl; - } - } else if (boost::iequals(sendReq.target, "#_internal")) { - INSTANCE->receiveInternal(sendReq); - } else if (sendReq.target.find_first_of("#_") == 0) { - // send to invoker - std::string invokeId = sendReq.target.substr(2, sendReq.target.length() - 2); - if (INSTANCE->_invokers.find(invokeId) != INSTANCE->_invokers.end()) { - tthread::lock_guard<tthread::recursive_mutex> lock(INSTANCE->_mutex); - try { - INSTANCE->_invokers[invokeId].send(sendReq); - } catch(...) { - LOG(ERROR) << "Exception caught while sending event to invoker " << invokeId; - } - } else { - LOG(ERROR) << "Can not send to invoked component '" << invokeId << "', no such invokeId" << std::endl; - Event e("error.communication", Event::PLATFORM); - INSTANCE->receiveInternal(e); - } - } else if (sendReq.target.length() == 0 && - (sendReq.type.length() == 0 || - boost::equals(sendReq.type, "http://www.w3.org/TR/scxml/#SCXMLEventProcessor"))) { + if (sendReq.target.length() == 0) { /** * If neither the 'target' nor the 'targetexpr' attribute is specified, the * SCXML Processor must add the event will be added to the external event @@ -804,9 +783,13 @@ void Interpreter::delayedSend(void* userdata, std::string eventName) { */ INSTANCE->_externalQueue.push(sendReq); } else { - IOProcessor ioProc; - if (sendReq.type.length() > 0) - ioProc = INSTANCE->getIOProcessor(sendReq.type); + /** + * If neither the 'type' nor the 'typeexpr' is defined, the SCXML Processor + * must assume the default value of http://www.w3.org/TR/scxml/#SCXMLEventProcessor + */ + if (sendReq.type.length() == 0) + sendReq.type = "http://www.w3.org/TR/scxml/#SCXMLEventProcessor"; + IOProcessor ioProc = INSTANCE->getIOProcessor(sendReq.type); if (ioProc) { try { ioProc.send(sendReq); @@ -814,10 +797,12 @@ void Interpreter::delayedSend(void* userdata, std::string eventName) { LOG(ERROR) << "Exception caught while sending event to ioprocessor " << sendReq.type; } } else { - Event exceptionEvent; - exceptionEvent.name = "error.execution"; - exceptionEvent.type = Event::PLATFORM; - exceptionEvent.sendid = sendReq.sendid; + /** + * If the SCXML Processor does not support the type that is specified, it + * must place the event error.execution on the internal event queue. + */ + Event exceptionEvent("error.execution", Event::PLATFORM); +// exceptionEvent.sendid = sendReq.sendid; INSTANCE->receiveInternal(exceptionEvent); } } @@ -825,7 +810,7 @@ void Interpreter::delayedSend(void* userdata, std::string eventName) { INSTANCE->_sendIds.erase(sendReq.sendid); } -void Interpreter::invoke(const Arabica::DOM::Node<std::string>& element) { +void InterpreterImpl::invoke(const Arabica::DOM::Node<std::string>& element) { InvokeRequest invokeReq; invokeReq.Event::type = Event::EXTERNAL; try { @@ -903,7 +888,7 @@ void Interpreter::invoke(const Arabica::DOM::Node<std::string>& element) { // test 422 if (invokeReq.type.size() == 0) invokeReq.type = "http://www.w3.org/TR/scxml/"; - + Invoker invoker(Factory::createInvoker(invokeReq.type, this)); if (invoker) { tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); @@ -937,7 +922,7 @@ void Interpreter::invoke(const Arabica::DOM::Node<std::string>& element) { } } -void Interpreter::cancelInvoke(const Arabica::DOM::Node<std::string>& element) { +void InterpreterImpl::cancelInvoke(const Arabica::DOM::Node<std::string>& element) { std::string invokeId; if (HAS_ATTR(element, "idlocation") && _dataModel) { invokeId = _dataModel.evalAsString(ATTR(element, "idlocation")); @@ -965,7 +950,7 @@ void Interpreter::cancelInvoke(const Arabica::DOM::Node<std::string>& element) { // see: http://www.w3.org/TR/scxml/#EventDescriptors -bool Interpreter::nameMatch(const std::string& transitionEvent, const std::string& event) { +bool InterpreterImpl::nameMatch(const std::string& transitionEvent, const std::string& event) { if(transitionEvent.length() == 0 || event.length() == 0) return false; @@ -1007,7 +992,7 @@ bool Interpreter::nameMatch(const std::string& transitionEvent, const std::strin } -bool Interpreter::hasConditionMatch(const Arabica::DOM::Node<std::string>& conditional) { +bool InterpreterImpl::hasConditionMatch(const Arabica::DOM::Node<std::string>& conditional) { if (HAS_ATTR(conditional, "cond") && ATTR(conditional, "cond").length() > 0) { if (!_dataModel) { @@ -1027,7 +1012,7 @@ bool Interpreter::hasConditionMatch(const Arabica::DOM::Node<std::string>& condi } -void Interpreter::executeContent(const NodeList<std::string>& content, bool rethrow) { +void InterpreterImpl::executeContent(const NodeList<std::string>& content, bool rethrow) { for (unsigned int i = 0; i < content.getLength(); i++) { if (content.item(i).getNodeType() != Node_base::ELEMENT_NODE) continue; @@ -1035,7 +1020,7 @@ void Interpreter::executeContent(const NodeList<std::string>& content, bool reth } } -void Interpreter::executeContent(const NodeSet<std::string>& content, bool rethrow) { +void InterpreterImpl::executeContent(const NodeSet<std::string>& content, bool rethrow) { for (unsigned int i = 0; i < content.size(); i++) { if (content[i].getNodeType() != Node_base::ELEMENT_NODE) continue; @@ -1043,7 +1028,7 @@ void Interpreter::executeContent(const NodeSet<std::string>& content, bool rethr } } -void Interpreter::executeContent(const Arabica::DOM::Node<std::string>& content, bool rethrow) { +void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& content, bool rethrow) { if (content.getNodeType() != Node_base::ELEMENT_NODE) return; @@ -1258,7 +1243,7 @@ void Interpreter::executeContent(const Arabica::DOM::Node<std::string>& content, } } -void Interpreter::returnDoneEvent(const Arabica::DOM::Node<std::string>& state) { +void InterpreterImpl::returnDoneEvent(const Arabica::DOM::Node<std::string>& state) { if (_parentQueue != NULL) { Event done; done.name = "done.invoke." + _sessionId; @@ -1266,7 +1251,7 @@ void Interpreter::returnDoneEvent(const Arabica::DOM::Node<std::string>& state) } } -bool Interpreter::parentIsScxmlState(Arabica::DOM::Node<std::string> state) { +bool InterpreterImpl::parentIsScxmlState(const Arabica::DOM::Node<std::string>& state) { Arabica::DOM::Element<std::string> stateElem = (Arabica::DOM::Element<std::string>)state; Arabica::DOM::Element<std::string> parentElem = (Arabica::DOM::Element<std::string>)state.getParentNode(); if (boost::iequals(TAGNAME(parentElem), _xmlNSPrefix + "scxml")) @@ -1274,7 +1259,7 @@ bool Interpreter::parentIsScxmlState(Arabica::DOM::Node<std::string> state) { return false; } -bool Interpreter::isInFinalState(const Arabica::DOM::Node<std::string>& state) { +bool InterpreterImpl::isInFinalState(const Arabica::DOM::Node<std::string>& state) { if (isCompound(state)) { Arabica::XPath::NodeSet<std::string> childs = getChildStates(state); for (int i = 0; i < childs.size(); i++) { @@ -1292,7 +1277,7 @@ bool Interpreter::isInFinalState(const Arabica::DOM::Node<std::string>& state) { return false; } -bool Interpreter::isMember(const Arabica::DOM::Node<std::string>& node, const Arabica::XPath::NodeSet<std::string>& set) { +bool InterpreterImpl::isMember(const Arabica::DOM::Node<std::string>& node, const Arabica::XPath::NodeSet<std::string>& set) { for (int i = 0; i < set.size(); i++) { if (set[i] == node) return true; @@ -1300,7 +1285,7 @@ bool Interpreter::isMember(const Arabica::DOM::Node<std::string>& node, const Ar return false; } -Arabica::XPath::NodeSet<std::string> Interpreter::getChildStates(const Arabica::DOM::Node<std::string>& state) { +Arabica::XPath::NodeSet<std::string> InterpreterImpl::getChildStates(const Arabica::DOM::Node<std::string>& state) { Arabica::XPath::NodeSet<std::string> childs; Arabica::DOM::NodeList<std::string> childElems = state.getChildNodes(); @@ -1312,7 +1297,7 @@ Arabica::XPath::NodeSet<std::string> Interpreter::getChildStates(const Arabica:: return childs; } -Arabica::DOM::Node<std::string> Interpreter::getParentState(const Arabica::DOM::Node<std::string>& element) { +Arabica::DOM::Node<std::string> InterpreterImpl::getParentState(const Arabica::DOM::Node<std::string>& element) { Arabica::DOM::Node<std::string> parent = element.getParentNode(); while(parent && !isState(parent)) { parent = parent.getParentNode(); @@ -1320,7 +1305,7 @@ Arabica::DOM::Node<std::string> Interpreter::getParentState(const Arabica::DOM:: return parent; } -Arabica::DOM::Node<std::string> Interpreter::getAncestorElement(const Arabica::DOM::Node<std::string>& node, const std::string tagName) { +Arabica::DOM::Node<std::string> InterpreterImpl::getAncestorElement(const Arabica::DOM::Node<std::string>& node, const std::string tagName) { Arabica::DOM::Node<std::string> parent = node.getParentNode(); while(parent) { if (parent.getNodeType() == Node_base::ELEMENT_NODE && @@ -1340,7 +1325,7 @@ Arabica::DOM::Node<std::string> Interpreter::getAncestorElement(const Arabica::D we are speaking of proper ancestor (parent or parent of a parent, etc.) the LCCA is never a member of stateList. */ -Arabica::DOM::Node<std::string> Interpreter::findLCCA(const Arabica::XPath::NodeSet<std::string>& states) { +Arabica::DOM::Node<std::string> InterpreterImpl::findLCCA(const Arabica::XPath::NodeSet<std::string>& states) { #if 0 std::cout << "findLCCA: "; for (int i = 0; i < states.size(); i++) { @@ -1378,7 +1363,7 @@ NEXT_ANCESTOR: return ancestor; } -Arabica::XPath::NodeSet<std::string> Interpreter::getStates(const std::vector<std::string>& stateIds) { +Arabica::XPath::NodeSet<std::string> InterpreterImpl::getStates(const std::vector<std::string>& stateIds) { Arabica::XPath::NodeSet<std::string> states; std::vector<std::string>::const_iterator tokenIter = stateIds.begin(); while(tokenIter != stateIds.end()) { @@ -1388,7 +1373,7 @@ Arabica::XPath::NodeSet<std::string> Interpreter::getStates(const std::vector<st return states; } -Arabica::DOM::Node<std::string> Interpreter::getState(const std::string& stateId) { +Arabica::DOM::Node<std::string> InterpreterImpl::getState(const std::string& stateId) { if (_cachedStates.find(stateId) != _cachedStates.end()) { return _cachedStates[stateId]; @@ -1426,7 +1411,7 @@ FOUND: return Arabica::DOM::Node<std::string>(); } -Arabica::DOM::Node<std::string> Interpreter::getSourceState(const Arabica::DOM::Node<std::string>& transition) { +Arabica::DOM::Node<std::string> InterpreterImpl::getSourceState(const Arabica::DOM::Node<std::string>& transition) { if (boost::iequals(TAGNAME(transition.getParentNode()), _xmlNSPrefix + "initial")) return transition.getParentNode().getParentNode(); return transition.getParentNode(); @@ -1439,7 +1424,7 @@ Arabica::DOM::Node<std::string> Interpreter::getSourceState(const Arabica::DOM:: * attribute nor an <initial> element is specified, the SCXML Processor must use * the first child state in document order as the default initial state. */ -Arabica::XPath::NodeSet<std::string> Interpreter::getInitialStates(Arabica::DOM::Node<std::string> state) { +Arabica::XPath::NodeSet<std::string> InterpreterImpl::getInitialStates(Arabica::DOM::Node<std::string> state) { if (!state) { state = _scxml; } @@ -1477,7 +1462,7 @@ Arabica::XPath::NodeSet<std::string> Interpreter::getInitialStates(Arabica::DOM: return Arabica::XPath::NodeSet<std::string>(); } -NodeSet<std::string> Interpreter::getTargetStates(const Arabica::DOM::Node<std::string>& transition) { +NodeSet<std::string> InterpreterImpl::getTargetStates(const Arabica::DOM::Node<std::string>& transition) { NodeSet<std::string> targetStates; assert(boost::iequals(LOCALNAME(transition), "transition")); @@ -1495,7 +1480,7 @@ NodeSet<std::string> Interpreter::getTargetStates(const Arabica::DOM::Node<std:: std::string targetId = ((Arabica::DOM::Element<std::string>)transition).getAttribute("target"); - std::vector<std::string> targetIds = Interpreter::tokenizeIdRefs(ATTR(transition, "target")); + std::vector<std::string> targetIds = InterpreterImpl::tokenizeIdRefs(ATTR(transition, "target")); for (int i = 0; i < targetIds.size(); i++) { Arabica::DOM::Node<std::string> state = getState(targetIds[i]); assert(HAS_ATTR(state, "id")); @@ -1504,7 +1489,7 @@ NodeSet<std::string> Interpreter::getTargetStates(const Arabica::DOM::Node<std:: return targetStates; } -std::vector<std::string> Interpreter::tokenizeIdRefs(const std::string& idRefs) { +std::vector<std::string> InterpreterImpl::tokenizeIdRefs(const std::string& idRefs) { std::vector<std::string> ids; if (idRefs.length() > 0) { @@ -1518,7 +1503,7 @@ std::vector<std::string> Interpreter::tokenizeIdRefs(const std::string& idRefs) return ids; } -NodeSet<std::string> Interpreter::filterChildElements(const std::string& tagName, const NodeSet<std::string>& nodeSet) { +NodeSet<std::string> InterpreterImpl::filterChildElements(const std::string& tagName, const NodeSet<std::string>& nodeSet) { NodeSet<std::string> filteredChildElems; for (unsigned int i = 0; i < nodeSet.size(); i++) { filteredChildElems.push_back(filterChildElements(tagName, nodeSet[i])); @@ -1526,7 +1511,7 @@ NodeSet<std::string> Interpreter::filterChildElements(const std::string& tagName return filteredChildElems; } -NodeSet<std::string> Interpreter::filterChildElements(const std::string& tagName, const Node<std::string>& node) { +NodeSet<std::string> InterpreterImpl::filterChildElements(const std::string& tagName, const Node<std::string>& node) { NodeSet<std::string> filteredChildElems; NodeList<std::string> childs = node.getChildNodes(); for (unsigned int i = 0; i < childs.getLength(); i++) { @@ -1538,7 +1523,7 @@ NodeSet<std::string> Interpreter::filterChildElements(const std::string& tagName return filteredChildElems; } -NodeSet<std::string> Interpreter::getProperAncestors(const Arabica::DOM::Node<std::string>& s1, +NodeSet<std::string> InterpreterImpl::getProperAncestors(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2) { NodeSet<std::string> ancestors; if (isState(s1)) { @@ -1558,8 +1543,8 @@ NodeSet<std::string> Interpreter::getProperAncestors(const Arabica::DOM::Node<st return ancestors; } -bool Interpreter::isDescendant(const Arabica::DOM::Node<std::string>& s1, - const Arabica::DOM::Node<std::string>& s2) { +bool InterpreterImpl::isDescendant(const Arabica::DOM::Node<std::string>& s1, + const Arabica::DOM::Node<std::string>& s2) { Arabica::DOM::Node<std::string> parent = s1.getParentNode(); while(parent) { if (s2 == parent) @@ -1569,7 +1554,7 @@ bool Interpreter::isDescendant(const Arabica::DOM::Node<std::string>& s1, return false; } -bool Interpreter::isTargetless(const Arabica::DOM::Node<std::string>& transition) { +bool InterpreterImpl::isTargetless(const Arabica::DOM::Node<std::string>& transition) { if (transition.hasAttributes()) { if (((Arabica::DOM::Element<std::string>)transition).hasAttribute("target")) return false; @@ -1577,7 +1562,7 @@ bool Interpreter::isTargetless(const Arabica::DOM::Node<std::string>& transition return true; } -bool Interpreter::isState(const Arabica::DOM::Node<std::string>& state) { +bool InterpreterImpl::isState(const Arabica::DOM::Node<std::string>& state) { if (!state) return false; if (state.getNodeType() != Arabica::DOM::Node_base::ELEMENT_NODE) @@ -1597,7 +1582,7 @@ bool Interpreter::isState(const Arabica::DOM::Node<std::string>& state) { return false; } -bool Interpreter::isFinal(const Arabica::DOM::Node<std::string>& state) { +bool InterpreterImpl::isFinal(const Arabica::DOM::Node<std::string>& state) { std::string tagName = LOCALNAME(state); if (boost::iequals("final", tagName)) return true; @@ -1606,7 +1591,7 @@ bool Interpreter::isFinal(const Arabica::DOM::Node<std::string>& state) { return false; } -bool Interpreter::isInitial(const Arabica::DOM::Node<std::string>& state) { +bool InterpreterImpl::isInitial(const Arabica::DOM::Node<std::string>& state) { if (!isState(state)) return false; @@ -1620,7 +1605,7 @@ bool Interpreter::isInitial(const Arabica::DOM::Node<std::string>& state) { return false; } -bool Interpreter::isPseudoState(const Arabica::DOM::Node<std::string>& state) { +bool InterpreterImpl::isPseudoState(const Arabica::DOM::Node<std::string>& state) { std::string tagName = LOCALNAME(state); if (boost::iequals("initial", tagName)) return true; @@ -1629,11 +1614,11 @@ bool Interpreter::isPseudoState(const Arabica::DOM::Node<std::string>& state) { return false; } -bool Interpreter::isTransitionTarget(const Arabica::DOM::Node<std::string>& elem) { +bool InterpreterImpl::isTransitionTarget(const Arabica::DOM::Node<std::string>& elem) { return (isState(elem) || boost::iequals(LOCALNAME(elem), "history")); } -bool Interpreter::isAtomic(const Arabica::DOM::Node<std::string>& state) { +bool InterpreterImpl::isAtomic(const Arabica::DOM::Node<std::string>& state) { if (boost::iequals("final", LOCALNAME(state))) return true; @@ -1648,13 +1633,13 @@ bool Interpreter::isAtomic(const Arabica::DOM::Node<std::string>& state) { return true; } -bool Interpreter::isHistory(const Arabica::DOM::Node<std::string>& state) { +bool InterpreterImpl::isHistory(const Arabica::DOM::Node<std::string>& state) { if (boost::iequals("history", LOCALNAME(state))) return true; return false; } -bool Interpreter::isParallel(const Arabica::DOM::Node<std::string>& state) { +bool InterpreterImpl::isParallel(const Arabica::DOM::Node<std::string>& state) { if (!isState(state)) return false; if (boost::iequals("parallel", LOCALNAME(state))) @@ -1663,7 +1648,7 @@ bool Interpreter::isParallel(const Arabica::DOM::Node<std::string>& state) { } -bool Interpreter::isCompound(const Arabica::DOM::Node<std::string>& state) { +bool InterpreterImpl::isCompound(const Arabica::DOM::Node<std::string>& state) { if (!isState(state)) return false; @@ -1678,7 +1663,7 @@ bool Interpreter::isCompound(const Arabica::DOM::Node<std::string>& state) { return false; } -void Interpreter::setupIOProcessors() { +void InterpreterImpl::setupIOProcessors() { tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); std::map<std::string, IOProcessorImpl*>::iterator ioProcIter = Factory::getInstance()->_ioProcessors.begin(); while(ioProcIter != Factory::getInstance()->_ioProcessors.end()) { @@ -1723,7 +1708,7 @@ void Interpreter::setupIOProcessors() { } } -IOProcessor Interpreter::getIOProcessor(const std::string& type) { +IOProcessor InterpreterImpl::getIOProcessor(const std::string& type) { tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); if (_ioProcessors.find(type) == _ioProcessors.end()) { LOG(ERROR) << "No ioProcessor known for type " << type; @@ -1732,7 +1717,7 @@ IOProcessor Interpreter::getIOProcessor(const std::string& type) { return _ioProcessors[type]; } -void Interpreter::setCmdLineOptions(int argc, char** argv) { +void InterpreterImpl::setCmdLineOptions(int argc, char** argv) { char* key = NULL; char* value = NULL; for (int i = 0; i < argc; i++) { @@ -1758,7 +1743,7 @@ void Interpreter::setCmdLineOptions(int argc, char** argv) { /** * See: http://www.w3.org/TR/scxml/#LegalStateConfigurations */ -bool Interpreter::hasLegalConfiguration() { +bool InterpreterImpl::hasLegalConfiguration() { #if 0 std::cout << "Checking whether {"; @@ -1841,7 +1826,7 @@ bool Interpreter::hasLegalConfiguration() { return true; } -void Interpreter::dump() { +void InterpreterImpl::dump() { if (!_document) return; std::cout << _document; diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index c2e24fa..6701eff 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -29,20 +29,7 @@ namespace uscxml { class HTTPServletInvoker; - -class InterpreterMonitor { -public: - virtual ~InterpreterMonitor() {} - virtual void onStableConfiguration(Interpreter* interpreter) {} - virtual void beforeCompletion(Interpreter* interpreter) {} - virtual void afterCompletion(Interpreter* interpreter) {} - virtual void beforeMicroStep(Interpreter* interpreter) {} - virtual void beforeTakingTransitions(Interpreter* interpreter, const Arabica::XPath::NodeSet<std::string>& transitions) {} - virtual void beforeEnteringStates(Interpreter* interpreter, const Arabica::XPath::NodeSet<std::string>& statesToEnter) {} - virtual void afterEnteringStates(Interpreter* interpreter) {} - virtual void beforeExitingStates(Interpreter* interpreter, const Arabica::XPath::NodeSet<std::string>& statesToExit) {} - virtual void afterExitingStates(Interpreter* interpreter) {} -}; +class InterpreterMonitor; class NumAttr { public: @@ -71,32 +58,28 @@ public: class SCXMLParser : public Arabica::SAX2DOM::Parser<std::string> { public: - SCXMLParser(Interpreter* interpreter); + SCXMLParser(InterpreterImpl* interpreter); void startPrefixMapping(const std::string& /* prefix */, const std::string& /* uri */); Arabica::SAX::CatchErrorHandler<std::string> _errorHandler; - Interpreter* _interpreter; + InterpreterImpl* _interpreter; }; -class Interpreter { +enum Capabilities { + CAN_NOTHING = 0, + CAN_BASIC_HTTP = 1, + CAN_GENERIC_HTTP = 2, +}; + +class InterpreterImpl : public boost::enable_shared_from_this<InterpreterImpl> { public: + enum Binding { EARLY = 0, LATE = 1 }; - enum Capabilities { - CAN_NOTHING = 0, - CAN_BASIC_HTTP = 1, - CAN_GENERIC_HTTP = 2, - }; - - virtual ~Interpreter(); - - static Interpreter* fromDOM(const Arabica::DOM::Document<std::string>& dom); - static Interpreter* fromXML(const std::string& xml); - static Interpreter* fromURI(const std::string& uri); - static Interpreter* fromInputSource(Arabica::SAX::InputSource<std::string>& source); + virtual ~InterpreterImpl(); void start(); static void run(void*); @@ -202,6 +185,10 @@ public: return _ioProcessors; } + const std::map<std::string, Invoker>& getInvokers() { + return _invokers; + } + bool runOnMainThread(int fps, bool blocking = true); static bool isMember(const Arabica::DOM::Node<std::string>& node, const Arabica::XPath::NodeSet<std::string>& set); @@ -237,7 +224,7 @@ public: static const std::string getUUID(); protected: - Interpreter(); + InterpreterImpl(); void init(); void normalize(Arabica::DOM::Element<std::string>& scxml); @@ -261,7 +248,7 @@ protected: bool _running; bool _done; bool _isInitialized; - Binding _binding; + InterpreterImpl::Binding _binding; Arabica::XPath::NodeSet<std::string> _configuration; Arabica::XPath::NodeSet<std::string> _statesToInvoke; std::vector<std::string> _userDefinedStartConfiguration; @@ -298,7 +285,7 @@ protected: static bool nameMatch(const std::string& transitionEvent, const std::string& event); bool hasConditionMatch(const Arabica::DOM::Node<std::string>& conditional); bool isInFinalState(const Arabica::DOM::Node<std::string>& state); - bool parentIsScxmlState(Arabica::DOM::Node<std::string> state); + bool parentIsScxmlState(const Arabica::DOM::Node<std::string>& state); static boost::uuids::random_generator uuidGen; @@ -312,7 +299,7 @@ protected: IOProcessor getIOProcessor(const std::string& type); std::map<std::string, IOProcessor> _ioProcessors; - std::map<std::string, std::pair<Interpreter*, SendRequest> > _sendIds; + std::map<std::string, std::pair<InterpreterImpl*, SendRequest> > _sendIds; std::map<std::string, Invoker> _invokers; std::map<std::string, Invoker> _autoForwardees; std::map<Arabica::DOM::Node<std::string>, ExecutableContent> _executableContent; @@ -323,6 +310,282 @@ protected: friend class SCXMLParser; friend class USCXMLInvoker; + friend class SCXMLIOProcessor; + friend class Interpreter; +}; + +class Interpreter { +public: + static Interpreter fromDOM(const Arabica::DOM::Document<std::string>& dom); + static Interpreter fromXML(const std::string& xml); + static Interpreter fromURI(const std::string& uri); + static Interpreter fromInputSource(Arabica::SAX::InputSource<std::string>& source); + + Interpreter() : _impl() {} + Interpreter(boost::shared_ptr<InterpreterImpl> const impl) : _impl(impl) { } + Interpreter(const Interpreter& other) : _impl(other._impl) { } + virtual ~Interpreter() {}; + + operator bool() const { + return _impl; + } + bool operator< (const Interpreter& other) const { + return _impl < other._impl; + } + bool operator==(const Interpreter& other) const { + return _impl == other._impl; + } + bool operator!=(const Interpreter& other) const { + return _impl != other._impl; + } + Interpreter& operator= (const Interpreter& other) { + _impl = other._impl; + return *this; + } + + void start() { + return _impl->start(); + } + void join() { + return _impl->join(); + }; + bool isRunning() { + return _impl->isRunning(); + } + + void interpret() { + _impl->interpret(); + }; + + void addMonitor(InterpreterMonitor* monitor) { + return _impl->addMonitor(monitor); + } + + void removeMonitor(InterpreterMonitor* monitor) { + return _impl->removeMonitor(monitor); + } + + void setBaseURI(std::string baseURI) { + return _impl->setBaseURI(baseURI); + } + URL getBaseURI() { + return _impl->getBaseURI(); + } + bool toAbsoluteURI(URL& uri) { + return _impl->toAbsoluteURI(uri); + } + + void setCmdLineOptions(int argc, char** argv) { + return _impl->setCmdLineOptions(argc, argv); + } + Data getCmdLineOptions() { + return _impl->getCmdLineOptions(); + } + + InterpreterServlet* getHTTPServlet() { + return _impl->getHTTPServlet(); + } + + DataModel getDataModel() { + return _impl->getDataModel(); + } + void setParentQueue(uscxml::concurrency::BlockingQueue<SendRequest>* parentQueue) { + return _impl->setParentQueue(parentQueue); + } + std::string getXPathPrefix() { + return _impl->getXPathPrefix(); + } + std::string getXMLPrefix() { + return _impl->getXMLPrefix(); + } + Arabica::XPath::StandardNamespaceContext<std::string>& getNSContext() { + return _impl->getNSContext(); + } + std::string getXMLPrefixForNS(const std::string& ns) { + return _impl->getXMLPrefixForNS(ns); + } + + void inline receiveInternal(const Event& event) { + return _impl->receiveInternal(event); + } + void receive(const Event& event, bool toFront = false) { + return _impl->receive(event, toFront); + } + + Event getCurrentEvent() { + return _impl->getCurrentEvent(); + } + + Arabica::XPath::NodeSet<std::string> getConfiguration() { + return _impl->getConfiguration(); + } + void setConfiguration(const std::vector<std::string>& states) { + return _impl->setConfiguration(states); + } + void setInvokeRequest(const InvokeRequest& req) { + return _impl->setInvokeRequest(req); + } + + Arabica::DOM::Node<std::string> getState(const std::string& stateId) { + return _impl->getState(stateId); + } + Arabica::XPath::NodeSet<std::string> getStates(const std::vector<std::string>& stateIds) { + return _impl->getStates(stateIds); + } + + Arabica::DOM::Document<std::string>& getDocument() { + return _impl->getDocument(); + } + + void setCapabilities(unsigned int capabilities) { + return _impl->setCapabilities(capabilities); + } + + void setName(const std::string& name) { + return _impl->setName(name); + } + + const std::string& getName() { + return _impl->getName(); + } + const std::string& getSessionId() { + return _impl->getSessionId(); + } + + const std::map<std::string, IOProcessor>& getIOProcessors() { + return _impl->getIOProcessors(); + } + + const std::map<std::string, Invoker>& getInvokers() { + return _impl->getInvokers(); + } + + bool runOnMainThread(int fps, bool blocking = true) { + return _impl->runOnMainThread(fps, blocking); + } + + static bool isMember(const Arabica::DOM::Node<std::string>& node, const Arabica::XPath::NodeSet<std::string>& set) { + return InterpreterImpl::isMember(node, set); + } + + void dump() { + return _impl->dump(); + } + bool hasLegalConfiguration() { + return _impl->hasLegalConfiguration(); + } + + static bool isState(const Arabica::DOM::Node<std::string>& state) { + return InterpreterImpl::isState(state); + } + static bool isPseudoState(const Arabica::DOM::Node<std::string>& state) { + return InterpreterImpl::isPseudoState(state); + } + static bool isTransitionTarget(const Arabica::DOM::Node<std::string>& elem) { + return InterpreterImpl::isTransitionTarget(elem); + } + static bool isTargetless(const Arabica::DOM::Node<std::string>& transition) { + return InterpreterImpl::isTargetless(transition); + } + static bool isAtomic(const Arabica::DOM::Node<std::string>& state) { + return InterpreterImpl::isAtomic(state); + } + static bool isFinal(const Arabica::DOM::Node<std::string>& state) { + return InterpreterImpl::isFinal(state); + } + static bool isHistory(const Arabica::DOM::Node<std::string>& state) { + return InterpreterImpl::isHistory(state); + } + static bool isParallel(const Arabica::DOM::Node<std::string>& state) { + return InterpreterImpl::isParallel(state); + } + static bool isCompound(const Arabica::DOM::Node<std::string>& state) { + return InterpreterImpl::isCompound(state); + } + static bool isDescendant(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2) { + return InterpreterImpl::isDescendant(s1, s2); + } + + static std::vector<std::string> tokenizeIdRefs(const std::string& idRefs) { + return InterpreterImpl::tokenizeIdRefs(idRefs); + } + + bool isInitial(const Arabica::DOM::Node<std::string>& state) { + return _impl->isInitial(state); + } + Arabica::XPath::NodeSet<std::string> getInitialStates(Arabica::DOM::Node<std::string> state = Arabica::DOM::Node<std::string>()) { + return _impl->getInitialStates(state); + } + static Arabica::XPath::NodeSet<std::string> getChildStates(const Arabica::DOM::Node<std::string>& state) { + return InterpreterImpl::getChildStates(state); + } + static Arabica::DOM::Node<std::string> getParentState(const Arabica::DOM::Node<std::string>& element) { + return InterpreterImpl::getParentState(element); + } + static Arabica::DOM::Node<std::string> getAncestorElement(const Arabica::DOM::Node<std::string>& node, const std::string tagName) { + return InterpreterImpl::getAncestorElement(node, tagName); + } + Arabica::XPath::NodeSet<std::string> getTargetStates(const Arabica::DOM::Node<std::string>& transition) { + return _impl->getTargetStates(transition); + } + Arabica::DOM::Node<std::string> getSourceState(const Arabica::DOM::Node<std::string>& transition) { + return _impl->getSourceState(transition); + } + + static Arabica::XPath::NodeSet<std::string> filterChildElements(const std::string& tagname, const Arabica::DOM::Node<std::string>& node) { + return InterpreterImpl::filterChildElements(tagname, node); + } + static Arabica::XPath::NodeSet<std::string> filterChildElements(const std::string& tagName, const Arabica::XPath::NodeSet<std::string>& nodeSet) { + return InterpreterImpl::filterChildElements(tagName, nodeSet); + } + Arabica::DOM::Node<std::string> findLCCA(const Arabica::XPath::NodeSet<std::string>& states) { + return _impl->findLCCA(states); + } + Arabica::XPath::NodeSet<std::string> getProperAncestors(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2) { + return _impl->getProperAncestors(s1, s2); + } + static const std::string getUUID() { + return InterpreterImpl::getUUID(); + } + +#ifndef SWIG + boost::shared_ptr<InterpreterImpl> getImpl() { + return _impl; + } + + static std::map<std::string, boost::weak_ptr<InterpreterImpl> > getInstances() { + tthread::lock_guard<tthread::recursive_mutex> lock(_instanceMutex); + std::map<std::string, boost::weak_ptr<InterpreterImpl> >::iterator instIter = _instances.begin(); + while(instIter != _instances.end()) { + if (!instIter->second.lock()) { + _instances.erase(instIter++); + } else { + instIter++; + } + } + return _instances; + } + +#endif + +protected: + boost::shared_ptr<InterpreterImpl> _impl; + static std::map<std::string, boost::weak_ptr<InterpreterImpl> > _instances; + static tthread::recursive_mutex _instanceMutex; +}; + +class InterpreterMonitor { +public: + virtual ~InterpreterMonitor() {} + virtual void onStableConfiguration(Interpreter interpreter) {} + virtual void beforeCompletion(Interpreter interpreter) {} + virtual void afterCompletion(Interpreter interpreter) {} + virtual void beforeMicroStep(Interpreter interpreter) {} + virtual void beforeTakingTransitions(Interpreter interpreter, const Arabica::XPath::NodeSet<std::string>& transitions) {} + virtual void beforeEnteringStates(Interpreter interpreter, const Arabica::XPath::NodeSet<std::string>& statesToEnter) {} + virtual void afterEnteringStates(Interpreter interpreter) {} + virtual void beforeExitingStates(Interpreter interpreter, const Arabica::XPath::NodeSet<std::string>& statesToExit) {} + virtual void afterExitingStates(Interpreter interpreter) {} }; } diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h index ae88225..72a2a99 100644 --- a/src/uscxml/Message.h +++ b/src/uscxml/Message.h @@ -81,7 +81,7 @@ protected: protected: Arabica::DOM::Document<std::string> toNode(const Arabica::DOM::Document<std::string>& factory, const Data& data); -#ifndef SWIGJAVA +#ifndef SWIG friend std::ostream& operator<< (std::ostream& os, const Data& data); #endif }; diff --git a/src/uscxml/debug/SCXMLDotWriter.h b/src/uscxml/debug/SCXMLDotWriter.h index e6e2215..0666aa5 100644 --- a/src/uscxml/debug/SCXMLDotWriter.h +++ b/src/uscxml/debug/SCXMLDotWriter.h @@ -18,10 +18,10 @@ public: std::string content; }; - SCXMLDotWriter(Interpreter* interpreter); + SCXMLDotWriter(InterpreterImpl* interpreter); ~SCXMLDotWriter(); - static void toDot(const std::string& filename, Interpreter* interpreter); + static void toDot(const std::string& filename, InterpreterImpl* interpreter); void writeSCXMLElement(std::ostream& os, const Arabica::DOM::Element<std::string>& elem); void writeStateElement(std::ostream& os, const Arabica::DOM::Element<std::string>& elem); void writeTransitionElement(std::ostream& os, const Arabica::DOM::Element<std::string>& elem); diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp index 2f05be9..3c97805 100644 --- a/src/uscxml/interpreter/InterpreterDraft6.cpp +++ b/src/uscxml/interpreter/InterpreterDraft6.cpp @@ -19,8 +19,8 @@ void InterpreterDraft6::interpret() { } // dump(); - if (_sessionId.length() == 0) - _sessionId = getUUID(); + // just make sure we have a session id + assert(_sessionId.length() > 0); std::string datamodelName; if (datamodelName.length() == 0 && HAS_ATTR(_scxml, "datamodel")) @@ -137,7 +137,7 @@ void InterpreterDraft6::mainEventLoop() { monIter = _monitors.begin(); while(monIter != _monitors.end()) { try { - (*monIter)->beforeMicroStep(this); + (*monIter)->beforeMicroStep(shared_from_this()); } catch (Event e) { LOG(ERROR) << "Syntax error when calling beforeMicroStep on monitors: " << std::endl << e << std::endl; } catch (...) { @@ -165,7 +165,7 @@ void InterpreterDraft6::mainEventLoop() { monIter = _monitors.begin(); while(monIter != _monitors.end()) { try { - (*monIter)->beforeTakingTransitions(this, enabledTransitions); + (*monIter)->beforeTakingTransitions(shared_from_this(), enabledTransitions); } catch (Event e) { LOG(ERROR) << "Syntax error when calling beforeTakingTransitions on monitors: " << std::endl << e << std::endl; } catch (...) { @@ -197,7 +197,7 @@ void InterpreterDraft6::mainEventLoop() { // if (!_sendQueue || _sendQueue->isEmpty()) { while(monIter != _monitors.end()) { try { - (*monIter)->onStableConfiguration(this); + (*monIter)->onStableConfiguration(shared_from_this()); } catch (Event e) { LOG(ERROR) << "Syntax error when calling onStableConfiguration on monitors: " << std::endl << e << std::endl; } catch (...) { @@ -276,7 +276,7 @@ EXIT_INTERPRETER: monIter = _monitors.begin(); while(monIter != _monitors.end()) { try { - (*monIter)->beforeCompletion(this); + (*monIter)->beforeCompletion(shared_from_this()); } catch (Event e) { LOG(ERROR) << "Syntax error when calling beforeCompletion on monitors: " << std::endl << e << std::endl; } catch (...) { @@ -287,7 +287,7 @@ EXIT_INTERPRETER: exitInterpreter(); if (_sendQueue) { - std::map<std::string, std::pair<Interpreter*, SendRequest> >::iterator sendIter = _sendIds.begin(); + std::map<std::string, std::pair<InterpreterImpl*, SendRequest> >::iterator sendIter = _sendIds.begin(); while(sendIter != _sendIds.end()) { _sendQueue->cancelEvent(sendIter->first); sendIter++; @@ -297,7 +297,7 @@ EXIT_INTERPRETER: monIter = _monitors.begin(); while(monIter != _monitors.end()) { try { - (*monIter)->afterCompletion(this); + (*monIter)->afterCompletion(shared_from_this()); } catch (Event e) { LOG(ERROR) << "Syntax error when calling afterCompletion on monitors: " << std::endl << e << std::endl; } catch (...) { @@ -343,10 +343,10 @@ Arabica::XPath::NodeSet<std::string> InterpreterDraft6::selectTransitions(const states.push_back(parent); } } - LOOP: +LOOP: index++; } - + #if 0 std::cout << "Enabled transitions: " << std::endl; for (int i = 0; i < enabledTransitions.size(); i++) { @@ -354,7 +354,7 @@ Arabica::XPath::NodeSet<std::string> InterpreterDraft6::selectTransitions(const } std::cout << std::endl; #endif - + enabledTransitions = filterPreempted(enabledTransitions); return enabledTransitions; } @@ -373,9 +373,9 @@ bool InterpreterDraft6::isEnabledTransition(const Node<std::string>& transition, } else { return false; } - + std::vector<std::string> eventNames = tokenizeIdRefs(eventName); - + if (eventNames.size() > 0 && hasConditionMatch(transition)) { std::vector<std::string>::iterator eventIter = eventNames.begin(); while(eventIter != eventNames.end()) { @@ -387,7 +387,7 @@ bool InterpreterDraft6::isEnabledTransition(const Node<std::string>& transition, } return false; } - + Arabica::XPath::NodeSet<std::string> InterpreterDraft6::selectEventlessTransitions() { Arabica::XPath::NodeSet<std::string> enabledTransitions; @@ -423,7 +423,7 @@ Arabica::XPath::NodeSet<std::string> InterpreterDraft6::selectEventlessTransitio states.push_back(parent); } } - LOOP: +LOOP: index++; } @@ -451,7 +451,7 @@ Arabica::XPath::NodeSet<std::string> InterpreterDraft6::filterPreempted(const Ar if (isPreemptingTransition(t2, t)) { #if 0 std::cout << "#####" << std::endl << "Transition " << std::endl - << t2 << std::endl << " preempts " << std::endl << t << std::endl << "#####" << std::endl; + << t2 << std::endl << " preempts " << std::endl << t << std::endl << "#####" << std::endl; #endif goto LOOP; } @@ -500,7 +500,7 @@ bool InterpreterDraft6::isCrossingBounds(const Node<std::string>& transition) { bool InterpreterDraft6::isWithinParallel(const Node<std::string>& transition) { if (isTargetless(transition)) return false; - + Node<std::string> source; if (HAS_ATTR(transition, "type") && boost::iequals(ATTR(transition, "type"), "internal")) { source = getSourceState(transition); @@ -509,7 +509,7 @@ bool InterpreterDraft6::isWithinParallel(const Node<std::string>& transition) { } NodeSet<std::string> targets = getTargetStates(transition); targets.push_back(source); - + Node<std::string> lcpa = findLCPA(targets); return lcpa; } @@ -526,7 +526,7 @@ Node<std::string> InterpreterDraft6::findLCPA(const Arabica::XPath::NodeSet<std: } ancestor = ancestors[i]; break; - NEXT_ANCESTOR: +NEXT_ANCESTOR: ; } return ancestor; @@ -619,7 +619,7 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e for (int j = 0; j < _configuration.size(); j++) { if (isDescendant(_configuration[j], ancestor)) statesToExit.push_back(_configuration[j]); - } + } } } // remove statesToExit from _statesToInvoke @@ -642,11 +642,11 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e } std::cout << std::endl; #endif - + monIter = _monitors.begin(); while(monIter != _monitors.end()) { try { - (*monIter)->beforeExitingStates(this, statesToExit); + (*monIter)->beforeExitingStates(shared_from_this(), statesToExit); } catch (Event e) { LOG(ERROR) << "Syntax error when calling beforeExitingStates on monitors: " << std::endl << e << std::endl; } catch (...) { @@ -707,7 +707,7 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e monIter = _monitors.begin(); while(monIter != _monitors.end()) { try { - (*monIter)->afterExitingStates(this); + (*monIter)->afterExitingStates(shared_from_this()); } catch (Event e) { LOG(ERROR) << "Syntax error when calling afterExitingStates on monitors: " << std::endl << e << std::endl; } catch (...) { @@ -824,7 +824,7 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>& monIter = _monitors.begin(); while(monIter != _monitors.end()) { try { - (*monIter)->beforeEnteringStates(this, statesToEnter); + (*monIter)->beforeEnteringStates(shared_from_this(), statesToEnter); } catch (Event e) { LOG(ERROR) << "Syntax error when calling beforeEnteringStates on monitors: " << std::endl << e << std::endl; } catch (...) { @@ -891,7 +891,7 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>& monIter = _monitors.begin(); while(monIter != _monitors.end()) { try { - (*monIter)->afterEnteringStates(this); + (*monIter)->afterEnteringStates(shared_from_this()); } catch (Event e) { LOG(ERROR) << "Syntax error when calling afterEnteringStates on monitors: " << std::endl << e << std::endl; } catch (...) { diff --git a/src/uscxml/interpreter/InterpreterDraft6.h b/src/uscxml/interpreter/InterpreterDraft6.h index 9ecfd3b..36dedce 100644 --- a/src/uscxml/interpreter/InterpreterDraft6.h +++ b/src/uscxml/interpreter/InterpreterDraft6.h @@ -5,7 +5,7 @@ namespace uscxml { -class InterpreterDraft6 : public Interpreter { +class InterpreterDraft6 : public InterpreterImpl { protected: void interpret(); void mainEventLoop(); diff --git a/src/uscxml/interpreter/InterpreterDraft7.h b/src/uscxml/interpreter/InterpreterDraft7.h index 1dc9350..7600041 100644 --- a/src/uscxml/interpreter/InterpreterDraft7.h +++ b/src/uscxml/interpreter/InterpreterDraft7.h @@ -5,7 +5,7 @@ namespace uscxml { -class InterpreterDraft7 : public Interpreter { +class InterpreterDraft7 : public InterpreterImpl { void interpret(); void mainEventLoop(); void exitInterpreter(); diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp index 1d01e12..e653607 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp @@ -26,7 +26,7 @@ V8DataModel::V8DataModel() { // _contexts.push_back(v8::Context::New()); } -boost::shared_ptr<DataModelImpl> V8DataModel::create(Interpreter* interpreter) { +boost::shared_ptr<DataModelImpl> V8DataModel::create(InterpreterImpl* interpreter) { boost::shared_ptr<V8DataModel> dm = boost::shared_ptr<V8DataModel>(new V8DataModel()); dm->_interpreter = interpreter; v8::Locker locker; @@ -246,17 +246,17 @@ Data V8DataModel::getValueAsData(const v8::Handle<v8::Value>& value) { v8::Handle<v8::Value> V8DataModel::getDocumentAsValue(const Arabica::DOM::Document<std::string>& doc) { v8::Handle<v8::Function> retCtor = Arabica::DOM::V8Document::getTmpl()->GetFunction(); v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance()); - + struct Arabica::DOM::V8Document::V8DocumentPrivate* retPrivData = new Arabica::DOM::V8Document::V8DocumentPrivate(); retPrivData->dom = _dom; retPrivData->nativeObj = new Arabica::DOM::Document<std::string>(doc); - + retObj->SetInternalField(0, Arabica::DOM::V8DOM::toExternal(retPrivData)); retObj.MakeWeak(0, Arabica::DOM::V8Document::jsDestructor); - + return retObj; } - + v8::Handle<v8::Value> V8DataModel::getDataAsValue(const Data& data) { if (data.compound.size() > 0) { v8::Handle<v8::Object> value = v8::Object::New(); diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h index e67e4ca..760b638 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h @@ -22,7 +22,7 @@ class V8DataModel : public DataModelImpl { public: V8DataModel(); virtual ~V8DataModel(); - virtual boost::shared_ptr<DataModelImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<DataModelImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; diff --git a/src/uscxml/plugins/element/fetch/FetchElement.cpp b/src/uscxml/plugins/element/fetch/FetchElement.cpp index eabe0a2..56c1815 100644 --- a/src/uscxml/plugins/element/fetch/FetchElement.cpp +++ b/src/uscxml/plugins/element/fetch/FetchElement.cpp @@ -18,7 +18,7 @@ bool connect(pluma::Host& host) { } #endif -boost::shared_ptr<ExecutableContentImpl> FetchElement::create(Interpreter* interpreter) { +boost::shared_ptr<ExecutableContentImpl> FetchElement::create(InterpreterImpl* interpreter) { boost::shared_ptr<FetchElement> invoker = boost::shared_ptr<FetchElement>(new FetchElement()); invoker->_interpreter = interpreter; return invoker; diff --git a/src/uscxml/plugins/element/fetch/FetchElement.h b/src/uscxml/plugins/element/fetch/FetchElement.h index b553293..e293afe 100644 --- a/src/uscxml/plugins/element/fetch/FetchElement.h +++ b/src/uscxml/plugins/element/fetch/FetchElement.h @@ -13,7 +13,7 @@ class FetchElement : public ExecutableContentImpl, public URLMonitor { public: FetchElement() {} virtual ~FetchElement(); - boost::shared_ptr<ExecutableContentImpl> create(Interpreter* interpreter); + boost::shared_ptr<ExecutableContentImpl> create(InterpreterImpl* interpreter); std::string getLocalName() { return "fetch"; diff --git a/src/uscxml/plugins/element/postpone/PostponeElement.cpp b/src/uscxml/plugins/element/postpone/PostponeElement.cpp index baa8e62..54f2499 100644 --- a/src/uscxml/plugins/element/postpone/PostponeElement.cpp +++ b/src/uscxml/plugins/element/postpone/PostponeElement.cpp @@ -16,7 +16,7 @@ bool connect(pluma::Host& host) { } #endif -boost::shared_ptr<ExecutableContentImpl> PostponeElement::create(Interpreter* interpreter) { +boost::shared_ptr<ExecutableContentImpl> PostponeElement::create(InterpreterImpl* interpreter) { boost::shared_ptr<PostponeElement> invoker = boost::shared_ptr<PostponeElement>(new PostponeElement()); invoker->_interpreter = interpreter; return invoker; @@ -97,21 +97,21 @@ void PostponeElement::enterElement(const Arabica::DOM::Node<std::string>& node) void PostponeElement::exitElement(const Arabica::DOM::Node<std::string>& node) { } -void PostponeElement::Resubmitter::postpone(const Event& event, std::string until, uint64_t timeout, bool chained, Interpreter* interpreter) { +void PostponeElement::Resubmitter::postpone(const Event& event, std::string until, uint64_t timeout, bool chained, InterpreterImpl* interpreter) { Resubmitter* resubmitter = getInstance(interpreter); resubmitter->_postponedEvents.push_back(Postponed(event, until, timeout, chained)); } -void PostponeElement::Resubmitter::onStableConfiguration(Interpreter* interpreter) { +void PostponeElement::Resubmitter::onStableConfiguration(Interpreter interpreter) { std::list<Postponed>::iterator eventIter = _postponedEvents.begin(); bool dispatched = false; while(eventIter != _postponedEvents.end()) { try { // LOG(INFO) << "Reevaluating: >> " << eventIter->first << " <<"; - if ((!dispatched || eventIter->chaining) && interpreter->getDataModel().evalAsBool(eventIter->until)) { + if ((!dispatched || eventIter->chaining) && interpreter.getDataModel().evalAsBool(eventIter->until)) { // LOG(INFO) << " -> is TRUE"; eventIter->event.name += ".postponed"; - interpreter->receive(eventIter->event, true); + interpreter.receive(eventIter->event, true); _postponedEvents.erase(eventIter); dispatched = true; } @@ -127,21 +127,21 @@ void PostponeElement::Resubmitter::onStableConfiguration(Interpreter* interprete } -void PostponeElement::Resubmitter::afterCompletion(Interpreter* interpreter) { +void PostponeElement::Resubmitter::afterCompletion(Interpreter interpreter) { tthread::lock_guard<tthread::recursive_mutex> lock(PostponeElement::Resubmitter::_accessLock); _instances.erase(interpreter); delete this; // committing suicide is ok if we are careful } -std::map<Interpreter*, PostponeElement::Resubmitter*> PostponeElement::Resubmitter::_instances; +std::map<Interpreter, PostponeElement::Resubmitter*> PostponeElement::Resubmitter::_instances; tthread::recursive_mutex PostponeElement::Resubmitter::_accessLock; -PostponeElement::Resubmitter* PostponeElement::Resubmitter::getInstance(Interpreter* interpreter) { +PostponeElement::Resubmitter* PostponeElement::Resubmitter::getInstance(InterpreterImpl* interpreter) { tthread::lock_guard<tthread::recursive_mutex> lock(PostponeElement::Resubmitter::_accessLock); - if (_instances.find(interpreter) == _instances.end()) { - _instances[interpreter] = new Resubmitter(interpreter); + if (_instances.find(interpreter->shared_from_this()) == _instances.end()) { + _instances[interpreter->shared_from_this()] = new Resubmitter(interpreter); } - return _instances[interpreter]; + return _instances[interpreter->shared_from_this()]; } }
\ No newline at end of file diff --git a/src/uscxml/plugins/element/postpone/PostponeElement.h b/src/uscxml/plugins/element/postpone/PostponeElement.h index 7886415..f0c42c0 100644 --- a/src/uscxml/plugins/element/postpone/PostponeElement.h +++ b/src/uscxml/plugins/element/postpone/PostponeElement.h @@ -23,7 +23,7 @@ public: PostponeElement() {} virtual ~PostponeElement() {} - boost::shared_ptr<ExecutableContentImpl> create(Interpreter* interpreter); + boost::shared_ptr<ExecutableContentImpl> create(InterpreterImpl* interpreter); std::string getLocalName() { return "postpone"; @@ -44,19 +44,19 @@ protected: // once per interpreter class Resubmitter : public InterpreterMonitor { public: - Resubmitter(Interpreter* interpreter) { + Resubmitter(InterpreterImpl* interpreter) { interpreter->addMonitor(this); } - static Resubmitter* getInstance(Interpreter* interpreter); - static void postpone(const Event& event, std::string until, uint64_t timeout, bool chained, Interpreter* interpreter); + static Resubmitter* getInstance(InterpreterImpl* interpreter); + static void postpone(const Event& event, std::string until, uint64_t timeout, bool chained, InterpreterImpl* interpreter); // InterpreterMonitor - void onStableConfiguration(Interpreter* interpreter); - void afterCompletion(Interpreter* interpreter); + void onStableConfiguration(Interpreter interpreter); + void afterCompletion(Interpreter interpreter); std::list<Postponed> _postponedEvents; - static std::map<Interpreter*, Resubmitter*> _instances; + static std::map<Interpreter, Resubmitter*> _instances; static tthread::recursive_mutex _accessLock; }; diff --git a/src/uscxml/plugins/element/response/ResponseElement.cpp b/src/uscxml/plugins/element/response/ResponseElement.cpp index cd7ef2d..675bc1e 100644 --- a/src/uscxml/plugins/element/response/ResponseElement.cpp +++ b/src/uscxml/plugins/element/response/ResponseElement.cpp @@ -16,7 +16,7 @@ bool connect(pluma::Host& host) { } #endif -boost::shared_ptr<ExecutableContentImpl> ResponseElement::create(Interpreter* interpreter) { +boost::shared_ptr<ExecutableContentImpl> ResponseElement::create(InterpreterImpl* interpreter) { boost::shared_ptr<ResponseElement> invoker = boost::shared_ptr<ResponseElement>(new ResponseElement()); invoker->_interpreter = interpreter; return invoker; diff --git a/src/uscxml/plugins/element/response/ResponseElement.h b/src/uscxml/plugins/element/response/ResponseElement.h index de3991c..333dd98 100644 --- a/src/uscxml/plugins/element/response/ResponseElement.h +++ b/src/uscxml/plugins/element/response/ResponseElement.h @@ -13,7 +13,7 @@ class ResponseElement : public ExecutableContentImpl { public: ResponseElement() {} virtual ~ResponseElement() {} - boost::shared_ptr<ExecutableContentImpl> create(Interpreter* interpreter); + boost::shared_ptr<ExecutableContentImpl> create(InterpreterImpl* interpreter); std::string getLocalName() { return "response"; diff --git a/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.cpp b/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.cpp index 05af363..aaf6bc4 100644 --- a/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.cpp +++ b/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.cpp @@ -24,7 +24,7 @@ FFMPEGInvoker::FFMPEGInvoker() { FFMPEGInvoker::~FFMPEGInvoker() { }; -boost::shared_ptr<IOProcessorImpl> FFMPEGInvoker::create(Interpreter* interpreter) { +boost::shared_ptr<IOProcessorImpl> FFMPEGInvoker::create(InterpreterImpl* interpreter) { boost::shared_ptr<FFMPEGInvoker> invoker = boost::shared_ptr<FFMPEGInvoker>(new FFMPEGInvoker()); invoker->_interpreter = interpreter; return invoker; diff --git a/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.h b/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.h index 734467f..972c4ff 100644 --- a/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.h +++ b/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.h @@ -13,7 +13,7 @@ class FFMPEGInvoker : public InvokerImpl { public: FFMPEGInvoker(); virtual ~FFMPEGInvoker(); - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; diff --git a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp index 65ea531..b2a16f3 100644 --- a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp +++ b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp @@ -37,7 +37,7 @@ DirMonInvoker::~DirMonInvoker() { _thread->join(); }; -boost::shared_ptr<IOProcessorImpl> DirMonInvoker::create(Interpreter* interpreter) { +boost::shared_ptr<IOProcessorImpl> DirMonInvoker::create(InterpreterImpl* interpreter) { boost::shared_ptr<DirMonInvoker> invoker = boost::shared_ptr<DirMonInvoker>(new DirMonInvoker()); invoker->_interpreter = interpreter; return invoker; diff --git a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h index e2abf54..a58da10 100644 --- a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h +++ b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h @@ -56,7 +56,7 @@ class DirMonInvoker : public InvokerImpl, public DirectoryWatchMonitor { public: DirMonInvoker(); virtual ~DirMonInvoker(); - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp index 3b1a828..932452e 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() { }; -boost::shared_ptr<IOProcessorImpl> OSGInvoker::create(Interpreter* interpreter) { +boost::shared_ptr<IOProcessorImpl> OSGInvoker::create(InterpreterImpl* interpreter) { boost::shared_ptr<OSGInvoker> invoker = boost::shared_ptr<OSGInvoker> (new OSGInvoker()); invoker->_interpreter = interpreter; return invoker; diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h index acfa55c..e79b250 100644 --- a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h +++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h @@ -20,7 +20,7 @@ class OSGInvoker : public InvokerImpl, public Arabica::DOM::Events::EventListene public: OSGInvoker(); virtual ~OSGInvoker(); - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.cpp b/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.cpp index 93a238c..de39424 100644 --- a/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.cpp +++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.cpp @@ -52,7 +52,7 @@ OSGConverter::~OSGConverter() { } }; -boost::shared_ptr<IOProcessorImpl> OSGConverter::create(Interpreter* interpreter) { +boost::shared_ptr<IOProcessorImpl> OSGConverter::create(InterpreterImpl* interpreter) { boost::shared_ptr<OSGConverter> invoker = boost::shared_ptr<OSGConverter>(new OSGConverter()); invoker->_interpreter = interpreter; return invoker; diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.h b/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.h index 28c908d..d3cee30 100644 --- a/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.h +++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.h @@ -15,7 +15,7 @@ class OSGConverter : public InvokerImpl { public: OSGConverter(); virtual ~OSGConverter(); - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; diff --git a/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.cpp b/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.cpp index 6371a43..b69f569 100644 --- a/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.cpp +++ b/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.cpp @@ -22,7 +22,7 @@ HeartbeatInvoker::~HeartbeatInvoker() { cancel(""); }; -boost::shared_ptr<IOProcessorImpl> HeartbeatInvoker::create(Interpreter* interpreter) { +boost::shared_ptr<IOProcessorImpl> HeartbeatInvoker::create(InterpreterImpl* interpreter) { boost::shared_ptr<HeartbeatInvoker> invoker = boost::shared_ptr<HeartbeatInvoker>(new HeartbeatInvoker()); invoker->_interpreter = interpreter; return invoker; diff --git a/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h b/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h index 11be295..5a6272e 100644 --- a/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h +++ b/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h @@ -13,7 +13,7 @@ class HeartbeatInvoker : public InvokerImpl { public: HeartbeatInvoker(); virtual ~HeartbeatInvoker(); - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; diff --git a/src/uscxml/plugins/invoker/http/HTTPServletInvoker.cpp b/src/uscxml/plugins/invoker/http/HTTPServletInvoker.cpp index 223fe03..03e62bd 100644 --- a/src/uscxml/plugins/invoker/http/HTTPServletInvoker.cpp +++ b/src/uscxml/plugins/invoker/http/HTTPServletInvoker.cpp @@ -25,7 +25,7 @@ HTTPServletInvoker::~HTTPServletInvoker() { }; -boost::shared_ptr<IOProcessorImpl> HTTPServletInvoker::create(Interpreter* interpreter) { +boost::shared_ptr<IOProcessorImpl> HTTPServletInvoker::create(InterpreterImpl* interpreter) { boost::shared_ptr<HTTPServletInvoker> invoker = boost::shared_ptr<HTTPServletInvoker>(new HTTPServletInvoker()); invoker->_interpreter = interpreter; return invoker; diff --git a/src/uscxml/plugins/invoker/http/HTTPServletInvoker.h b/src/uscxml/plugins/invoker/http/HTTPServletInvoker.h index 229ead5..06a286c 100644 --- a/src/uscxml/plugins/invoker/http/HTTPServletInvoker.h +++ b/src/uscxml/plugins/invoker/http/HTTPServletInvoker.h @@ -14,7 +14,7 @@ class HTTPServletInvoker : public InvokerImpl, public HTTPServlet { public: HTTPServletInvoker(); virtual ~HTTPServletInvoker(); - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; diff --git a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp index 1a1416a..786c196 100644 --- a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp +++ b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp @@ -25,7 +25,7 @@ MilesSessionInvoker::MilesSessionInvoker() { MilesSessionInvoker::~MilesSessionInvoker() { }; -boost::shared_ptr<IOProcessorImpl> MilesSessionInvoker::create(Interpreter* interpreter) { +boost::shared_ptr<IOProcessorImpl> MilesSessionInvoker::create(InterpreterImpl* interpreter) { boost::shared_ptr<MilesSessionInvoker> invoker = boost::shared_ptr<MilesSessionInvoker>(new MilesSessionInvoker()); invoker->_interpreter = interpreter; return invoker; diff --git a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h index fa66038..c552d1f 100644 --- a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h +++ b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h @@ -24,7 +24,7 @@ class MilesSessionInvoker : public InvokerImpl { public: MilesSessionInvoker(); virtual ~MilesSessionInvoker(); - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; diff --git a/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp b/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp index e7c2e10..d226784 100644 --- a/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp +++ b/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp @@ -21,7 +21,7 @@ SampleInvoker::SampleInvoker() { SampleInvoker::~SampleInvoker() { }; -boost::shared_ptr<IOProcessorImpl> SampleInvoker::create(Interpreter* interpreter) { +boost::shared_ptr<IOProcessorImpl> SampleInvoker::create(InterpreterImpl* interpreter) { boost::shared_ptr<SampleInvoker> invoker = boost::shared_ptr<SampleInvoker>(new SampleInvoker()); invoker->_interpreter = interpreter; return invoker; diff --git a/src/uscxml/plugins/invoker/sample/SampleInvoker.h b/src/uscxml/plugins/invoker/sample/SampleInvoker.h index d689bda..9261f2e 100644 --- a/src/uscxml/plugins/invoker/sample/SampleInvoker.h +++ b/src/uscxml/plugins/invoker/sample/SampleInvoker.h @@ -13,7 +13,7 @@ class SampleInvoker : public InvokerImpl { public: SampleInvoker(); virtual ~SampleInvoker(); - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp index a142231..fc2ac2b 100644 --- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp +++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp @@ -21,10 +21,9 @@ USCXMLInvoker::USCXMLInvoker() : _cancelled(false) { USCXMLInvoker::~USCXMLInvoker() { _cancelled = true; - delete _invokedInterpreter; }; -boost::shared_ptr<IOProcessorImpl> USCXMLInvoker::create(Interpreter* interpreter) { +boost::shared_ptr<IOProcessorImpl> USCXMLInvoker::create(InterpreterImpl* interpreter) { boost::shared_ptr<USCXMLInvoker> invoker = boost::shared_ptr<USCXMLInvoker>(new USCXMLInvoker()); invoker->_parentInterpreter = interpreter; return invoker; @@ -36,7 +35,7 @@ Data USCXMLInvoker::getDataModelVariables() { } void USCXMLInvoker::send(const SendRequest& req) { - _invokedInterpreter->_externalQueue.push(req); + _invokedInterpreter.getImpl()->_externalQueue.push(req); } void USCXMLInvoker::cancel(const std::string sendId) { @@ -54,27 +53,27 @@ void USCXMLInvoker::invoke(const InvokeRequest& req) { LOG(ERROR) << "Cannot invoke nested SCXML interpreter, neither src attribute nor DOM is given"; } if (_invokedInterpreter) { - DataModel dataModel(_invokedInterpreter->getDataModel()); + DataModel dataModel(_invokedInterpreter.getImpl()->getDataModel()); if (dataModel) { } - _invokedInterpreter->setParentQueue(this); + _invokedInterpreter.getImpl()->setParentQueue(this); // transfer namespace prefixes - _invokedInterpreter->_nsURL = _parentInterpreter->_nsURL; - _invokedInterpreter->_xpathPrefix = _parentInterpreter->_xpathPrefix; - _invokedInterpreter->_nsToPrefix = _parentInterpreter->_nsToPrefix; + _invokedInterpreter.getImpl()->_nsURL = _parentInterpreter->_nsURL; + _invokedInterpreter.getImpl()->_xpathPrefix = _parentInterpreter->_xpathPrefix; + _invokedInterpreter.getImpl()->_nsToPrefix = _parentInterpreter->_nsToPrefix; std::map<std::string, std::string>::iterator nsIter = _parentInterpreter->_nsToPrefix.begin(); while(nsIter != _parentInterpreter->_nsToPrefix.end()) { - _invokedInterpreter->_nsContext.addNamespaceDeclaration(nsIter->first, nsIter->second); + _invokedInterpreter.getImpl()->_nsContext.addNamespaceDeclaration(nsIter->first, nsIter->second); nsIter++; } - _invokedInterpreter->_xmlNSPrefix = _parentInterpreter->_xmlNSPrefix; - _invokedInterpreter->_sessionId = req.invokeid; + _invokedInterpreter.getImpl()->_xmlNSPrefix = _parentInterpreter->_xmlNSPrefix; + _invokedInterpreter.getImpl()->_sessionId = req.invokeid; /// test240 assumes that invoke request params will carry over to the datamodel - _invokedInterpreter->setInvokeRequest(req); + _invokedInterpreter.getImpl()->setInvokeRequest(req); - _invokedInterpreter->start(); + _invokedInterpreter.getImpl()->start(); } else { /// test 530 _parentInterpreter->receive(Event("done.invoke." + _invokeId, Event::PLATFORM)); diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h index b1386b1..4b2c2d5 100644 --- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h +++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h @@ -20,7 +20,7 @@ class USCXMLInvoker : public: USCXMLInvoker(); virtual ~USCXMLInvoker(); - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; names.insert("scxml"); @@ -39,8 +39,8 @@ public: protected: bool _cancelled; - Interpreter* _invokedInterpreter; - Interpreter* _parentInterpreter; + Interpreter _invokedInterpreter; + InterpreterImpl* _parentInterpreter; }; #ifdef BUILD_AS_PLUGINS diff --git a/src/uscxml/plugins/invoker/sqlite3/Sqlite3Invoker.cpp b/src/uscxml/plugins/invoker/sqlite3/Sqlite3Invoker.cpp index e217eaa..1d563ec 100644 --- a/src/uscxml/plugins/invoker/sqlite3/Sqlite3Invoker.cpp +++ b/src/uscxml/plugins/invoker/sqlite3/Sqlite3Invoker.cpp @@ -21,7 +21,7 @@ Sqlite3Invoker::Sqlite3Invoker() { Sqlite3Invoker::~Sqlite3Invoker() { }; -boost::shared_ptr<IOProcessorImpl> Sqlite3Invoker::create(Interpreter* interpreter) { +boost::shared_ptr<IOProcessorImpl> Sqlite3Invoker::create(InterpreterImpl* interpreter) { boost::shared_ptr<Sqlite3Invoker> invoker = boost::shared_ptr<Sqlite3Invoker>(new Sqlite3Invoker()); invoker->_interpreter = interpreter; return invoker; diff --git a/src/uscxml/plugins/invoker/sqlite3/Sqlite3Invoker.h b/src/uscxml/plugins/invoker/sqlite3/Sqlite3Invoker.h index 505d263..35bfec4 100644 --- a/src/uscxml/plugins/invoker/sqlite3/Sqlite3Invoker.h +++ b/src/uscxml/plugins/invoker/sqlite3/Sqlite3Invoker.h @@ -13,7 +13,7 @@ class Sqlite3Invoker : public InvokerImpl { public: Sqlite3Invoker(); virtual ~Sqlite3Invoker(); - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; diff --git a/src/uscxml/plugins/invoker/system/SystemInvoker.cpp b/src/uscxml/plugins/invoker/system/SystemInvoker.cpp index 492d6d3..468628c 100644 --- a/src/uscxml/plugins/invoker/system/SystemInvoker.cpp +++ b/src/uscxml/plugins/invoker/system/SystemInvoker.cpp @@ -21,7 +21,7 @@ SystemInvoker::SystemInvoker() { SystemInvoker::~SystemInvoker() { }; -boost::shared_ptr<IOProcessorImpl> SystemInvoker::create(Interpreter* interpreter) { +boost::shared_ptr<IOProcessorImpl> SystemInvoker::create(InterpreterImpl* interpreter) { boost::shared_ptr<SystemInvoker> invoker = boost::shared_ptr<SystemInvoker>(new SystemInvoker()); invoker->_interpreter = interpreter; return invoker; diff --git a/src/uscxml/plugins/invoker/system/SystemInvoker.h b/src/uscxml/plugins/invoker/system/SystemInvoker.h index 67bd1a9..0292d41 100644 --- a/src/uscxml/plugins/invoker/system/SystemInvoker.h +++ b/src/uscxml/plugins/invoker/system/SystemInvoker.h @@ -13,7 +13,7 @@ class SystemInvoker : public InvokerImpl { public: SystemInvoker(); virtual ~SystemInvoker(); - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; diff --git a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp index 4005d03..5439413 100644 --- a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp +++ b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp @@ -28,7 +28,7 @@ UmundoInvoker::~UmundoInvoker() { } }; -boost::shared_ptr<IOProcessorImpl> UmundoInvoker::create(Interpreter* interpreter) { +boost::shared_ptr<IOProcessorImpl> UmundoInvoker::create(InterpreterImpl* interpreter) { boost::shared_ptr<UmundoInvoker> invoker = boost::shared_ptr<UmundoInvoker>(new UmundoInvoker()); invoker->_interpreter = interpreter; return invoker; @@ -250,7 +250,7 @@ void UmundoInvoker::changed(umundo::ServiceDescription desc) { } std::multimap<std::string, std::pair<std::string, umundo::Node*> > UmundoInvoker::_nodes; -umundo::Node* UmundoInvoker::getNode(Interpreter* interpreter, const std::string& domain) { +umundo::Node* UmundoInvoker::getNode(InterpreterImpl* interpreter, const std::string& domain) { std::pair<_nodes_t::iterator, _nodes_t::iterator> range = _nodes.equal_range(interpreter->getName()); for (_nodes_t::iterator it = range.first; it != range.second; it++) { if (it->second.first.compare(domain) == 0) diff --git a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.h b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.h index a7f45f1..db944cd 100644 --- a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.h +++ b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.h @@ -20,7 +20,7 @@ class UmundoInvoker : public InvokerImpl, public umundo::TypedReceiver, public u public: UmundoInvoker(); virtual ~UmundoInvoker(); - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; @@ -57,7 +57,7 @@ protected: static std::multimap<std::string, std::pair<std::string, umundo::Node*> > _nodes; typedef std::multimap<std::string, std::pair<std::string, umundo::Node*> > _nodes_t; - static umundo::Node* getNode(Interpreter* interpreter, const std::string& domain); + static umundo::Node* getNode(InterpreterImpl* interpreter, const std::string& domain); }; #ifdef BUILD_AS_PLUGINS diff --git a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp index a1f803d..9ae62a8 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp +++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp @@ -3,7 +3,7 @@ #include <windows.h> #endif -#include "uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h" +#include "uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.h" #include "uscxml/Message.h" #include <iostream> #include <event2/dns.h> @@ -29,24 +29,24 @@ namespace uscxml { #ifdef BUILD_AS_PLUGINS PLUMA_CONNECTOR bool connect(pluma::Host& host) { - host.add( new EventIOProcessorProvider() ); + host.add( new BasicHTTPIOProcessorProvider() ); return true; } #endif // see http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor -EventIOProcessor::EventIOProcessor() { +BasicHTTPIOProcessor::BasicHTTPIOProcessor() { } -EventIOProcessor::~EventIOProcessor() { +BasicHTTPIOProcessor::~BasicHTTPIOProcessor() { HTTPServer* httpServer = HTTPServer::getInstance(); httpServer->unregisterServlet(this); } -boost::shared_ptr<IOProcessorImpl> EventIOProcessor::create(Interpreter* interpreter) { - boost::shared_ptr<EventIOProcessor> io = boost::shared_ptr<EventIOProcessor>(new EventIOProcessor()); +boost::shared_ptr<IOProcessorImpl> BasicHTTPIOProcessor::create(InterpreterImpl* interpreter) { + boost::shared_ptr<BasicHTTPIOProcessor> io = boost::shared_ptr<BasicHTTPIOProcessor>(new BasicHTTPIOProcessor()); io->_interpreter = interpreter; // register at http server @@ -61,14 +61,14 @@ boost::shared_ptr<IOProcessorImpl> EventIOProcessor::create(Interpreter* interpr return io; } -Data EventIOProcessor::getDataModelVariables() { +Data BasicHTTPIOProcessor::getDataModelVariables() { Data data; assert(_url.length() > 0); data.compound["location"] = Data(_url, Data::VERBATIM); return data; } -void EventIOProcessor::httpRecvRequest(const HTTPServer::Request& req) { +void BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) { Event reqEvent = req; reqEvent.type = Event::EXTERNAL; bool scxmlStructFound = false; @@ -116,7 +116,7 @@ void EventIOProcessor::httpRecvRequest(const HTTPServer::Request& req) { evhttp_send_reply(req.curlReq, 200, "OK", NULL); } -void EventIOProcessor::send(const SendRequest& req) { +void BasicHTTPIOProcessor::send(const SendRequest& req) { bool isLocal = false; std::string target; @@ -167,9 +167,9 @@ void EventIOProcessor::send(const SendRequest& req) { } } -void EventIOProcessor::downloadStarted(const URL& url) {} +void BasicHTTPIOProcessor::downloadStarted(const URL& url) {} -void EventIOProcessor::downloadCompleted(const URL& url) { +void BasicHTTPIOProcessor::downloadCompleted(const URL& url) { std::map<std::string, std::pair<URL, SendRequest> >::iterator reqIter = _sendRequests.begin(); while(reqIter != _sendRequests.end()) { if (reqIter->second.first == url) { @@ -181,7 +181,7 @@ void EventIOProcessor::downloadCompleted(const URL& url) { assert(false); } -void EventIOProcessor::downloadFailed(const URL& url, int errorCode) { +void BasicHTTPIOProcessor::downloadFailed(const URL& url, int errorCode) { std::map<std::string, std::pair<URL, SendRequest> >::iterator reqIter = _sendRequests.begin(); while(reqIter != _sendRequests.end()) { diff --git a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.h index c549b2b..1848e5e 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h +++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.h @@ -1,5 +1,5 @@ -#ifndef EVENTIOPROCESSOR_H_2CUY93KU -#define EVENTIOPROCESSOR_H_2CUY93KU +#ifndef BASICHTTPIOPROCESSOR_H_2CUY93KU +#define BASICHTTPIOPROCESSOR_H_2CUY93KU #include "uscxml/concurrency/eventqueue/DelayedEventQueue.h" #include "uscxml/server/HTTPServer.h" @@ -18,13 +18,11 @@ namespace uscxml { -class EventIOServer; - -class EventIOProcessor : public IOProcessorImpl, public HTTPServlet, public URLMonitor { +class BasicHTTPIOProcessor : public IOProcessorImpl, public HTTPServlet, public URLMonitor { public: - EventIOProcessor(); - virtual ~EventIOProcessor(); - virtual boost::shared_ptr<IOProcessorImpl> create(uscxml::Interpreter* interpreter); + BasicHTTPIOProcessor(); + virtual ~BasicHTTPIOProcessor(); + virtual boost::shared_ptr<IOProcessorImpl> create(uscxml::InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; @@ -58,9 +56,9 @@ protected: }; #ifdef BUILD_AS_PLUGINS -PLUMA_INHERIT_PROVIDER(EventIOProcessor, IOProcessorImpl); +PLUMA_INHERIT_PROVIDER(BasicHTTPIOProcessor, IOProcessorImpl); #endif } -#endif /* end of include guard: EVENTIOPROCESSOR_H_2CUY93KU */
\ No newline at end of file +#endif /* end of include guard: BASICHTTPIOPROCESSOR_H_2CUY93KU */
\ No newline at end of file diff --git a/src/uscxml/plugins/ioprocessor/dom/DOMIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/dom/DOMIOProcessor.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/uscxml/plugins/ioprocessor/dom/DOMIOProcessor.cpp diff --git a/src/uscxml/plugins/ioprocessor/dom/DOMIOProcessor.h b/src/uscxml/plugins/ioprocessor/dom/DOMIOProcessor.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/uscxml/plugins/ioprocessor/dom/DOMIOProcessor.h diff --git a/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp new file mode 100644 index 0000000..387075b --- /dev/null +++ b/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp @@ -0,0 +1,141 @@ +#ifdef _WIN32 +#include <winsock2.h> +#include <windows.h> +#endif + +#include "uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.h" +#include "uscxml/Message.h" +#include <iostream> +#include <event2/dns.h> +#include <event2/buffer.h> +#include <event2/keyvalq_struct.h> + +#include <string.h> + +#include <io/uri.hpp> +#include <glog/logging.h> + +#ifndef _WIN32 +#include <netdb.h> +#include <arpa/inet.h> +#endif + +#ifdef BUILD_AS_PLUGINS +#include <Pluma/Connector.hpp> +#endif + +namespace uscxml { + +#ifdef BUILD_AS_PLUGINS +PLUMA_CONNECTOR +bool connect(pluma::Host& host) { + host.add( new SCXMLIOProcessorProvider() ); + return true; +} +#endif + +// see http://www.w3.org/TR/scxml/#SCXMLEventProcessor + +SCXMLIOProcessor::SCXMLIOProcessor() { +} + +SCXMLIOProcessor::~SCXMLIOProcessor() { +} + + +boost::shared_ptr<IOProcessorImpl> SCXMLIOProcessor::create(InterpreterImpl* interpreter) { + boost::shared_ptr<SCXMLIOProcessor> io = boost::shared_ptr<SCXMLIOProcessor>(new SCXMLIOProcessor()); + io->_interpreter = interpreter; + + // register at http server + std::string path = interpreter->getName(); + int i = 2; + while (!HTTPServer::registerServlet(path + "/scxml", io.get())) { + std::stringstream ss; + ss << interpreter->getName() << i++; + path = ss.str(); + } + return io; +} + +Data SCXMLIOProcessor::getDataModelVariables() { + Data data; + assert(_url.length() > 0); + data.compound["location"] = Data(_url, Data::VERBATIM); + return data; +} + + +void SCXMLIOProcessor::send(const SendRequest& req) { + // see http://www.w3.org/TR/scxml/#SendTargets + + SendRequest reqCopy(req); + // test 253 + reqCopy.origintype = "scxml"; + reqCopy.origin = _url; + + if (false) { + } else if (boost::iequals(reqCopy.target, "#_internal")) { + /** + * #_internal: If the target is the special term '#_internal', the Processor + * must add the event to the internal event queue of the sending session. + */ + _interpreter->receiveInternal(reqCopy); + + } else if(reqCopy.target.find_first_of("#_scxml_") == 0) { + /** + * #_scxml_sessionid: If the target is the special term '#_scxml_sessionid', + * where sessionid is the id of an SCXML session that is accessible to the + * Processor, the Processor must add the event to the external queue of that + * session. The set of SCXML sessions that are accessible to a given SCXML + * Processor is platform-dependent. + */ + std::string sessionId = reqCopy.target.substr(8, reqCopy.target.length() - 8); + std::map<std::string, boost::weak_ptr<InterpreterImpl> > instances = Interpreter::getInstances(); + if (instances.find(sessionId) != instances.end()) { + boost::shared_ptr<InterpreterImpl> other = instances[sessionId].lock(); + other->receive(reqCopy); + } else { + LOG(ERROR) << "Can not send to scxml session " << sessionId << " - not known" << std::endl; + _interpreter->receiveInternal(Event("error.communication", Event::PLATFORM)); + } + + + } else if (boost::iequals(reqCopy.target, "#_parent")) { + /** + * #_parent: If the target is the special term '#_parent', the Processor must + * add the event to the external event queue of the SCXML session that invoked + * the sending session, if there is one. + */ + if (_interpreter->_parentQueue != NULL) { + _interpreter->_parentQueue->push(reqCopy); + } else { + LOG(ERROR) << "Can not send to parent, we were not invoked" << std::endl; + _interpreter->receiveInternal(Event("error.communication", Event::PLATFORM)); + } + } else if (reqCopy.target.find_first_of("#_") == 0) { + /** + * #_invokeid: If the target is the special term '#_invokeid', where invokeid + * is the invokeid of an SCXML session that the sending session has created + * by <invoke>, the Processor must add the event to the external queue of that + * session. + */ + std::string invokeId = reqCopy.target.substr(2, reqCopy.target.length() - 2); + if (_interpreter->_invokers.find(invokeId) != _interpreter->_invokers.end()) { + tthread::lock_guard<tthread::recursive_mutex> lock(_interpreter->_mutex); + try { + _interpreter->_invokers[invokeId].send(reqCopy); + } catch(...) { + LOG(ERROR) << "Exception caught while sending event to invoker " << invokeId; + } + } else { + LOG(ERROR) << "Can not send to invoked component '" << invokeId << "', no such invokeId" << std::endl; + _interpreter->receiveInternal(Event("error.communication", Event::PLATFORM)); + } + } else { + } +} + + + +}
\ No newline at end of file diff --git a/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.h b/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.h new file mode 100644 index 0000000..a4f3f7c --- /dev/null +++ b/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.h @@ -0,0 +1,36 @@ +#ifndef SCXMLIOProcessor_H_2CUY93KU +#define SCXMLIOProcessor_H_2CUY93KU + +#include "uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.h" + +#ifdef BUILD_AS_PLUGINS +#include "uscxml/plugins/Plugins.h" +#endif + +namespace uscxml { + +class SCXMLIOProcessor : public BasicHTTPIOProcessor { +public: + SCXMLIOProcessor(); + virtual ~SCXMLIOProcessor(); + virtual boost::shared_ptr<IOProcessorImpl> create(uscxml::InterpreterImpl* interpreter); + + virtual std::set<std::string> getNames() { + std::set<std::string> names; + names.insert("http://www.w3.org/TR/scxml/#SCXMLEventProcessor"); + names.insert("scxml"); + return names; + } + + virtual void send(const SendRequest& req); + + Data getDataModelVariables(); +}; + +#ifdef BUILD_AS_PLUGINS +PLUMA_INHERIT_PROVIDER(SCXMLIOProcessor, IOProcessorImpl); +#endif + +} + +#endif /* end of include guard: SCXMLIOProcessor_H_2CUY93KU */
\ No newline at end of file diff --git a/src/uscxml/server/InterpreterServlet.cpp b/src/uscxml/server/InterpreterServlet.cpp index 99b81b2..0386c3b 100644 --- a/src/uscxml/server/InterpreterServlet.cpp +++ b/src/uscxml/server/InterpreterServlet.cpp @@ -4,7 +4,7 @@ namespace uscxml { -InterpreterServlet::InterpreterServlet(Interpreter* interpreter) { +InterpreterServlet::InterpreterServlet(InterpreterImpl* interpreter) { _interpreter = interpreter; std::stringstream path; @@ -18,7 +18,7 @@ InterpreterServlet::InterpreterServlet(Interpreter* interpreter) { _path = path.str(); } -boost::shared_ptr<IOProcessorImpl> InterpreterServlet::create(Interpreter* interpreter) { +boost::shared_ptr<IOProcessorImpl> InterpreterServlet::create(InterpreterImpl* interpreter) { // we instantiate directly in Interpreter boost::shared_ptr<IOProcessorImpl> io = boost::shared_ptr<InterpreterServlet>(new InterpreterServlet(interpreter)); return io; diff --git a/src/uscxml/server/InterpreterServlet.h b/src/uscxml/server/InterpreterServlet.h index 18e1d28..6c61e47 100644 --- a/src/uscxml/server/InterpreterServlet.h +++ b/src/uscxml/server/InterpreterServlet.h @@ -11,10 +11,10 @@ class Interpreter; class InterpreterServlet : public HTTPServlet, public IOProcessorImpl { public: InterpreterServlet() {}; - InterpreterServlet(Interpreter* interpreter); + InterpreterServlet(InterpreterImpl* interpreter); virtual ~InterpreterServlet() {} - virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; @@ -50,7 +50,7 @@ public: } protected: - Interpreter* _interpreter; + InterpreterImpl* _interpreter; tthread::recursive_mutex _mutex; std::map<std::string, HTTPServer::Request> _requests; |