summaryrefslogtreecommitdiffstats
path: root/src/uscxml
diff options
context:
space:
mode:
Diffstat (limited to 'src/uscxml')
-rw-r--r--src/uscxml/Factory.h9
-rw-r--r--src/uscxml/Interpreter.cpp100
-rw-r--r--src/uscxml/Interpreter.h10
-rw-r--r--src/uscxml/Message.h1
-rw-r--r--src/uscxml/interpreter/InterpreterDraft6.cpp54
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp8
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h5
-rw-r--r--src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp4
-rw-r--r--src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h1
-rw-r--r--src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp21
-rw-r--r--src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h1
-rw-r--r--src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp16
-rw-r--r--src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h2
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;
}