/** * Copyright 2010 JBoss Inc * * 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. */ package org.drools.bpel.compiler; import java.io.ByteArrayInputStream; import java.net.URL; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.ode.bpel.compiler.bom.Activity; import org.apache.ode.bpel.compiler.bom.AssignActivity; import org.apache.ode.bpel.compiler.bom.BpelObjectFactory; import org.apache.ode.bpel.compiler.bom.Catch; import org.apache.ode.bpel.compiler.bom.Copy; import org.apache.ode.bpel.compiler.bom.EmptyActivity; import org.apache.ode.bpel.compiler.bom.FlowActivity; import org.apache.ode.bpel.compiler.bom.From; import org.apache.ode.bpel.compiler.bom.IfActivity; import org.apache.ode.bpel.compiler.bom.InvokeActivity; import org.apache.ode.bpel.compiler.bom.Link; 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.OnMessage; import org.apache.ode.bpel.compiler.bom.PickActivity; import org.apache.ode.bpel.compiler.bom.Process; import org.apache.ode.bpel.compiler.bom.ReceiveActivity; import org.apache.ode.bpel.compiler.bom.RepeatUntilActivity; import org.apache.ode.bpel.compiler.bom.ReplyActivity; import org.apache.ode.bpel.compiler.bom.RethrowActivity; import org.apache.ode.bpel.compiler.bom.ScopeActivity; import org.apache.ode.bpel.compiler.bom.SequenceActivity; import org.apache.ode.bpel.compiler.bom.SwitchActivity; import org.apache.ode.bpel.compiler.bom.TerminateActivity; import org.apache.ode.bpel.compiler.bom.ThrowActivity; import org.apache.ode.bpel.compiler.bom.To; import org.apache.ode.bpel.compiler.bom.WaitActivity; import org.apache.ode.bpel.compiler.bom.WhileActivity; import org.apache.ode.utils.DOMUtils; import org.apache.ode.utils.StreamUtils; import org.drools.RuleBase; import org.drools.bpel.core.BPELActivity; import org.drools.bpel.core.BPELAssign; import org.drools.bpel.core.BPELEmpty; import org.drools.bpel.core.BPELExit; import org.drools.bpel.core.BPELFaultHandler; import org.drools.bpel.core.BPELFlow; import org.drools.bpel.core.BPELIf; import org.drools.bpel.core.BPELInvoke; import org.drools.bpel.core.BPELPick; import org.drools.bpel.core.BPELProcess; import org.drools.bpel.core.BPELReceive; import org.drools.bpel.core.BPELRepeatUntil; import org.drools.bpel.core.BPELReply; import org.drools.bpel.core.BPELRethrow; import org.drools.bpel.core.BPELScope; import org.drools.bpel.core.BPELSequence; import org.drools.bpel.core.BPELThrow; import org.drools.bpel.core.BPELWait; import org.drools.bpel.core.BPELWhile; import org.drools.bpel.core.BPELActivity.SourceLink; import org.drools.bpel.core.BPELActivity.TargetLink; import org.drools.bpel.xpath.XMLDataType; import org.drools.bpel.xpath.XPathDialectConfiguration; import org.drools.common.AbstractRuleBase; import org.drools.compiler.DroolsError; import org.drools.compiler.PackageBuilder; import org.drools.compiler.PackageBuilderConfiguration; import org.drools.compiler.ProcessBuilder; import org.drools.io.ResourceFactory; import org.drools.process.core.context.variable.Variable; import org.drools.process.core.context.variable.VariableScope; import org.drools.process.core.datatype.DataType; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; public class BPELCompiler { public void loadProcess(RuleBase ruleBase, String fileName) { try { BPELCompiler compiler = new BPELCompiler(); BPELProcess process = compiler.compileProcess( BPELCompiler.class.getResource(fileName)); PackageBuilderConfiguration configuration = new PackageBuilderConfiguration(); configuration.addDialect("XPath2.0", new XPathDialectConfiguration()); PackageBuilder packageBuilder = new PackageBuilder(configuration); ProcessBuilder processBuilder = new ProcessBuilder(packageBuilder); processBuilder.buildProcess(process, ResourceFactory.newClassPathResource(fileName)); if (!processBuilder.getErrors().isEmpty()) { for (DroolsError error: processBuilder.getErrors()) { System.err.println(error); } throw new IllegalArgumentException("Could not build process " + fileName); } ((AbstractRuleBase) ruleBase).addProcess(process); } catch (Throwable t) { throw new IllegalArgumentException("Could not load process " + fileName, t); } } public BPELProcess compileProcess(URL bpelFile) throws Exception { InputSource isrc = new InputSource(new ByteArrayInputStream(StreamUtils.read(bpelFile))); Process process = BpelObjectFactory.getInstance().parse(isrc, bpelFile.toURI()); return compileProcess(process); } private BPELProcess compileProcess(Process process) { BPELProcess result = new BPELProcess(); result.setName(process.getName()); result.setId(process.getTargetNamespace()); result.setPackageName("org.drools.bpel"); result.setVersion("1.0"); result.setNamespaceContext(process.getNamespaceContext()); BPELActivity activity = compileActivity(process.getRootActivity()); result.setActivity(activity); // variables VariableScope variableScope = result.getVariableScope(); List<Variable> variables = new ArrayList<Variable>(); for (org.apache.ode.bpel.compiler.bom.Variable variable: process.getVariables()) { Variable bpelVariable = new Variable(); bpelVariable.setName(variable.getName()); bpelVariable.setType(getDataType(variable.getTypeName().toString())); variables.add(bpelVariable); } variableScope.setVariables(variables); // fault handlers if (process.getFaultHandler() != null) { List<BPELFaultHandler> faultHandlers = new ArrayList<BPELFaultHandler>(); for (Catch catcher: process.getFaultHandler().getCatches()) { BPELFaultHandler faultHandler = new BPELFaultHandler(); faultHandler.setFaultName( catcher.getFaultName() == null ? null : catcher.getFaultName().toString()); faultHandler.setFaultVariable(catcher.getFaultVariable()); faultHandler.setActivity(compileActivity(catcher.getActivity())); faultHandlers.add(faultHandler); } result.setFaultHandlers(faultHandlers); } return result; } private BPELActivity compileActivity(Activity activity) { BPELActivity result = null; if (activity instanceof ReceiveActivity) { ReceiveActivity receiveActivity = (ReceiveActivity) activity; BPELReceive receive = new BPELReceive(); receive.setCreateInstance(receiveActivity.isCreateInstance()); receive.setOperation( receiveActivity.getPartnerLink(), receiveActivity.getPortType().toString(), receiveActivity.getOperation()); receive.setVariable(receiveActivity.getVariable()); result = receive; } else if (activity instanceof ReplyActivity) { ReplyActivity replyActivity = (ReplyActivity) activity; BPELReply reply = new BPELReply(); reply.setPartnerLink(replyActivity.getPartnerLink()); reply.setPortType(replyActivity.getPortType().toString()); reply.setOperation(replyActivity.getOperation()); reply.setVariable(replyActivity.getVariable()); if (replyActivity.getFaultName() != null) { reply.setFaultName(replyActivity.getFaultName().toString()); } result = reply; } else if (activity instanceof InvokeActivity) { InvokeActivity invokeActivity = (InvokeActivity) activity; BPELInvoke invoke = new BPELInvoke(); invoke.setPartnerLink(invokeActivity.getPartnerLink()); invoke.setPortType(invokeActivity.getPortType().toString()); invoke.setOperation(invokeActivity.getOperation()); invoke.setInputVariable(invokeActivity.getInputVar()); if (invokeActivity.getOutputVar() != null) { invoke.setOutputVariable(invokeActivity.getOutputVar()); } result = invoke; } else if (activity instanceof SequenceActivity) { SequenceActivity sequenceActivity = (SequenceActivity) activity; BPELSequence sequence = new BPELSequence(); List<BPELActivity> subActivities = new ArrayList<BPELActivity>(); for (Activity subActivity: sequenceActivity.getActivities()) { subActivities.add(compileActivity(subActivity)); } sequence.setActivities(subActivities); result = sequence; } else if (activity instanceof FlowActivity) { FlowActivity flowActivity = (FlowActivity) activity; BPELFlow flow = new BPELFlow(); List<BPELActivity> subActivities = new ArrayList<BPELActivity>(); for (Activity subActivity: flowActivity.getActivities()) { subActivities.add(compileActivity(subActivity)); } flow.setActivities(subActivities); String[] links = new String[flowActivity.getLinks().size()]; int i = 0; for (Link link: flowActivity.getLinks()) { links[i++] = link.getLinkName(); } flow.setLinks(links); result = flow; } else if (activity instanceof AssignActivity) { AssignActivity assignActivity = (AssignActivity) activity; BPELAssign assign = new BPELAssign(); for (Copy copy: assignActivity.getCopies()) { BPELAssign.Copy bpelCopy = assign.new Copy(); From from = copy.getFrom(); To to = copy.getTo(); if (from.isVariableVal()) { BPELAssign.VariableRef bpelFrom = assign.new VariableRef( from.getAsVariableVal().getVariable(), from.getAsVariableVal().getPart(), from.getAsVariableVal().getHeader(), from.getAsVariableVal().getLocation() == null ? null : from.getAsVariableVal().getLocation().toString()); bpelCopy.setFrom(bpelFrom); } else if (from.isLiteralVal()) { Element literal = from.getAsLiteralVal().getLiteral(); org.w3c.dom.Node child = literal.getFirstChild(); if (child.getNodeType() == org.w3c.dom.Node.TEXT_NODE && "".equals(child.getTextContent().trim())) { child = child.getNextSibling(); } BPELAssign.Literal bpelFrom = assign.new Literal(DOMUtils.domToString(child)); bpelCopy.setFrom(bpelFrom); } else { BPELAssign.Expression bpelFrom = assign.new Expression(from.getAsExpression().toString()); bpelCopy.setFrom(bpelFrom); } if (to.isVariableVal()) { BPELAssign.VariableRef bpelTo = assign.new VariableRef( to.getAsVariableVal().getVariable(), to.getAsVariableVal().getPart(), to.getAsVariableVal().getHeader(), to.getAsVariableVal().getLocation() == null ? null : to.getAsVariableVal().getLocation().toString()); bpelCopy.setTo(bpelTo); } else { String expression = to.getAsExpression().toString(); try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document document = factory.newDocumentBuilder().parse(new ByteArrayInputStream(expression.getBytes())); expression = DOMUtils.domToString(document.getFirstChild().getFirstChild()); String varName; String partName; int dotloc = expression.indexOf('.'); if (dotloc == -1) { varName = expression; partName = null; } else { varName = expression.substring(1, dotloc); partName = expression.substring(dotloc + 1); } BPELAssign.VariableRef bpelTo = assign.new VariableRef(varName, partName, null, null); bpelCopy.setTo(bpelTo); } catch (Throwable t) { throw new IllegalArgumentException( "Could not parse expression " + expression, t); } } assign.addCopy(bpelCopy); } result = assign; } else if (activity instanceof EmptyActivity) { result = new BPELEmpty(); } else if (activity instanceof ThrowActivity) { ThrowActivity throwActivity = (ThrowActivity) activity; BPELThrow bpelThrow = new BPELThrow(); bpelThrow.setFaultName(throwActivity.getFaultName().toString()); bpelThrow.setFaultVariable(throwActivity.getFaultVariable()); result = bpelThrow; } else if (activity instanceof RethrowActivity) { result = new BPELRethrow(); } else if (activity instanceof PickActivity) { PickActivity pickActivity = (PickActivity) activity; BPELPick pick = new BPELPick(); pick.setCreateInstance(pickActivity.isCreateInstance()); for (OnMessage onMessage: pickActivity.getOnMessages()) { BPELPick.OnMessage bpelOnMessage = pick.new OnMessage(); bpelOnMessage.setPartnerLink(onMessage.getPartnerLink()); bpelOnMessage.setPortType(onMessage.getPortType().toString()); bpelOnMessage.setOperation(onMessage.getOperation()); bpelOnMessage.setVariable(onMessage.getVariable()); bpelOnMessage.setActivity(compileActivity(onMessage.getActivity())); pick.addOnMessage(bpelOnMessage); } for (OnAlarm onAlarm: pickActivity.getOnAlarms()) { BPELPick.OnAlarm bpelOnAlarm = pick.new OnAlarm(); if (onAlarm.getFor() != null) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document document = factory.newDocumentBuilder().parse(new ByteArrayInputStream(onAlarm.getFor().toString().getBytes())); String expression = DOMUtils.domToString(document.getFirstChild().getFirstChild()); bpelOnAlarm.setForExpression(expression); } catch (Throwable t) { throw new IllegalArgumentException( "Could not parse for expression", t); } } if (onAlarm.getUntil() != null) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document document = factory.newDocumentBuilder().parse(new ByteArrayInputStream(onAlarm.getUntil().toString().getBytes())); String expression = DOMUtils.domToString(document.getFirstChild().getFirstChild()); bpelOnAlarm.setUntilExpression(expression); } catch (Throwable t) { throw new IllegalArgumentException( "Could not parse for expression", t); } } bpelOnAlarm.setActivity(compileActivity(onAlarm.getActivity())); pick.addOnAlarm(bpelOnAlarm); } result = pick; } else if (activity instanceof ScopeActivity) { ScopeActivity scopeActivity = (ScopeActivity) activity; BPELScope scope = new BPELScope(); VariableScope variableScope = scope.getVariableScope(); List<Variable> variables = new ArrayList<Variable>(); for (org.apache.ode.bpel.compiler.bom.Variable variable: scopeActivity.getScope().getVariables()) { Variable bpelVariable = new Variable(); bpelVariable.setName(variable.getName()); bpelVariable.setType(getDataType(variable.getTypeName().toString())); variables.add(bpelVariable); } variableScope.setVariables(variables); List<BPELFaultHandler> faultHandlers = new ArrayList<BPELFaultHandler>(); if (scopeActivity.getScope().getFaultHandler() != null) { for (Catch catcher: scopeActivity.getScope().getFaultHandler().getCatches()) { BPELFaultHandler faultHandler = new BPELFaultHandler(); faultHandler.setFaultName( catcher.getFaultName() == null ? null : catcher.getFaultName().toString()); faultHandler.setFaultVariable(catcher.getFaultVariable()); faultHandler.setActivity(compileActivity(catcher.getActivity())); faultHandlers.add(faultHandler); } scope.setFaultHandlers(faultHandlers); } scope.setActivity(compileActivity(scopeActivity.getChildActivity())); result = scope; } else if (activity instanceof SwitchActivity) { SwitchActivity switchActivity = (SwitchActivity) activity; BPELIf bpelSwitch = new BPELIf(); for (SwitchActivity.Case bpelCase: switchActivity.getCases()) { bpelSwitch.addCase(bpelCase.getCondition().toString(), compileActivity(bpelCase.getActivity())); } result = bpelSwitch; } else if (activity instanceof IfActivity) { IfActivity ifActivity = (IfActivity) activity; BPELIf bpelSwitch = new BPELIf(); bpelSwitch.addCase(ifActivity.getCondition().toString(), compileActivity(ifActivity.getActivity())); for (IfActivity.Case bpelCase: ifActivity.getCases()) { bpelSwitch.addCase( bpelCase.getCondition() == null ? null : bpelCase.getCondition().toString(), compileActivity(bpelCase.getActivity())); } result = bpelSwitch; } else if (activity instanceof WaitActivity) { WaitActivity waitActivity = (WaitActivity) activity; BPELWait wait = new BPELWait(); if (waitActivity.getFor() != null) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document document = factory.newDocumentBuilder().parse(new ByteArrayInputStream(waitActivity.getFor().toString().getBytes())); String expression = DOMUtils.domToString(document.getFirstChild().getFirstChild()); wait.setForExpression(expression); } catch (Throwable t) { throw new IllegalArgumentException( "Could not parse for expression", t); } } if (waitActivity.getUntil() != null) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document document = factory.newDocumentBuilder().parse(new ByteArrayInputStream(waitActivity.getUntil().toString().getBytes())); String expression = DOMUtils.domToString(document.getFirstChild().getFirstChild()); wait.setUntilExpression(expression); } catch (Throwable t) { throw new IllegalArgumentException( "Could not parse for expression", t); } } result = wait; } else if (activity instanceof WhileActivity) { WhileActivity whileActivity = (WhileActivity) activity; BPELWhile bpelWhile = new BPELWhile(); bpelWhile.setActivity( whileActivity.getCondition().toString(), compileActivity(whileActivity.getActivity())); result = bpelWhile; } else if (activity instanceof RepeatUntilActivity) { RepeatUntilActivity repeatUntilActivity = (RepeatUntilActivity) activity; BPELRepeatUntil bpelRepeatUntil = new BPELRepeatUntil(); bpelRepeatUntil.setActivity(compileActivity(repeatUntilActivity.getActivity())); bpelRepeatUntil.setCondition(repeatUntilActivity.getCondition().toString()); result = bpelRepeatUntil; } else if (activity instanceof TerminateActivity) { result = new BPELExit(); } else { // TODO: compensate // BPEL2.0: ForEach, CompensateScope, Rethrow, Validate throw new IllegalArgumentException("Unknown activity type " + activity.getClass()); } result.setName(activity.getName()); SourceLink[] sourceLinks = new SourceLink[activity.getLinkSources().size()]; int i = 0; for (LinkSource linkSource: activity.getLinkSources()) { sourceLinks[i] = new SourceLink(linkSource.getLinkName()); if (linkSource.getTransitionCondition() != null) { sourceLinks[i].setTransitionCondition(linkSource.getTransitionCondition().getTextValue()); } i++; } if (sourceLinks.length > 0) { result.setSourceLinks(sourceLinks); } TargetLink[] targetLinks = new TargetLink[activity.getLinkTargets().size()]; i = 0; for (LinkTarget linkTarget: activity.getLinkTargets()) { targetLinks[i++] = new TargetLink(linkTarget.getLinkName()); } if (targetLinks.length > 0) { result.setTargetLinks(targetLinks); } return result; } private DataType getDataType(String typeName) { return new XMLDataType(typeName); } }