blob: 00d8ccd710be9f536292367923d8a709227054f0 [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.compiler;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import javax.wsdl.Definition;
import javax.wsdl.Message;
import javax.wsdl.Operation;
import javax.wsdl.Part;
import javax.wsdl.PortType;
import javax.wsdl.WSDLException;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.ode.bpel.compiler.api.CompilationException;
import org.apache.ode.bpel.compiler.api.CompilationMessage;
import org.apache.ode.bpel.compiler.api.CompileListener;
import org.apache.ode.bpel.compiler.api.CompilerContext;
import org.apache.ode.bpel.compiler.api.ExpressionCompiler;
import org.apache.ode.bpel.compiler.api.ExpressionValidator;
import org.apache.ode.bpel.compiler.api.SourceLocation;
import org.apache.ode.bpel.compiler.bom.Activity;
import org.apache.ode.bpel.compiler.bom.Bpel11QNames;
import org.apache.ode.bpel.compiler.bom.Bpel20QNames;
import org.apache.ode.bpel.compiler.bom.BpelObject;
import org.apache.ode.bpel.compiler.bom.Catch;
import org.apache.ode.bpel.compiler.bom.CompensationHandler;
import org.apache.ode.bpel.compiler.bom.Correlation;
import org.apache.ode.bpel.compiler.bom.CorrelationSet;
import org.apache.ode.bpel.compiler.bom.Expression;
import org.apache.ode.bpel.compiler.bom.Expression11;
import org.apache.ode.bpel.compiler.bom.FaultHandler;
import org.apache.ode.bpel.compiler.bom.Import;
import org.apache.ode.bpel.compiler.bom.LinkSource;
import org.apache.ode.bpel.compiler.bom.LinkTarget;
import org.apache.ode.bpel.compiler.bom.OnAlarm;
import org.apache.ode.bpel.compiler.bom.OnEvent;
import org.apache.ode.bpel.compiler.bom.PartnerLink;
import org.apache.ode.bpel.compiler.bom.PartnerLinkType;
import org.apache.ode.bpel.compiler.bom.Process;
import org.apache.ode.bpel.compiler.bom.Property;
import org.apache.ode.bpel.compiler.bom.PropertyAlias;
import org.apache.ode.bpel.compiler.bom.Scope;
import org.apache.ode.bpel.compiler.bom.ScopeActivity;
import org.apache.ode.bpel.compiler.bom.ScopeLikeActivity;
import org.apache.ode.bpel.compiler.bom.TerminationHandler;
import org.apache.ode.bpel.compiler.bom.Variable;
import org.apache.ode.bpel.compiler.wsdl.Definition4BPEL;
import org.apache.ode.bpel.compiler.wsdl.WSDLFactory4BPEL;
import org.apache.ode.bpel.obj.DebugInfo;
import org.apache.ode.bpel.obj.OActivity;
import org.apache.ode.bpel.obj.OAssign;
import org.apache.ode.bpel.obj.OCatch;
import org.apache.ode.bpel.obj.OCompensate;
import org.apache.ode.bpel.obj.OConstantExpression;
import org.apache.ode.bpel.obj.OConstantVarType;
import org.apache.ode.bpel.obj.OConstants;
import org.apache.ode.bpel.obj.OElementVarType;
import org.apache.ode.bpel.obj.OEventHandler;
import org.apache.ode.bpel.obj.OExpression;
import org.apache.ode.bpel.obj.OExpressionLanguage;
import org.apache.ode.bpel.obj.OExtVar;
import org.apache.ode.bpel.obj.OFlow;
import org.apache.ode.bpel.obj.OLValueExpression;
import org.apache.ode.bpel.obj.OLink;
import org.apache.ode.bpel.obj.OMessageVarType;
import org.apache.ode.bpel.obj.OPartnerLink;
import org.apache.ode.bpel.obj.OProcess;
import org.apache.ode.bpel.obj.ORethrow;
import org.apache.ode.bpel.obj.OScope;
import org.apache.ode.bpel.obj.OSequence;
import org.apache.ode.bpel.obj.OVarType;
import org.apache.ode.bpel.obj.OXsdTypeVarType;
import org.apache.ode.bpel.obj.OXslSheet;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.NSContext;
import org.apache.ode.utils.Namespaces;
import org.apache.ode.utils.StreamUtils;
import org.apache.ode.utils.fs.FileUtils;
import org.apache.ode.utils.msg.MessageBundle;
import org.apache.ode.utils.stl.CollectionsX;
import org.apache.ode.utils.stl.MemberOfFunction;
import org.apache.ode.utils.stl.UnaryFunction;
import org.apache.ode.utils.xsd.SchemaModel;
import org.apache.ode.utils.xsd.XSUtils;
import org.apache.ode.utils.xsd.XsdException;
import org.apache.ode.utils.xsl.XslTransformHandler;
import org.apache.xerces.xni.parser.XMLEntityResolver;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
/**
* Compiler for converting BPEL process descriptions (and their associated WSDL and XSD documents) into compiled representations
* suitable for execution by the ODE BPEL Service Provider. TODO: Move process validation into this class.
*/
public abstract class BpelCompiler implements CompilerContext {
/** Class-severity logger. */
protected static final Logger __log = LoggerFactory.getLogger(BpelCompiler.class);
/** Standardized compiler messages. */
private static final CommonCompilationMessages __cmsgs = MessageBundle.getMessages(CommonCompilationMessages.class);
private org.apache.ode.bpel.compiler.bom.Process _processDef;
private Date _generatedDate;
@SuppressWarnings("unchecked")
private HashMap<Class, ActivityGenerator> _actGenerators = new HashMap<Class, ActivityGenerator>();
private boolean _supressJoinFailure = false;
/** Are we currently in an atomic scope context? */
private boolean _atomicScope = false;
/** Are we currently compiling an isolated scope context. */
private boolean _isolatedScope = false;
/** Syntactic scope stack. */
private StructureStack _structureStack = new StructureStack();
/** Fault/compensate recovery stack. */
private Stack<OScope> _recoveryContextStack = new Stack<OScope>();
/** History of compiled activities */
private List<OActivity> _compiledActivities = new ArrayList<OActivity>();
private OProcess _oprocess;
private ResourceFinder _resourceFinder;
private WSDLRegistry _wsdlRegistry;
private final List<CompilationMessage> _errors = new ArrayList<CompilationMessage>();
private CompileListener _compileListener;
private final HashMap<String, ExpressionCompiler> _expLanguageCompilers = new HashMap<String, ExpressionCompiler>();
private final HashMap<String, OExpressionLanguage> _expLanguages = new HashMap<String, OExpressionLanguage>();
private ExpressionValidatorFactory _expressionValidatorFactory = new ExpressionValidatorFactory(System.getProperties());
private WSDLFactory4BPEL _wsdlFactory;
private OExpressionLanguage _konstExprLang;
private Map<QName, Node> _customProcessProperties;
private URI _processURI;
BpelCompiler(WSDLFactory4BPEL wsdlFactory) {
_wsdlFactory = wsdlFactory;
_wsdlRegistry = new WSDLRegistry(this);
}
public void addWsdlImport(URI from, URI wsdlImport, SourceLocation sloc) {
Definition4BPEL def;
try {
WSDLReader r = _wsdlFactory.newWSDLReader();
WSDLLocatorImpl locator = new WSDLLocatorImpl(_resourceFinder, _resourceFinder.resolve(from, wsdlImport));
def = (Definition4BPEL) r.readWSDL(locator);
} catch (WSDLException e) {
recoveredFromError(sloc, new CompilationException(__cmsgs.errWsdlParseError(e.getFaultCode(), e.getLocation(), e
.getMessage())));
throw new CompilationException(__cmsgs.errWsdlImportFailed(wsdlImport.toASCIIString(), e.getFaultCode())
.setSource(sloc), e);
}
try {
_wsdlRegistry.addDefinition(def, _resourceFinder, _resourceFinder.resolve(from, wsdlImport));
if (__log.isDebugEnabled())
__log.debug("Added WSDL Definition: " + wsdlImport);
} catch (CompilationException ce) {
recoveredFromError(sloc, ce);
}
}
public void addXsdImport(URI from, URI location, SourceLocation sloc) {
URI resFrom = _resourceFinder.resolve(from, location);
if (__log.isDebugEnabled())
__log.debug("Adding XSD import from " + resFrom + " location " + location);
XMLEntityResolver resolver = new WsdlFinderXMLEntityResolver(_resourceFinder,
location, new HashMap<URI,byte[]>(), true);
try {
InputStream xsdStream = _resourceFinder.openResource(resFrom);
byte[] data;
try {
data = StreamUtils.read(xsdStream);
} finally {
xsdStream.close();
}
Map<URI, byte[]> schemas = XSUtils.captureSchema(resFrom, data, resolver, 0);
_wsdlRegistry.addSchemas(schemas);
} catch (XsdException e) {
CompilationException ce = new CompilationException(__cmsgs.errInvalidImport(location.toString()));
recoveredFromError(sloc, ce);
} catch (MalformedURLException e) {
CompilationException ce = new CompilationException(__cmsgs.errInvalidImport(location.toString()));
recoveredFromError(sloc, ce);
} catch (IOException e) {
CompilationException ce = new CompilationException(__cmsgs.errInvalidImport(location.toString()));
recoveredFromError(sloc, ce);
}
}
public void setResourceFinder(ResourceFinder finder) {
if (finder == null) {
_resourceFinder = new DefaultResourceFinder();
} else {
_resourceFinder = finder;
}
}
public void setCompileListener(CompileListener compileListener) {
_compileListener = compileListener;
}
public CompileListener getCompileListener() {
return _compileListener;
}
public void setCustomProperties(Map<QName, Node> customProperties) {
_customProcessProperties = customProperties;
}
/**
* Get the process definition.
*
* @return the process definition
*/
public Process getProcessDef() {
return _processDef;
}
public PortType resolvePortType(final QName portTypeName) {
if (portTypeName == null)
throw new NullPointerException("Null portTypeName argument!");
PortType portType = _wsdlRegistry.getPortType(portTypeName);
if (portType == null)
throw new CompilationException(__cmsgs.errUndeclaredPortType(portTypeName));
return portType;
}
public OLink resolveLink(String linkName) {
OLink ret = null;
// Fist find where the link is declared.
for (Iterator<OActivity> i = _structureStack.iterator(); i.hasNext();) {
OActivity oact = i.next();
if (oact instanceof OFlow)
ret = ((OFlow) oact).getLocalLink(linkName);
if (ret != null)
return ret;
}
throw new CompilationException(__cmsgs.errUndeclaredLink(linkName));
}
public OScope.Variable resolveVariable(String varName) {
for (Iterator<OScope> i = _structureStack.oscopeIterator(); i.hasNext();) {
OScope.Variable var = i.next().getLocalVariable(varName);
if (var != null)
return var;
}
// A "real" variable couldn't be found, checking if we're dealing with a
// process custom property
if (_customProcessProperties != null && _customProcessProperties.get(QName.valueOf(varName)) != null) {
}
throw new CompilationException(__cmsgs.errUndeclaredVariable(varName));
}
public List<OScope.Variable> getAccessibleVariables() {
ArrayList<OScope.Variable> result = new ArrayList<OScope.Variable>();
for (Iterator<OScope> i = _structureStack.oscopeIterator(); i.hasNext();) {
result.addAll(i.next().getVariables().values());
}
return result;
}
public OScope.Variable resolveMessageVariable(String inputVar) throws CompilationException {
OScope.Variable var = resolveVariable(inputVar);
if (!(var.getType() instanceof OMessageVarType))
throw new CompilationException(__cmsgs.errMessageVariableRequired(inputVar));
return var;
}
public OScope.Variable resolveMessageVariable(String inputVar, QName messageType) throws CompilationException {
OScope.Variable var = resolveMessageVariable(inputVar);
if (!((OMessageVarType) var.getType()).getMessageType().equals(messageType))
throw new CompilationException(__cmsgs.errVariableTypeMismatch(var.getName(), messageType,
((OMessageVarType) var.getType()).getMessageType()));
return var;
}
public OProcess.OProperty resolveProperty(QName name) {
for (OProcess.OProperty prop : _oprocess.getProperties()) {
if (prop.getName().equals(name))
return prop;
}
throw new CompilationException(__cmsgs.errUndeclaredProperty(name));
}
public OProcess.OPropertyAlias resolvePropertyAlias(OScope.Variable variable, QName propertyName) {
if (!(variable.getType() instanceof OMessageVarType))
throw new CompilationException(__cmsgs.errMessageVariableRequired(variable.getName()));
OProcess.OProperty property = resolveProperty(propertyName);
OProcess.OPropertyAlias alias = property.getAlias(variable.getType());
if (alias == null)
throw new CompilationException(__cmsgs.errUndeclaredPropertyAlias(variable.getType().toString(), propertyName));
return alias;
}
public OScope resolveCompensatableScope(final String scopeToCompensate) throws CompilationException {
if (_recoveryContextStack.isEmpty())
throw new CompilationException(__cmsgs.errCompensateNAtoContext());
OScope recoveryContext = _recoveryContextStack.peek();
OScope scopeToComp = CollectionsX.find_if(recoveryContext.getCompensatable(), new MemberOfFunction<OScope>() {
public boolean isMember(OScope o) {
return o.getName() != null && o.getName().equals(scopeToCompensate);
}
});
if (scopeToComp == null)
throw new CompilationException(__cmsgs.errCompensateOfInvalidScope(scopeToCompensate));
return scopeToComp;
}
public String getSourceLocation() {
return _processDef.getSource() == null ? null : _processDef.getSource();
}
public OScope.CorrelationSet resolveCorrelationSet(String csetName) {
for (Iterator<OScope> i = _structureStack.oscopeIterator(); i.hasNext();) {
OScope.CorrelationSet cset = i.next().getCorrelationSet(csetName);
if (cset != null)
return cset;
}
throw new CompilationException(__cmsgs.errUndeclaredCorrelationSet(csetName));
}
@SuppressWarnings("unchecked")
public OMessageVarType resolveMessageType(QName messageType) {
OMessageVarType msgType = _oprocess.getMessageTypes().get(messageType);
if (msgType == null) {
Message msg = _wsdlRegistry.getMessage(messageType);
if (msg == null) {
throw new CompilationException(__cmsgs.errUndeclaredMessage(messageType.getLocalPart(), messageType
.getNamespaceURI()));
}
List<OMessageVarType.Part> parts = new ArrayList<OMessageVarType.Part>();
CollectionsX.transform(parts, ((List<Part>) msg.getOrderedParts(null)),
new UnaryFunction<Part, OMessageVarType.Part>() {
public OMessageVarType.Part apply(Part part) {
OVarType partType;
if (part.getElementName() != null) {
partType = resolveElementType(part.getElementName());
} else {
partType = resolveXsdType(part.getTypeName());
}
OMessageVarType.Part opart = new OMessageVarType.Part(_oprocess, part.getName(), partType);
opart.setDebugInfo(createDebugInfo(_processDef, ("Message Variable Part: " + (part.getName()))));
return opart;
}
});
msgType = new OMessageVarType(_oprocess, msg.getQName(), parts);
msgType.setDebugInfo(createDebugInfo(_processDef, ("Message Type: " + (msg.getQName()))));
_oprocess.getMessageTypes().put(msg.getQName(), msgType);
}
return msgType;
}
public OXsdTypeVarType resolveXsdType(QName typeName) throws CompilationException {
OXsdTypeVarType type = _oprocess.getXsdTypes().get(typeName);
if (type == null) {
__log.debug("Resolving XSD type " + typeName);
SchemaModel model = null;
try {
model = _wsdlRegistry.getSchemaModel();
} catch (IllegalArgumentException iaa) { }
if (model == null || !model.knowsSchemaType(typeName))
throw new CompilationException(__cmsgs.errUndeclaredXsdType(typeName));
type = new OXsdTypeVarType(_oprocess);
type.setDebugInfo(createDebugInfo(_processDef, ("XSD Type: " + typeName)));
type.setXsdType(typeName);
type.setSimple(_wsdlRegistry.getSchemaModel().isSimpleType(typeName));
_oprocess.getXsdTypes().put(typeName, type);
}
return type;
}
public OMessageVarType.Part resolvePart(OScope.Variable var, String partname) {
if (!(var.getType() instanceof OMessageVarType))
throw new CompilationException(__cmsgs.errMessageVariableRequired(var.getName()));
OMessageVarType msgVarType = (OMessageVarType) var.getType();
OMessageVarType.Part part = msgVarType.getParts().get(partname);
if (part == null)
throw new CompilationException(__cmsgs.errUndeclaredMessagePart(var.getName(), ((OMessageVarType) var.getType()).getMessageType(),
partname));
return part;
}
public OMessageVarType.Part resolveHeaderPart(OScope.Variable var, String partname) {
if (!(var.getType() instanceof OMessageVarType))
throw new CompilationException(__cmsgs.errMessageVariableRequired(var.getName()));
OMessageVarType msgVarType = (OMessageVarType) var.getType();
return msgVarType.getParts().get(partname);
}
public PartnerLinkType resolvePartnerLinkType(QName partnerLinkType) {
PartnerLinkType plinkType = _wsdlRegistry.getPartnerLinkType(partnerLinkType);
if (plinkType == null)
throw new CompilationException(__cmsgs.errUndeclaredPartnerLinkType(partnerLinkType));
return plinkType;
}
public OPartnerLink resolvePartnerLink(String name) {
for (Iterator<OScope> i = _structureStack.oscopeIterator(); i.hasNext();) {
OPartnerLink oplink = i.next().getLocalPartnerLink(name);
if (oplink != null)
return oplink;
}
throw new CompilationException(__cmsgs.errUndeclaredPartnerLink(name));
}
@SuppressWarnings("unchecked")
public Operation resolvePartnerRoleOperation(final OPartnerLink partnerLink, final String operationName) {
if (partnerLink.getPartnerRolePortType() == null) {
throw new CompilationException(__cmsgs.errPartnerLinkDoesNotDeclarePartnerRole(partnerLink.getName()));
}
Operation found = CollectionsX.find_if((List<Operation>) partnerLink.getPartnerRolePortType().getOperations(),
new MemberOfFunction<Operation>() {
public boolean isMember(Operation o) {
// Guard against WSDL4j funny business.
if ((o.getInput() == null || o.getInput().getMessage() == null)
&& (o.getOutput() == null || o.getOutput().getMessage() == null)) {
return false;
}
return o.getName().equals(operationName);
}
});
if (found == null)
throw new CompilationException(__cmsgs
.errUndeclaredOperation(partnerLink.getPartnerRolePortType().getQName(), operationName));
return found;
}
@SuppressWarnings("unchecked")
public Operation resolveMyRoleOperation(final OPartnerLink partnerLink, final String operationName) {
if (partnerLink.getMyRolePortType() == null) {
throw new CompilationException(__cmsgs.errPartnerLinkDoesNotDeclareMyRole(partnerLink.getName()));
}
Operation found = CollectionsX.find_if((List<Operation>) partnerLink.getMyRolePortType().getOperations(),
new MemberOfFunction<Operation>() {
public boolean isMember(Operation o) {
// Again, guard against WSDL4J's "help"
if ((o.getInput() == null || o.getInput().getMessage() == null)
&& (o.getOutput() == null || o.getOutput().getMessage() == null))
return false;
return o.getName().equals(operationName);
}
});
if (found == null) {
throw new CompilationException(__cmsgs.errUndeclaredOperation(partnerLink.getMyRolePortType().getQName(), operationName));
}
return found;
}
/**
* Produce a boolean {@link OExpression} expression that returns a constant
* value.
*
* @param value
* constant value to return
* @return {@link OExpression} returning a constant value.
*/
public OExpression constantExpr(boolean value) {
OConstantExpression ce = new OConstantExpression(_oprocess, value ? Boolean.TRUE : Boolean.FALSE);
ce.setDebugInfo(createDebugInfo(_processDef, ("Constant Boolean Expression: " + value)));
ce.setExpressionLanguage(_konstExprLang);
return ce;
}
public OLValueExpression compileLValueExpr(Expression expression) throws CompilationException {
return compileLValueExpr(expression, null, null, new Object[1]);
}
public OLValueExpression compileLValueExpr(Expression expression, OVarType rootNodeType, Object requestedResultType, Object[] resultType) throws CompilationException {
return (OLValueExpression) compileExpr(expression, false, true, rootNodeType, requestedResultType, resultType);
}
public OExpression compileJoinCondition(Expression expression) throws CompilationException {
return compileExpr(expression, true, false, null, null, new Object[1]);
}
public OExpression compileExpr(Expression expression) throws CompilationException {
return compileExpr(expression, null, null, new Object[1]);
}
public OExpression compileExpr(Expression expression, OVarType rootNodeType, Object requestedResultType, Object[] resultType) throws CompilationException {
return compileExpr(expression, false, false, rootNodeType, requestedResultType, resultType);
}
public OExpression compileExpr(String expr, NSContext nc) {
// Does this really work?
BpelObject cur = _structureStack.topSource();
return compileExpr(new Expression11(cur.getElement(),cur.getElement().getOwnerDocument().createTextNode(expr)), false, false, null, null, new Object[1]);
}
private OExpression compileExpr(Expression expression, boolean isJoinCondition, boolean isLValue, OVarType rootNodeType, Object requestedResultType, Object[] resultType) {
String expLang = getExpressionLanguage(expression);
ExpressionCompiler ec = findExpLangCompiler(expLang);
ec.setCompilerContext(this);
ExpressionValidator ev = _expressionValidatorFactory.getValidator();
try {
OExpression oexpr;
if (isJoinCondition) {
oexpr = ec.compileJoinCondition(expression);
} else {
oexpr = ec.compile(expression);
resultType[0] = ev.validate(expression, rootNodeType, requestedResultType);
}
oexpr.setDebugInfo(createDebugInfo(expression, expression.toString()));
OExpressionLanguage expLanguage = _expLanguages.get(expLang);
if (expLanguage == null) {
expLanguage = new OExpressionLanguage(_oprocess, ec.getProperties());
expLanguage.setDebugInfo(createDebugInfo(_processDef, ("Expression Language: " + expLang)));
expLanguage.setExpressionLanguageUri(expLang);
_expLanguages.put(expLang, expLanguage);
_oprocess.getExpressionLanguages().add(expLanguage);
}
oexpr.setExpressionLanguage(expLanguage);
// Cleaning up expression compiler for furter compilation
ec.setCompilerContext(null);
return oexpr;
} catch (CompilationException ce) {
if (ce.getCompilationMessage().source == null)
ce.getCompilationMessage().setSource(expression);
throw ce;
}
}
public OProcess getOProcess() throws CompilationException {
return _oprocess;
}
public void recoveredFromError(SourceLocation where, CompilationException bce) throws CompilationException {
if (bce.getCompilationMessage().source == null)
bce.getCompilationMessage().source = where;
if (_compileListener == null) {
switch (bce.getCompilationMessage().severity) {
case CompilationMessage.INFO:
if (__log.isInfoEnabled()) {
__log.info(bce.toErrorMessage());
}
break;
case CompilationMessage.WARN:
if (__log.isWarnEnabled()) {
__log.warn(bce.toErrorMessage());
}
break;
case CompilationMessage.ERROR:
if (__log.isErrorEnabled()) {
__log.error(bce.toErrorMessage());
}
}
} else {
if (__log.isDebugEnabled()) {
__log.debug(bce.toErrorMessage(), bce);
}
_compileListener.onCompilationMessage(bce.getCompilationMessage());
}
_errors.add(bce.getCompilationMessage());
}
public static long getVersion(String dirName) {
try {
return Integer.parseInt(dirName.substring(dirName.lastIndexOf("-") + 1));
} catch (Throwable t) {
return 0;
}
}
/**
* Compile a process.
*/
public OProcess compile(final Process process, ResourceFinder rf, long version) throws CompilationException {
if (process == null)
throw new NullPointerException("Null process parameter");
setResourceFinder(rf);
_processURI = process.getURI();
_processDef = process;
_generatedDate = new Date();
_structureStack.clear();
String bpelVersionUri = null;
switch (process.getBpelVersion()) {
case BPEL11:
bpelVersionUri = Bpel11QNames.NS_BPEL4WS_2003_03;
break;
case BPEL20_DRAFT:
bpelVersionUri = Bpel20QNames.NS_WSBPEL2_0;
break;
case BPEL20:
bpelVersionUri = Bpel20QNames.NS_WSBPEL2_0_FINAL_EXEC;
break;
default:
throw new IllegalStateException("Bad bpel version: " + process.getBpelVersion());
}
_oprocess = new OProcess(bpelVersionUri);
_oprocess.setGuid(null);
_oprocess.setConstants(makeConstants());
_oprocess.setDebugInfo(createDebugInfo(process, "process"));
_oprocess.setNamespaceContext(process.getNamespaceContext());
if (process.getTargetNamespace() == null) {
_oprocess.setTargetNamespace("--UNSPECIFIED--");
recoveredFromError(process, new CompilationException(__cmsgs.errProcessNamespaceNotSpecified()));
} else {
_oprocess.setTargetNamespace(_processDef.getTargetNamespace());
}
if (process.getName() == null) {
_oprocess.setProcessName("--UNSPECIFIED--");
recoveredFromError(process, new CompilationException(__cmsgs.errProcessNameNotSpecified()));
} else {
_oprocess.setProcessName(_processDef.getName());
}
_oprocess.setCompileDate(_generatedDate);
_konstExprLang = new OExpressionLanguage(_oprocess, null);
_konstExprLang.setDebugInfo(createDebugInfo(_processDef, "Constant Value Expression Language"));
_konstExprLang.setExpressionLanguageUri("uri:www.fivesight.com/konstExpression");
_konstExprLang.getProperties().put("runtime-class",
"org.apache.ode.bpel.runtime.explang.konst.KonstExpressionLanguageRuntimeImpl");
_oprocess.getExpressionLanguages().add(_konstExprLang);
// Process the imports. Note, we expect all processes (Event BPEL 1.1)
// to have an import declaration. This should be automatically generated
// by the 1.1 parser.
for (Import imprt : _processDef.getImports()) {
try {
compile(_processURI, imprt);
} catch (CompilationException bce) {
// We try to recover from import problems by continuing
recoveredFromError(imprt, bce);
}
}
_expressionValidatorFactory.getValidator().bpelImportsLoaded(_processDef, this);
switch (_processDef.getSuppressJoinFailure()) {
case NO:
case NOTSET:
_supressJoinFailure = false;
break;
case YES:
_supressJoinFailure = true;
break;
}
// compile ALL wsdl properties; needed for property extraction
Definition4BPEL[] defs = _wsdlRegistry.getDefinitions();
for (Definition4BPEL def : defs) {
for (Property property : def.getProperties()) {
compile(property);
}
}
// compile ALL wsdl property aliases
for (Definition4BPEL def1 : defs) {
for (PropertyAlias propertyAlias : def1.getPropertyAliases()) {
compile(propertyAlias);
}
}
OScope procesScope = new OScope(_oprocess, null);
procesScope.setName("__PROCESS_SCOPE:" + (process.getName()));
procesScope.setDebugInfo(createDebugInfo(process, null));
_oprocess.setProcesScope(compileScope(procesScope, process, new java.lang.Runnable() {
public void run() {
if (process.getRootActivity() == null) {
throw new CompilationException(__cmsgs.errNoRootActivity());
}
// Process custom properties are created as variables associated
// with the top scope
if (_customProcessProperties != null) {
for (Map.Entry<QName, Node> customVar : _customProcessProperties.entrySet()) {
final OScope oscope = _structureStack.topScope();
OVarType varType = new OConstantVarType(_oprocess, customVar.getValue());
OScope.Variable ovar = new OScope.Variable(_oprocess, varType);
ovar.setName(customVar.getKey().getLocalPart());
ovar.setDeclaringScope(oscope);
ovar.setDebugInfo(createDebugInfo(null, "Process custom property variable"));
oscope.addLocalVariable(ovar);
if (__log.isDebugEnabled())
__log.debug("Compiled custom property variable " + ovar);
}
}
_structureStack.topScope().setActivity(compile(process.getRootActivity()));
}
}));
assert _structureStack.size() == 0;
boolean hasErrors = false;
StringBuffer sb = new StringBuffer();
for (CompilationMessage msg : _errors) {
if (msg.severity >= CompilationMessage.ERROR) {
hasErrors = true;
sb.append('\t');
sb.append(msg.toErrorString());
sb.append('\n');
}
}
XslTransformHandler.getInstance().clearXSLSheets(_oprocess.getQName());
_expressionValidatorFactory.getValidator().bpelCompilationCompleted(_processDef);
if (hasErrors) {
throw new CompilationException(__cmsgs.errCompilationErrors(_errors.size(), sb.toString()));
}
{
String digest = "version:" + version + ";" + _oprocess.digest();
_oprocess.setGuid(org.apache.ode.utils.GUID.makeGUID(digest));
if (__log.isDebugEnabled()) {
__log.debug("Compiled process digest: " + digest + "\nguid: " + _oprocess.getGuid());
}
}
return _oprocess;
}
private OConstants makeConstants() {
OConstants constants = new OConstants(_oprocess);
constants.setQnConflictingReceive(new javax.xml.namespace.QName(getBpwsNamespace() , "conflictingReceive"));
constants.setQnConflictingRequest(new javax.xml.namespace.QName(getBpwsNamespace() , "conflictingRequest"));
constants.setQnCorrelationViolation(new javax.xml.namespace.QName(getBpwsNamespace() , "correlationViolation"));
constants.setQnForcedTermination(new javax.xml.namespace.QName(getBpwsNamespace() , "forcedTermination"));
constants.setQnJoinFailure(new javax.xml.namespace.QName(getBpwsNamespace() , "joinFailure"));
constants.setQnMismatchedAssignmentFailure(new javax.xml.namespace.QName(getBpwsNamespace() , "mismatchedAssignment"));
constants.setQnMissingReply(new javax.xml.namespace.QName(getBpwsNamespace() , "missingReply"));
constants.setQnMissingRequest(new javax.xml.namespace.QName(getBpwsNamespace() , "missingRequest"));
constants.setQnSelectionFailure(new javax.xml.namespace.QName(getBpwsNamespace() , "selectionFailure"));
constants.setQnUninitializedVariable(new javax.xml.namespace.QName(getBpwsNamespace() , "uninitializedVariable"));
constants.setQnXsltInvalidSource(new javax.xml.namespace.QName(getBpwsNamespace() , "xsltInvalidSource"));
constants.setQnSubLanguageExecutionFault(new javax.xml.namespace.QName(getBpwsNamespace() , "subLanguageExecutionFault"));
constants.setQnUninitializedPartnerRole(new javax.xml.namespace.QName(getBpwsNamespace() , "uninitializedPartnerRole"));
constants.setQnForEachCounterError(new javax.xml.namespace.QName(getBpwsNamespace() , "forEachCounterError"));
constants.setQnInvalidBranchCondition(new javax.xml.namespace.QName(getBpwsNamespace() , "invalidBranchCondition"));
constants.setQnInvalidExpressionValue(new javax.xml.namespace.QName(getBpwsNamespace() , "invalidExpressionValue"));
constants.setQnRetiredProcess(new javax.xml.namespace.QName(getOdeNamespace() , "retiredProcess"));
constants.setQnTooManyInstances(new javax.xml.namespace.QName(getOdeNamespace() , "tooManyInstances"));
constants.setQnUnknownFault(new javax.xml.namespace.QName(getOdeNamespace() , "unknownFault"));
constants.setQnTooManyProcesses(new javax.xml.namespace.QName(getOdeNamespace() , "tooManyProcesses"));
constants.setQnTooHugeProcesses(new javax.xml.namespace.QName(getOdeNamespace() , "tooHugeProcesses"));
return constants;
}
private String getOdeNamespace() {
return Namespaces.ODE_EXTENSION_NS;
}
// TODO unused?
// private String getBpelPartnerLinkUri(){
// switch(_processDef.getBpelVersion()){
// case Process.BPEL_V110:
// return Constants.NS_BPEL4WS_PARTNERLINK_2003_05;
// case Process.BPEL_V200:
// return Constants.NS_WSBPEL_PARTNERLINK_2004_03;
// default:
// throw new IllegalStateException("Bad bpel version.");
// }
// }
/**
* Compile an import declaration. According to the specification:
* <blockquote> A BPEL4WSWS-BPEL process definition relies on XML Schema and
* WSDL 1.1 for the definition of datatypes and service interfaces. Process
* definitions also rely on other constructs such as partner link types,
* message properties and property aliases (defined later in this
* specification) which are defined within WSDL 1.1 documents using the WSDL
* 1.1 language extensibility feature.
*
* The &lt;import&gt; element is used within a BPEL4WSWS-BPEL process to
* explicitly indicate a dependency on external XML Schema or WSDL
* definitions. Any number of <import> elements may appear as initial
* children of the <process> element, before any other child element. Each
* <import> element contains three mandatory attributes:
* <ol>
* <li>namespace -- The namespace attribute specifies the URI namespace of
* the imported definitions. </li>
* <li>location -- The location attribute contains a URI indicating the
* location of a document that contains relevant definitions in the
* namespace specified. The document located at the URI MUST contain
* definitions belonging to the same namespace as indicated by the namespace
* attribute. </li>
* <li>importType -- The importType attribute identifies the type of
* document being imported by providing the URI of the encoding language.
* The value MUST be set to "http://www.w3.org/2001/XMLSchema" when
* importing XML Schema 1.0 documents, and to
* "http://schemas.xmlsoap.org/wsdl/" when importing WSDL 1.1 documents.
*
* @param imprt
* BOM representation of the import
*/
private void compile(URI current, Import imprt) {
try {
if (imprt.getImportType() == null)
throw new CompilationException(__cmsgs.errUnspecifiedImportType().setSource(imprt));
if (imprt.getLocation() == null)
throw new CompilationException(__cmsgs.errMissingImportLocation().setSource(imprt));
if (Import.IMPORTTYPE_WSDL11.equals(imprt.getImportType())) {
addWsdlImport(current, imprt.getLocation(), imprt);
} else if (Import.IMPORTTYPE_XMLSCHEMA10.equals(imprt.getImportType())) {
addXsdImport(current, imprt.getLocation(), imprt);
} else
throw new CompilationException(__cmsgs.errUnknownImportType(imprt.getImportType()).setSource(imprt));
} catch (CompilationException ce) {
if (ce.getCompilationMessage().source == null)
ce.getCompilationMessage().setSource(imprt);
throw ce;
}
}
public OActivity compile(final Activity source) {
if (source == null)
throw new IllegalArgumentException("null-argument");
boolean previousSupressJoinFailure = _supressJoinFailure;
switch (source.getSuppressJoinFailure()) {
case NO:
_supressJoinFailure = false;
break;
case YES:
_supressJoinFailure = true;
break;
}
OActivity compiled;
try {
compiled = (source instanceof ScopeLikeActivity) ? compileSLC((ScopeLikeActivity) source, new OScope.Variable[0])
: compileActivity(true, source);
compiled.setSuppressJoinFailure(_supressJoinFailure);
} finally {
_supressJoinFailure = previousSupressJoinFailure;
}
if (__log.isDebugEnabled())
__log.debug("Compiled activity " + compiled);
return compiled;
}
private OCompensate createDefaultCompensateActivity(BpelObject source, String desc) {
OCompensate activity = new OCompensate(_oprocess, getCurrent());
activity.setName("__autoGenCompensate:" + (_structureStack.topScope().getName()));
activity.setDebugInfo(createDebugInfo(source, desc));
return activity;
}
public OScope compileSLC(final ScopeLikeActivity source, final OScope.Variable[] variables) {
final OScope implicitScope = new OScope(_oprocess, getCurrent());
implicitScope.setImplicitScope(true);
implicitScope.setName(createName(source, "implicit-scope"));
implicitScope.setDebugInfo(createDebugInfo(source, ("Scope-like construct " + source)));
compileScope(implicitScope, source.getScope(), new Runnable() {
public void run() {
compileLinks(source);
for (OScope.Variable v : variables) {
v.setDeclaringScope(implicitScope);
implicitScope.addLocalVariable(v);
}
if (source instanceof ScopeActivity) {
Activity scopeChild = ((ScopeActivity) source).getChildActivity();
if (scopeChild == null)
throw new CompilationException(__cmsgs.errEmptyScope().setSource(source));
implicitScope.setActivity(compile(scopeChild));
} else {
implicitScope.setActivity(compileActivity(false, source));
}
}
});
return implicitScope;
}
private OActivity compileActivity(final boolean doLinks, final Activity source) {
final ActivityGenerator actgen = findActivityGen(source);
final OActivity oact = actgen.newInstance(source);
oact.setName(createName(source, "activity"));
oact.setDebugInfo(createDebugInfo(source, ("Activity body for " + source)));
_compiledActivities.add(oact);
compile(oact, source, new Runnable() {
public void run() {
if (doLinks)
compileLinks(source);
actgen.compile(oact, source);
}
});
return oact;
}
private void compileLinks(Activity source) {
/* Source Links Fixup */
for (LinkSource ls : source.getLinkSources())
compileLinkSource(ls);
/* Target Links Fixup */
for (LinkTarget lt : source.getLinkTargets())
compileLinkTarget(lt);
_structureStack.topActivity().setJoinCondition(((source.getJoinCondition()) == null) || (source.getLinkTargets().isEmpty()) ? null : compileJoinCondition(source.getJoinCondition()));
}
private String createName(Activity source, String type) {
if (source.getName() != null)
return source.getName();
return source.getType().getLocalPart() + "-" + type + "-line-" + source.getLineNo();
}
private OProcess.OProperty compile(Property property) {
OProcess.OProperty oproperty = new OProcess.OProperty(_oprocess);
oproperty.setName(property.getName());
oproperty.setDebugInfo(createDebugInfo(_processDef, ("Property " + (property.getName()))));
if (!_wsdlRegistry.getSchemaModel().isSimpleType(property.getPropertyType()))
throw new CompilationException(__cmsgs.errPropertyDeclaredWithComplexType(property.getName(),
property.getPropertyType()).setSource(property));
_oprocess.getProperties().add(oproperty);
if (__log.isDebugEnabled())
__log.debug("Compiled property " + oproperty);
return oproperty;
}
private OProcess.OPropertyAlias compile(PropertyAlias src) {
OProcess.OProperty property = resolveProperty(src.getPropertyName());
OProcess.OPropertyAlias alias = new OProcess.OPropertyAlias(_oprocess);
alias.setDebugInfo(createDebugInfo(_processDef, ((("PropertyAlias " + (src.getPropertyName())) + " for ") + (src.getMessageType()))));
if (src.getMessageType() == null) {
throw new CompilationException(__cmsgs.errAliasUndeclaredMessage(src.getPropertyName(), src.getQuery().getPath()));
}
OMessageVarType messageType = resolveMessageType(src.getMessageType());
OVarType rootNodeType = messageType;
alias.setVarType(messageType);
// bpel 2.0 excludes declaration of part;
// bpel 1.1 requires it
if (src.getPart() != null) {
alias.setPart(messageType.getParts().get(src.getPart()));
if (alias.getPart() == null)
throw new CompilationException(__cmsgs.errUnknownPartInAlias(src.getPart(),
messageType.getMessageType().toString()));
rootNodeType = alias.getPart().getType();
} else if (src.getHeader() != null) {
alias.setHeader(src.getHeader());
rootNodeType = new OElementVarType(_oprocess, QName.valueOf("{http://www.w3.org/2001/XMLSchema}any"));
}
if (src.getQuery() != null)
alias.setLocation(compileExpr(src.getQuery(), rootNodeType, null, new java.lang.Object[1]));
property.getAliases().add(alias);
alias.setDebugInfo(createDebugInfo(_processDef, (((src.getMessageType()) + " --> ") + (src.getPropertyName()))));
return alias;
}
private void compileLinkTarget(LinkTarget target) {
OLink ol = resolveLink(target.getLinkName());
assert ol != null;
ol.setDebugInfo(createDebugInfo(target, target.toString()));
if (ol.getTarget() != null)
throw new CompilationException(__cmsgs.errDuplicateLinkTarget(target.getLinkName()).setSource(target));
ol.setTarget(_structureStack.topActivity());
_structureStack.topActivity().getTargetLinks().add(ol);
}
private void compileLinkSource(LinkSource linksrc) {
OLink ol = resolveLink(linksrc.getLinkName());
assert ol != null;
ol.setDebugInfo(createDebugInfo(linksrc, linksrc.toString()));
if (ol.getSource() != null)
throw new CompilationException(__cmsgs.errDuplicateLinkSource(linksrc.getLinkName()).setSource(linksrc));
ol.setSource(_structureStack.topActivity());
ol.setTransitionCondition((linksrc.getTransitionCondition()) == null ? constantExpr(true) : compileExpr(linksrc.getTransitionCondition()));
_structureStack.topActivity().getSourceLinks().add(ol);
_structureStack.topActivity().getOutgoingLinks().add(ol);
}
private void compile(final PartnerLink plink) {
OPartnerLink oplink = new OPartnerLink(_oprocess);
oplink.setDebugInfo(createDebugInfo(plink, plink.toString()));
try {
PartnerLinkType plinkType = resolvePartnerLinkType(plink.getPartnerLinkType());
oplink.setPartnerLinkType(plinkType.getName());
oplink.setName(plink.getName());
oplink.setInitializePartnerRole(plink.isInitializePartnerRole());
if (plink.hasMyRole()) {
PartnerLinkType.Role myRole = plinkType.getRole(plink.getMyRole());
if (myRole == null)
throw new CompilationException(__cmsgs.errUndeclaredRole(plink.getMyRole(), plinkType.getName()));
oplink.setMyRoleName(myRole.getName());
QName portType = myRole.getPortType();
if (portType == null)
throw new CompilationException(__cmsgs.errMissingMyRolePortType(myRole.getPortType(), plink.getMyRole(), plinkType.getName()));
oplink.setMyRolePortType(resolvePortType(portType));
}
if (plink.isInitializePartnerRole() && !plink.hasPartnerRole()) {
throw new CompilationException(__cmsgs.errPartnerLinkNoPartnerRoleButInitialize(plink.getName()));
}
if (plink.hasPartnerRole()) {
PartnerLinkType.Role partnerRole = plinkType.getRole(plink.getPartnerRole());
if (partnerRole == null)
throw new CompilationException(__cmsgs.errUndeclaredRole(plink.getPartnerRole(), plinkType.getName()));
oplink.setPartnerRoleName(partnerRole.getName());
QName portType = partnerRole.getPortType();
if (portType == null)
throw new CompilationException(__cmsgs.errMissingPartnerRolePortType(partnerRole.getPortType(), plink.getPartnerRole(), plinkType.getName()));
oplink.setPartnerRolePortType(resolvePortType(portType));
}
oplink.setDeclaringScope(_structureStack.topScope());
if (oplink.getDeclaringScope().getPartnerLinks().containsKey(oplink.getName()))
throw new CompilationException(__cmsgs.errDuplicatePartnerLinkDecl(oplink.getName()));
oplink.getDeclaringScope().getPartnerLinks().put(oplink.getName(), oplink);
_oprocess.getAllPartnerLinks().add(oplink);
} catch (CompilationException ce) {
ce.getCompilationMessage().setSource(plink);
throw ce;
}
}
private void compile(CorrelationSet cset) {
OScope oscope = _structureStack.topScope();
OScope.CorrelationSet ocset = new OScope.CorrelationSet(_oprocess);
ocset.setName(cset.getName());
ocset.setDeclaringScope(oscope);
ocset.setDebugInfo(createDebugInfo(cset, cset.toString()));
QName[] setprops = cset.getProperties();
for (int j = 0; j < setprops.length; ++j)
ocset.getProperties().add(resolveProperty(setprops[j]));
oscope.addCorrelationSet(ocset);
}
public OActivity getCurrent() {
return _structureStack.topActivity();
}
public void compile(OActivity context, BpelObject source, Runnable run) {
DefaultActivityGenerator.defaultExtensibilityElements(context, source);
_structureStack.push(context, source);
try {
run.run();
} finally {
OActivity popped = _structureStack.pop();
OActivity newtop = _structureStack.topActivity();
OScope topScope = _structureStack.topScope();
if (newtop != null) {
newtop.getNested().add(popped);
// Transfer outgoing and incoming links, excluding the locally defined links.
newtop.getIncomingLinks().addAll(popped.getIncomingLinks());
if (newtop instanceof OFlow) newtop.getIncomingLinks().removeAll(((OFlow) newtop).getLocalLinks());
newtop.getOutgoingLinks().addAll(popped.getOutgoingLinks());
if (newtop instanceof OFlow) newtop.getOutgoingLinks().removeAll(((OFlow) newtop).getLocalLinks());
// Transfer variables read/writen
newtop.getVariableRd().addAll(popped.getVariableRd());
newtop.getVariableWr().addAll(popped.getVariableWr());
}
if (topScope != null && popped instanceof OScope) topScope.getCompensatable().add((OScope) popped);
}
}
private OScope compileScope(final OScope oscope, final Scope src, final Runnable init) {
if (oscope.getName() == null)
throw new IllegalArgumentException("Unnamed scope:" + src);
oscope.setDebugInfo(createDebugInfo(src, src.toString()));
//TODO: Is the logic incorrect?
boolean previousAtomicScope = _atomicScope;
if (src.getAtomicScope() != null) {
boolean newValue = src.getAtomicScope().booleanValue();
if (_atomicScope)
throw new CompilationException(__cmsgs.errAtomicScopeNesting(newValue));
oscope.setAtomicScope(_atomicScope = newValue);
}
if (src.getIsolatedScope() != null) {
if (src.getIsolatedScope()) {
if (_isolatedScope)
throw new CompilationException(__cmsgs.errIsolatedScopeNesting());
oscope.setIsolatedScope(_isolatedScope = true);
}
}
try {
compile(oscope, src, new Runnable() {
public void run() {
for (Variable var : src.getVariables()) {
try {
compile(var);
} catch (CompilationException ce) {
recoveredFromError(var, ce);
}
}
for (CorrelationSet cset : src.getCorrelationSetDecls()) {
try {
compile(cset);
} catch (CompilationException ce) {
recoveredFromError(cset, ce);
}
}
for (PartnerLink plink : src.getPartnerLinks()) {
try {
compile(plink);
} catch (CompilationException ce) {
recoveredFromError(plink, ce);
}
}
if (!src.getEvents().isEmpty() || !src.getAlarms().isEmpty()) {
oscope.setEventHandler(new org.apache.ode.bpel.obj.OEventHandler(_oprocess));
oscope.getEventHandler().setDebugInfo(createDebugInfo(src, ("Event Handler for " + src)));
}
for (OnEvent onEvent : src.getEvents()) {
try {
compile(onEvent);
} catch (CompilationException ce) {
recoveredFromError(src, ce);
}
}
for (OnAlarm onAlarm : src.getAlarms()) {
try {
compile(onAlarm);
} catch (CompilationException ce) {
recoveredFromError(src, ce);
}
}
if (init != null)
try {
init.run();
} catch (CompilationException ce) {
recoveredFromError(src, ce);
}
try {
compile(src.getCompensationHandler());
} catch (CompilationException bce) {
recoveredFromError(src.getCompensationHandler(), bce);
}
try {
compile(src.getTerminationHandler());
} catch (CompilationException bce) {
recoveredFromError(src.getTerminationHandler(), bce);
}
try {
compile(src.getFaultHandler());
} catch (CompilationException bce) {
recoveredFromError(src.getFaultHandler(), bce);
}
}
});
} finally {
_atomicScope = previousAtomicScope;
}
return oscope;
}
private void compile(final OnAlarm onAlarm) {
OScope oscope = _structureStack.topScope();
assert oscope.getEventHandler() != null;
final OEventHandler.OAlarm oalarm = new OEventHandler.OAlarm(_oprocess);
oalarm.setDebugInfo(createDebugInfo(onAlarm, ("OnAlarm Event Handler: " + onAlarm)));
if (onAlarm.getFor() != null && onAlarm.getUntil() == null) {
oalarm.setForExpr(compileExpr(onAlarm.getFor()));
} else if (onAlarm.getFor() == null && onAlarm.getUntil() != null) {
oalarm.setUntilExpr(compileExpr(onAlarm.getUntil()));
} else if (onAlarm.getFor() != null && onAlarm.getUntil() != null) {
throw new CompilationException(__cmsgs.errInvalidAlarm().setSource(onAlarm));
} else if (onAlarm.getRepeatEvery() == null) {
throw new CompilationException(__cmsgs.errInvalidAlarm().setSource(onAlarm));
}
if (onAlarm.getRepeatEvery() != null)
oalarm.setRepeatExpr(compileExpr(onAlarm.getRepeatEvery()));
if (onAlarm.getActivity() == null) throw new CompilationException(__cmsgs.errInvalidAlarm().setSource(onAlarm));
oalarm.setActivity(compile(onAlarm.getActivity()));
// Check links crossing restrictions.
for (OLink link : oalarm.getIncomingLinks())
try {
throw new CompilationException(__cmsgs.errLinkCrossesEventHandlerBoundary(link.getName()).setSource(onAlarm));
} catch (CompilationException ce) {
recoveredFromError(onAlarm, ce);
}
for (OLink link : oalarm.getOutgoingLinks())
try {
throw new CompilationException(__cmsgs.errLinkCrossesEventHandlerBoundary(link.getName()).setSource(onAlarm));
} catch (CompilationException ce) {
recoveredFromError(onAlarm, ce);
}
oscope.getEventHandler().getOnAlarms().add(oalarm);
}
private void compile(final OnEvent onEvent) {
final OScope oscope = _structureStack.topScope();
assert oscope.getEventHandler() != null;
final OEventHandler.OEvent oevent = new OEventHandler.OEvent(_oprocess, oscope);
oevent.setName("__eventHandler:");
oevent.setDebugInfo(createDebugInfo(onEvent, null));
compile(oevent, onEvent, new Runnable() {
public void run() {
switch (_processDef.getBpelVersion()) {
case BPEL11:
oevent.setVariable(resolveMessageVariable(onEvent.getVariable()));
break;
case BPEL20_DRAFT:
case BPEL20:
if (onEvent.getMessageType() == null && onEvent.getElementType() == null)
throw new CompilationException(__cmsgs.errVariableDeclMissingType(onEvent.getVariable()).setSource(onEvent));
if (onEvent.getMessageType() != null && onEvent.getElementType() != null)
throw new CompilationException(__cmsgs.errVariableDeclInvalid(onEvent.getVariable()).setSource(onEvent));
OVarType varType;
if (onEvent.getMessageType() != null)
varType = resolveMessageType(onEvent.getMessageType());
else if (onEvent.getElement() != null)
varType = resolveElementType(onEvent.getElementType());
else
throw new CompilationException(__cmsgs.errUnrecognizedVariableDeclaration(onEvent.getVariable()));
oevent.setVariable(new org.apache.ode.bpel.obj.OScope.Variable(_oprocess , varType));
oevent.getVariable().setName(onEvent.getVariable());
oevent.getVariable().setDeclaringScope(_structureStack.topScope());
oevent.addLocalVariable(oevent.getVariable());
break;
default:
throw new AssertionError("Unexpected BPEL VERSION constatnt: " + _processDef.getBpelVersion());
}
oevent.setPartnerLink(resolvePartnerLink(onEvent.getPartnerLink()));
oevent.setOperation(resolveMyRoleOperation(oevent.getPartnerLink(), onEvent.getOperation()));
oevent.setMessageExchangeId(onEvent.getMessageExchangeId());
oevent.setRoute(onEvent.getRoute());
if (onEvent.getPortType() != null && !onEvent.getPortType().equals(oevent.getPartnerLink().getMyRolePortType().getQName()))
throw new CompilationException(__cmsgs.errPortTypeMismatch(onEvent.getPortType(),
oevent.getPartnerLink().getMyRolePortType().getQName()));
Set<String> csetNames = new HashSet<String>(); // prevents duplicate cset in on one set of correlations
for (Correlation correlation : onEvent.getCorrelations()) {
if( csetNames.contains(correlation.getCorrelationSet() ) ) {
throw new CompilationException(__cmsgs.errDuplicateUseCorrelationSet(correlation
.getCorrelationSet()));
}
OScope.CorrelationSet cset = resolveCorrelationSet(correlation.getCorrelationSet());
switch (correlation.getInitiate()) {
case UNSET:
case NO:
oevent.getMatchCorrelations().add(cset);
oevent.getPartnerLink().addCorrelationSetForOperation(oevent.getOperation(), cset, false);
break;
case YES:
oevent.getInitCorrelations().add(cset);
break;
case JOIN:
cset.setHasJoinUseCases(true);
oevent.getJoinCorrelations().add(cset);
oevent.getPartnerLink().addCorrelationSetForOperation(oevent.getOperation(), cset, true);
}
for (OProcess.OProperty property : cset.getProperties()) {
// Force resolution of alias, to make sure that we have
// one for this variable-property pair.
resolvePropertyAlias(oevent.getVariable(), property.getName());
}
csetNames.add(correlation.getCorrelationSet());
}
if (onEvent.getActivity() == null) throw new CompilationException(__cmsgs.errInvalidAlarm().setSource(onEvent));
oevent.setActivity(compile(onEvent.getActivity()));
}
});
// Check links crossing restrictions.
for (OLink link : oevent.getIncomingLinks())
try {
throw new CompilationException(__cmsgs.errLinkCrossesEventHandlerBoundary(link.getName()));
} catch (CompilationException ce) {
recoveredFromError(onEvent, ce);
}
for (OLink link : oevent.getOutgoingLinks())
try {
throw new CompilationException(__cmsgs.errLinkCrossesEventHandlerBoundary(link.getName()));
} catch (CompilationException ce) {
recoveredFromError(onEvent, ce);
}
oscope.getEventHandler().getOnMessages().add(oevent);
}
private DebugInfo createDebugInfo(BpelObject bpelObject, String description) {
int lineNo = bpelObject == null ? -1 : bpelObject.getLineNo();
String str = description == null && bpelObject != null ? bpelObject.toString() : null;
Map<QName, Object> extElmt = bpelObject == null ? null : bpelObject.getExtensibilityElements();
DebugInfo debugInfo = new DebugInfo(_processDef.getSource(), lineNo, extElmt);
debugInfo.setDescription(str);
return debugInfo;
}
private void compile(final Variable src) {
final OScope oscope = _structureStack.topScope();
if (src.getKind() == null)
throw new CompilationException(__cmsgs.errVariableDeclMissingType(src.getName()).setSource(src));
if (oscope.getLocalVariable(src.getName()) != null)
throw new CompilationException(__cmsgs.errDuplicateVariableDecl(src.getName()).setSource(src));
if (src.getTypeName() == null) throw new CompilationException(__cmsgs.errUnrecognizedVariableDeclaration(src.getName()));
OVarType varType;
switch (src.getKind()) {
case ELEMENT:
varType = resolveElementType(src.getTypeName());
break;
case MESSAGE:
varType = resolveMessageType(src.getTypeName());
break;
case SCHEMA:
varType = resolveXsdType(src.getTypeName());
break;
default:
throw new CompilationException(__cmsgs.errUnrecognizedVariableDeclaration(src.getName()));
}
OScope.Variable ovar = new OScope.Variable(_oprocess, varType);
ovar.setName(src.getName());
ovar.setDeclaringScope(oscope);
ovar.setDebugInfo(createDebugInfo(src, null));
ovar.setExtVar(compileExtVar(src));
oscope.addLocalVariable(ovar);
if (__log.isDebugEnabled())
__log.debug("Compiled variable " + ovar);
}
private void compile(TerminationHandler terminationHandler) {
OScope oscope = _structureStack.topScope();
oscope.setTerminationHandler(new org.apache.ode.bpel.obj.OTerminationHandler(_oprocess , oscope));
oscope.getTerminationHandler().setName("__terminationHandler:" + (oscope.getName()));
oscope.getTerminationHandler().setDebugInfo(createDebugInfo(terminationHandler, null));
if (terminationHandler == null) {
oscope.getTerminationHandler().setActivity(createDefaultCompensateActivity(null, ("Auto-generated \'compensate all\' pseudo-activity for default termination handler on " + (oscope.toString()))));
} else {
_recoveryContextStack.push(oscope);
try {
oscope.getTerminationHandler().setActivity(compile(terminationHandler.getActivity()));
} finally {
_recoveryContextStack.pop();
}
}
}
private void compile(CompensationHandler compensationHandler) {
OScope oscope = _structureStack.topScope();
oscope.setCompensationHandler(new org.apache.ode.bpel.obj.OCompensationHandler(_oprocess , oscope));
oscope.getCompensationHandler().setName("__compenationHandler_" + (oscope.getName()));
oscope.getCompensationHandler().setDebugInfo(createDebugInfo(compensationHandler, null));
if (compensationHandler == null) {
oscope.getCompensationHandler().setActivity(createDefaultCompensateActivity(compensationHandler, ("Auto-generated \'compensate all\' pseudo-activity for default compensation handler on " + (oscope.toString()))));
} else {
_recoveryContextStack.push(oscope);
try {
oscope.getCompensationHandler().setActivity(compile(compensationHandler.getActivity()));
} finally {
_recoveryContextStack.pop();
}
}
}
private void compile(FaultHandler fh) {
OScope oscope = _structureStack.topScope();
oscope.setFaultHandler(new org.apache.ode.bpel.obj.OFaultHandler(_oprocess));
if (fh == null) {
// The default fault handler compensates all child activities
// AND then rethrows the fault!
final OCatch defaultCatch = new OCatch(_oprocess, oscope);
defaultCatch.setName("__defaultFaultHandler:" + (oscope.getName()));
defaultCatch.setFaultName(null); // catch any fault
defaultCatch.setFaultVariable(null);
OSequence sequence = new OSequence(_oprocess, defaultCatch);
sequence.setName("__defaultFaultHandler_sequence:" + (oscope.getName()));
sequence.setDebugInfo(createDebugInfo(fh, "Auto-generated sequence activity."));
ORethrow rethrow = new ORethrow(_oprocess, sequence);
rethrow.setName("__defaultFaultHandler_rethrow:" + (oscope.getName()));
rethrow.setDebugInfo(createDebugInfo(fh, "Auto-generated re-throw activity."));
sequence.getSequence().add(createDefaultCompensateActivity(fh, "Default compensation handler for " + oscope));
sequence.getSequence().add(rethrow);
defaultCatch.setActivity(sequence);
oscope.getFaultHandler().getCatchBlocks().add(defaultCatch);
if (__log.isDebugEnabled())
__log.debug("Compiled default catch block " + defaultCatch + " for " + oscope);
} else {
_recoveryContextStack.push(oscope);
try {
int i = 0;
for (final Catch catchSrc : fh.getCatches()) {
final OCatch ctch = new OCatch(_oprocess, oscope);
ctch.setDebugInfo(createDebugInfo(catchSrc, catchSrc.toString()));
ctch.setName((("__catch#" + i) + ":") + (_structureStack.topScope().getName()));
ctch.setFaultName(catchSrc.getFaultName());
compile(ctch, catchSrc, new Runnable() {
public void run() {
if (catchSrc.getFaultVariable() != null) {
OScope.Variable faultVar;
switch (_processDef.getBpelVersion()) {
case BPEL11:
faultVar = resolveVariable(catchSrc.getFaultVariable());
if (!(faultVar.getType() instanceof OMessageVarType))
throw new CompilationException(__cmsgs.errMessageVariableRequired(
catchSrc.getFaultVariable()).setSource(catchSrc));
break;
case BPEL20_DRAFT:
case BPEL20:
if (catchSrc.getFaultVariableMessageType() == null
&& catchSrc.getFaultVariableElementType() == null)
throw new CompilationException(__cmsgs.errVariableDeclMissingType(
catchSrc.getFaultVariable()).setSource(catchSrc));
if (catchSrc.getFaultVariableMessageType() != null
&& catchSrc.getFaultVariableElementType() != null)
throw new CompilationException(__cmsgs.errVariableDeclMissingType(
catchSrc.getFaultVariable()).setSource(catchSrc));
OVarType faultVarType;
if (catchSrc.getFaultVariableMessageType() != null)
faultVarType = resolveMessageType(catchSrc.getFaultVariableMessageType());
else if (catchSrc.getFaultVariableElementType() != null)
faultVarType = resolveElementType(catchSrc.getFaultVariableElementType());
else
throw new CompilationException(__cmsgs.errUnrecognizedVariableDeclaration(catchSrc
.getFaultVariable()));
faultVar = new OScope.Variable(_oprocess, faultVarType);
faultVar.setName(catchSrc.getFaultVariable());
faultVar.setDeclaringScope(_structureStack.topScope());
ctch.addLocalVariable(faultVar);
break;
default:
throw new AssertionError("Unexpected BPEL VERSION constatnt: " + _processDef.getBpelVersion());
}
ctch.setFaultVariable(faultVar);
}
if (catchSrc.getActivity() == null)
throw new CompilationException(__cmsgs.errEmptyCatch().setSource(catchSrc));
_structureStack.topScope().setActivity(compile(catchSrc.getActivity()));
}
});
oscope.getFaultHandler().getCatchBlocks().add(ctch);
++i;
}
} finally {
_recoveryContextStack.pop();
}
}
}
public OXslSheet compileXslt(String docStrUri) throws CompilationException {
URI docUri;
try {
docUri = new URI(FileUtils.encodePath(docStrUri));
} catch (URISyntaxException e) {
throw new CompilationException(__cmsgs.errInvalidDocXsltUri(docStrUri));
}
String sheetBody = loadXsltSheet(_processURI.resolve(docUri));
if (sheetBody == null) {
throw new CompilationException(__cmsgs.errCantFindXslt(docStrUri));
}
OXslSheet oXslSheet = new OXslSheet(_oprocess);
oXslSheet.setUri(docUri);
oXslSheet.setSheetBody(sheetBody);
_oprocess.getXslSheets().put(oXslSheet.getUri(), oXslSheet);
return oXslSheet;
}
private String loadXsltSheet(URI uri) {
// TODO: lots of null returns, should have some better error messages.
InputStream is;
try {
is = _resourceFinder.openResource(uri);
} catch (Exception e1) {
return null;
}
if (is == null)
return null;
try {
// verify that sheet is well-formed and preserve encoding.
Document doc = DOMUtils.parse(is);
return DOMUtils.domToString(doc);
} catch (Exception e) {
__log.debug("IO error", e);
// todo: this should produce a message
return null;
} finally {
try {
is.close();
} catch (Exception ex) {
// No worries.
}
}
}
public boolean isPartnerLinkAssigned(String plink) {
for (OActivity act : _compiledActivities) {
if (act instanceof OAssign) {
OAssign assign = (OAssign) act;
for (OAssign.Copy copy : assign.getCopy()) {
if (copy.getTo() instanceof OAssign.PartnerLinkRef) {
if (((OAssign.PartnerLinkRef) copy.getTo()).getPartnerLink().getName().equals(plink))
return true;
}
}
}
}
return false;
}
public Definition[] getWsdlDefinitions() {
Definition[] result = new Definition[_wsdlRegistry.getDefinitions().length];
for (int m = 0; m < _wsdlRegistry.getDefinitions().length; m++) {
Definition4BPEL definition4BPEL = _wsdlRegistry.getDefinitions()[m];
result[m] = definition4BPEL.getDefinition();
}
return result;
}
private OElementVarType resolveElementType(QName faultVariableElementType) {
OElementVarType type = _oprocess.getElementTypes().get(faultVariableElementType);
if (type == null) {
type = new OElementVarType(_oprocess, faultVariableElementType);
_oprocess.getElementTypes().put(faultVariableElementType, type);
}
return type;
}
@SuppressWarnings("unchecked")
private ActivityGenerator findActivityGen(Activity source) {
Class actClass = source.getClass();
for (Map.Entry<Class, ActivityGenerator> me : _actGenerators.entrySet()) {
Class<?> cls = me.getKey();
if (cls.isAssignableFrom(actClass)) {
ActivityGenerator gen = me.getValue();
gen.setContext(this);
return gen;
}
}
throw new CompilationException(__cmsgs.errUnknownActivity(actClass.getName()).setSource(source));
}
@SuppressWarnings("unchecked")
protected void registerActivityCompiler(Class defClass, ActivityGenerator generator) {
if (__log.isDebugEnabled()) {
__log.debug("Adding compiler for nodes class \"" + defClass.getName() + " = " + generator);
}
_actGenerators.put(defClass, generator);
}
private ExpressionCompiler findExpLangCompiler(String expLang) {
ExpressionCompiler compiler = _expLanguageCompilers.get(expLang);
if (compiler == null) {
throw new CompilationException(__cmsgs.errUnknownExpressionLanguage(expLang));
}
return compiler;
}
private String getExpressionLanguage(Expression exp) {
String expLang = exp.getExpressionLanguage();
if (expLang == null)
expLang = _processDef.getExpressionLanguage();
if (expLang == null)
expLang = getDefaultExpressionLanguage();
return expLang;
}
protected abstract String getDefaultExpressionLanguage();
protected abstract String getBpwsNamespace();
protected void registerExpressionLanguage(String expLangUri, ExpressionCompiler expressionCompiler) {
_expLanguageCompilers.put(expLangUri, expressionCompiler);
}
@SuppressWarnings("unchecked")
protected void registerExpressionLanguage(String expLangUri, String classname) throws Exception {
Class cls = Class.forName(classname);
registerExpressionLanguage(expLangUri, (ExpressionCompiler) cls.newInstance());
}
public List<OActivity> getActivityStack() {
ArrayList<OActivity> rval = new ArrayList<OActivity>(_structureStack._stack);
Collections.reverse(rval);
return rval;
}
public Map<URI, Source> getSchemaSources() {
return _wsdlRegistry.getSchemaSources();
}
/**
* Retrieves the base URI that the BPEL Process execution contextis running relative to.
*
* @return URI - the URI representing the absolute physical file path location that this process is defined within.
* @throws IOException
* @throws MalformedURLException
*/
public URI getBaseResourceURI() {
return _resourceFinder.getBaseResourceURI();
}
public NSContext tryCacheNamespaceContext(NSContext nsContext) {
if (getOProcess().getNamespaceContext().equals(nsContext)) {
return getOProcess().getNamespaceContext();
} else {
return nsContext;
}
}
/**
* Compile external variable declaration.
* @param src variable object
* @return compiled {@link OExtVar} representation.
*/
private OExtVar compileExtVar(Variable src) {
if (!src.isExternal())
return null;
OExtVar oextvar = new OExtVar(_oprocess);
oextvar.setExternalVariableId(src.getExternalId());
oextvar.setDebugInfo(createDebugInfo(src, null));
if (src.getExternalId() == null)
throw new CompilationException(__cmsgs.errMustSpecifyExternalVariableId(src.getName()));
if (src.getRelated() == null)
throw new CompilationException(__cmsgs.errMustSpecifyRelatedVariable(src.getName()));
oextvar.setRelated(resolveVariable(src.getRelated()));
return oextvar;
}
private static class StructureStack {
private Stack<OActivity> _stack = new Stack<OActivity>();
private Map<OActivity,BpelObject> _srcMap = new HashMap<OActivity,BpelObject>();
public void push(OActivity act, BpelObject src) {
_stack.push(act);
_srcMap.put(act, src);
}
public BpelObject topSource() {
return _srcMap.get(topActivity());
}
public OScope topScope() {
List<OScope> scopeStack = scopeStack();
return scopeStack.isEmpty() ? null : scopeStack.get(scopeStack.size() - 1);
}
public OScope rootScope() {
for (OActivity oActivity : _stack)
if (oActivity instanceof OScope)
return (OScope) oActivity;
return null;
}
public OActivity pop() {
return _stack.pop();
}
public void clear() {
_stack.clear();
}
public int size() {
return _stack.size();
}
public Iterator<OScope> oscopeIterator() {
List<OScope> scopeStack = scopeStack();
Collections.reverse(scopeStack);
return scopeStack.iterator();
}
private List<OScope> scopeStack() {
ArrayList<OScope> newList = new ArrayList<OScope>();
CollectionsX.filter(newList, _stack.iterator(), OScope.class);
return newList;
}
public OActivity topActivity() {
return _stack.isEmpty() ? null : _stack.peek();
}
public Iterator<OActivity> iterator() {
ArrayList<OActivity> rval = new ArrayList<OActivity>(_stack);
Collections.reverse(rval);
return rval.iterator();
}
}
}