diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-03-31 23:58:37 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-03-31 23:58:37 (GMT) |
commit | c912952fb5e8072770262c64932c1d8cf2027cf0 (patch) | |
tree | d21ae1340c96f9fe1105f9cdaa62d84342f58cd9 /src | |
parent | f64620e28a55dbddaeeefef2e7b8a6a433f21c82 (diff) | |
download | uscxml-c912952fb5e8072770262c64932c1d8cf2027cf0.zip uscxml-c912952fb5e8072770262c64932c1d8cf2027cf0.tar.gz uscxml-c912952fb5e8072770262c64932c1d8cf2027cf0.tar.bz2 |
Various bug-fixes for W3C test conformance and stack traces with exceptions and segfaults
Diffstat (limited to 'src')
-rw-r--r-- | src/uscxml/Factory.h | 9 | ||||
-rw-r--r-- | src/uscxml/Interpreter.cpp | 100 | ||||
-rw-r--r-- | src/uscxml/Interpreter.h | 10 | ||||
-rw-r--r-- | src/uscxml/Message.h | 1 | ||||
-rw-r--r-- | src/uscxml/interpreter/InterpreterDraft6.cpp | 54 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp | 8 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h | 5 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp | 4 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h | 1 | ||||
-rw-r--r-- | src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp | 21 | ||||
-rw-r--r-- | src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h | 1 | ||||
-rw-r--r-- | src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp | 16 | ||||
-rw-r--r-- | src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h | 2 |
13 files changed, 183 insertions, 49 deletions
diff --git a/src/uscxml/Factory.h b/src/uscxml/Factory.h index 9cfc202..b86c5d1 100644 --- a/src/uscxml/Factory.h +++ b/src/uscxml/Factory.h @@ -157,6 +157,10 @@ public: return *this; } + virtual std::set<std::string> getNames() { + return _impl->getNames(); + } + virtual Data getDataModelVariables() const { return _impl->getDataModelVariables(); }; @@ -242,6 +246,7 @@ public: virtual bool evalAsBool(const std::string& expr) = 0; virtual void assign(const std::string& location, const std::string& expr) = 0; virtual void assign(const std::string& location, const Data& data) = 0; + virtual bool isDefined(const std::string& expr) = 0; protected: Interpreter* _interpreter; @@ -315,6 +320,10 @@ public: return _impl->assign(location, data); } + virtual bool isDefined(const std::string& expr) { + return _impl->isDefined(expr); + } + protected: boost::shared_ptr<DataModelImpl> _impl; }; diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 482a42c..7289b82 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -198,8 +198,10 @@ bool Interpreter::toAbsoluteURI(URL& uri) { } Interpreter::~Interpreter() { + tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); if (_thread) { _running = false; + // unblock event queue Event event; _externalQueue.push(event); _thread->join(); @@ -237,7 +239,7 @@ bool Interpreter::runOnMainThread(int fps, bool blocking) { _lastRunOnMainThread = tthread::timeStamp(); - tthread::lock_guard<tthread::mutex> lock(_mutex); + tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); std::map<std::string, IOProcessor>::iterator ioProcessorIter = _ioProcessors.begin(); while(ioProcessorIter != _ioProcessors.end()) { ioProcessorIter->second.runOnMainThread(); @@ -356,7 +358,7 @@ void Interpreter::internalDoneSend(const Arabica::DOM::Node<std::string>& state) Arabica::DOM::Node<std::string> doneData = doneDatas[0]; NodeList<std::string> doneChilds = doneData.getChildNodes(); for (int i = 0; i < doneChilds.getLength(); i++) { - if (!doneChilds.item(i).getNodeType() == Node_base::ELEMENT_NODE) + if (doneChilds.item(i).getNodeType() != Node_base::ELEMENT_NODE) continue; if (boost::iequals(TAGNAME(doneChilds.item(i)), _xmlNSPrefix + "param")) { if (!HAS_ATTR(doneChilds.item(i), "name")) { @@ -427,8 +429,6 @@ void Interpreter::send(const Arabica::DOM::Node<std::string>& element) { sendReq.type = _dataModel.evalAsString(ATTR(element, "typeexpr")); } else if (HAS_ATTR(element, "type")) { sendReq.type = ATTR(element, "type"); - } else { - sendReq.type = "http://www.w3.org/TR/scxml/#SCXMLEventProcessor"; } } catch (Event e) { LOG(ERROR) << "Syntax error in send element typeexpr:" << std::endl << e << std::endl; @@ -458,7 +458,7 @@ void Interpreter::send(const Arabica::DOM::Node<std::string>& element) { * See 3.14 IDs for details. * */ - sendReq.sendid = getUUID(); + sendReq.sendid = ATTR(getParentState(element), "id") + "." + getUUID(); if (HAS_ATTR(element, "idlocation") && _dataModel) { _dataModel.assign(ATTR(element, "idlocation"), "'" + sendReq.sendid + "'"); } @@ -622,6 +622,10 @@ void Interpreter::delayedSend(void* userdata, std::string eventName) { Interpreter* 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 @@ -637,7 +641,7 @@ void Interpreter::delayedSend(void* userdata, std::string eventName) { // send to invoker std::string invokeId = sendReq.target.substr(2, sendReq.target.length() - 2); if (INSTANCE->_invokers.find(invokeId) != INSTANCE->_invokers.end()) { - tthread::lock_guard<tthread::mutex> lock(INSTANCE->_mutex); + tthread::lock_guard<tthread::recursive_mutex> lock(INSTANCE->_mutex); try { INSTANCE->_invokers[invokeId].send(sendReq); } catch(...) { @@ -646,7 +650,9 @@ void Interpreter::delayedSend(void* userdata, std::string eventName) { } else { LOG(ERROR) << "Can not send to invoked component '" << invokeId << "', no such invokeId" << std::endl; } - } else if (sendReq.target.length() == 0) { + } else if (sendReq.target.length() == 0 && + (sendReq.type.length() == 0 || + boost::equals(sendReq.type, "http://www.w3.org/TR/scxml/#SCXMLEventProcessor"))) { /** * If neither the 'target' nor the 'targetexpr' attribute is specified, the * SCXML Processor must add the event will be added to the external event @@ -661,6 +667,8 @@ void Interpreter::delayedSend(void* userdata, std::string eventName) { } catch(...) { LOG(ERROR) << "Exception caught while sending event to ioprocessor " << sendReq.type; } + } else { + INSTANCE->_internalQueue.push_back(Event("error.execution")); } } assert(INSTANCE->_sendIds.find(sendReq.sendid) != INSTANCE->_sendIds.end()); @@ -697,12 +705,18 @@ void Interpreter::invoke(const Arabica::DOM::Node<std::string>& element) { } // id - if (HAS_ATTR(element, "idlocation") && _dataModel) { - invokeReq.invokeid = _dataModel.evalAsString(ATTR(element, "idlocation")); - } else if (HAS_ATTR(element, "id")) { - invokeReq.invokeid = ATTR(element, "id"); - } else { - assert(false); + try { + if (HAS_ATTR(element, "id")) { + invokeReq.invokeid = ATTR(element, "id"); + } else { + invokeReq.invokeid = ATTR(getParentState(element), "id") + "." + getUUID(); + if (HAS_ATTR(element, "idlocation") && _dataModel) { + _dataModel.assign(ATTR(element, "idlocation"), "'" + invokeReq.invokeid + "'"); + } + } + } catch (Event e) { + LOG(ERROR) << "Syntax error in invoke element idlocation:" << std::endl << e << std::endl; + return; } // namelist @@ -743,7 +757,7 @@ void Interpreter::invoke(const Arabica::DOM::Node<std::string>& element) { continue; } std::string paramKey = ATTR(params[i], "name"); - boost::algorithm::to_lower(paramKey); + //boost::algorithm::to_lower(paramKey); invokeReq.params.insert(std::make_pair(paramKey, paramValue)); } @@ -815,7 +829,7 @@ void Interpreter::invoke(const Arabica::DOM::Node<std::string>& element) { Invoker invoker(Factory::createInvoker(invokeReq.type, this)); if (invoker) { - tthread::lock_guard<tthread::mutex> lock(_mutex); + tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); try { invoker.setInvokeId(invokeReq.invokeid); invoker.setType(invokeReq.type); @@ -966,9 +980,7 @@ void Interpreter::executeContent(const Arabica::DOM::Node<std::string>& content, } else if (boost::iequals(TAGNAME(content), _xmlNSPrefix + "raise")) { // --- RAISE -------------------------- if (HAS_ATTR(content, "event")) { - Event event; - event.name = ATTR(content, "event"); - _internalQueue.push_back(event); + _internalQueue.push_back(Event(ATTR(content, "event"))); } } else if (boost::iequals(TAGNAME(content), _xmlNSPrefix + "if")) { // --- IF / ELSEIF / ELSE -------------- @@ -1057,6 +1069,8 @@ void Interpreter::executeContent(const Arabica::DOM::Node<std::string>& content, // --- LOG -------------------------- Arabica::DOM::Element<std::string> logElem = (Arabica::DOM::Element<std::string>)content; if (logElem.hasAttribute("expr")) { + if (logElem.hasAttribute("label")) + std::cout << logElem.getAttribute("label") << ": "; if (_dataModel) { try { std::cout << _dataModel.evalAsString(logElem.getAttribute("expr")) << std::endl; @@ -1066,14 +1080,22 @@ void Interpreter::executeContent(const Arabica::DOM::Node<std::string>& content, throw e; } } else { - std::cout << logElem.getAttribute("expr") << std::endl; + if (logElem.hasAttribute("label")) + std::cout << std::endl; } } } else if (boost::iequals(TAGNAME(content), _xmlNSPrefix + "assign")) { // --- ASSIGN -------------------------- if (_dataModel && HAS_ATTR(content, "location") && HAS_ATTR(content, "expr")) { try { - _dataModel.assign(ATTR(content, "location"), ATTR(content, "expr")); + if (!_dataModel.isDefined(ATTR(content, "location"))) { + // test 286 + LOG(ERROR) << "Assigning to undeclared location '" << ATTR(content, "location") << "' not allowed." << std::endl; + _internalQueue.push_back(Event("error.execution")); + return; + } else { + _dataModel.assign(ATTR(content, "location"), ATTR(content, "expr")); + } } catch (Event e) { LOG(ERROR) << "Syntax error in attributes of assign element:" << std::endl << e << std::endl; if (rethrow) @@ -1179,6 +1201,11 @@ void Interpreter::executeContent(const Arabica::DOM::Node<std::string>& content, } void Interpreter::returnDoneEvent(const Arabica::DOM::Node<std::string>& state) { + if (_parentQueue != NULL) { + Event done; + done.name = "done.invoke." + _sessionId; + _parentQueue->push(done); + } } bool Interpreter::parentIsScxmlState(Arabica::DOM::Node<std::string> state) { @@ -1227,6 +1254,26 @@ 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> parent = element.getParentNode(); + while(parent && !isState(parent)) { + parent = parent.getParentNode(); + } + return parent; +} + +bool Interpreter::hasAncestorElement(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 && + boost::iequals(TAGNAME(parent), tagName)) { + return true; + } + parent = parent.getParentNode(); + } + return false; +} + /** See: http://www.w3.org/TR/scxml/#LCCA The Least Common Compound Ancestor is the <state> or <scxml> element s such that s is a proper ancestor @@ -1591,7 +1638,7 @@ bool Interpreter::isCompound(const Arabica::DOM::Node<std::string>& state) { } void Interpreter::setupIOProcessors() { - tthread::lock_guard<tthread::mutex> lock(_mutex); + 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()) { if (boost::iequals(ioProcIter->first, "basichttp") && !(_capabilities & CAN_BASIC_HTTP)) { @@ -1603,6 +1650,15 @@ void Interpreter::setupIOProcessors() { _ioProcessors[ioProcIter->first].setType(ioProcIter->first); _ioProcessors[ioProcIter->first].setInterpreter(this); + // register aliases + std::set<std::string> names = _ioProcessors[ioProcIter->first].getNames(); + std::set<std::string>::iterator nameIter = names.begin(); + while(nameIter != names.end()) { + if (!boost::equal(*nameIter, ioProcIter->first)) + _ioProcessors[*nameIter] = _ioProcessors[ioProcIter->first]; + nameIter++; + } + if (_dataModel) { try { _dataModel.registerIOProcessor(ioProcIter->first, _ioProcessors[ioProcIter->first]); @@ -1617,7 +1673,7 @@ void Interpreter::setupIOProcessors() { } IOProcessor Interpreter::getIOProcessor(const std::string& type) { - tthread::lock_guard<tthread::mutex> lock(_mutex); + tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); if (_ioProcessors.find(type) == _ioProcessors.end()) { LOG(ERROR) << "No ioProcessor known for type " << type; return IOProcessor(); diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index 9443a05..9d21ab4 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -177,6 +177,9 @@ public: void setConfiguration(const std::vector<std::string>& states) { _userDefinedStartConfiguration = states; } + void setInvokeRequest(const InvokeRequest& req) { + _invokeReq = req; + } Arabica::DOM::Node<std::string> getState(const std::string& stateId); Arabica::XPath::NodeSet<std::string> getStates(const std::vector<std::string>& stateIds); @@ -220,6 +223,8 @@ public: bool isInitial(const Arabica::DOM::Node<std::string>& state); Arabica::XPath::NodeSet<std::string> getInitialStates(Arabica::DOM::Node<std::string> state = Arabica::DOM::Node<std::string>()); static Arabica::XPath::NodeSet<std::string> getChildStates(const Arabica::DOM::Node<std::string>& state); + static Arabica::DOM::Node<std::string> getParentState(const Arabica::DOM::Node<std::string>& element); + static bool hasAncestorElement(const Arabica::DOM::Node<std::string>& node, const std::string tagName); Arabica::XPath::NodeSet<std::string> getTargetStates(const Arabica::DOM::Node<std::string>& transition); Arabica::DOM::Node<std::string> getSourceState(const Arabica::DOM::Node<std::string>& transition); @@ -238,7 +243,7 @@ protected: bool _stable; tthread::thread* _thread; - tthread::mutex _mutex; + tthread::recursive_mutex _mutex; URL _baseURI; Arabica::DOM::Document<std::string> _document; @@ -257,7 +262,8 @@ protected: Arabica::XPath::NodeSet<std::string> _configuration; Arabica::XPath::NodeSet<std::string> _statesToInvoke; std::vector<std::string> _userDefinedStartConfiguration; - + InvokeRequest _invokeReq; + DataModel _dataModel; std::map<std::string, Arabica::XPath::NodeSet<std::string> > _historyValue; diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h index 176ae86..eed9836 100644 --- a/src/uscxml/Message.h +++ b/src/uscxml/Message.h @@ -95,6 +95,7 @@ public: }; Event() : type(INTERNAL) {} + Event(const std::string& name) : name(name), type(INTERNAL) {} Event(const Arabica::DOM::Node<std::string>& xmlString) : type(INTERNAL) {}; bool operator< (const Event& other) const { return this < &other; diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp index 7e32ef8..8682b8d 100644 --- a/src/uscxml/interpreter/InterpreterDraft6.cpp +++ b/src/uscxml/interpreter/InterpreterDraft6.cpp @@ -9,6 +9,7 @@ using namespace Arabica::DOM; // see: http://www.w3.org/TR/scxml/#AlgorithmforSCXMLInterpretation void InterpreterDraft6::interpret() { + _mutex.lock(); if (!_isInitialized) init(); @@ -16,7 +17,8 @@ void InterpreterDraft6::interpret() { return; // dump(); - _sessionId = getUUID(); + if (_sessionId.length() == 0) + _sessionId = getUUID(); std::string datamodelName; if (datamodelName.length() == 0 && HAS_ATTR(_scxml, "datamodel")) @@ -49,7 +51,9 @@ void InterpreterDraft6::interpret() { // initialize all data elements NodeSet<std::string> dataElems = _xpath.evaluate("//" + _xpathPrefix + "data", _scxml).asNodeSet(); for (unsigned int i = 0; i < dataElems.size(); i++) { - initializeData(dataElems[i]); + // do not process data elements of nested documents from invokers + if (!hasAncestorElement(dataElems[i], _xmlNSPrefix + "invoke")) + initializeData(dataElems[i]); } } else if(_dataModel) { // initialize current data elements @@ -97,16 +101,17 @@ void InterpreterDraft6::interpret() { assert(initialTransitions.size() > 0); enterStates(initialTransitions); + _mutex.unlock(); // assert(hasLegalConfiguration()); mainEventLoop(); - if (_parentQueue) { - // send one final event to unblock eventual listeners - Event quit; - quit.name = "done.state.scxml"; - _parentQueue->push(quit); - } +// if (_parentQueue) { +// // send one final event to unblock eventual listeners +// Event quit; +// quit.name = "done.state.scxml"; +// _parentQueue->push(quit); +// } // set datamodel to null from this thread if(_dataModel) @@ -122,12 +127,31 @@ void InterpreterDraft6::initializeData(const Arabica::DOM::Node<std::string>& da LOG(ERROR) << "Cannot initialize data when no datamodel is given!"; return; } - try { - if (!HAS_ATTR(data, "id")) { - LOG(ERROR) << "Data element has no id!"; - return; + + if (!HAS_ATTR(data, "id")) { + LOG(ERROR) << "Data element has no id!"; + return; + } + + /// test 240 + if (_invokeReq.params.find(ATTR(data, "id")) != _invokeReq.params.end()) { + try { + _dataModel.assign(ATTR(data, "id"), _invokeReq.params.find(ATTR(data, "id"))->second); + } catch (Event e) { + LOG(ERROR) << "Syntax error when initializing data from parameters:" << std::endl << e << std::endl; + } + return; + } + if (_invokeReq.namelist.find(ATTR(data, "id")) != _invokeReq.namelist.end()) { + try { + _dataModel.assign(ATTR(data, "id"), _invokeReq.namelist.find(ATTR(data, "id"))->second); + } catch (Event e) { + LOG(ERROR) << "Syntax error when initializing data from namelist:" << std::endl << e << std::endl; } + return; + } + try { if (HAS_ATTR(data, "expr")) { std::string value = ATTR(data, "expr"); _dataModel.assign(ATTR(data, "id"), value); @@ -161,7 +185,7 @@ void InterpreterDraft6::initializeData(const Arabica::DOM::Node<std::string>& da } catch (Event e) { LOG(ERROR) << "Syntax error in data element:" << std::endl << e << std::endl; - } + } } void InterpreterDraft6::mainEventLoop() { @@ -263,7 +287,7 @@ void InterpreterDraft6::mainEventLoop() { #endif _currEvent.type = Event::EXTERNAL; // make sure it is set to external if (!_running) - exitInterpreter(); + goto EXIT_INTERPRETER; if (_dataModel && boost::iequals(_currEvent.name, "cancel.invoke." + _sessionId)) break; @@ -307,6 +331,8 @@ void InterpreterDraft6::mainEventLoop() { if (!enabledTransitions.empty()) microstep(enabledTransitions); } + +EXIT_INTERPRETER: monIter = _monitors.begin(); while(monIter != _monitors.end()) { try { diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp index 4072862..0663db4 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp @@ -285,6 +285,14 @@ void V8DataModel::eval(const std::string& expr) { evalAsValue(expr); } +bool V8DataModel::isDefined(const std::string& expr) { + v8::Locker locker; + v8::HandleScope handleScope; + v8::Context::Scope contextScope(_contexts.back()); + v8::Handle<v8::Value> result = evalAsValue(expr); + return !result->IsUndefined(); +} + bool V8DataModel::evalAsBool(const std::string& expr) { v8::Locker locker; v8::HandleScope handleScope; diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h index 6d4ca63..a9db5ca 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h @@ -38,7 +38,7 @@ public: virtual void registerIOProcessor(const std::string& name, const IOProcessor& ioprocessor); virtual bool validate(const std::string& location, const std::string& schema); - + virtual uint32_t getLength(const std::string& expr); virtual void pushContext(); virtual void popContext(); @@ -49,7 +49,8 @@ public: virtual Data getStringAsData(const std::string& content); virtual Data getValueAsData(const v8::Handle<v8::Value>& value); - + virtual bool isDefined(const std::string& expr); + virtual std::string evalAsString(const std::string& expr); virtual bool evalAsBool(const std::string& expr); virtual double evalAsNumber(const std::string& expr); diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp index fe881dc..c9d2237 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp @@ -142,4 +142,8 @@ void SWIDataModel::assign(const std::string& location, const std::string& expr) eval(expr); } +bool SWIDataModel::isDefined(const std::string& expr) { + return true; +} + }
\ No newline at end of file diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h index 63300dd..52d1e34 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h @@ -39,6 +39,7 @@ public: virtual void eval(const std::string& expr); virtual void assign(const std::string& location, const std::string& expr); virtual void assign(const std::string& location, const Data& data); + virtual bool isDefined(const std::string& expr); virtual Data getStringAsData(const std::string& content); diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp index c0e87d7..292b79e 100644 --- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp +++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp @@ -15,11 +15,12 @@ bool connect(pluma::Host& host) { } #endif -USCXMLInvoker::USCXMLInvoker() { + USCXMLInvoker::USCXMLInvoker() : _cancelled(false) { } USCXMLInvoker::~USCXMLInvoker() { + _cancelled = true; delete _invokedInterpreter; }; @@ -35,7 +36,7 @@ Data USCXMLInvoker::getDataModelVariables() { } void USCXMLInvoker::send(const SendRequest& req) { - assert(false); + _invokedInterpreter->_externalQueue.push(req); } void USCXMLInvoker::cancel(const std::string sendId) { @@ -50,11 +51,11 @@ void USCXMLInvoker::invoke(const InvokeRequest& req) { } else { LOG(ERROR) << "Cannot invoke nested SCXML interpreter, neither src attribute nor DOM is given"; } - DataModel dataModel(_invokedInterpreter->getDataModel()); - if (dataModel) { - - } if (_invokedInterpreter) { + DataModel dataModel(_invokedInterpreter->getDataModel()); + if (dataModel) { + + } _invokedInterpreter->setParentQueue(this); // transfer namespace prefixes _invokedInterpreter->_nsURL = _parentInterpreter->_nsURL; @@ -66,11 +67,19 @@ void USCXMLInvoker::invoke(const InvokeRequest& req) { nsIter++; } _invokedInterpreter->_xmlNSPrefix = _parentInterpreter->_xmlNSPrefix; + _invokedInterpreter->_sessionId = req.invokeid; + + /// test240 assumes that invoke request params will carry over to the datamodel + _invokedInterpreter->setInvokeRequest(req); + _invokedInterpreter->start(); } } void USCXMLInvoker::push(const SendRequest& event) { + // test 252 + if (_cancelled) + return; SendRequest copyEvent(event); copyEvent.invokeid = _invokeId; _parentInterpreter->receive(copyEvent); diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h index 857ffe2..b1386b1 100644 --- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h +++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h @@ -38,6 +38,7 @@ public: virtual void push(const SendRequest& event); protected: + bool _cancelled; Interpreter* _invokedInterpreter; Interpreter* _parentInterpreter; }; diff --git a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp index ad47896..a1f803d 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp +++ b/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp @@ -118,7 +118,14 @@ void EventIOProcessor::httpRecvRequest(const HTTPServer::Request& req) { void EventIOProcessor::send(const SendRequest& req) { - std::string target = req.target; + bool isLocal = false; + std::string target; + if (req.target.length() > 0) { + target = req.target; + } else { + isLocal = true; + target = _url; + } URL targetURL(target); // event name @@ -152,7 +159,12 @@ void EventIOProcessor::send(const SendRequest& req) { targetURL.addMonitor(this); _sendRequests[req.sendid] = std::make_pair(targetURL, req); - URLFetcher::fetchURL(targetURL); + if (isLocal) { + // test201 use a blocking request with local communication + targetURL.download(true); + } else { + URLFetcher::fetchURL(targetURL); + } } void EventIOProcessor::downloadStarted(const URL& url) {} diff --git a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h b/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h index 5446624..c549b2b 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h +++ b/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h @@ -29,7 +29,7 @@ public: virtual std::set<std::string> getNames() { std::set<std::string> names; names.insert("basichttp"); - names.insert("http://www.w3.org/TR/scxml/#SCXMLEventProcessor"); + names.insert("http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"); return names; } |