diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-04-01 22:28:07 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-04-01 22:28:07 (GMT) |
commit | f19be97dea6fd8da994392d6fa7de5b3f0d9bf3e (patch) | |
tree | 4583fe7d5fa44f128ce92284429b6ee9f2c631bf /src/uscxml | |
parent | c912952fb5e8072770262c64932c1d8cf2027cf0 (diff) | |
download | uscxml-f19be97dea6fd8da994392d6fa7de5b3f0d9bf3e.zip uscxml-f19be97dea6fd8da994392d6fa7de5b3f0d9bf3e.tar.gz uscxml-f19be97dea6fd8da994392d6fa7de5b3f0d9bf3e.tar.bz2 |
Still more bugfixes and added w3c tests
Diffstat (limited to 'src/uscxml')
-rw-r--r-- | src/uscxml/Factory.h | 9 | ||||
-rw-r--r-- | src/uscxml/Interpreter.cpp | 220 | ||||
-rw-r--r-- | src/uscxml/Interpreter.h | 2 | ||||
-rw-r--r-- | src/uscxml/URL.cpp | 1 | ||||
-rw-r--r-- | src/uscxml/interpreter/InterpreterDraft6.cpp | 16 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp | 46 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h | 4 |
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); |