/*- * ============LICENSE_START======================================================= * OPENECOMP - MSO * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= */ package org.openecomp.mso.bpmn.core; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; import java.net.URI; import java.util.Iterator; import javax.xml.transform.stream.StreamSource; import org.camunda.bpm.engine.ProcessEngineException; import org.camunda.bpm.engine.delegate.DelegateExecution; //import java.util.logging.Logger; import org.camunda.bpm.engine.delegate.Expression; import org.openecomp.mso.logger.MessageEnum; import org.openecomp.mso.logger.MsoLogger; import net.sf.saxon.Configuration; import net.sf.saxon.s9api.DocumentBuilder; import net.sf.saxon.s9api.Processor; import net.sf.saxon.s9api.QName; import net.sf.saxon.s9api.XQueryCompiler; import net.sf.saxon.s9api.XQueryEvaluator; import net.sf.saxon.s9api.XQueryExecutable; import net.sf.saxon.s9api.XdmAtomicValue; import net.sf.saxon.s9api.XdmItem; import net.sf.saxon.s9api.XdmNode; /** * Executes an XQuery script. *
* Required fields:
* scriptFile: the XQuery script file path
* outputVariable: the output variable name
*
* Optional fields:
* xmlInputVariables: CSV list of variables containing
* XML data to be injected into the script
* atomicInputVariables: CSV list of variables containing
* atomic data to be injected into the script
*/
public class XQueryScriptTask extends BaseTask {
private static MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL);
private Expression scriptFile;
private Expression xmlInputVariables;
private Expression atomicInputVariables;
private Expression outputVariable;
public void execute(DelegateExecution execution) throws Exception {
if (msoLogger.isDebugEnabled()) {
msoLogger.debug("Started Executing " + getTaskName());
}
String theScriptFile =
getStringField(scriptFile, execution, "scriptFile");
String theXmlInputVariables =
getOptionalStringField(xmlInputVariables, execution, "xmlInputVariables");
String theAtomicInputVariables =
getOptionalStringField(atomicInputVariables, execution, "atomicInputVariables");
String theOutputVariable =
getStringField(outputVariable, execution, "outputVariable");
if (msoLogger.isDebugEnabled()) {
System.out.println("scriptFile = " + theScriptFile
+ " xmlInputVariables = " + theXmlInputVariables
+ " atomicInputVariables = " + theAtomicInputVariables
+ "outputVariable = " + theOutputVariable);
}
String[] xmlInputVariableArray = (theXmlInputVariables == null)
? new String[0] : theXmlInputVariables.split(",[ ]*");
String[] atomicInputVariableArray = (theAtomicInputVariables == null)
? new String[0] : theAtomicInputVariables.split(",[ ]*");
Boolean shouldFail = (Boolean) execution.getVariable("shouldFail");
if (shouldFail != null && shouldFail) {
throw new ProcessEngineException(getClass().getSimpleName() + " Failed");
}
// The script could be compiled once and reused, but we are reading it
// and compiling it every time.
Configuration configuration = new Configuration();
Processor processor = new Processor(configuration);
XQueryCompiler compiler = processor.newXQueryCompiler();
XQueryExecutable executable = compile(compiler, theScriptFile);
// The evaluator must not be shared by multiple threads. Here is where
// the initial context may be set, as well as values of external variables.
XQueryEvaluator evaluator = executable.load();
// Convert XML string variable content to document-node objects and inject
// these into the evaluator. Note: the script must accept the document-node
// type. Most MSO scripts today expect element() input, not document-node
// input. TODO: figure out how to pass the variable data as element() types.
for (String xmlInputVariable : xmlInputVariableArray) {
if (msoLogger.isDebugEnabled()) {
msoLogger.debug("Injecting XML variable '" + xmlInputVariable + "'");
msoLogger.debug("printing the variable content>>'" + execution.getVariable(xmlInputVariable) +"'");
}
String xml = (String) execution.getVariable(xmlInputVariable);
DocumentBuilder documentBuilder = processor.newDocumentBuilder();
StreamSource source = new StreamSource(new ByteArrayInputStream(xml.getBytes("UTF-8")));
XdmNode xdmNode = documentBuilder.build(source);
// Inject the document-node object into the XQueryEvaluator.
// TODO: transform it to an element()
QName variable = new QName(xmlInputVariable);
evaluator.setExternalVariable(variable, xdmNode);
}
// Inject atomic variables into the evaluator.
for (String atomicInputVariable : atomicInputVariableArray) {
if (msoLogger.isDebugEnabled()) {
System.out.println("Injecting object variable '"
+ atomicInputVariable + "'");
}
QName variable = new QName(atomicInputVariable);
Object value = execution.getVariable(atomicInputVariable);
if (value == null) {
// The variable value is null, so we have no way to know what
// type it is. I don't know how to deal with this, so for
// now, just skip it.
msoLogger.warn (MessageEnum.BPMN_VARIABLE_NULL, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.DataError, atomicInputVariable);
continue;
}
// There might be a better way to do this...
if (value instanceof BigDecimal) {
evaluator.setExternalVariable(variable,
new XdmAtomicValue((BigDecimal) value));
} else if (value instanceof Boolean) {
evaluator.setExternalVariable(variable,
new XdmAtomicValue((Boolean) value));
} else if (value instanceof Double) {
evaluator.setExternalVariable(variable,
new XdmAtomicValue((Double) value));
} else if (value instanceof Float) {
evaluator.setExternalVariable(variable,
new XdmAtomicValue((Float) value));
} else if (value instanceof Long) {
evaluator.setExternalVariable(variable,
new XdmAtomicValue((Long) value));
} else if (value instanceof String) {
evaluator.setExternalVariable(variable,
new XdmAtomicValue((String) value));
} else if (value instanceof URI) {
evaluator.setExternalVariable(variable,
new XdmAtomicValue((URI) value));
} else {
throw new BadInjectedFieldException(
"atomicInputVariables", getTaskName(),
"'" + atomicInputVariable + "' type is not supported: "
+ value.getClass());
}
}
// Evaluate the query and collect the output.
StringBuilder output = new StringBuilder();
Iterator