From cddf5ac2ab3345f5f218f6f3a0f716eeccc5d74c Mon Sep 17 00:00:00 2001 From: David Caruana Date: Fri, 11 Aug 2006 18:01:56 +0000 Subject: [PATCH] First cut of hooking Alfresco JavaScript into jBPM process definition. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3486 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../repo/jscript/RhinoScriptService.java | 9 +- .../workflow/jbpm/AlfrescoJavaScript.java | 211 ++++++++++++++++++ .../repo/workflow/jbpm/JBPMEngineTest.java | 21 +- .../workflow/jbpm/test_processdefinition.xml | 21 +- 4 files changed, 256 insertions(+), 6 deletions(-) create mode 100644 source/java/org/alfresco/repo/workflow/jbpm/AlfrescoJavaScript.java diff --git a/source/java/org/alfresco/repo/jscript/RhinoScriptService.java b/source/java/org/alfresco/repo/jscript/RhinoScriptService.java index 3db17e597c..11d6ede4fc 100644 --- a/source/java/org/alfresco/repo/jscript/RhinoScriptService.java +++ b/source/java/org/alfresco/repo/jscript/RhinoScriptService.java @@ -38,6 +38,7 @@ import org.alfresco.service.namespace.QName; import org.apache.log4j.Logger; import org.mozilla.javascript.Context; import org.mozilla.javascript.ImporterTopLevel; +import org.mozilla.javascript.NativeJavaObject; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; @@ -252,6 +253,12 @@ public class RhinoScriptService implements ScriptService // execute the script Object result = cx.evaluateReader(scope, reader, "AlfrescoScript", 1, null); + // extract java object result if wrapped by rhinoscript + if (result != null && result.getClass().equals(NativeJavaObject.class)) + { + result = Context.jsToJava(result, Object.class); + } + return result; } catch (Throwable err) @@ -260,7 +267,7 @@ public class RhinoScriptService implements ScriptService } finally { - cx.exit(); + Context.exit(); if (logger.isDebugEnabled()) { diff --git a/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoJavaScript.java b/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoJavaScript.java new file mode 100644 index 0000000000..d3a40d7435 --- /dev/null +++ b/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoJavaScript.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * 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.alfresco.repo.workflow.jbpm; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.ScriptService; +import org.dom4j.Element; +import org.jbpm.context.def.VariableAccess; +import org.jbpm.context.exe.ContextInstance; +import org.jbpm.graph.exe.ExecutionContext; +import org.jbpm.graph.exe.Token; +import org.jbpm.jpdl.xml.JpdlXmlReader; +import org.springframework.beans.factory.BeanFactory; +import org.xml.sax.InputSource; + +/** + * A jBPM Action Handler for executing Alfresco Script + * + * The configuration of this action is as follows: + * + * + * It's exactly the same as jBPM's own script configuration. + * + * @author davidc + */ +public class AlfrescoJavaScript extends JBPMSpringActionHandler +{ + private static final long serialVersionUID = -2908748080671212745L; + + private static JpdlXmlReader jpdlReader = new JpdlXmlReader((InputSource)null); + private ScriptService scriptService; + private Element script; + + + /* (non-Javadoc) + * @see org.alfresco.repo.workflow.jbpm.JBPMSpringActionHandler#initialiseHandler(org.springframework.beans.factory.BeanFactory) + */ + @Override + protected void initialiseHandler(BeanFactory factory) + { + scriptService = (ScriptService)factory.getBean(ServiceRegistry.SCRIPT_SERVICE.getLocalName()); + } + + + /* (non-Javadoc) + * @see org.jbpm.graph.def.ActionHandler#execute(org.jbpm.graph.exe.ExecutionContext) + */ + @SuppressWarnings("unchecked") + public void execute(ExecutionContext executionContext) throws Exception + { + // extract action configuration + String expression = null; + List variableAccesses = null; + if (script.isTextOnly()) + { + expression = script.getTextTrim(); + } + else + { + variableAccesses = jpdlReader.readVariableAccesses(script); + expression = script.element("expression").getTextTrim(); + } + + // construct script arguments and execute + Map inputMap = createInputMap(executionContext, variableAccesses); + Object result = scriptService.executeScriptString(expression, inputMap); + + // map script return variable to process context + VariableAccess returnVariable = getWritableVariable(variableAccesses); + if (returnVariable != null) + { + ContextInstance contextInstance = executionContext.getContextInstance(); + Token token = executionContext.getToken(); + contextInstance.setVariable(returnVariable.getVariableName(), result, token); + } + } + + + /** + * Construct map of arguments to pass to script + * + * Based on the elements of the action configuration. + * + * @param executionContext the execution context + * @param variableAccesses the variable configuration + * @return the map of script arguments + */ + @SuppressWarnings("unchecked") + public Map createInputMap(ExecutionContext executionContext, List variableAccesses) + { + Map inputMap = new HashMap(); + + // initialise process variables + Token token = executionContext.getToken(); + inputMap.put("executionContext", executionContext); + inputMap.put("token", token); + if (executionContext.getNode() != null) + { + inputMap.put("node", executionContext.getNode()); + } + if (executionContext.getTask() != null) + { + inputMap.put("task", executionContext.getTask()); + } + if (executionContext.getTaskInstance() != null) + { + inputMap.put("taskInstance", executionContext.getTaskInstance()); + } + + // if no readable variableInstances are specified, + ContextInstance contextInstance = executionContext.getContextInstance(); + if (!hasReadableVariable(variableAccesses)) + { + // copy all the variableInstances of the context into the interpreter + Map variables = contextInstance.getVariables(token); + if (variables != null) + { + for (Map.Entry entry : variables.entrySet()) + { + String variableName = (String) entry.getKey(); + Object variableValue = entry.getValue(); + inputMap.put(variableName, variableValue); + } + } + } + else + { + // copy the specified variableInstances into the interpreterz + for (VariableAccess variableAccess : variableAccesses) + { + if (variableAccess.isReadable()) + { + String variableName = variableAccess.getVariableName(); + String mappedName = variableAccess.getMappedName(); + Object variableValue = contextInstance.getVariable(variableName, token); + inputMap.put(mappedName, variableValue); + } + } + } + + return inputMap; + } + + + /** + * Determine if there are variables to read from the process context + * + * @param variableAccesses the variables configuration + * @return true => there are variables to read + */ + private boolean hasReadableVariable(List variableAccesses) + { + if (variableAccesses != null) + { + for (VariableAccess variableAccess : variableAccesses) + { + if (variableAccess.isReadable()) + { + return true; + } + } + } + return false; + } + + + /** + * Determine if there is a variable to write back to the process context + * + * @param variableAccesses the variables configuration + * @return true => there is a variable to write + */ + private VariableAccess getWritableVariable(List variableAccesses) + { + if (variableAccesses != null) + { + for (VariableAccess variableAccess : variableAccesses) + { + if (variableAccess.isWritable()) + { + return variableAccess; + } + } + } + return null; + } + +} diff --git a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngineTest.java b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngineTest.java index d17a4b7e09..bd6c0209f7 100644 --- a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngineTest.java +++ b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngineTest.java @@ -59,7 +59,7 @@ public class JBPMEngineTest extends BaseSpringTest WorkflowDefinition testWorkflowDef; NodeRef testNodeRef; - + //@Override protected void onSetUpInTransaction() throws Exception { @@ -308,6 +308,7 @@ public class JBPMEngineTest extends BaseSpringTest WorkflowDefinition workflowDef = getTestDefinition(); Map parameters = new HashMap(); parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), "admin"); + parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef); WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters); assertNotNull(path); assertNotNull(path); @@ -331,6 +332,7 @@ public class JBPMEngineTest extends BaseSpringTest WorkflowDefinition workflowDef = getTestDefinition(); Map parameters = new HashMap(); parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), "admin"); + parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef); WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters); assertNotNull(path); assertNotNull(path); @@ -359,7 +361,22 @@ public class JBPMEngineTest extends BaseSpringTest assertEquals(WorkflowTaskState.IN_PROGRESS, tasks1.get(0).state); WorkflowTask updatedTask = taskComponent.endTask(tasks1.get(0).id, null); assertNotNull(updatedTask); - assertEquals(WorkflowTaskState.COMPLETED, updatedTask.state); + } + + + public void testScript() + { + WorkflowDefinition workflowDef = getTestDefinition(); + Map parameters = new HashMap(); + parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), "admin"); + parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef); + WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters); + assertNotNull(path); + List tasks1 = workflowComponent.getTasksForWorkflowPath(path.id); + assertNotNull(tasks1); + assertEquals(1, tasks1.size()); + WorkflowTask updatedTask = taskComponent.endTask(tasks1.get(0).id, path.node.transitions[0]); + assertNotNull(updatedTask); } diff --git a/source/java/org/alfresco/repo/workflow/jbpm/test_processdefinition.xml b/source/java/org/alfresco/repo/workflow/jbpm/test_processdefinition.xml index e41d513b34..65056d5e30 100644 --- a/source/java/org/alfresco/repo/workflow/jbpm/test_processdefinition.xml +++ b/source/java/org/alfresco/repo/workflow/jbpm/test_processdefinition.xml @@ -9,8 +9,22 @@ - - + + + + + + + @@ -20,6 +34,7 @@ @@ -27,7 +42,7 @@ - + \ No newline at end of file