summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-04-01 22:28:07 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-04-01 22:28:07 (GMT)
commitf19be97dea6fd8da994392d6fa7de5b3f0d9bf3e (patch)
tree4583fe7d5fa44f128ce92284429b6ee9f2c631bf /src
parentc912952fb5e8072770262c64932c1d8cf2027cf0 (diff)
downloaduscxml-f19be97dea6fd8da994392d6fa7de5b3f0d9bf3e.zip
uscxml-f19be97dea6fd8da994392d6fa7de5b3f0d9bf3e.tar.gz
uscxml-f19be97dea6fd8da994392d6fa7de5b3f0d9bf3e.tar.bz2
Still more bugfixes and added w3c tests
Diffstat (limited to 'src')
-rw-r--r--src/uscxml/Factory.h9
-rw-r--r--src/uscxml/Interpreter.cpp220
-rw-r--r--src/uscxml/Interpreter.h2
-rw-r--r--src/uscxml/URL.cpp1
-rw-r--r--src/uscxml/interpreter/InterpreterDraft6.cpp16
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp46
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h4
7 files changed, 140 insertions, 158 deletions
diff --git a/src/uscxml/Factory.h b/src/uscxml/Factory.h
index b86c5d1..e257e45 100644
--- a/src/uscxml/Factory.h
+++ b/src/uscxml/Factory.h
@@ -246,13 +246,10 @@ 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;
+ virtual bool isDeclared(const std::string& expr) = 0;
protected:
Interpreter* _interpreter;
- std::string _sessionId;
- std::string _name;
-
};
class DataModel {
@@ -320,8 +317,8 @@ public:
return _impl->assign(location, data);
}
- virtual bool isDefined(const std::string& expr) {
- return _impl->isDefined(expr);
+ virtual bool isDeclared(const std::string& expr) {
+ return _impl->isDeclared(expr);
}
protected:
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index 7289b82..366b6d6 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -361,31 +361,43 @@ void Interpreter::internalDoneSend(const Arabica::DOM::Node<std::string>& state)
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")) {
- LOG(ERROR) << "param element is missing name attribut";
- continue;
- }
- std::string paramValue;
- if (HAS_ATTR(doneChilds.item(i), "expr") && _dataModel) {
- std::string location = _dataModel.evalAsString(ATTR(doneChilds.item(i), "expr"));
- paramValue = _dataModel.evalAsString(location);
- } else if(HAS_ATTR(doneChilds.item(i), "location") && _dataModel) {
- paramValue = _dataModel.evalAsString(ATTR(doneChilds.item(i), "location"));
- } else {
- LOG(ERROR) << "param element is missing expr or location or no datamodel is specified";
- continue;
+ try {
+ if (!HAS_ATTR(doneChilds.item(i), "name")) {
+ LOG(ERROR) << "param element is missing name attribut";
+ continue;
+ }
+ std::string paramValue;
+ if (HAS_ATTR(doneChilds.item(i), "expr") && _dataModel) {
+ std::string expr = _dataModel.evalAsString(ATTR(doneChilds.item(i), "expr"));
+ paramValue = _dataModel.evalAsString(expr);
+ } else if(HAS_ATTR(doneChilds.item(i), "location") && _dataModel) {
+ paramValue = _dataModel.evalAsString(ATTR(doneChilds.item(i), "location"));
+ } else {
+ LOG(ERROR) << "param element is missing expr or location or no datamodel is specified";
+ continue;
+ }
+ /// test 294
+ event.data.compound[ATTR(doneChilds.item(i), "name")] = paramValue;
+ } catch (Event e) {
+ e.name = "error.execution";
+ _internalQueue.push_back(e);
}
- event.data.compound[ATTR(doneChilds.item(i), "name")] = paramValue;
}
if (boost::iequals(TAGNAME(doneChilds.item(i)), _xmlNSPrefix + "content")) {
if (HAS_ATTR(doneChilds.item(i), "expr")) {
- if (_dataModel) {
- event.data.compound["content"] = Data(_dataModel.evalAsString(ATTR(doneChilds.item(i), "expr")), Data::VERBATIM);
- } else {
- LOG(ERROR) << "content element has expr attribute but no datamodel is specified.";
+ try {
+ if (_dataModel) {
+ /// test 294
+ event.data = Data(_dataModel.evalAsString(ATTR(doneChilds.item(i), "expr")), Data::VERBATIM);
+ } else {
+ LOG(ERROR) << "content element has expr attribute but no datamodel is specified.";
+ }
+ } catch (Event e) {
+ e.name = "error.execution";
+ _internalQueue.push_back(e);
}
} else if (doneChilds.item(i).hasChildNodes()) {
- event.data.compound["content"] = Data(doneChilds.item(i).getFirstChild().getNodeValue(), Data::VERBATIM);
+ event.data = Data(doneChilds.item(i).getFirstChild().getNodeValue(), Data::VERBATIM);
} else {
LOG(ERROR) << "content element does not specify any content.";
}
@@ -399,6 +411,60 @@ 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) {
+ if (HAS_ATTR(content, "expr")) {
+ if (_dataModel) {
+ /// this is out of spec
+ std::string contentValue = _dataModel.evalAsString(ATTR(content, "expr"));
+ text = contentValue;
+ // sendReq.data.atom = contentValue;
+ // sendReq.data.type = Data::VERBATIM;
+ } else {
+ LOG(ERROR) << "content element has expr attribute but no datamodel is specified.";
+ }
+ } else if (content.hasChildNodes()) {
+ bool presentAsDOM = false;
+ NodeList<std::string> contentChilds = content.getChildNodes();
+ for (int i = 0; i < contentChilds.getLength(); i++) {
+ if (contentChilds.item(i).getNodeType() == Node_base::ELEMENT_NODE) {
+ presentAsDOM = true;
+ break;
+ }
+ }
+ if (presentAsDOM) {
+ // use the whole dom
+ Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
+ dom = domFactory.createDocument(content.getNamespaceURI(), "", 0);
+ Node<std::string> newNode = dom.importNode(content, true);
+ dom.appendChild(newNode);
+ } else {
+ Node<std::string> textChild = content.getFirstChild();
+ while(textChild && textChild.getNodeType() != Node_base::TEXT_NODE) {
+ textChild = textChild.getNextSibling();
+ }
+ if (textChild && textChild.getNodeType() == Node_base::TEXT_NODE) {
+ /// create space normalized string
+ std::istringstream iss(content.getFirstChild().getNodeValue());
+ std::stringstream content;
+ std::string seperator;
+ do {
+ std::string token;
+ iss >> token;
+ if (token.length() > 0) {
+ content << seperator << token;
+ seperator = " ";
+ }
+ } while (iss);
+ text = content.str();
+ } else {
+ LOG(ERROR) << "content element has neither text nor element children.";
+ }
+ }
+ } else {
+ LOG(ERROR) << "content element does not specify any content.";
+ }
+}
+
void Interpreter::send(const Arabica::DOM::Node<std::string>& element) {
SendRequest sendReq;
try {
@@ -544,63 +610,12 @@ void Interpreter::send(const Arabica::DOM::Node<std::string>& element) {
return;
}
try {
-
// content
NodeSet<std::string> contents = filterChildElements(_xmlNSPrefix + "content", element);
if (contents.size() > 1)
LOG(ERROR) << "Only a single content element is allowed for send elements - using first one";
if (contents.size() > 0) {
- if (HAS_ATTR(contents[0], "expr")) {
- if (_dataModel) {
- /// this is out of spec
- std::string contentValue = _dataModel.evalAsString(ATTR(contents[0], "expr"));
- sendReq.content = contentValue;
-// sendReq.data.atom = contentValue;
-// sendReq.data.type = Data::VERBATIM;
- } else {
- LOG(ERROR) << "content element has expr attribute but no datamodel is specified.";
- }
- } else if (contents[0].hasChildNodes()) {
- bool presentAsDOM = false;
- NodeList<std::string> contentChilds = contents[0].getChildNodes();
- for (int i = 0; i < contentChilds.getLength(); i++) {
- if (contentChilds.item(i).getNodeType() == Node_base::ELEMENT_NODE) {
- presentAsDOM = true;
- break;
- }
- }
- if (presentAsDOM) {
- // use the whole dom
- Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
- sendReq.dom = domFactory.createDocument(contents[0].getNamespaceURI(), "", 0);
- Node<std::string> newNode = sendReq.dom.importNode(contents[0], true);
- sendReq.dom.appendChild(newNode);
- } else {
- Node<std::string> textChild = contents[0].getFirstChild();
- while(textChild && textChild.getNodeType() != Node_base::TEXT_NODE) {
- textChild = textChild.getNextSibling();
- }
- if (textChild && textChild.getNodeType() == Node_base::TEXT_NODE) {
- /// create space normalized string
- std::istringstream iss(contents[0].getFirstChild().getNodeValue());
- std::stringstream content;
- std::string seperator;
- do {
- std::string token;
- iss >> token;
- if (token.length() > 0) {
- content << seperator << token;
- seperator = " ";
- }
- } while (iss);
- sendReq.content = content.str();
- } else {
- LOG(ERROR) << "content element has neither text nor element children.";
- }
- }
- } else {
- LOG(ERROR) << "content element does not specify any content.";
- }
+ processContentElement(contents[0], sendReq.dom, sendReq.content);
}
} catch (Event e) {
LOG(ERROR) << "Syntax error in send element content:" << std::endl << e << std::endl;
@@ -764,63 +779,11 @@ void Interpreter::invoke(const Arabica::DOM::Node<std::string>& element) {
// content
try {
-
- // content
NodeSet<std::string> contents = filterChildElements(_xmlNSPrefix + "content", element);
if (contents.size() > 1)
LOG(ERROR) << "Only a single content element is allowed for send elements - using first one";
if (contents.size() > 0) {
- if (HAS_ATTR(contents[0], "expr")) {
- if (_dataModel) {
- /// this is out of spec
- std::string contentValue = _dataModel.evalAsString(ATTR(contents[0], "expr"));
- invokeReq.content = contentValue;
- // sendReq.data.atom = contentValue;
- // sendReq.data.type = Data::VERBATIM;
- } else {
- LOG(ERROR) << "content element has expr attribute but no datamodel is specified.";
- }
- } else if (contents[0].hasChildNodes()) {
- bool presentAsDOM = false;
- NodeList<std::string> contentChilds = contents[0].getChildNodes();
- for (int i = 0; i < contentChilds.getLength(); i++) {
- if (contentChilds.item(i).getNodeType() == Node_base::ELEMENT_NODE) {
- presentAsDOM = true;
- break;
- }
- }
- if (presentAsDOM) {
- // use the whole dom
- Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
- invokeReq.dom = domFactory.createDocument(contents[0].getNamespaceURI(), "", 0);
- Node<std::string> newNode = invokeReq.dom.importNode(contents[0], true);
- invokeReq.dom.appendChild(newNode);
- } else {
- Node<std::string> textChild = contents[0].getFirstChild();
- while(textChild && textChild.getNodeType() != Node_base::TEXT_NODE) {
- textChild = textChild.getNextSibling();
- }
- if (textChild && textChild.getNodeType() == Node_base::TEXT_NODE) {
- /// create space normalized string
- std::istringstream iss(contents[0].getFirstChild().getNodeValue());
- std::stringstream content;
- std::string seperator;
- do {
- std::string token;
- iss >> token;
- if (token.length() > 0) {
- content << seperator << token;
- seperator = " ";
- }
- } while (iss);
- invokeReq.content = content.str();
- } else {
- LOG(ERROR) << "content element has neither text nor element children.";
- }
- }
- } else {
- LOG(ERROR) << "content element does not specify any content.";
- }
+ processContentElement(contents[0], invokeReq.dom, invokeReq.content);
}
} catch (Event e) {
LOG(ERROR) << "Syntax error in send element content:" << std::endl << e << std::endl;
@@ -1088,10 +1051,12 @@ void Interpreter::executeContent(const Arabica::DOM::Node<std::string>& content,
// --- ASSIGN --------------------------
if (_dataModel && HAS_ATTR(content, "location") && HAS_ATTR(content, "expr")) {
try {
- if (!_dataModel.isDefined(ATTR(content, "location"))) {
+ if (!_dataModel.isDeclared(ATTR(content, "location"))) {
// test 286
LOG(ERROR) << "Assigning to undeclared location '" << ATTR(content, "location") << "' not allowed." << std::endl;
- _internalQueue.push_back(Event("error.execution"));
+ Event e("error.execution");
+ _internalQueue.push_back(e);
+ throw e;
return;
} else {
_dataModel.assign(ATTR(content, "location"), ATTR(content, "expr"));
@@ -1124,6 +1089,9 @@ void Interpreter::executeContent(const Arabica::DOM::Node<std::string>& content,
srcContent << _cachedURLs[scriptUrl.asString()];
} else {
srcContent << scriptUrl;
+ if (scriptUrl.downloadFailed()) {
+ LOG(ERROR) << "script element source cannot be downloaded";
+ }
_cachedURLs[scriptUrl.asString()] = scriptUrl;
}
diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h
index 9d21ab4..b48080a 100644
--- a/src/uscxml/Interpreter.h
+++ b/src/uscxml/Interpreter.h
@@ -282,6 +282,8 @@ protected:
void executeContent(const Arabica::DOM::NodeList<std::string>& content, bool rethrow = false);
void executeContent(const Arabica::XPath::NodeSet<std::string>& content, bool rethrow = false);
+ void processContentElement(const Arabica::DOM::Node<std::string>& element, Arabica::DOM::Document<std::string>& dom, std::string& text);
+
void send(const Arabica::DOM::Node<std::string>& element);
void invoke(const Arabica::DOM::Node<std::string>& element);
void cancelInvoke(const Arabica::DOM::Node<std::string>& element);
diff --git a/src/uscxml/URL.cpp b/src/uscxml/URL.cpp
index a31b0c4..b441bbf 100644
--- a/src/uscxml/URL.cpp
+++ b/src/uscxml/URL.cpp
@@ -500,6 +500,7 @@ void URLFetcher::perform() {
LOG(ERROR) << "Unhandled curl status";
case CURLM_BAD_HANDLE:
case CURLM_BAD_EASY_HANDLE:
+ case CURLE_FILE_COULDNT_READ_FILE:
case CURLM_OUT_OF_MEMORY:
case CURLM_INTERNAL_ERROR:
case CURLM_BAD_SOCKET:
diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp
index 8682b8d..b53ba4e 100644
--- a/src/uscxml/interpreter/InterpreterDraft6.cpp
+++ b/src/uscxml/interpreter/InterpreterDraft6.cpp
@@ -64,7 +64,7 @@ void InterpreterDraft6::interpret() {
}
// executeGlobalScriptElements
- NodeSet<std::string> globalScriptElems = _xpath.evaluate("/" + _xpathPrefix + "script", _scxml).asNodeSet();
+ NodeSet<std::string> globalScriptElems = filterChildElements(_xmlNSPrefix + "script", _scxml);
for (unsigned int i = 0; i < globalScriptElems.size(); i++) {
if (_dataModel)
executeContent(globalScriptElems[i]);
@@ -303,11 +303,17 @@ void InterpreterDraft6::mainEventLoop() {
for (unsigned int j = 0; j < invokes.size(); j++) {
Arabica::DOM::Element<std::string> invokeElem = (Arabica::DOM::Element<std::string>)invokes[j];
std::string invokeId;
- if (HAS_ATTR(invokeElem, "id"))
+ if (HAS_ATTR(invokeElem, "id")) {
invokeId = ATTR(invokeElem, "id");
- if (HAS_ATTR(invokeElem, "idlocation") && _dataModel)
- invokeId = _dataModel.evalAsString(ATTR(invokeElem, "idlocation"));
-
+ } else {
+ if (HAS_ATTR(invokeElem, "idlocation") && _dataModel) {
+ try {
+ invokeId = _dataModel.evalAsString(ATTR(invokeElem, "idlocation"));
+ } catch(Event e) {
+ LOG(ERROR) << "Syntax error while assigning idlocation from invoke:" << std::endl << e << std::endl;
+ }
+ }
+ }
std::string autoForward = invokeElem.getAttribute("autoforward");
if (boost::iequals(invokeId, _currEvent.invokeid)) {
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
index 0663db4..affd641 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
@@ -57,14 +57,13 @@ boost::shared_ptr<DataModelImpl> V8DataModel::create(Interpreter* interpreter) {
docObj->SetInternalField(0, Arabica::DOM::V8DOM::toExternal(privData));
context->Global()->Set(v8::String::New("document"), docObj);
+ context->Global()->Set(v8::String::New("_sessionid"), v8::String::New(interpreter->getSessionId().c_str()), v8::ReadOnly);
+ context->Global()->Set(v8::String::New("_name"), v8::String::New(interpreter->getName().c_str()), v8::ReadOnly);
+ context->Global()->Set(v8::String::New("_ioprocessors"), v8::Object::New(), v8::ReadOnly);
dm->_contexts.push_back(context);
// instantiate objects - we have to have a context for that!
-
- dm->setName(interpreter->getName());
- dm->setSessionId(interpreter->getSessionId());
- dm->eval("_ioprocessors = {};");
dm->eval("_invokers = {};");
dm->eval("_x = {};");
@@ -72,17 +71,12 @@ boost::shared_ptr<DataModelImpl> V8DataModel::create(Interpreter* interpreter) {
}
void V8DataModel::registerIOProcessor(const std::string& name, const IOProcessor& ioprocessor) {
- assign("_ioprocessors['" + name + "']", ioprocessor.getDataModelVariables());
-}
-
-void V8DataModel::setSessionId(const std::string& sessionId) {
- _sessionId = sessionId;
- assign("_sessionId", "'" + sessionId + "'");
-}
-
-void V8DataModel::setName(const std::string& name) {
- _name = name;
- assign("_name", "'" + name + "'");
+ v8::Locker locker;
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(_contexts.front());
+ v8::Handle<v8::Object> global = _contexts.front()->Global();
+ v8::Handle<v8::Object> ioProcessors = global->Get(v8::String::New("_ioprocessors"))->ToObject();
+ ioProcessors->Set(v8::String::New(name.c_str()),getDataAsValue(ioprocessor.getDataModelVariables()));
}
V8DataModel::~V8DataModel() {
@@ -285,12 +279,28 @@ void V8DataModel::eval(const std::string& expr) {
evalAsValue(expr);
}
-bool V8DataModel::isDefined(const std::string& expr) {
+bool V8DataModel::isDeclared(const std::string& expr) {
+ /**
+ * Undeclared variables can be checked by trying to access them and catching
+ * a reference error.
+ */
+
v8::Locker locker;
v8::HandleScope handleScope;
v8::Context::Scope contextScope(_contexts.back());
- v8::Handle<v8::Value> result = evalAsValue(expr);
- return !result->IsUndefined();
+
+ v8::TryCatch tryCatch;
+ v8::Handle<v8::String> source = v8::String::New(expr.c_str());
+ v8::Handle<v8::Script> script = v8::Script::Compile(source);
+
+ v8::Handle<v8::Value> result;
+ if (!script.IsEmpty())
+ result = script->Run();
+
+ if (result.IsEmpty())
+ return false;
+
+ return true;
}
bool V8DataModel::evalAsBool(const std::string& expr) {
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h
index a9db5ca..441297d 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h
@@ -31,8 +31,6 @@ public:
}
virtual void initialize();
- virtual void setSessionId(const std::string& sessionId);
- virtual void setName(const std::string& name);
virtual void setEvent(const Event& event);
virtual void registerIOProcessor(const std::string& name, const IOProcessor& ioprocessor);
@@ -49,7 +47,7 @@ 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 bool isDeclared(const std::string& expr);
virtual std::string evalAsString(const std::string& expr);
virtual bool evalAsBool(const std::string& expr);