blob: 37c3386380ae6aabc56b2f34fa552ff351e5b9a8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.ode.bpel.extension.bpel4restlight;
import java.io.IOException;
import org.apache.ode.bpel.common.FaultException;
import org.apache.ode.bpel.eapi.ExtensionContext;
import org.apache.ode.bpel.obj.OScope;
import org.apache.ode.bpel.obj.OScope.Variable;
import org.apache.ode.bpel.obj.OVarType;
import org.apache.ode.bpel.obj.OXsdTypeVarType;
import org.apache.ode.utils.DOMUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
/**
* This class provides some utility methods for the BPEL REST extension
* activities.
*
* @author Michael Hahn (mhahn.dev@gmail.com)
*
*/
public class Bpel4RestLightUtil {
private static final String VARIABLE_VALUE_REFERENCE = "$bpelvar[";
/**
* This method extracts the request message payload from the provided extension
* activity. This request payload is either provided through a specified BPEL
* variable ('request' attribute) or statically defined within the process model
* as the child node of the extension activity.
*
* @param context
* The extension context required to resolve variable values
* @param element
* The extension activity DOM element containing the request payload
* @return The request message payload
*
* @throws FaultException
*/
public static String extractRequestPayload(ExtensionContext context, Element element) throws FaultException {
String requestPayload = null;
String requestPayloadVariableName = getMethodAttributeValue(context, element,
MethodAttribute.REQUEST_PAYLOAD_VARIABLE);
// Check if a reference to a variable is specified
if (requestPayloadVariableName != null && !requestPayloadVariableName.isEmpty()) {
// Get the request variable value
Node requestVariableNode = context.readVariable(requestPayloadVariableName);
// Check if the specified variable provides data
if (requestVariableNode != null) {
requestPayload = variableData2String(requestVariableNode);
}
}
// If no variable was specified or the variable doesn't provide data, we check
// if a static request payload is specified as the child element of the
// extension activity
if (requestPayload == null) {
Node request = DOMUtils.findChildByType(element, Node.ELEMENT_NODE);
if (request != null) {
requestPayload = DOMUtils.domToString(request);
}
}
if (requestPayload == null) {
throw new FaultException(Bpel4RestLightExtensionBundle.FAULT_QNAME,
"REST extension activity does not specify any request payload.");
}
return requestPayload;
}
/**
* This method writes the response payload to a specified BPEL variable.
*
* @param context
* The extension context required to resolve a variable and write a
* new value to it
* @param responsePayload
* The payload of the response which will be written to the specified
* variable
* @param processVariableName
* The name of the variable to write to
* @throws FaultException
*/
public static void writeResponsePayload(ExtensionContext context, Object responsePayload,
String processVariableName) throws FaultException {
if (responsePayload != null && !responsePayload.toString().isEmpty()) {
OScope.Variable bpelVariable = context.getVisibleVariables().get(processVariableName);
// Create a new instance of the variables' type, to see if we need a wrapper
Document doc = DOMUtils.newDocument();
Node val = bpelVariable.getType().newInstance(doc);
// Check if we need a temporary simple type wrapper
if (val.getNodeType() == Node.TEXT_NODE) {
// Create a wrapper element and add the response payload as text node
Element tempwrapper = doc.createElementNS(null, "temporary-simple-type-wrapper");
doc.appendChild(tempwrapper);
tempwrapper.appendChild(val);
// Set the response payload
val.setTextContent(responsePayload.toString());
// Return the wrapper element
val = tempwrapper;
} else {
// Convert the structured XML response payload to DOM
try {
val = DOMUtils.stringToDOM(responsePayload.toString());
} catch (SAXException e) {
throw new FaultException(Bpel4RestLightExtensionBundle.FAULT_QNAME,
"BPEL4REST: Writing the response payload to BPEL variable '" + processVariableName
+ "' caused an exception: " + e.getMessage(),
e);
} catch (IOException e) {
throw new FaultException(Bpel4RestLightExtensionBundle.FAULT_QNAME,
"BPEL4REST: Writing the response payload to BPEL variable '" + processVariableName
+ "' caused an exception: " + e.getMessage(),
e);
}
}
// Write the variable value
context.writeVariable(bpelVariable, val);
}
}
public static String extractAcceptHeader(ExtensionContext context, Element element) throws FaultException {
return getMethodAttributeValue(context, element, MethodAttribute.ACCEPT_HEADER);
}
/**
* This method extracts special predefined attributes (see
* {@link MethodAttribute}) from an extension activity. Therefore, references to
* a variable value via '$bpelVar[varName]' are also automatically resolved.
*
* @param context
* The extension context required to resolve variable values
* @param element
* The extension activity DOM element containing the attribute value
* @param methodAttribute
* Attribute whose content has to be returned
* @return The value of the attribute
* @throws FaultException
*/
public static String getMethodAttributeValue(ExtensionContext context, Element element,
MethodAttribute methodAttribute) throws FaultException {
String result = "";
switch (methodAttribute) {
case REQUEST_URI:
result = element.getAttribute("uri");
if (result == null || result.isEmpty()) {
result = element.getAttribute("requestUri");
} else {
// Resolve a possible variable value reference
result = resolveVariableValueReference(context, result);
}
break;
case REQUEST_PAYLOAD_VARIABLE:
result = element.getAttribute("request");
if (result == null || result.isEmpty()) {
result = element.getAttribute("requestPayload");
}
break;
case RESPONSE_PAYLOAD_VARIABLE:
result = element.getAttribute("response");
if (result == null || result.isEmpty()) {
result = element.getAttribute("responsePayload");
}
break;
case STATUS_CODE_VARIABLE:
result = element.getAttribute("statusCode");
break;
case ACCEPT_HEADER:
result = element.getAttribute("accept");
// Resolve a possible variable value reference
if (result != null && !result.isEmpty()) {
result = resolveVariableValueReference(context, result);
}
break;
}
return result;
}
/**
* Resolves references to variable values specified in an extension activity via
* '$bpelVar[varName]'.
*
* @param context
* The extension context to lookup and resolve variables and their
* values.
* @param variableValueReference
* A potential variable value reference.
*
* @return If the 'variableValueReference' parameter contains a variable value
* reference ($bpelVar[varName]), the actual value of the variable is
* returned, else the provided parameter value is returned.
* @throws FaultException
*/
public static String resolveVariableValueReference(ExtensionContext context, String variableValueReference)
throws FaultException {
String variableValue = variableValueReference;
// Check if a concrete variable name ("varName") or a reference to the value of
// a variable
// is specified ("$bpelVar[varName]")
if (variableValueReference.startsWith(VARIABLE_VALUE_REFERENCE)) {
String variableName = variableValueReference.substring(variableValueReference.indexOf("[") + 1,
variableValueReference.indexOf("]"));
Variable variable = context.getVisibleVariables().get(variableName);
// We only support simple type variables, therefore the value of the variable is
// directly provided within a <temporary-simple-type-wrapper/> element.
if (variable != null && isSimpleType(variable.getType())) {
Node variableContent = context.readVariable(variableName);
if (variableContent.getTextContent() != null) {
variableValue = variableContent.getTextContent();
}
} else {
throw new FaultException(Bpel4RestLightExtensionBundle.FAULT_QNAME,
"References to the value of a BPEL variable using '$bpelVar[varName]' only support simple type variables.");
}
}
return variableValue;
}
public static String variableData2String(Node variableData) {
String result = null;
if (variableData != null) {
if ("temporary-simple-type-wrapper".equals(variableData.getLocalName())) {
result = variableData.getTextContent();
} else {
result = DOMUtils.domToString(variableData);
}
}
return result;
}
/**
* Checks if the type is a simple type or not.
*
* @param type
* to check
*
* @return True, if the type is simple, False otherwise.
*/
private static boolean isSimpleType(OVarType type) {
boolean result = false;
if (type instanceof OXsdTypeVarType) {
result = ((OXsdTypeVarType) type).isSimple();
}
return result;
}
}