bool InterpreterDraft6::isEnabledTransition(const Node<std::string>& transition, const std::string& event) {
	std::string eventName;
	if (HAS_ATTR(transition, "event")) {
		eventName = ATTR(transition, "event");
	} else if(HAS_ATTR(transition, "eventexpr")) {
		if (_dataModel) {
			eventName = _dataModel.evalAsString(ATTR(transition, "eventexpr"));
		} else {
			LOG(ERROR) << "Transition has eventexpr attribute with no datamodel defined";
			return false;
		}
	} else {
		return false;
	}

	std::list<std::string> eventNames = tokenizeIdRefs(eventName);
	std::list<std::string>::iterator eventIter = eventNames.begin();
	while(eventIter != eventNames.end()) {
		if(nameMatch(*eventIter, event) && hasConditionMatch(transition)) {
			return true;
		}
		eventIter++;
	}
	return false;
}
void PromelaDataModel::init(const Element<std::string>& dataElem,
                            const Node<std::string>& node,
                            const std::string& content) {
	// from <datamodel>
	if (HAS_ATTR(dataElem, "id")) {
		Element<std::string> dataElemCopy = dataElem;
		std::string identifier = ATTR(dataElem, "id");
		std::string type = (HAS_ATTR(dataElem, "type") ? ATTR(dataElem, "type") : "int");
		std::string arrSize;

		size_t bracketPos = type.find("[");
		if (bracketPos != std::string::npos) {
			arrSize = type.substr(bracketPos, type.length() - bracketPos);
			type = type.substr(0, bracketPos);
		}

		dataElemCopy.setAttribute("id", type + " " + identifier + arrSize);

		assign(dataElemCopy, node, content);
		dataElemCopy.setAttribute("id", identifier);

		return;
	}

	assign(dataElem, node, content);
}
Exemple #3
0
void CClientInfo::Config(const string& fileName)
{
	ifstream inFile(fileName.c_str(), ifstream::in);
	string inXml, inLine;
	while (getline(inFile, inLine))
		inXml += inLine;
	XmlVec confData(inXml.begin(), inXml.end());
	confData.push_back('\0');
	XmlDoc xmlDoc;
	try {
		xmlDoc.parse<0>(&confData[0]);
	} catch (...) {
		LOG("ERROR: failed to load the server config file.");
		return;
	}

	XmlNodePtr pNode = NULL;
	if ((pNode = xmlDoc.first_node("server_list"))) {
		XmlNodePtr pItem = pNode->first_node("server");
		while (pItem) {
			int    pId   = HAS_ATTR(pItem, "id")   ? atoi(ATTR_VALUE(pItem, "id")) : -1;
			string ipStr = HAS_ATTR(pItem, "ip")   ? ATTR_VALUE(pItem, "ip") : "127.0.0.1";
			int    port  = HAS_ATTR(pItem, "port") ? atoi(ATTR_VALUE(pItem, "port")) : 12345;
			m_svrMap[pId] = pair<string, int>(ipStr, port);
			pItem = pItem->next_sibling("server");
		}
	}
	if ((pNode = xmlDoc.first_node("parameters"))) {
		m_connNum = HAS_NODE(pNode, "conn_num") ? atoi(NODE_VALUE(pNode, "conn_num")) : 1;
		m_fixRate = HAS_NODE(pNode, "fix_rate") ? atoi(NODE_VALUE(pNode, "fix_rate")) : 0;
		m_initTimeout = HAS_NODE(pNode, "init_timeout") ? atoi(NODE_VALUE(pNode, "init_timeout")) : 20;
		m_videoLen = HAS_NODE(pNode, "video_len") ? atoi(NODE_VALUE(pNode, "video_len")) : 278;
		m_initBufferSize = HAS_NODE(pNode, "init_buffer_size") ? atoi(NODE_VALUE(pNode, "init_buffer_size")) : 10;
	}
	LOG("--------------------------------------------------");
	svrMap_t::const_iterator cIt = m_svrMap.begin();
	for (; cIt != m_svrMap.end(); ++cIt) {
		LOG("|server: id=%d, %s:%d.", (*cIt).first, (*cIt).second.first.c_str(), (*cIt).second.second);
	}
	LOG("|number of connections: %d.", m_connNum);
	LOG("|video length: %d.", m_videoLen);
	LOG("|fix rate: %d.", m_fixRate);
	LOG("|init buffer timeout: %d.", m_initTimeout);
	LOG("|init buffer size: %d.", m_initBufferSize);
	LOG("--------------------------------------------------");
	xmlDoc.clear();

	m_rateVec.push_back(350);
    m_rateVec.push_back(470);
    m_rateVec.push_back(630);
    m_rateVec.push_back(845);
    m_rateVec.push_back(1130);
    m_rateVec.push_back(1520);
    m_rateVec.push_back(2040);


}
void PromelaDataModel::assign(const Element<std::string>& assignElem,
                              const Node<std::string>& node,
                              const std::string& content) {
	std::string expr;
	std::string key;
	std::string value;

	if (node) {
		ERROR_EXECUTION_THROW("Assigning DOM node to variable is not supported");
	}

	if (HAS_ATTR(assignElem, "id")) {
		key = ATTR(assignElem, "id");
	} else if (HAS_ATTR(assignElem, "location")) {
		key = ATTR(assignElem, "location");
	}

	if (HAS_ATTR(assignElem, "expr")) {
		if (key.length() == 0) {
			ERROR_EXECUTION_THROW("Assign element has neither id nor location");
		}
		value = ATTR(assignElem, "expr");
	} else {
		value = content;
	}

	if (key.length() > 0) {
		PromelaParser parser(key);

		// declaration is an array?
		if (parser.ast->operands.size() > 0 &&
		        parser.ast->operands.back()->operands.size() > 0 &&
		        parser.ast->operands.back()->operands.back()->type == PML_VAR_ARRAY) {
			evaluateDecl(parser.ast);
			expr = content;
		} else if (value.length() > 0) {
			expr = key + " = " + value + ";";
		} else {
			// declaration
			expr = key + ";";
		}
	} else {
		expr = content;
	}

	PromelaParser parser(expr, 2, PromelaParser::PROMELA_DECL, PromelaParser::PROMELA_STMNT);
	if (parser.type == PromelaParser::PROMELA_DECL)
		evaluateDecl(parser.ast);
	if (parser.type == PromelaParser::PROMELA_STMNT)
		evaluateStmnt(parser.ast);
//	parser.dump();
//	std::cout << Data::toJSON(_variables) << std::endl;
}
Exemple #5
0
void XPathDataModel::init(const Element<std::string>& dataElem,
                          const Node<std::string>& node,
                          const std::string& content) {
    std::string location;
    if (HAS_ATTR(dataElem, "id")) {
        location = ATTR(dataElem, "id");
    } else if (HAS_ATTR(dataElem, "location")) {
        location = ATTR(dataElem, "location");
    }

    NodeSet<std::string> nodeSet;
    if (node || (content.length() > 0)) {
        _datamodel.appendChild(_doc.importNode(dataElem, true));
        nodeSet.push_back(dataElem);
    } else if (HAS_ATTR(dataElem, "expr")) {
        try {
            Element<std::string> container = _doc.createElement("data");
            container.setAttribute("id", location);
            XPathValue<std::string> expr = _xpath.evaluate_expr(ATTR(dataElem, "expr"), _doc);
            switch (expr.type()) {
            case NODE_SET: {
                for (size_t i = 0; i < expr.asNodeSet().size(); i++) {
                    container.appendChild(expr.asNodeSet()[i].cloneNode(true));
                    nodeSet.push_back(expr.asNodeSet()[i].cloneNode(true));
                }
                break;
            }
            case STRING:
                container.appendChild(_doc.createTextNode(expr.asString()));
                nodeSet.push_back(_doc.createTextNode(expr.asString()));
                break;
            case NUMBER: {
                container.appendChild(_doc.createTextNode(toStr(expr.asNumber())));
                nodeSet.push_back(_doc.createTextNode(toStr(expr.asNumber())));
                break;
            }
            case Arabica::XPath::BOOL:
            case ANY:
                ERROR_EXECUTION_THROW("expr evaluates to type ANY");
            }
            _datamodel.appendChild(container);
        } catch (SyntaxException e) {
            ERROR_EXECUTION_THROW(e.what());
        }
    } else {
        LOG(ERROR) << "data element has no content";
    }

    _varResolver.setVariable(location, nodeSet);
}
Exemple #6
0
static void printNodeSet(const std::list<XERCESC_NS::DOMElement*> nodes) {
	std::string seperator;
	for (auto nIter = nodes.begin(); nIter != nodes.end(); nIter++) {
		std::cerr << seperator << (HAS_ATTR(*nIter, "id") ? ATTR(*nIter, "id") : DOMUtils::xPathForNode(*nIter));
		seperator = ", ";
	}
}
Exemple #7
0
char * __mod_ssl_sni_common_handler (MyQttCtx   * myqtt_ctx,
				     MyQttConn  * conn,
				     const char * serverName,
				     axlPointer   user_data,
				     const char * attr_name)
{
	MyQttdCtx * ctx = user_data;
	axlNode   * node;

	/* find certificate node by Name */
	node = __mod_ssl_get_certificate_node_by_name (ctx, serverName);
	if (! node) {
		wrn ("No certificate was found for serverName=%s, requested by connecting ip=%s",
		     serverName, myqtt_conn_get_host_ip (conn));
		return NULL; /* no node certificate was found, finish
			      * here */
	} /* end if */

	if (! HAS_ATTR (node, attr_name)) {
		wrn ("No certificate was found for serverName=%s, requested by connecting ip=%s, node %s attribute was not defined",
		     serverName, myqtt_conn_get_host_ip (conn), attr_name);
		return NULL; /* no crt attr was found, finish here */
	} /* end if */

	/* ok, now report certificate location */
	if (__mod_ssl_debug)
		msg ("Reporting certificate %s=%s for serverName=%s", attr_name, ATTR_VALUE (node, attr_name), serverName);

	/* report certificate */
	return axl_strdup (ATTR_VALUE (node, attr_name));
}
Exemple #8
0
std::list<Breakpoint> Debugger::getQualifiedInvokeBreakpoints(InterpreterImpl* impl, const XERCESC_NS::DOMElement* invokeElem, const std::string invokeId, Breakpoint breakpointTemplate) {
	std::list<Breakpoint> breakpoints;

	Breakpoint bp = breakpointTemplate; // copy base as template
	bp.subject = Breakpoint::INVOKER;
	bp.element = invokeElem;
	bp.invokeId = invokeId;

	if (HAS_ATTR(invokeElem, "type")) {
		bp.invokeType = ATTR(invokeElem, "type");
	} else if (HAS_ATTR(invokeElem, "typeexpr")) {
		bp.invokeType = impl->evalAsData(ATTR(invokeElem, "typeexpr")).atom;
	}

	breakpoints.push_back(bp);

	return breakpoints;
}
Exemple #9
0
std::list<Breakpoint> getQualifiedInvokeBreakpoints(Interpreter interpreter, const Arabica::DOM::Element<std::string>& invokeElem, const std::string invokeId, Breakpoint breakpointTemplate) {
	std::list<Breakpoint> breakpoints;

	Breakpoint bp = breakpointTemplate; // copy base as template
	bp.subject = Breakpoint::INVOKER;
	bp.element = invokeElem;
	bp.invokeId = invokeId;

	if (HAS_ATTR(invokeElem, "type")) {
		bp.invokeType = ATTR(invokeElem, "type");
	} else if (HAS_ATTR(invokeElem, "typeexpr")) {
		bp.invokeType = interpreter.getDataModel().evalAsString(ATTR(invokeElem, "typeexpr"));
	}

	breakpoints.push_back(bp);

	return breakpoints;
}
Exemple #10
0
void XPathDataModel::assign(const NodeSet<std::string>& key,
                            const std::string& value,
                            const Element<std::string>& assignElem) {
    if (key.size() == 0)
        return;
    for (size_t i = 0; i < key.size(); i++) {
        Node<std::string> node = key[i];
        switch (node.getNodeType()) {
        case Node_base::ATTRIBUTE_NODE: {
            Attr<std::string> attr(node);
            attr.setValue(value);
            break;
        }
        case Node_base::TEXT_NODE: {
            Text<std::string> text(node);
            text.setNodeValue(value);
            break;
        }
        case Node_base::ELEMENT_NODE: {
            Element<std::string> element(node);
            if (HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "addattribute")) {
                // addattribute: Add an attribute with the name specified by 'attr'
                // and value specified by 'expr' to the node specified by 'location'.
                if (!HAS_ATTR(assignElem, "attr"))
                    ERROR_EXECUTION_THROW("Assign element is missing 'attr'");
                element.setAttribute(ATTR(assignElem, "attr"), value);
            } else {
                /// test 547
                while(element.hasChildNodes())
                    element.removeChild(element.getChildNodes().item(0));
                Text<std::string> text = _doc.createTextNode(value);
                element.appendChild(text);
            }
            break;
        }
        default:
            ERROR_EXECUTION_THROW("Unsupported node type with assign");
            break;
        }
    }
}
Arabica::XPath::NodeSet<std::string> InterpreterDraft6::selectEventlessTransitions() {
	Arabica::XPath::NodeSet<std::string> enabledTransitions;

	NodeSet<std::string> states;
	for (unsigned int i = 0; i < _configuration.size(); i++) {
		if (isAtomic(_configuration[i]))
			states.push_back(_configuration[i]);
	}
	states.to_document_order();

#if 0
	std::cout << "Atomic States: ";
	for (int i = 0; i < atomicStates.size(); i++) {
		std::cout << ATTR(atomicStates[i], "id") << ", ";
	}
	std::cout << std::endl;
#endif

	unsigned int index = 0;
	while(states.size() > index) {
		bool foundTransition = false;
		NodeSet<std::string> transitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", states[index]);
		for (unsigned int k = 0; k < transitions.size(); k++) {
			if (!HAS_ATTR(transitions[k], "event") && hasConditionMatch(transitions[k])) {
				enabledTransitions.push_back(transitions[k]);
				foundTransition = true;
				goto LOOP;
			}
		}
		if (!foundTransition) {
			Node<std::string> parent = states[index].getParentNode();
			if (parent) {
				states.push_back(parent);
			}
		}
LOOP:
		index++;
	}

#if 0
	std::cout << "Enabled eventless transitions: " << std::endl;
	for (int i = 0; i < enabledTransitions.size(); i++) {
		std::cout << enabledTransitions[i] << std::endl << "----" << std::endl;
	}
	std::cout << std::endl;
#endif

	enabledTransitions = filterPreempted(enabledTransitions);
	return enabledTransitions;
}
Exemple #12
0
void FetchElement::enterElement(const Arabica::DOM::Element<std::string>& node) {
	if (!HAS_ATTR(node, "src") && !HAS_ATTR(node, "srcexpr")) {
		LOG(ERROR) << "Fetch element requires src or srcexpr";
		return;
	}
	if (HAS_ATTR(node, "srcexpr") && !_interpreter->getDataModel()) {
		LOG(ERROR) << "Fetch element with srcexpr requires datamodel";
		return;
	}
	_source = (HAS_ATTR(node, "src") ? ATTR(node, "src") : _interpreter->getDataModel().evalAsString(ATTR(node, "srcexpr")));

	if (!HAS_ATTR(node, "callback") && !HAS_ATTR(node, "callbackexpr")) {
		LOG(ERROR) << "Fetch element requires callback or callbackexpr";
		return;
	}
	if (HAS_ATTR(node, "callbackexpr") && !_interpreter->getDataModel()) {
		LOG(ERROR) << "Fetch element with callbackexpr requires datamodel";
		return;
	}
	_callback = (HAS_ATTR(node, "callback") ? ATTR(node, "callback") : _interpreter->getDataModel().evalAsString(ATTR(node, "callbackexpr")));

	_type = (HAS_ATTR(node, "type") ? ATTR(node, "type") : "text");
	if (!iequals(_type, "text") &&
	        !iequals(_type, "url") &&
	        !iequals(_type, "json") &&
	        !iequals(_type, "xml")) {
		LOG(ERROR) << "Fetch element type attribute not one of text, url, json, xml.";
		return;
	}

	_targetUrl = URL(_source);
	if (!_targetUrl.isAbsolute()) {
		if (!_targetUrl.toAbsolute(_interpreter->getBaseURL(node))) {
			LOG(ERROR) << "Cannot transform " << _source << " into absolute URL";
			return;
		}
	}

	_targetUrl.addMonitor(this);
	URLFetcher::fetchURL(_targetUrl);

}
bool InterpreterDraft6::isWithinParallel(const Node<std::string>& transition) {
	if (isTargetless(transition))
		return false;

	Node<std::string> source;
	if (HAS_ATTR(transition, "type") && iequals(ATTR(transition, "type"), "internal")) {
		source = getSourceState(transition);
	} else {
		source = getSourceState(transition).getParentNode();
	}
	NodeSet<std::string> targets = getTargetStates(transition);
	targets.push_back(source);

	Node<std::string> lcpa = findLCPA(targets);
	return lcpa;
}
Exemple #14
0
void DebugSession::breakExecution(Data replyData) {
	std::lock_guard<std::recursive_mutex> lock(_mutex);

	std::list<XERCESC_NS::DOMElement*> configuration = _interpreter.getConfiguration();
	for (auto state : configuration) {
		if (HAS_ATTR(state, "id")) {
			replyData.compound["activeStates"].array.push_back(Data(ATTR(state, "id"), Data::VERBATIM));
			if (isAtomic(state)) {
				replyData.compound["basicStates"].array.push_back(Data(ATTR(state, "id"), Data::VERBATIM));
			}
		}
	}

	replyData.compound["replyType"] = Data("breakpoint", Data::VERBATIM);
	_debugger->pushData(shared_from_this(), replyData);

	// wait for resume from the client
	_resumeCond.wait(_mutex);
}
Exemple #15
0
/** 
 * @brief Init the valvulad log module.
 */
void valvulad_log_init (ValvuladCtx * ctx)
{
	/* get current valvulad configuration */
	axlDoc  * doc = ctx->config;
	axlNode * node;

	/* check log reporting */
	node = axl_doc_get (doc, "/valvula/global-settings/log-reporting");
	if (node == NULL) {
		abort_error ("Unable to find log configuration <valvula/global-settings/log-reporting>");
		return;
	} /* end if */

	/* check enabled attribute */
	if (! HAS_ATTR (node, "enabled")) {
		abort_error ("Missing attribute 'enabled' located at <valvula/global-settings/log-reporting>. Unable to determine if log is enabled");
		return;
	}

	/* check if log reporting is enabled or not */
	if (! HAS_ATTR_VALUE (node, "enabled", "yes")) {
		msg ("log reporting to file disabled");
		return;
	}

	/* check for syslog usage */
	ctx->use_syslog = HAS_ATTR_VALUE (node, "use-syslog", "yes");
	msg ("Checking for usage of syslog %d", ctx->use_syslog);
	if (ctx->use_syslog) {
		/* open syslog */
		openlog ("valvulad", LOG_PID, LOG_MAIL);
		msg ("Using syslog facility for logging");
		return;
	} /* end if */

	return;
}
Exemple #16
0
/** 
 * @internal Function that creates a connection to the MySQL database
 * configured on the xml node.
 */ 
MYSQL * mod_sasl_mysql_get_connection (TurbulenceCtx  * ctx,
				       axlNode        * auth_db_node_conf, 
				       axlError      ** err)
{
	MYSQL   * conn;
	int       port = 0;
	int       reconnect = 1;
	axlDoc  * doc;
	axlNode * node;

	if (ctx == NULL || auth_db_node_conf == NULL) {
		axl_error_report (err, -1, "Received null ctx, auth db node or sql query, failed to run SQL command");
		return NULL;
	} /* end if */

	/* check if the connection is already defined */
	conn = axl_node_annotate_get (auth_db_node_conf, "mysql-conn", axl_false);
	if (conn) {
		/* reuse connection */
		return conn;
	} /* end if */

	/* get document containing MySQL settings */
	doc  = axl_node_annotate_get (auth_db_node_conf, "mysql-conf", axl_false);
	if (doc == NULL) {
		axl_error_report (err, -1, "Found no xml document defining MySQL settings to connect to the database");
		return NULL;
	} /* end if */

	/* get the node that contains the configuration */
	node = axl_doc_get (doc, "/sasl-auth-db/connection-settings");

	/* create a mysql connection */
	conn = mysql_init (NULL);

	/* get port */
	if (HAS_ATTR (node, "port") && strlen (ATTR_VALUE (node, "port")) > 0) {
		/* get port configured by the user */
		port = atoi (ATTR_VALUE (node, "port"));
	}
	
	/* create a connection */
	if (mysql_real_connect (conn, 
				/* get host */
				ATTR_VALUE (node, "host"), 
				/* get user */
				ATTR_VALUE (node, "user"), 
				/* get password */
				ATTR_VALUE (node, "password"), 
				/* get database */
				ATTR_VALUE (node, "database"), 
				port, NULL, 0) == NULL) {
		axl_error_report (err, mysql_errno (conn), "Mysql connect error: %s, failed to run SQL command", mysql_error (conn));
		return NULL;
	} /* end if */

	/* flag here to reconnect in case of lost connection */
	mysql_options (conn, MYSQL_OPT_RECONNECT, (const char *) &reconnect);

	/* record connection */
	axl_node_annotate_data_full (auth_db_node_conf, "mysql-conn", NULL, conn, (axlDestroyFunc) mysql_close);

	return conn;
}
Exemple #17
0
void RespondElement::enterElement(const Arabica::DOM::Element<std::string>& node) {
	// try to get the request id
	if (!HAS_ATTR(node, "to")) {
		LOG(ERROR) << "Respond element requires to attribute";
		return;
	}
	if (HAS_ATTR(node, "to") && !_interpreter->getDataModel()) {
		LOG(ERROR) << "Respond element with to requires datamodel";
		return;
	}
	std::string requestId = _interpreter->getDataModel().evalAsString(ATTR(node, "to"));

	// try to get the request object
	InterpreterHTTPServlet* servlet = _interpreter->getHTTPServlet();
	tthread::lock_guard<tthread::recursive_mutex> lock(servlet->getMutex());

	if (servlet->getRequests().find(requestId) == servlet->getRequests().end()) {
		LOG(ERROR) << "No matching HTTP request for respond element";
		return;
	}

	assert(servlet->getRequests().find(requestId) != servlet->getRequests().end());
	HTTPServer::Request httpReq = servlet->getRequests()[requestId];
	assert(httpReq.evhttpReq != NULL);
	HTTPServer::Reply httpReply(httpReq);
	servlet->getRequests().erase(requestId);

	// get the status or default to 200
	std::string statusStr = (HAS_ATTR(node, "status") ? ATTR(node, "status") : "200");
	if (!isNumeric(statusStr.c_str(), 10)) {
		LOG(ERROR) << "Respond element with non-numeric status " << statusStr;
		return;
	}
	httpReply.status = strTo<int>(statusStr);;

	// extract the content
	Arabica::XPath::NodeSet<std::string> contents = InterpreterImpl::filterChildElements(_interpreter->getNameSpaceInfo().getXMLPrefixForNS(getNamespace()) + "content", node);
	if (contents.size() > 0) {
		Arabica::DOM::Element<std::string> contentElem = Arabica::DOM::Element<std::string>(contents[0]);
		if (HAS_ATTR(contentElem, "expr")) { // -- content is evaluated string from datamodel ------
			if (_interpreter->getDataModel()) {
				try {
					Data contentData = _interpreter->getDataModel().getStringAsData(ATTR(contentElem, "expr"));
					if (contentData.atom.length() > 0) {
						httpReply.content = contentData.atom;
						httpReply.headers["Content-Type"] = "text/plain";
					} else if (contentData.binary) {
						httpReply.content = std::string(contentData.binary.getData(), contentData.binary.getSize());
						httpReply.headers["Content-Type"] = contentData.binary.getMimeType();
					} else if (contentData.node) {
						std::stringstream ss;
						ss << contentData.node;
						httpReply.content = ss.str();;
						httpReply.headers["Content-Type"] = "application/xml";
					} else {
						httpReply.content = Data::toJSON(contentData);
						httpReply.headers["Content-Type"] = "application/json";
					}
				} catch (Event e) {
					LOG(ERROR) << "Syntax error with expr in content child of Respond element:" << std::endl << e << std::endl;
					return;
				}
			} else {
				LOG(ERROR) << "content element has expr attribute but no datamodel is specified.";
				return;
			}
		} else if (HAS_ATTR(contentElem, "file") || HAS_ATTR(contentElem, "fileexpr")) { // -- content is from file ------
			URL file;
			if (HAS_ATTR(contentElem, "fileexpr")) {
				if (_interpreter->getDataModel()) {
					try {
						file = "file://" + _interpreter->getDataModel().evalAsString(ATTR(contentElem, "fileexpr"));
					} catch (Event e) {
						LOG(ERROR) << "Syntax error with fileexpr in content child of Respond element:" << std::endl << e << std::endl;
						return;
					}
				}
			} else {
				file = "file://" + ATTR(contentElem, "fileexpr");
			}
			if (file) {
				httpReply.content = file.getInContent();
				size_t lastDot;
				if ((lastDot = file.path().find_last_of(".")) != std::string::npos) {
					std::string extension = file.path().substr(lastDot + 1);
					std::string mimeType = URL::getMimeType(extension);
					if (mimeType.length() > 0) {
						httpReply.headers["Content-Type"] = mimeType;
					}
				}
			}
		} else if (contents[0].hasChildNodes()) {  // -- content embedded as child nodes ------
			httpReply.content = contents[0].getFirstChild().getNodeValue();
		} else {
			LOG(ERROR) << "content element does not specify any content.";
			return;
		}
	}

	// process headers
	Arabica::XPath::NodeSet<std::string> headers = InterpreterImpl::filterChildElements(_interpreter->getNameSpaceInfo().getXMLPrefixForNS(getNamespace()) + "header", node);
	for (int i = 0; i < headers.size(); i++) {
		Arabica::DOM::Element<std::string> headerElem = Arabica::DOM::Element<std::string>(headers[i]);

		std::string name;
		if (HAS_ATTR(headerElem, "name")) {
			name = ATTR(headerElem, "name");
		} else if(HAS_ATTR(headerElem, "nameexpr")) {
			if (_interpreter->getDataModel()) {
				try {
					name = _interpreter->getDataModel().evalAsString(ATTR(headerElem, "nameexpr"));
				} catch (Event e) {
					LOG(ERROR) << "Syntax error with nameexpr in header child of Respond element:" << std::endl << e << std::endl;
					return;
				}
			} else {
				LOG(ERROR) << "header element has nameexpr attribute but no datamodel is specified.";
				return;
			}
		} else {
			LOG(ERROR) << "header element has no name or nameexpr attribute.";
			return;
		}

		std::string value;
		if (HAS_ATTR(headerElem, "value")) {
			value = ATTR(headerElem, "value");
		} else if(HAS_ATTR(headerElem, "valueexpr")) {
			if (_interpreter->getDataModel()) {
				try {
					value = _interpreter->getDataModel().evalAsString(ATTR(headerElem, "valueexpr"));
				} catch (Event e) {
					LOG(ERROR) << "Syntax error with valueexpr in header child of Respond element:" << std::endl << e << std::endl;
					return;
				}
			} else {
				LOG(ERROR) << "header element has valueexpr attribute but no datamodel is specified.";
				return;
			}
		} else {
			LOG(ERROR) << "header element has no value or valueexpr attribute.";
			return;
		}

		httpReply.headers[name] = value;
	}

	// send the reply
	HTTPServer::reply(httpReply);
	servlet->getRequests().erase(requestId);
}
Exemple #18
0
void XPathDataModel::assign(const Element<std::string>& key,
                            const NodeSet<std::string>& value,
                            const Element<std::string>& assignElem) {
    Element<std::string> element(key);
    if (value.size() == 0 || !value[0])
        return;

    if (false) {
    } else if (assignElem && HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "firstchild")) {
        // firstchild: Insert the value specified by 'expr' before all of the children at 'location'.
        for (size_t i = value.size(); i; i--) {
            Node<std::string> importedNode = (value[i-1].getOwnerDocument() == _doc ? value[i-1].cloneNode(true) : _doc.importNode(value[i-1], true));
            element.insertBefore(importedNode, element.getFirstChild());
        }
    } else if (assignElem && HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "lastchild")) {
        // lastchild: Insert the value specified by 'expr' after all of the children at 'location'.
        for (size_t i = 0; i < value.size(); i++) {
            Node<std::string> importedNode = (value[i].getOwnerDocument() == _doc ? value[i].cloneNode(true) : _doc.importNode(value[i], true));
            element.appendChild(importedNode);
        }
    } else if (assignElem && HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "previoussibling")) {
        // previoussibling: Insert the value specified by 'expr' before the
        // node specified by 'location', keeping the same parent.
        Node<std::string> parent = element.getParentNode();
        if (!parent)
            ERROR_EXECUTION_THROW("Node has no parent");
        for (size_t i = 0; i < value.size(); i++) {
            Node<std::string> importedNode = (value[i].getOwnerDocument() == _doc ? value[i].cloneNode(true) : _doc.importNode(value[i], true));
            parent.insertBefore(importedNode, element);
        }
    } else if (assignElem && HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "nextsibling")) {
        // nextsibling: Insert the value specified by 'expr' after the node
        // specified by 'location', keeping the same parent.
        Node<std::string> parent = element.getParentNode();
        if (!parent)
            ERROR_EXECUTION_THROW("Node has no parent");
        for (size_t i = value.size(); i; i--) {
            Node<std::string> importedNode = (value[i-1].getOwnerDocument() == _doc ? value[i-1].cloneNode(true) : _doc.importNode(value[i-1], true));
            Node<std::string> nextSibling = element.getNextSibling();
            if (nextSibling) {
                parent.insertBefore(importedNode, element.getNextSibling());
            } else {
                parent.appendChild(importedNode);
            }
        }
    } else if (assignElem && HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "replace")) {
        // replace: Replace the node specified by 'location' by the value specified by 'expr'.
        Node<std::string> parent = element.getParentNode();
        if (!parent)
            ERROR_EXECUTION_THROW("Node has no parent");
        if (value.size() != 1)
            ERROR_EXECUTION_THROW("Value not singular");
        Node<std::string> importedNode = (value[0].getOwnerDocument() == _doc ? value[0].cloneNode(true) : _doc.importNode(value[0], true));
        parent.replaceChild(importedNode, element);
    } else if (assignElem && HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "delete")) {
        // delete: Delete the node specified by 'location'. ('expr' is ignored.).
        Node<std::string> parent = element.getParentNode();
        if (!parent)
            ERROR_EXECUTION_THROW("Node has no parent");
        parent.removeChild(element);
    } else {
        // replacechildren: Replace all the children at 'location' with the value specified by 'expr'.
        while(element.hasChildNodes())
            element.removeChild(element.getChildNodes().item(0));
        for (size_t i = 0; i < value.size(); i++) {
            Node<std::string> importedNode = element.getOwnerDocument().importNode(value[i], true);
            element.appendChild(importedNode);
        }
    }
}
Exemple #19
0
/** 
 * @internal Terminates the myqttd excution, returing the exit signal
 * provided as first parameter. This function is used to notify a
 * context that a signal was received.
 * 
 * @param ctx The myqttd context to terminate.
 * @param _signal The exit code to return.
 */
void myqttd_signal_exit (MyQttdCtx * ctx, int _signal)
{
	/* get myqttd context */
	axlDoc           * doc;
	axlNode          * node;
	MyQttAsyncQueue  * queue;
	char             * backtrace_file;

	/* lock the mutex and check */
	myqtt_mutex_lock (&ctx->exit_mutex);
	if (ctx->is_exiting) {
		msg ("process already existing, signal received=%d, doing nothing...", _signal);

		/* other thread is already cleaning */
		myqtt_mutex_unlock (&ctx->exit_mutex);
		return;
	} /* end if */

	msg ("received termination signal (%d) on PID %d, preparing exit process", _signal, getpid ()); 

	/* flag that myqttd is existing and do all cleanup
	 * operations */
	ctx->is_exiting = axl_true;
	myqtt_mutex_unlock (&ctx->exit_mutex);
	
	switch (_signal) {
	case SIGINT:
		msg ("caught SIGINT, terminating myqttd..");
		break;
	case SIGTERM:
		msg ("caught SIGTERM, terminating myqttd..");
		break;
#if defined(AXL_OS_UNIX)
	case SIGKILL:
		msg ("caught SIGKILL, terminating myqttd..");
		break;
	case SIGQUIT:
		msg ("caught SIGQUIT, terminating myqttd..");
		break;
#endif
	case SIGSEGV:
	case SIGABRT:
		error ("caught %s, anomalous termination (this is an internal myqttd or module error)",
		       _signal == SIGSEGV ? "SIGSEGV" : "SIGABRT");
		
		/* check current termination option */
		doc  = myqttd_config_get (ctx);
		node = axl_doc_get (doc, "/myqtt/global-settings/on-bad-signal");
		error ("applying configured action %s", (node && HAS_ATTR (node, "action")) ? ATTR_VALUE (node, "action") : "not defined");
		if (HAS_ATTR_VALUE (node, "action", "ignore")) {
			/* do notify if enabled */
			CHECK_AND_REPORT_MAIL_TO ("Bad signal received at myqttd process, default action: ignore",
						  "Received termination signal but it was ignored.",
						  NULL);

			/* ignore the signal emision */
			return;
		} else if (HAS_ATTR_VALUE (node, "action", "hold")) {
			/* lock the process */
			error ("Bad signal found, locking process, now you can attach or terminate pid: %d", 
			       getpid ());
			CHECK_AND_REPORT_MAIL_TO ("Bad signal received a myqttd process, default action: hold",
						  "Received termination signal and the process was hold for examination",
						  NULL);
			queue = myqtt_async_queue_new ();
			myqtt_async_queue_pop (queue);
			return;
		} else if (HAS_ATTR_VALUE (node, "action", "backtrace")) {
			/* create temporal file */
			error ("Bad signal found, creating backtrace for current process: %d", getpid ());
			backtrace_file = myqttd_support_get_backtrace (ctx, getpid ());
			if (backtrace_file == NULL)
				error ("..backtrace error, unable to produce backtrace..");
			else
				error ("..backtrace created at: %s", backtrace_file);

			/* check if we have to do a mail notification */
			CHECK_AND_REPORT_MAIL_TO ("Bad signal received a myqttd process, default action: backtrace",
						  NULL, backtrace_file);
			/* release backtrace */
			axl_free (backtrace_file);
		}

		/* signal myqtt to not terminate threads (to avoid
		 * deadlocks) */
		exit (-1);
		break;
	default:
		msg ("terminating myqttd..");
		break;
	} /* end if */

	/* Unlock the listener here. Do not perform any deallocation
	 * operation here because we are in the middle of a signal
	 * handler execution. By unlocking the listener, the
	 * myqttd_cleanup is called cleaning the room. */
	msg ("Unlocking myqttd listener: %p", ctx);
	/* unlock the current listener */
	myqtt_listener_unlock (MYQTTD_MYQTT_CTX (ctx));

	return;
} /* end if */
// a macrostep
InterpreterState InterpreterDraft6::step(bool blocking) {
	try {

		monIter_t monIter;
		NodeSet<std::string> enabledTransitions;
		
		// setup document and interpreter
		if (!_isInitialized)
			init();
		
		// if we failed return false
		if (!_isInitialized)
			return INIT_FAILED;
		
		// run initial transitions
		if (!_stable) {
			stabilize();
			// we might only need a single step
			if (!_running)
				goto EXIT_INTERPRETER;
			return INITIALIZED;
		}
		
		if (!_running)
			return FINISHED;
		
		// read an external event and react
		if (blocking) {
			// wait until an event becomes available
			while(_externalQueue.isEmpty()) {
				_condVar.wait(_mutex);
			}
		} else {
			// return immediately if external queue is empty
			if (_externalQueue.isEmpty())
				return NOTHING_TODO;
		}
		_currEvent = _externalQueue.pop();

	#if VERBOSE
		std::cout << "Received externalEvent event " << _currEvent.name << std::endl;
		if (_running && _currEvent.name == "unblock.and.die") {
			std::cout << "Still running " << this << std::endl;
		} else {
			std::cout << "Aborting " << this << std::endl;
		}
	#endif
		_currEvent.eventType = Event::EXTERNAL; // make sure it is set to external

		// when we were blocking on destructor invocation
		if (!_running) {
			goto EXIT_INTERPRETER;
			return INTERRUPTED;
		}
		// --- MONITOR: beforeProcessingEvent ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent);
			}
			USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent)
		}
		
		if (iequals(_currEvent.name, "cancel.invoke." + _sessionId))
			return INTERRUPTED;
		
		try {
			_dataModel.setEvent(_currEvent);
		} catch (Event e) {
			LOG(ERROR) << "Syntax error while setting external event:" << std::endl << e << std::endl << _currEvent;
		}

		for (std::map<std::string, Invoker>::iterator invokeIter = _invokers.begin();
				 invokeIter != _invokers.end();
				 invokeIter++) {
			if (iequals(invokeIter->first, _currEvent.invokeid)) {
				Arabica::XPath::NodeSet<std::string> finalizes = filterChildElements(_nsInfo.xmlNSPrefix + "finalize", invokeIter->second.getElement());
				for (int k = 0; k < finalizes.size(); k++) {
					Element<std::string> finalizeElem = Element<std::string>(finalizes[k]);
					executeContent(finalizeElem);
				}
			}
			if (HAS_ATTR(invokeIter->second.getElement(), "autoforward") && DOMUtils::attributeIsTrue(ATTR(invokeIter->second.getElement(), "autoforward"))) {
				try {
					// do not autoforward to invokers that send to #_parent from the SCXML IO Processor!
					// Yes do so, see test229!
					// if (!boost::equals(_currEvent.getOriginType(), "http://www.w3.org/TR/scxml/#SCXMLEventProcessor"))
					invokeIter->second.send(_currEvent);
				} catch(...) {
					LOG(ERROR) << "Exception caught while sending event to invoker " << invokeIter->first;
				}
			}
		}

		
		// run internal processing until we reach a stable configuration again
		enabledTransitions = selectTransitions(_currEvent.name);
		if (!enabledTransitions.empty()) {
			// test 403b
			enabledTransitions.to_document_order();
			microstep(enabledTransitions);
		}

		stabilize();
		return PROCESSED;
		
	EXIT_INTERPRETER:
		if (!_running) {
			// --- MONITOR: beforeCompletion ------------------------------
			for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
				try {
					(*monIter)->beforeCompletion(shared_from_this());
				}
				USCXML_MONITOR_CATCH_BLOCK(beforeCompletion)
			}
			
			exitInterpreter();
			if (_sendQueue) {
				std::map<std::string, std::pair<InterpreterImpl*, SendRequest> >::iterator sendIter = _sendIds.begin();
				while(sendIter != _sendIds.end()) {
					_sendQueue->cancelEvent(sendIter->first);
					sendIter++;
				}
			}
			
			// --- MONITOR: afterCompletion ------------------------------
			for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
				try {
					(*monIter)->afterCompletion(shared_from_this());
				}
				USCXML_MONITOR_CATCH_BLOCK(afterCompletion)
			}
			return FINISHED;
		}
		
		assert(hasLegalConfiguration());
		_mutex.unlock();

		// remove datamodel
		if(_dataModel)
			_dataModel = DataModel();

		return PROCESSED;
		
	} catch (boost::bad_weak_ptr e) {
		LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl;
		return INTERRUPTED;
	}
	
	// set datamodel to null from this thread
	if(_dataModel)
		_dataModel = DataModel();

}
Exemple #21
0
void XPathDataModel::assign(const Element<std::string>& assignElem,
                            const Node<std::string>& node,
                            const std::string& content) {
    std::string location;
    if (HAS_ATTR(assignElem, "id")) {
        location = ATTR(assignElem, "id");
    } else if (HAS_ATTR(assignElem, "location")) {
        location = ATTR(assignElem, "location");
    }

    // test 326ff
    XPathValue<std::string> key = _xpath.evaluate_expr(location, _doc);
#ifdef VERBOSE
    LOG(INFO) << "Key XPath : " << key.asString();
#endif
#if 0
    if (key.type() == NODE_SET) {
        try {
            for (size_t i = 0; i < key.asNodeSet().size(); i++) {
                Node<std::string> node = key.asNodeSet()[i];
                if (node == _varResolver.resolveVariable("", "_ioprocessors").asNodeSet()[0])
                    ERROR_EXECUTION_THROW("Cannot assign _ioProcessors");
                if (node == _varResolver.resolveVariable("", "_sessionid").asNodeSet()[0])
                    ERROR_EXECUTION_THROW("Cannot assign _sessionid");
                if (node == _varResolver.resolveVariable("", "_name").asNodeSet()[0])
                    ERROR_EXECUTION_THROW("Cannot assign _name");
                if (node == _varResolver.resolveVariable("", "_event").asNodeSet()[0])
                    ERROR_EXECUTION_THROW("Cannot assign _event");
            }
        } catch (Event e) {}
    }
#endif
    NodeSet<std::string> nodeSet;
    if (node) {
        Node<std::string> data = node;
        while (data) {
            // do not add empty text as a node
            if (data.getNodeType() == Node_base::TEXT_NODE) {
                std::string trimmed = data.getNodeValue();
                boost::trim(trimmed);
                if (trimmed.length() == 0) {
                    data = data.getNextSibling();
                    continue;
                }
            }
            nodeSet.push_back(data);
            data = data.getNextSibling();
        }
        assign(key, nodeSet, assignElem);
    } else if (content.length() > 0) {
        Text<std::string> textNode = _doc.createTextNode(spaceNormalize(content));
        nodeSet.push_back(textNode);
        assign(key, nodeSet, assignElem);
    } else if (HAS_ATTR(assignElem, "expr")) {
        XPathValue<std::string> value = _xpath.evaluate_expr(ATTR(assignElem, "expr"), _doc);
#ifdef VERBOSE
        LOG(INFO) << "Value XPath : " << value.asString();
#endif
        assign(key, value, assignElem);
    } else {
        LOG(ERROR) << "assign element has no content";
    }

//	std::cout << _datamodel << std::endl;
}
// process transitions until we are in a stable configuration again
void InterpreterDraft6::stabilize() {

	monIter_t monIter;
	NodeSet<std::string> enabledTransitions;
	_stable = false;
	
	if (_configuration.size() == 0) {
		// goto initial configuration
		NodeSet<std::string> initialTransitions = getDocumentInitialTransitions();
		assert(initialTransitions.size() > 0);
		enterStates(initialTransitions);
	}
	
	do { // process microsteps for enabled transitions until there are no more left

		enabledTransitions = selectEventlessTransitions();
		
		if (enabledTransitions.size() == 0) {
			if (_internalQueue.size() == 0) {
				_stable = true;
			} else {
				_currEvent = _internalQueue.front();
				_internalQueue.pop_front();
#if VERBOSE
				std::cout << "Received internal event " << _currEvent.name << std::endl;
#endif
				
				// --- MONITOR: beforeProcessingEvent ------------------------------
				for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
					try {
						(*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent);
					}
					USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent)
				}
				
				if (_dataModel)
					_dataModel.setEvent(_currEvent);
				enabledTransitions = selectTransitions(_currEvent.name);
			}
		}
		
		if (!enabledTransitions.empty()) {
			// test 403b
			enabledTransitions.to_document_order();
			microstep(enabledTransitions);
		}
	} while(!_internalQueue.empty() || !_stable);
	
	monIter = _monitors.begin();
	
	// --- MONITOR: onStableConfiguration ------------------------------
	for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
		try {
			(*monIter)->onStableConfiguration(shared_from_this());
		}
		USCXML_MONITOR_CATCH_BLOCK(onStableConfiguration)
	}

	// when we reach a stable configuration, invoke
	for (unsigned int i = 0; i < _statesToInvoke.size(); i++) {
		NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _statesToInvoke[i]);
		for (unsigned int j = 0; j < invokes.size(); j++) {
			if (!HAS_ATTR(invokes[j], "persist") || !DOMUtils::attributeIsTrue(ATTR(invokes[j], "persist"))) {
				invoke(invokes[j]);
			}
		}
	}
	_statesToInvoke = NodeSet<std::string>();

}
Exemple #23
0
void StateTransitionMonitor::beforeEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {
	std::lock_guard<std::recursive_mutex> lock(_mutex);
	std::cerr << "Entering: " << (HAS_ATTR(state, "id") ? ATTR(state, "id") : DOMUtils::xPathForNode(state)) << std::endl;

}
void InterpreterDraft6::mainEventLoop() {
	monIter_t monIter;

	while(_running) {
		NodeSet<std::string> enabledTransitions;
		_stable = false;

		// Here we handle eventless transitions and transitions
		// triggered by internal events until machine is stable
		while(_running && !_stable) {
#if VERBOSE
			std::cout << "Configuration: ";
			for (int i = 0; i < _configuration.size(); i++) {
				std::cout << ATTR(_configuration[i], "id") << ", ";
			}
			std::cout << std::endl;
#endif

			enabledTransitions = selectEventlessTransitions();
			if (enabledTransitions.size() == 0) {
				if (_internalQueue.size() == 0) {
					_stable = true;
				} else {
					_currEvent = _internalQueue.front();
					_internalQueue.pop_front();
#if VERBOSE
					std::cout << "Received internal event " << _currEvent.name << std::endl;
#endif

					// --- MONITOR: beforeProcessingEvent ------------------------------
					for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
						try {
							(*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent);
						}
						USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent)
					}

					if (_dataModel)
						_dataModel.setEvent(_currEvent);
					enabledTransitions = selectTransitions(_currEvent.name);
				}
			}
			if (!enabledTransitions.empty()) {
				// test 403b
				enabledTransitions.to_document_order();
				microstep(enabledTransitions);
			}
		}

		for (unsigned int i = 0; i < _statesToInvoke.size(); i++) {
			NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _statesToInvoke[i]);
			for (unsigned int j = 0; j < invokes.size(); j++) {
				if (!HAS_ATTR(invokes[j], "persist") || !DOMUtils::attributeIsTrue(ATTR(invokes[j], "persist"))) {
					invoke(invokes[j]);
				}
			}
		}
		_statesToInvoke = NodeSet<std::string>();

		if (!_internalQueue.empty())
			continue;

		// assume that we have a legal configuration as soon as the internal queue is empty
		assert(hasLegalConfiguration());

		monIter = _monitors.begin();

		// --- MONITOR: onStableConfiguration ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->onStableConfiguration(shared_from_this());
			}
			USCXML_MONITOR_CATCH_BLOCK(onStableConfiguration)
		}

		_mutex.unlock();
		
		// whenever we have a stable configuration, run the mainThread hooks with 200fps
		while(_externalQueue.isEmpty() && _thread == NULL) {
			runOnMainThread(200);
		}
		_mutex.lock();

		while(_externalQueue.isEmpty()) {
			_condVar.wait(_mutex);
		}
		_currEvent = _externalQueue.pop();
#if VERBOSE
		std::cout << "Received externalEvent event " << _currEvent.name << std::endl;
		if (_running && _currEvent.name == "unblock.and.die") {
			std::cout << "Still running " << this << std::endl;
		} else {
			std::cout << "Aborting " << this << std::endl;
		}
#endif
		_currEvent.eventType = Event::EXTERNAL; // make sure it is set to external
		if (!_running)
			goto EXIT_INTERPRETER;

		// --- MONITOR: beforeProcessingEvent ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent);
			}
			USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent)
		}

		if (_dataModel && iequals(_currEvent.name, "cancel.invoke." + _sessionId))
			break;

		if (_dataModel) {
			try {
				_dataModel.setEvent(_currEvent);
			} catch (Event e) {
				LOG(ERROR) << "Syntax error while setting external event:" << std::endl << e << std::endl << _currEvent;
			}
		}
		for (std::map<std::string, Invoker>::iterator invokeIter = _invokers.begin();
		        invokeIter != _invokers.end();
		        invokeIter++) {
			if (iequals(invokeIter->first, _currEvent.invokeid)) {
				Arabica::XPath::NodeSet<std::string> finalizes = filterChildElements(_nsInfo.xmlNSPrefix + "finalize", invokeIter->second.getElement());
				for (int k = 0; k < finalizes.size(); k++) {
					Element<std::string> finalizeElem = Element<std::string>(finalizes[k]);
					executeContent(finalizeElem);
				}
			}
			if (HAS_ATTR(invokeIter->second.getElement(), "autoforward") && DOMUtils::attributeIsTrue(ATTR(invokeIter->second.getElement(), "autoforward"))) {
				try {
					// do not autoforward to invokers that send to #_parent from the SCXML IO Processor!
					// Yes do so, see test229!
					// if (!boost::equals(_currEvent.getOriginType(), "http://www.w3.org/TR/scxml/#SCXMLEventProcessor"))
					invokeIter->second.send(_currEvent);
				} catch(...) {
					LOG(ERROR) << "Exception caught while sending event to invoker " << invokeIter->first;
				}
			}
		}
		enabledTransitions = selectTransitions(_currEvent.name);
		if (!enabledTransitions.empty()) {
			// test 403b
			enabledTransitions.to_document_order();
			microstep(enabledTransitions);
		}
	}

EXIT_INTERPRETER:
	// --- MONITOR: beforeCompletion ------------------------------
	for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
		try {
			(*monIter)->beforeCompletion(shared_from_this());
		}
		USCXML_MONITOR_CATCH_BLOCK(beforeCompletion)
	}

	exitInterpreter();
	if (_sendQueue) {
		std::map<std::string, std::pair<InterpreterImpl*, SendRequest> >::iterator sendIter = _sendIds.begin();
		while(sendIter != _sendIds.end()) {
			_sendQueue->cancelEvent(sendIter->first);
			sendIter++;
		}
	}

	// --- MONITOR: afterCompletion ------------------------------
	for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
		try {
			(*monIter)->afterCompletion(shared_from_this());
		}
		USCXML_MONITOR_CATCH_BLOCK(afterCompletion)
	}

}
Exemple #25
0
int  tbc_mod_gen_compile ()
{
	axlDtd   * dtd;
	axlDoc   * doc;
	axlError * error;
	axlNode  * node;
	axlNode  * moddef;
	char     * mod_name;
	char     * tolower;
	char     * toupper;
	char     * description;

	/* parse DTD document */
	dtd = axl_dtd_parse (TBC_MOD_GEN_DTD, -1, &error);
	if (dtd == NULL) {
		/* report error and dealloc resources */
		error ("Failed to parse DTD, error found: %s", axl_error_get (error));
		axl_error_free (error);

		return axl_false;
	} /* end if */
	
	/* nice, now parse the xml file */
	doc = axl_doc_parse_from_file (exarg_get_string ("compile"), &error);
	if (doc == NULL) {
		/* report error and dealloc resources */
		error ("unable to parse file: %s, error found: %s", 
		       exarg_get_string ("compile"),
		       axl_error_get (error));
		axl_error_free (error);
		axl_dtd_free (dtd);
	} /* end if */

	/* nice, now validate content */
	if (! axl_dtd_validate (doc, dtd, &error)) {
		/* report error and dealloc */
		error ("failed to validate module description provided: %s, error found: %s",
		       exarg_get_string ("compile"),
		       axl_error_get (error));
		axl_error_free (error);
		axl_doc_free (doc);
		axl_dtd_free (dtd);
		return axl_false;
	} /* end if */

	/* ok, now produce source code  */
	axl_dtd_free (dtd);

	/* open file */
	moddef   = axl_doc_get_root (doc);
	node     = axl_doc_get (doc, "/mod-def/name");
	mod_name = (char *) axl_node_get_content (node, NULL);
	mod_name = support_clean_name (mod_name);
	tolower  = support_to_lower (mod_name);
	toupper  = support_to_upper (mod_name);

	/* out dir */
	support_open_file (ctx, "%s%s.c", get_out_dir (), mod_name);

	/* place copyright if found */
	node     = axl_doc_get (doc, "/mod-def/copyright");
	if (node != NULL) {
		/* place the copyright */
	}  /* end if */
	
	write ("/* %s implementation */\n", mod_name);
	write ("#include <turbulence.h>\n\n");

	write ("/* use this declarations to avoid c++ compilers to mangle exported\n");
	write (" * names. */\n");
	write ("BEGIN_C_DECLS\n\n");

	write ("/* global turbulence context reference */\n");
	write ("TurbulenceCtx * ctx = NULL;\n\n");

	/* place here additional content */
	node    = axl_doc_get (doc, "/mod-def/source-code/additional-content");
	if (node != NULL) {
		write ("%s\n", axl_node_get_content (node, NULL));
	} /* end if */

	/* init handler */
	write ("/* %s init handler */\n", mod_name);
	write ("static int  %s_init (TurbulenceCtx * _ctx) {\n", tolower);

	push_indent ();
	write ("/* configure the module */\n");
	write ("TBC_MOD_PREPARE (_ctx);\n\n");
	pop_indent ();

	node = axl_doc_get (doc, "/mod-def/source-code/init");
	if (axl_node_get_content (node, NULL)) {
		/* write the content defined */
		write ("%s\n", axl_node_get_content (node, NULL));
	}
	write ("} /* end %s_init */\n\n", tolower);

	/* close handler */
	write ("/* %s close handler */\n", mod_name);
	write ("static void %s_close (TurbulenceCtx * _ctx) {\n", tolower);
	node = axl_doc_get (doc, "/mod-def/source-code/close");
	if (axl_node_get_content (node, NULL)) {
		/* write the content defined */
		write ("%s\n", axl_node_get_content (node, NULL));
	}
	write ("} /* end %s_close */\n\n", tolower);

	/* reconf handler */
	write ("/* %s reconf handler */\n", mod_name);
	write ("static void %s_reconf (TurbulenceCtx * _ctx) {\n", tolower);
	node = axl_doc_get (doc, "/mod-def/source-code/reconf");
	if (axl_node_get_content (node, NULL)) {
		/* write the content defined */
		write ("%s\n", axl_node_get_content (node, NULL));
	}
	write ("} /* end %s_reconf */\n\n", tolower);

	/* unload handler */
	write ("/* %s unload handler */\n", mod_name);
	write ("static void %s_unload (TurbulenceCtx * _ctx) {\n", tolower);
	node = axl_doc_get (doc, "/mod-def/source-code/unload");
	if (axl_node_get_content (node, NULL)) {
		/* write the content defined */
		write ("%s\n", axl_node_get_content (node, NULL));
	}
	write ("} /* end %s_unload */\n\n", tolower);

	/* ppath_selected handler */
	write ("/* %s ppath-selected handler */\n", mod_name);
	write ("static axl_bool %s_ppath_selected (TurbulenceCtx * _ctx, TurbulencePPathDef * ppath_selected, VortexConnection * conn) {\n", tolower);
	node = axl_doc_get (doc, "/mod-def/source-code/ppath-selected");
	if (axl_node_get_content (node, NULL)) {
		/* write the content defined */
		write ("%s\n", axl_node_get_content (node, NULL));
	}
	write ("} /* end %s_ppath_selected */\n\n", tolower);

	/* write handler description */
	write ("/* Entry point definition for all handlers included in this module */\n");
	write ("TurbulenceModDef module_def = {\n");

	push_indent ();

	write ("\"%s\",\n", mod_name);
	node        = axl_doc_get (doc, "/mod-def/description");
	description = (char *) axl_node_get_content (node, NULL);
	write ("\"%s\",\n", description ? description : "");
	write ("%s_init,\n", tolower);
	write ("%s_close,\n", tolower);
	write ("%s_reconf,\n", tolower);
	write ("%s_unload,\n", tolower);
	write ("%s_ppath_selected\n", tolower);
	pop_indent ();

	write ("};\n\n");

	write ("END_C_DECLS\n\n");
	
	/* close content */
	support_close_file (ctx);

	/* create the makefile required */
	support_open_file (ctx, "%sMakefile.am", get_out_dir ());
	
	write ("# Module definition\n");
	write ("EXTRA_DIST = %s\n\n", exarg_get_string ("compile"));
	
	       
	write ("INCLUDES = -Wall -g -ansi $(TURBULENCE_CFLAGS) -I../../src -DCOMPILATION_DATE=`date +%%s` \\\n");
	push_indent ();
	
	write ("-DVERSION=\\\"$(VERSION)\\\" \\\n");
	write ("$(AXL_CFLAGS) $(VORTEX_CFLAGS) $(EXARG_CFLAGS)\n\n");
	pop_indent ();
	
	write ("# configure module binary\n");
	write ("lib_LTLIBRARIES      = %s.la\n", mod_name);
	write ("%s_la_SOURCES  = %s.c %s\n", mod_name, mod_name,
	       HAS_ATTR (moddef, "sources") ? ATTR_VALUE (moddef, "sources") : "");
	write ("%s_la_LDFLAGS  = -module -ldl\n\n", mod_name);
	
	write ("# reconfigure module installation directory\n");
	write ("libdir = `turbulence-config --mod-dir`\n\n");
	
	write ("# configure site module installation\n");
	write ("modconfdir   = `turbulence-config --mod-xml`\n");
	write ("modconf_DATA = %s.xml %s.win32.xml\n\n", mod_name, mod_name);
	
	write ("%s.xml %s.win32.xml:\n", mod_name, mod_name);
	push_indent ();
	write ("echo \"<mod-turbulence location=\\\"`turbulence-config --mod-dir`/%s.so\\\"/>\" > %s.xml\n", mod_name, mod_name);
	write ("echo \"<mod-turbulence location=\\\"../modules/%s.dll\\\"/>\" > %s.win32.xml\n", mod_name, mod_name);
	pop_indent ();

	support_close_file (ctx);

	/* create autoconf if defined */
	if (exarg_is_defined ("enable-autoconf")) {

		msg ("found autoconf support files request..");
		
		/* create the autogen.sh */
		support_open_file (ctx, "%sautogen.sh", get_out_dir ());

		write ("# autogen.sh file created by tbc-mod-gen\n");
		write ("PACKAGE=\"%s: %s\"\n\n", mod_name, description);

		write ("(automake --version) < /dev/null > /dev/null 2>&1 || {\n");

		push_indent ();
		write ("echo;\n");
		write ("echo \"You must have automake installed to compile $PACKAGE\";\n");
		write ("echo;\n");
		write ("exit;\n");
		pop_indent ();

		write ("}\n\n");

		write ("(autoconf --version) < /dev/null > /dev/null 2>&1 || {\n");
		push_indent ();
		write ("echo;\n");
		write ("echo \"You must have autoconf installed to compile $PACKAGE\";\n");
		write ("echo;\n");
		write ("exit;\n");
		pop_indent ();
		write ("}\n\n");

		write ("echo \"Generating configuration files for $PACKAGE, please wait....\"\n");
		write ("echo;\n\n");

		write ("touch NEWS README AUTHORS ChangeLog\n");
		write ("libtoolize --force;\n");
		write ("aclocal $ACLOCAL_FLAGS;\n");
		write ("autoheader;\n");
		write ("automake --add-missing;\n");
		write ("autoconf;\n\n");

		write ("./configure $@ --enable-maintainer-mode --enable-compile-warnings\n");

		support_close_file (ctx);

		support_make_executable (ctx, "%sautogen.sh", get_out_dir ());

		/* now create the configure.ac file */

		support_open_file (ctx, "%sconfigure.ac", get_out_dir ());

		write ("dnl configure.ac template file created by tbc-mod-gen\n");
		write ("AC_INIT(%s.c)\n\n", mod_name);

		write ("dnl declare a global version value\n");
		write ("%s_VERSION=\"0.0.1\"\n", toupper);
		write ("AC_SUBST(%s_VERSION)\n\n", toupper);

		write ("AC_CONFIG_AUX_DIR(.)\n");
		write ("AM_INIT_AUTOMAKE(%s, $%s_VERSION)\n\n", mod_name, toupper);

		write ("AC_CONFIG_HEADER(config.h)\n");
		write ("AM_MAINTAINER_MODE\n");
		write ("AC_PROG_CC\n");
		write ("AC_ISC_POSIX\n");
		write ("AC_HEADER_STDC\n");
		write ("AM_PROG_LIBTOOL\n\n");

		write ("dnl external dependencies\n");
		write ("PKG_CHECK_MODULES(AXL, axl >= %s)\n\n", AXL_VERSION);

		write ("dnl general libries subsitution\n");
		write ("AC_SUBST(AXL_CFLAGS)\n");
		write ("AC_SUBST(AXL_LIBS)\n\n");

		write ("dnl external dependencies\n");
		write ("PKG_CHECK_MODULES(VORTEX, vortex >= %s) \n\n", VORTEX_VERSION);

		write ("dnl general libries subsitution\n");
		write ("AC_SUBST(VORTEX_CFLAGS)\n");
		write ("AC_SUBST(VORTEX_LIBS)\n\n");

		write ("dnl external dependencies\n");
		write ("PKG_CHECK_MODULES(EXARG, exarg)\n\n");

		write ("dnl general libries subsitution\n");
		write ("AC_SUBST(EXARG_CFLAGS)\n");
		write ("AC_SUBST(EXARG_LIBS)\n\n");
		
		write ("dnl external dependencies\n");
		write ("PKG_CHECK_MODULES(TURBULENCE, turbulence >= %s)\n\n", VERSION);

		write ("dnl general libries subsitution\n");
		write ("AC_SUBST(TURBULENCE_CFLAGS)\n");
		write ("AC_SUBST(TURBULENCE_LIBS)\n\n");

		write ("AC_OUTPUT([\n");
		write ("Makefile\n");
		write ("])\n\n");

		write ("echo \"------------------------------------------\"\n");
		write ("echo \"--       mod_template Settings          --\"\n");
		write ("echo \"------------------------------------------\"\n");
		write ("echo \"------------------------------------------\"\n");
		write ("echo \"--            Let it BEEP!              --\"\n");
		write ("echo \"--                                      --\"\n");
		write ("echo \"--     NOW TYPE: make; make install     --\"\n");
		write ("echo \"------------------------------------------\"\n");

		support_close_file (ctx);
		
	} /* end if */

	/* dealloc */
	axl_free (tolower);
	axl_free (toupper);
	axl_doc_free (doc);

	/* create the script file */
	support_open_file (ctx, "%sgen-code", get_out_dir ());

	write ("#!/bin/sh\n\n");

	/* write the mod gen */
	write ("tbc-mod-gen --compile %s --out-dir %s\n", exarg_get_string ("compile"), exarg_get_string ("out-dir"));
	
	support_close_file (ctx);

	support_make_executable (ctx, "%sgen-code", get_out_dir ());

	msg ("%s created!", mod_name);
	axl_free (mod_name);

	return axl_true;
}
Exemple #26
0
axl_bool mod_sasl_mysql_do_auth (TurbulenceCtx    * ctx, 
				 VortexConnection * conn,
				 axlNode          * auth_db_node_conf,
				 const char       * auth_id,
				 const char       * authorization_id,
				 const char       * formated_password,
				 const char       * password,
				 const char       * serverName,
				 const char       * sasl_method,
				 axlError        ** err)
{
	char        * query; 
	axlDoc      * doc;
	axlNode     * node;
	axl_bool      _result = axl_false;

	/* check import parameters without doing anything */
	if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, auth_id))
		return axl_false;
	if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, password))
		return axl_false;
	if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, formated_password))
		return axl_false;
	if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, serverName))
		return axl_false;
	if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, authorization_id))
		return axl_false;
	if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, sasl_method))
		return axl_false;
	if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, auth_id))
		return axl_false;
	if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, vortex_connection_get_host (conn)))
		return axl_false;

	/* get the auth query */
	doc  = axl_node_annotate_get (auth_db_node_conf, "mysql-conf", axl_false);
	if (doc == NULL) {
		axl_error_report (err, -1, "Found no xml document defining MySQL settings to connect to the database");
		return axl_false;
	} /* end if */

	/* check for ip filter reference */
	node  = axl_doc_get (doc, "/sasl-auth-db/ip-filter");
	if (node && HAS_ATTR (node, "query")) {
		/* ip filter defined, get query */
		query = axl_strdup (ATTR_VALUE (node, "query"));

		/* replace query with recognized tokens */
		axl_replace (query, "%u", auth_id);
		axl_replace (query, "%n", serverName);
		axl_replace (query, "%i", authorization_id);
		axl_replace (query, "%m", sasl_method);

		msg ("Checking IP filter for auth id [%s], query [%s]", auth_id, query);
		
		if (! mod_sasl_mysql_check_ip_filter_query (ctx, query, conn, auth_db_node_conf)) {
			error ("login failure: %s, ip filtered by defined expression associated to user: %s denied connection from %s", 
			       auth_id, auth_id, vortex_connection_get_host_ip (conn));
			axl_free (query);
			return 0;
		}
		msg ("IP not filtered by defined expression associated to user: %s allowed connection from %s", 
		       auth_id, vortex_connection_get_host_ip (conn));
		
		/* ip not filtered, now let the auth continue */
		axl_free (query);
	} /* end if */

	/***** ALT AUTHENTICATION *****/
	/* get alt password if defined <get-password-alt> */
	node =  axl_doc_get (doc, "/sasl-auth-db/get-password-alt");
	if (node) {
		/* get query */
		query = (char *) ATTR_VALUE_TRANS (node, "query");

		/* call to do auth operation */
		_result = __mod_sasl_mysql_prepare_query_and_auth (ctx, query, conn, auth_db_node_conf, auth_id, authorization_id,
								   formated_password, password,
								   serverName, sasl_method, axl_false, 
								   /* skip login error reporting */ axl_true, err);		

		/* clean for cleanup node <get-password-alt-cleanup> */
		node =  axl_doc_get (doc, "/sasl-auth-db/get-password-alt-cleanup");
		if (node) {
			/* get query */
			query = (char *) ATTR_VALUE_TRANS (node, "query");

			/* call and skip getting value reported */
			if (! __mod_sasl_mysql_prepare_query_and_auth (ctx, query, conn, auth_db_node_conf, auth_id, authorization_id,
								       formated_password, password,
								       serverName, sasl_method, axl_true, 
								       /* skip login error reporting */ axl_true, err))
				error ("Cleanup query failed, please, review <get-password-alt-cleanup>..");
			
		} /* end if */
	} /* end if */

	/**** MAIN AUTHENTICATION ****/
	/* if authentication failed, try with main table */
	if (! _result) {
		/* get the node that contains the configuration */
		node  = axl_doc_get (doc, "/sasl-auth-db/get-password");
		query = (char *) ATTR_VALUE (node, "query");

		/* call to do auth operation */
		_result = __mod_sasl_mysql_prepare_query_and_auth (ctx, query, conn, auth_db_node_conf, auth_id, authorization_id,
								   formated_password, password,
								   serverName, sasl_method, axl_false, 
								   /* skip login error reporting */ axl_false, err);
	} /* end if */
	
	/* now check for auth-log declaration to report it */
	node = axl_doc_get (doc, "/sasl-auth-db/auth-log");
	if (node) {
		/* log auth defined */
		query = axl_strdup (ATTR_VALUE (node, "query"));
	
		/* replace query with recognized tokens */
		axl_replace (query, "%t", _result ? "ok" : "failed");
		axl_replace (query, "%u", auth_id);
		axl_replace (query, "%n", serverName);
		axl_replace (query, "%i", authorization_id);
		axl_replace (query, "%m", sasl_method);
		axl_replace (query, "%p", vortex_connection_get_host (conn));
		
		msg ("Trying to auth-log %s:%s with query string %s", auth_id, _result ? "ok" : "failed", query);
		/* exec query */
		if (! mod_sasl_mysql_do_query (ctx, auth_db_node_conf, query, axl_true, err)) {
			error ("Unable to auth-log, failed query configured, error was: %d:%s",
			       axl_error_get_code (*err), axl_error_get (*err));
			axl_error_free (*err);
		}
		axl_free (query);
		
	} /* end if */

	if (!_result)
		error ("login failure: %s, failed from: %s", auth_id, vortex_connection_get_host_ip (conn));
	
	return _result ? 1 : 0;
}
Exemple #27
0
axl_bool mod_sasl_mysql_load_auth_db (TurbulenceCtx     * ctx,
				      SaslAuthBackend   * sasl_backend,
				      axlNode           * auth_db_node_conf,
				      axlError         ** err)
{
	MYSQL      * conn;
	const char * location;
	char       * basedir = NULL;
	axlDoc     * doc;
	axlError   * local_err = NULL;

	/* check if location is defined */
	if (! HAS_ATTR (auth_db_node_conf, "location")) {
		axl_error_report (err, -1, "Unable to open auth mysql database, 'location' attribute is not defined");
		return axl_false;
	} /* end if */

	/* find the node that holds the connection configuration */
	location = ATTR_VALUE (auth_db_node_conf, "location");

	/* check if the location is relative or not */
	if (! turbulence_file_is_fullpath (location)) {
		/* get base dir of the sasl.conf that represents this
		   backend */
		basedir  = turbulence_base_dir (common_sasl_get_file_path (sasl_backend));

		/* now build a new path */
		location = axl_strdup_printf ("%s%s%s", basedir, VORTEX_FILE_SEPARATOR, location);
		msg ("Found relative file to auth mysql db settings, resolved to: %s", location);
	} /* end if */

	/* now load the file */
	doc      = axl_doc_parse_from_file (location, &local_err);
	/* check for error and report */
	if (doc == NULL) {
		axl_error_report (err, -1, "Failed to open auth mysql db at %s error was %s", location, axl_error_get (local_err));
		axl_error_free (local_err);
	} /* end if */

	/* dealloc some variables */
	if (basedir) {
		axl_free (basedir);
		axl_free ((char *) location);
	} /* end if */

	/* return if error */
	if (doc == NULL) {
		return axl_false;
	} /* end if */

	/* do DTD validation */
        if (! axl_dtd_validate (doc, mysql_sasl_dtd, &local_err)) {
		axl_error_report (err, -1, "Failed to open auth mysql db at %s, found DTD error %s", location, axl_error_get (local_err));
		axl_error_free (local_err);
		axl_doc_free (doc);
		return axl_false;
	} /* end if */

	/* link the document to this node so we can reuse it later */
	axl_node_annotate_data_full (auth_db_node_conf, "mysql-conf", NULL, doc, (axlDestroyFunc) axl_doc_free);

	/* request to load msyql database */
	conn = mod_sasl_mysql_get_connection (ctx, auth_db_node_conf, err);
	if (conn == NULL) 
		return axl_false;

	msg ("load database ok");

	/* connection ok, this means we have loaded the database */
	return axl_true;
}
void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions) {
	NodeSet<std::string> statesToExit;
	monIter_t monIter;

#if VERBOSE
	std::cout << _name << ": Enabled exit transitions: " << std::endl;
	for (int i = 0; i < enabledTransitions.size(); i++) {
		std::cout << enabledTransitions[i] << std::endl;
	}
	std::cout << std::endl;
#endif

	for (int i = 0; i < enabledTransitions.size(); i++) {
		Element<std::string> t = ((Element<std::string>)enabledTransitions[i]);
		if (!isTargetless(t)) {
			Node<std::string> ancestor;
			Node<std::string> source = getSourceState(t);
//			std::cout << t << std::endl << TAGNAME(t) << std::endl;
			NodeSet<std::string> tStates = getTargetStates(t);
			bool isInternal = (HAS_ATTR(t, "type") && iequals(ATTR(t, "type"), "internal")); // external is default
			bool allDescendants = true;
			for (int j = 0; j < tStates.size(); j++) {
				if (!isDescendant(tStates[j], source)) {
					allDescendants = false;
					break;
				}
			}
			if (isInternal && allDescendants && isCompound(source)) {
				ancestor = source;
			} else {
				NodeSet<std::string> tmpStates;
				tmpStates.push_back(source);
				tmpStates.insert(tmpStates.end(), tStates.begin(), tStates.end());
#if VERBOSE
				std::cout << _name << ": tmpStates: ";
				for (int i = 0; i < tmpStates.size(); i++) {
					std::cout << ATTR(tmpStates[i], "id") << ", ";
				}
				std::cout << std::endl;
#endif
				ancestor = findLCCA(tmpStates);
			}
#if VERBOSE
			std::cout << _name << ": Ancestor: " << ATTR(ancestor, "id") << std::endl;;
#endif
			for (int j = 0; j < _configuration.size(); j++) {
				if (isDescendant(_configuration[j], ancestor))
					statesToExit.push_back(_configuration[j]);
			}
		}
	}
	// remove statesToExit from _statesToInvoke
	std::list<Node<std::string> > tmp;
	for (int i = 0; i < _statesToInvoke.size(); i++) {
		if (!isMember(_statesToInvoke[i], statesToExit)) {
			tmp.push_back(_statesToInvoke[i]);
		}
	}
	_statesToInvoke = NodeSet<std::string>();
	_statesToInvoke.insert(_statesToInvoke.end(), tmp.begin(), tmp.end());

	statesToExit.forward(false);
	statesToExit.sort();

#if VERBOSE
	std::cout << _name << ": States to exit: ";
	for (int i = 0; i < statesToExit.size(); i++) {
		std::cout << LOCALNAME(statesToExit[i]) << ":" << ATTR(statesToExit[i], "id") << ", ";
	}
	std::cout << std::endl;
#endif

	for (int i = 0; i < statesToExit.size(); i++) {
		NodeSet<std::string> histories = filterChildElements(_nsInfo.xmlNSPrefix + "history", statesToExit[i]);
		for (int j = 0; j < histories.size(); j++) {
			Element<std::string> historyElem = (Element<std::string>)histories[j];
			std::string historyType = (historyElem.hasAttribute("type") ? historyElem.getAttribute("type") : "shallow");
			NodeSet<std::string> historyNodes;
			for (int k = 0; k < _configuration.size(); k++) {
				if (iequals(historyType, "deep")) {
					if (isAtomic(_configuration[k]) && isDescendant(_configuration[k], statesToExit[i]))
						historyNodes.push_back(_configuration[k]);
				} else {
					if (_configuration[k].getParentNode() == statesToExit[i])
						historyNodes.push_back(_configuration[k]);
				}
			}
			_historyValue[historyElem.getAttribute("id")] = historyNodes;
#if VERBOSE
			std::cout << _name << ": History node " << ATTR(historyElem, "id") << " contains: ";
			for (int i = 0; i < historyNodes.size(); i++) {
				std::cout << ATTR(historyNodes[i], "id") << ", ";
			}
			std::cout << std::endl;
#endif

		}
	}

	for (int i = 0; i < statesToExit.size(); i++) {
		// --- MONITOR: beforeExitingState ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->beforeExitingState(shared_from_this(), Element<std::string>(statesToExit[i]), (i + 1 < statesToExit.size()));
			}
			USCXML_MONITOR_CATCH_BLOCK(beforeExitingState)
		}

		NodeSet<std::string> onExits = filterChildElements(_nsInfo.xmlNSPrefix + "onExit", statesToExit[i]);
		for (int j = 0; j < onExits.size(); j++) {
			Element<std::string> onExitElem = (Element<std::string>)onExits[j];
			executeContent(onExitElem);
		}

		// --- MONITOR: afterExitingState ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->afterExitingState(shared_from_this(), Element<std::string>(statesToExit[i]), (i + 1 < statesToExit.size()));
			}
			USCXML_MONITOR_CATCH_BLOCK(afterExitingState)
		}

		NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", statesToExit[i]);
		for (int j = 0; j < invokes.size(); j++) {
			Element<std::string> invokeElem = (Element<std::string>)invokes[j];
			if (HAS_ATTR(invokeElem, "persist") && DOMUtils::attributeIsTrue(ATTR(invokeElem, "persist"))) {
				// extension for flattened SCXML documents, we will need an explicit uninvoke element
			} else {
				cancelInvoke(invokeElem);
			}
		}

		// remove statesToExit[i] from _configuration - test409
		tmp.clear();
		for (int j = 0; j < _configuration.size(); j++) {
			if (_configuration[j] != statesToExit[i]) {
				tmp.push_back(_configuration[j]);
			}
		}
		_configuration = NodeSet<std::string>();
		_configuration.insert(_configuration.end(), tmp.begin(), tmp.end());
	}
}
Exemple #29
0
void PostponeElement::enterElement(const Arabica::DOM::Element<std::string>& node) {
	if (!_interpreter->getDataModel()) {
		LOG(ERROR) << "Postpone element requires a datamodel";
		return;
	}

	// under which condition will we postpone the current event?
	if (HAS_ATTR(node, "cond")) {
		std::string cond = ATTR(node, "cond");
		try {
			if (!_interpreter->getDataModel().evalAsBool(cond))
				return;
		} catch (Event e) {
			LOG(ERROR) << "Syntax error in cond attribute of postpone element:" << std::endl << e << std::endl;
			return;
		}
	}

	// chaining causes the event to fire if the condition was true since postponing
	bool chained = false;
	if (HAS_ATTR(node, "chaining")) {
		chained = iequals(ATTR(node, "chaining"), "true");
	}

	// when will we refire the event?
	std::string until;
	try {
		if (HAS_ATTR(node, "untilexpr")) {
			until = _interpreter->getDataModel().evalAsString(ATTR(node, "untilexpr"));
		} else if (HAS_ATTR(node, "until")) {
			until = ATTR(node, "until");
		}
	} catch (Event e) {
		LOG(ERROR) << "Syntax error in postpone element untilexpr:" << std::endl << e << std::endl;
		return;
	}

	if (until.length() == 0) {
		LOG(ERROR) << "Postpone element requires until or untilexpr attribute ";
		return;
	}

//	LOG(INFO) << until;

#if 0
	std::string timeoutStr = "0s";
	try {
		if (HAS_ATTR(node, "timeoutexpr")) {
			timeoutStr = _interpreter->getDataModel().evalAsString(ATTR(node, "timeoutexpr"));
		} else if (HAS_ATTR(node, "timeout")) {
			timeoutStr = ATTR(node, "timeout");
		}
	} catch (Event e) {
		LOG(ERROR) << "Syntax error in postpone element timeoutexpr:" << std::endl << e << std::endl;
		return;
	}

	uint64_t timeout = 0;
	NumAttr timeoutAttr(timeoutStr);
	if (iequals(timeoutAttr.unit, "s")) {
		timeout = strTo<int>(timeoutAttr.value) * 1000;
	} else if (iequals(timeoutAttr.unit, "ms")) {
		timeout = strTo<int>(timeoutAttr.value);
	}
	if (timeout > 0) {
		timeout += tthread::chrono::system_clock::now();
	}
#endif
	Event currEvent = _interpreter->getCurrentEvent();
	Resubmitter::postpone(currEvent, until, 0, chained, _interpreter);
}
void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions) {
	NodeSet<std::string> statesToEnter;
	NodeSet<std::string> statesForDefaultEntry;
	monIter_t monIter;

#if VERBOSE
	std::cout << _name << ": Enabled enter transitions: " << std::endl;
	for (int i = 0; i < enabledTransitions.size(); i++) {
		std::cout << "\t" << enabledTransitions[i] << std::endl;
	}
	std::cout << std::endl;
#endif

	for (int i = 0; i < enabledTransitions.size(); i++) {
		Element<std::string> transition = ((Element<std::string>)enabledTransitions[i]);
		if (!isTargetless(transition)) {
			std::string transitionType = (iequals(transition.getAttribute("type"), "internal") ? "internal" : "external");
			NodeSet<std::string> tStates = getTargetStates(transition);

#if VERBOSE
			std::cout << _name << ": Target States: ";
			for (int i = 0; i < tStates.size(); i++) {
				std::cout << ATTR(tStates[i], "id") << ", ";
			}
			std::cout << std::endl;
#endif

			Node<std::string> ancestor;
			Node<std::string> source = getSourceState(transition);
#if VERBOSE
			std::cout << _name << ": Source States: " << ATTR(source, "id") << std::endl;
#endif
			assert(source);

			bool allDescendants = true;
			for (int j = 0; j < tStates.size(); j++) {
				if (!isDescendant(tStates[j], source)) {
					allDescendants = false;
					break;
				}
			}
			if (iequals(transitionType, "internal") &&
			        isCompound(source) &&
			        allDescendants) {
				ancestor = source;
			} else {
				NodeSet<std::string> tmpStates;
				tmpStates.push_back(source);
				tmpStates.insert(tmpStates.end(), tStates.begin(), tStates.end());

				ancestor = findLCCA(tmpStates);
			}

#if VERBOSE
			std::cout << _name << ": Ancestor: " << ATTR(ancestor, "id") << std::endl;
#endif

			for (int j = 0; j < tStates.size(); j++) {
				addStatesToEnter(tStates[j], statesToEnter, statesForDefaultEntry);
			}

#if VERBOSE
			std::cout << _name << ": States to enter: ";
			for (int i = 0; i < statesToEnter.size(); i++) {
				std::cout << LOCALNAME(statesToEnter[i]) << ":" << ATTR(statesToEnter[i], "id") << ", ";
			}
			std::cout << std::endl;
#endif

			for (int j = 0; j < tStates.size(); j++) {
				NodeSet<std::string> ancestors = getProperAncestors(tStates[j], ancestor);

#if VERBOSE
				std::cout << _name << ": Proper Ancestors of " << ATTR(tStates[j], "id") << " and " << ATTR(ancestor, "id") << ": ";
				for (int i = 0; i < ancestors.size(); i++) {
					std::cout << ATTR(ancestors[i], "id") << ", ";
				}
				std::cout << std::endl;
#endif

				for (int k = 0; k < ancestors.size(); k++) {
					statesToEnter.push_back(ancestors[k]);
					if(isParallel(ancestors[k])) {
						NodeSet<std::string> childs = getChildStates(ancestors[k]);
						for (int l = 0; l < childs.size(); l++) {
							bool someIsDescendant = false;
							for (int m = 0; m < statesToEnter.size(); m++) {
								if (isDescendant(statesToEnter[m], childs[l])) {
									someIsDescendant = true;
									break;
								}
							}
							if (!someIsDescendant) {
								addStatesToEnter(childs[l], statesToEnter, statesForDefaultEntry);
							}
						}
					}
				}
			}
		}
	}
	statesToEnter.to_document_order();

#if VERBOSE
	std::cout << _name << ": States to enter: ";
	for (int i = 0; i < statesToEnter.size(); i++) {
		std::cout << ATTR(statesToEnter[i], "id") << ", ";
	}
	std::cout << std::endl;
#endif

	for (int i = 0; i < statesToEnter.size(); i++) {
		Element<std::string> stateElem = (Element<std::string>)statesToEnter[i];

		// extension for flattened interpreters
		for (unsigned int k = 0; k < statesToEnter.size(); k++) {
			NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", statesToEnter[k]);
			for (unsigned int j = 0; j < invokes.size(); j++) {
				if (HAS_ATTR(invokes[j], "persist") && DOMUtils::attributeIsTrue(ATTR(invokes[j], "persist"))) {
					invoke(invokes[j]);
				}
			}
		}

		// --- MONITOR: beforeEnteringState ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->beforeEnteringState(shared_from_this(), stateElem, (i + 1 < statesToEnter.size()));
			}
			USCXML_MONITOR_CATCH_BLOCK(beforeEnteringState)
		}

		// extension for flattened SCXML documents, we will need an explicit uninvoke element
		NodeSet<std::string> uninvokes = filterChildElements(_nsInfo.xmlNSPrefix + "uninvoke", statesToEnter[i]);
		for (int j = 0; j < uninvokes.size(); j++) {
			Element<std::string> uninvokeElem = (Element<std::string>)uninvokes[j];
			cancelInvoke(uninvokeElem);
		}

		_configuration.push_back(stateElem);
		_statesToInvoke.push_back(stateElem);

//		if (_binding == LATE && stateElem.getAttribute("isFirstEntry").size() > 0) {
		if (_binding == LATE && !isMember(stateElem, _alreadyEntered)) {
			NodeSet<std::string> dataModelElems = filterChildElements(_nsInfo.xmlNSPrefix + "datamodel", stateElem);
			if(dataModelElems.size() > 0 && _dataModel) {
				Arabica::XPath::NodeSet<std::string> dataElems = filterChildElements(_nsInfo.xmlNSPrefix + "data", dataModelElems[0]);
				for (int j = 0; j < dataElems.size(); j++) {
					if (dataElems[j].getNodeType() == Node_base::ELEMENT_NODE)
						initializeData(Element<std::string>(dataElems[j]));
				}
			}
			_alreadyEntered.push_back(stateElem);
//			stateElem.setAttribute("isFirstEntry", "");
		}
		// execute onentry executable content
		NodeSet<std::string> onEntryElems = filterChildElements(_nsInfo.xmlNSPrefix + "onEntry", stateElem);
		executeContent(onEntryElems, false);

		// --- MONITOR: afterEnteringState ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->afterEnteringState(shared_from_this(), stateElem, (i + 1 < statesToEnter.size()));
			}
			USCXML_MONITOR_CATCH_BLOCK(afterEnteringState)
		}

		if (isMember(stateElem, statesForDefaultEntry)) {
			// execute initial transition content for compound states
			Arabica::XPath::NodeSet<std::string> transitions = _xpath.evaluate("" + _nsInfo.xpathPrefix + "initial/" + _nsInfo.xpathPrefix + "transition", stateElem).asNodeSet();
			for (int j = 0; j < transitions.size(); j++) {
				executeContent(transitions[j]);
			}
		}

		if (isFinal(stateElem)) {
			internalDoneSend(stateElem);
			Element<std::string> parent = (Element<std::string>)stateElem.getParentNode();

			if (isParallel(parent.getParentNode())) {
				Element<std::string> grandParent = (Element<std::string>)parent.getParentNode();

				Arabica::XPath::NodeSet<std::string> childs = getChildStates(grandParent);
				bool inFinalState = true;
				for (int j = 0; j < childs.size(); j++) {
					if (!isInFinalState(childs[j])) {
						inFinalState = false;
						break;
					}
				}
				if (inFinalState) {
					internalDoneSend(parent);
				}
			}
		}
	}
	for (int i = 0; i < _configuration.size(); i++) {
		Element<std::string> stateElem = (Element<std::string>)_configuration[i];
		if (isFinal(stateElem) && parentIsScxmlState(stateElem)) {
			_running = false;
			_done = true;
		}
	}
}