diff --git a/config/alfresco/core-services-context.xml b/config/alfresco/core-services-context.xml index f381a269c1..57175cdbd3 100644 --- a/config/alfresco/core-services-context.xml +++ b/config/alfresco/core-services-context.xml @@ -549,17 +549,22 @@ + alfresco/model/dictionaryModel.xml alfresco/model/systemModel.xml + org/alfresco/repo/security/authentication/userModel.xml + + alfresco/model/contentModel.xml alfresco/model/bpmModel.xml alfresco/model/wcmModel.xml + alfresco/model/forumModel.xml + + alfresco/model/applicationModel.xml alfresco/model/wcmAppModel.xml - alfresco/model/forumModel.xml - org/alfresco/repo/security/authentication/userModel.xml org/alfresco/repo/action/actionModel.xml org/alfresco/repo/rule/ruleModel.xml org/alfresco/repo/version/version_model.xml diff --git a/config/alfresco/messages/workflow-interpreter-help.txt b/config/alfresco/messages/workflow-interpreter-help.txt index dd66a44977..23712969a3 100644 --- a/config/alfresco/messages/workflow-interpreter-help.txt +++ b/config/alfresco/messages/workflow-interpreter-help.txt @@ -91,6 +91,18 @@ ok> var [*] person var bpm:assignee* person admin,fred +ok> var [*] group + + Define or update a (usr:authorityContainer) node ref variable. + + variable name + [*] if specified, define a collection + variable value (comma-seperate to specify a list of values) + + e.g. + + var bpm:groupAssignee group GROUP_Engineering + ok> var package Define or update a (bpm:workflowPackage) node ref variable. diff --git a/config/alfresco/model/bpmModel.xml b/config/alfresco/model/bpmModel.xml index d88eaf5a7e..98e30814de 100644 --- a/config/alfresco/model/bpmModel.xml +++ b/config/alfresco/model/bpmModel.xml @@ -12,6 +12,8 @@ + + @@ -310,6 +312,29 @@ + + + + + + + + + + false + false + + + + usr:authorityContainer + true + false + + + + + + diff --git a/config/alfresco/script-services-context.xml b/config/alfresco/script-services-context.xml index 6e76da9bfe..97978a58ca 100644 --- a/config/alfresco/script-services-context.xml +++ b/config/alfresco/script-services-context.xml @@ -70,6 +70,9 @@ + + + diff --git a/config/alfresco/workflow-context.xml b/config/alfresco/workflow-context.xml index 641750714b..d6bbad2982 100644 --- a/config/alfresco/workflow-context.xml +++ b/config/alfresco/workflow-context.xml @@ -34,6 +34,8 @@ + + @@ -87,6 +89,8 @@ + + ${spaces.store} /${spaces.company_home.childname} diff --git a/config/alfresco/workflow/submit_processdefinition.xml b/config/alfresco/workflow/submit_processdefinition.xml index e94c292b9e..b5f8057c5b 100644 --- a/config/alfresco/workflow/submit_processdefinition.xml +++ b/config/alfresco/workflow/submit_processdefinition.xml @@ -56,7 +56,7 @@ - #{bpm_assignees[wcmwf_approveCnt]} + #{bpm_assignees.get(wcmwf_approveCnt)} diff --git a/config/alfresco/workflow/workflowModel.xml b/config/alfresco/workflow/workflowModel.xml index f946336b1c..fee647d2ac 100644 --- a/config/alfresco/workflow/workflowModel.xml +++ b/config/alfresco/workflow/workflowModel.xml @@ -24,6 +24,13 @@ + + bpm:startTask + + bpm:groupAssignee + + + bpm:startTask diff --git a/source/java/org/alfresco/repo/jscript/People.java b/source/java/org/alfresco/repo/jscript/People.java index cd4ae29534..f212abdc29 100644 --- a/source/java/org/alfresco/repo/jscript/People.java +++ b/source/java/org/alfresco/repo/jscript/People.java @@ -16,8 +16,14 @@ */ package org.alfresco.repo.jscript; +import java.util.Set; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.security.authority.AuthorityDAO; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.AuthorityService; +import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.security.PersonService; import org.mozilla.javascript.Scriptable; @@ -30,6 +36,7 @@ public final class People extends BaseScriptImplementation implements Scopeable { /** Repository Service Registry */ private ServiceRegistry services; + private AuthorityDAO authorityDAO; /** Root scope for this object */ private Scriptable scope; @@ -44,6 +51,16 @@ public final class People extends BaseScriptImplementation implements Scopeable this.services = serviceRegistry; } + /** + * Set the authority DAO + * + * @param authorityDAO authority dao + */ + public void setAuthorityDAO(AuthorityDAO authorityDAO) + { + this.authorityDAO = authorityDAO; + } + /** * @see org.alfresco.repo.jscript.Scopeable#setScope(org.mozilla.javascript.Scriptable) */ @@ -55,6 +72,7 @@ public final class People extends BaseScriptImplementation implements Scopeable /** * Gets the Person given the username * + * @param username the username of the person to get * @return the person node (type cm:person) or null if no such person exists */ public Node getPerson(String username) @@ -68,5 +86,88 @@ public final class People extends BaseScriptImplementation implements Scopeable } return person; } + + /** + * Gets the Group given the group name + * + * @param groupName name of group to get + * @return the group node (type usr:authorityContainer) or null if no such group exists + */ + public Node getGroup(String groupName) + { + Node group = null; + NodeRef groupRef = authorityDAO.getAuthorityNodeRefOrNull(groupName); + if (groupRef != null) + { + group = new Node(groupRef, services, scope); + } + return group; + } + + /** + * Gets the members (people) of a group (including all sub-groups) + * + * @param group the group to retrieve members for + * @param recurse recurse into sub-groups + * @return the members of the group + */ + public Node[] getMembers(Node group) + { + return getContainedAuthorities(group, AuthorityType.USER, true); + } + + /** + * Gets the members (people) of a group + * + * @param group the group to retrieve members for + * @param recurse recurse into sub-groups + * @return the members of the group + */ + public Node[] getMembers(Node group, boolean recurse) + { + return getContainedAuthorities(group, AuthorityType.USER, recurse); + } + + /** + * Get Contained Authorities + * + * @param container authority containers + * @param type authority type to filter by + * @param recurse recurse into sub-containers + * @return contained authorities + */ + private Node[] getContainedAuthorities(Node container, AuthorityType type, boolean recurse) + { + Node[] members = null; + if (container.getType().equals(ContentModel.TYPE_AUTHORITY_CONTAINER)) + { + AuthorityService authorityService = services.getAuthorityService(); + String groupName = (String)container.getProperties().get(ContentModel.PROP_AUTHORITY_NAME); + Set authorities = authorityService.getContainedAuthorities(type, groupName, !recurse); + members = new Node[authorities.size()]; + int i = 0; + for (String authority : authorities) + { + AuthorityType authorityType = AuthorityType.getAuthorityType(authority); + if (authorityType.equals(AuthorityType.GROUP)) + { + Node group = getGroup(authority); + if (group != null) + { + members[i++] = group; + } + } + else if (authorityType.equals(AuthorityType.USER)) + { + Node person = getPerson(authority); + if (person != null) + { + members[i++] = person; + } + } + } + } + return members; + } } diff --git a/source/java/org/alfresco/repo/workflow/WorkflowInterpreter.java b/source/java/org/alfresco/repo/workflow/WorkflowInterpreter.java index 617e918a14..0d004245f0 100644 --- a/source/java/org/alfresco/repo/workflow/WorkflowInterpreter.java +++ b/source/java/org/alfresco/repo/workflow/WorkflowInterpreter.java @@ -38,6 +38,8 @@ import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.avmsync.AVMDifference; import org.alfresco.service.cmr.avmsync.AVMSyncService; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.security.authority.AuthorityDAO; +import org.alfresco.repo.transaction.TransactionUtil; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.ContentWriter; @@ -46,6 +48,7 @@ import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.workflow.WorkflowDefinition; import org.alfresco.service.cmr.workflow.WorkflowDeployment; +import org.alfresco.service.cmr.workflow.WorkflowException; import org.alfresco.service.cmr.workflow.WorkflowInstance; import org.alfresco.service.cmr.workflow.WorkflowPath; import org.alfresco.service.cmr.workflow.WorkflowService; @@ -54,6 +57,7 @@ import org.alfresco.service.cmr.workflow.WorkflowTaskState; import org.alfresco.service.cmr.workflow.WorkflowTransition; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.ApplicationContextHelper; import org.alfresco.util.GUID; import org.springframework.context.ApplicationContext; @@ -70,6 +74,8 @@ public class WorkflowInterpreter private WorkflowService workflowService; private NamespaceService namespaceService; private NodeService nodeService; + private TransactionService transactionService; + private AuthorityDAO authorityDAO; private AVMService avmService; private AVMSyncService avmSyncService; private PersonService personService; @@ -167,6 +173,22 @@ public class WorkflowInterpreter this.personService = personService; } + /** + * @param transactionService transactionService + */ + public void setTransactionService(TransactionService transactionService) + { + this.transactionService = transactionService; + } + + /** + * @param authorityDAO authorityDAO + */ + public void setAuthorityDAO(AuthorityDAO authorityDAO) + { + this.authorityDAO = authorityDAO; + } + /** * @param fileFolderService fileFolderService */ @@ -220,7 +242,13 @@ public class WorkflowInterpreter { public String doWork() throws Exception { - return executeCommand(line); + return TransactionUtil.executeInUserTransaction(transactionService, new TransactionUtil.TransactionWork() + { + public String doWork() throws Exception + { + return executeCommand(line); + } + }); } }, username); } @@ -882,6 +910,45 @@ public class WorkflowInterpreter } out.println("set var " + qname + " = " + vars.get(qname)); } + else if (command[2].equals("group")) + { + boolean multi = false; + if (command[1].endsWith("*")) + { + command[1] = command[1].substring(0, command[1].length() -1); + multi = true; + } + QName qname = QName.createQName(command[1], namespaceService); + String[] strValues = command[3].split(","); + if (!multi && strValues.length > 1) + { + return "Syntax Error.\n"; + } + if (!multi) + { + NodeRef auth = authorityDAO.getAuthorityNodeRefOrNull(strValues[0]); + if (auth == null) + { + throw new WorkflowException("Group " + strValues[0] + " does not exist."); + } + vars.put(qname, auth); + } + else + { + List values = new ArrayList(); + for (String strValue : strValues) + { + NodeRef auth = authorityDAO.getAuthorityNodeRefOrNull(strValue); + if (auth == null) + { + throw new WorkflowException("Group " + strValue + " does not exist."); + } + values.add(auth); + } + vars.put(qname, (Serializable)values); + } + out.println("set var " + qname + " = " + vars.get(qname)); + } else if (command[2].equals("avmpackage")) { // lookup source folder of changes @@ -979,5 +1046,5 @@ public class WorkflowInterpreter { return username; } - + } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoAssignment.java b/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoAssignment.java index de072856a6..e1c717ede8 100644 --- a/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoAssignment.java +++ b/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoAssignment.java @@ -17,14 +17,20 @@ package org.alfresco.repo.workflow.jbpm; import java.util.Collection; +import java.util.Set; import org.alfresco.model.ContentModel; +import org.alfresco.repo.jscript.Node; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.security.AuthorityService; +import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.workflow.WorkflowException; import org.dom4j.Element; import org.jbpm.graph.exe.ExecutionContext; import org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator; import org.jbpm.taskmgmt.def.AssignmentHandler; import org.jbpm.taskmgmt.exe.Assignable; +import org.springframework.beans.factory.BeanFactory; /** @@ -33,13 +39,24 @@ import org.jbpm.taskmgmt.exe.Assignable; * * @author davidc */ -public class AlfrescoAssignment implements AssignmentHandler +public class AlfrescoAssignment extends JBPMSpringAssignmentHandler { private static final long serialVersionUID = 1025667849552265719L; + private ServiceRegistry services; private Element actor; private Element pooledactors; + + /* (non-Javadoc) + * @see org.alfresco.repo.workflow.jbpm.JBPMSpringActionHandler#initialiseHandler(org.springframework.beans.factory.BeanFactory) + */ + @Override + protected void initialiseHandler(BeanFactory factory) + { + services = (ServiceRegistry)factory.getBean(ServiceRegistry.SERVICE_REGISTRY); + } + /* (non-Javadoc) * @see org.jbpm.taskmgmt.def.AssignmentHandler#assign(org.jbpm.taskmgmt.exe.Assignable, org.jbpm.graph.exe.ExecutionContext) @@ -63,7 +80,8 @@ public class AlfrescoAssignment implements AssignmentHandler { if (actorValStr.startsWith("#{")) { - Object eval = JbpmExpressionEvaluator.evaluate(actorValStr, executionContext); + String expression = actorValStr.substring(2, actorValStr.length() -1); + Object eval = AlfrescoJavaScript.executeScript(executionContext, services, expression, null); if (eval == null) { throw new WorkflowException("actor expression '" + actorValStr + "' evaluates to null"); @@ -73,9 +91,9 @@ public class AlfrescoAssignment implements AssignmentHandler { assignedActor = (String)eval; } - else if (eval instanceof JBPMNode) + else if (eval instanceof Node) { - JBPMNode node = (JBPMNode)eval; + Node node = (Node)eval; if (!node.getType().equals(ContentModel.TYPE_PERSON)) { throw new WorkflowException("actor expression does not evaluate to a person"); @@ -106,49 +124,52 @@ public class AlfrescoAssignment implements AssignmentHandler { if (pooledactorValStr.startsWith("#{")) { - Object eval = JbpmExpressionEvaluator.evaluate(pooledactorValStr, executionContext); + String expression = pooledactorValStr.substring(2, pooledactorValStr.length() -1); + Object eval = AlfrescoJavaScript.executeScript(executionContext, services, expression, null); if (eval == null) { throw new WorkflowException("pooledactors expression '" + pooledactorValStr + "' evaluates to null"); } - if (eval instanceof Collection) + if (eval instanceof Node[]) { - Collection coll = (Collection)eval; - assignedPooledActors = new String[coll.size()]; + Node[] nodes = (Node[])eval; + assignedPooledActors = new String[nodes.length]; int i = 0; - for (Object obj : coll) + for (Node node : (Node[])nodes) { - if (!(obj instanceof JBPMNode)) + if (node.getType().equals(ContentModel.TYPE_PERSON)) { - throw new WorkflowException("pooledactors does not refer to a collection of people"); + assignedPooledActors[i++] = (String)node.getProperties().get(ContentModel.PROP_USERNAME); } - JBPMNode node = (JBPMNode)obj; - if (!node.getType().equals(ContentModel.TYPE_PERSON)) + else if (node.getType().equals(ContentModel.TYPE_AUTHORITY_CONTAINER)) { - throw new WorkflowException("pooledactors expression does not evaluate to a collection of people"); + assignedPooledActors[i++] = (String)node.getProperties().get(ContentModel.PROP_AUTHORITY_NAME); + } + else + { + throw new WorkflowException("pooledactors expression does not evaluate to a collection of authorities"); } - assignedPooledActors[i++] = (String)node.getProperties().get(ContentModel.PROP_USERNAME); } } - else if (eval instanceof JBPMNode) + else if (eval instanceof Node) { - JBPMNode node = (JBPMNode)eval; + assignedPooledActors = new String[1]; + Node node = (Node)eval; if (node.getType().equals(ContentModel.TYPE_PERSON)) { assignedPooledActors[0] = (String)node.getProperties().get(ContentModel.PROP_USERNAME); } - // TODO: Support Group + else if (node.getType().equals(ContentModel.TYPE_AUTHORITY_CONTAINER)) + { + assignedPooledActors[0] = (String)node.getProperties().get(ContentModel.PROP_AUTHORITY_NAME); + } else { - throw new WorkflowException("pooledactors expression does not evaluate to a collection of people"); + throw new WorkflowException("pooledactors expression does not evaluate to a collection of authorities"); } } - else - { - throw new WorkflowException("pooledactor expression does not evaluate to a group or collection of people"); - } } else { diff --git a/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoJavaScript.java b/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoJavaScript.java index 5a630ccb5c..73a768c2af 100644 --- a/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoJavaScript.java +++ b/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoJavaScript.java @@ -56,7 +56,6 @@ public class AlfrescoJavaScript extends JBPMSpringActionHandler private static final long serialVersionUID = -2908748080671212745L; private static JpdlXmlReader jpdlReader = new JpdlXmlReader((InputSource)null); - private ScriptService scriptService; private ServiceRegistry services; private Element script; @@ -67,7 +66,6 @@ public class AlfrescoJavaScript extends JBPMSpringActionHandler @Override protected void initialiseHandler(BeanFactory factory) { - scriptService = (ScriptService)factory.getBean(ServiceRegistry.SCRIPT_SERVICE.getLocalName()); services = (ServiceRegistry)factory.getBean(ServiceRegistry.SERVICE_REGISTRY); } @@ -116,9 +114,8 @@ public class AlfrescoJavaScript extends JBPMSpringActionHandler expression = expressionElement.getTextTrim(); } - // construct script arguments and execute - Map inputMap = createInputMap(executionContext, variableAccesses); - Object result = scriptService.executeScriptString(expression, inputMap); + // execute + Object result = executeScript(executionContext, services, expression, variableAccesses); // map script return variable to process context VariableAccess returnVariable = getWritableVariable(variableAccesses); @@ -130,6 +127,24 @@ public class AlfrescoJavaScript extends JBPMSpringActionHandler } } + + /** + * Execute a script + * + * @param context jBPM execution context + * @param services Alfresco service registry + * @param expression script to execute + * @param variableAccesses (optional) list of jBPM variables to map into script (all, if not supplied) + * @return script result + */ + public static Object executeScript(ExecutionContext context, ServiceRegistry services, String expression, List variableAccesses) + { + Map inputMap = createInputMap(context, services, variableAccesses); + ScriptService scriptService = services.getScriptService(); + Object result = scriptService.executeScriptString(expression, inputMap); + return result; + } + /** * Construct map of arguments to pass to script @@ -141,7 +156,7 @@ public class AlfrescoJavaScript extends JBPMSpringActionHandler * @return the map of script arguments */ @SuppressWarnings("unchecked") - public Map createInputMap(ExecutionContext executionContext, List variableAccesses) + private static Map createInputMap(ExecutionContext executionContext, ServiceRegistry services, List variableAccesses) { Map inputMap = new HashMap(); @@ -216,7 +231,7 @@ public class AlfrescoJavaScript extends JBPMSpringActionHandler * @param variableAccesses the variables configuration * @return true => there are variables to read */ - private boolean hasReadableVariable(List variableAccesses) + private static boolean hasReadableVariable(List variableAccesses) { if (variableAccesses != null) { @@ -238,7 +253,7 @@ public class AlfrescoJavaScript extends JBPMSpringActionHandler * @param variableAccesses the variables configuration * @return true => there is a variable to write */ - private VariableAccess getWritableVariable(List variableAccesses) + private static VariableAccess getWritableVariable(List variableAccesses) { if (variableAccesses != null) { diff --git a/source/java/org/alfresco/repo/workflow/jbpm/ForEachFork.java b/source/java/org/alfresco/repo/workflow/jbpm/ForEachFork.java index c9569ccfcb..6ce1f4cfae 100644 --- a/source/java/org/alfresco/repo/workflow/jbpm/ForEachFork.java +++ b/source/java/org/alfresco/repo/workflow/jbpm/ForEachFork.java @@ -20,27 +20,37 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.workflow.WorkflowException; import org.dom4j.Element; -import org.jbpm.graph.def.ActionHandler; import org.jbpm.graph.def.Node; import org.jbpm.graph.def.Transition; import org.jbpm.graph.exe.ExecutionContext; import org.jbpm.graph.exe.Token; import org.jbpm.instantiation.FieldInstantiator; -import org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator; +import org.springframework.beans.factory.BeanFactory; /** * For each "item in collection", create a fork. */ -public class ForEachFork implements ActionHandler +public class ForEachFork extends JBPMSpringActionHandler { private static final long serialVersionUID = 4643103713602441652L; + private ServiceRegistry services; private Element foreach; private String var; + + /* (non-Javadoc) + * @see org.alfresco.repo.workflow.jbpm.JBPMSpringActionHandler#initialiseHandler(org.springframework.beans.factory.BeanFactory) + */ + @Override + protected void initialiseHandler(BeanFactory factory) + { + services = (ServiceRegistry)factory.getBean(ServiceRegistry.SERVICE_REGISTRY); + } /** * Create a new child token for each item in list. @@ -68,7 +78,8 @@ public class ForEachFork implements ActionHandler { if (forEachCollStr.startsWith("#{")) { - Object eval = JbpmExpressionEvaluator.evaluate(forEachCollStr, executionContext); + String expression = forEachCollStr.substring(2, forEachCollStr.length() -1); + Object eval = AlfrescoJavaScript.executeScript(executionContext, services, expression, null); if (eval == null) { throw new WorkflowException("forEach expression '" + forEachCollStr + "' evaluates to null"); @@ -85,11 +96,23 @@ public class ForEachFork implements ActionHandler } } + // expression evaluates to Node array + else if (eval instanceof org.alfresco.repo.jscript.Node[]) + { + org.alfresco.repo.jscript.Node[] nodes = (org.alfresco.repo.jscript.Node[])eval; + forEachColl = new ArrayList(nodes.length); + for (org.alfresco.repo.jscript.Node node : nodes) + { + forEachColl.add(new JBPMNode(node.getNodeRef(), services)); + } + } + // expression evaluates to collection else if (eval instanceof Collection) { forEachColl = (List)eval; } + } } else diff --git a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java index 0d071e7566..215e0eaa6d 100644 --- a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java +++ b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -33,6 +34,7 @@ import org.alfresco.i18n.I18NUtil; import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authority.AuthorityDAO; import org.alfresco.repo.workflow.BPMEngine; import org.alfresco.repo.workflow.TaskComponent; import org.alfresco.repo.workflow.WorkflowComponent; @@ -49,6 +51,8 @@ import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.service.cmr.security.AuthorityService; +import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.workflow.WorkflowDefinition; import org.alfresco.service.cmr.workflow.WorkflowDeployment; @@ -108,6 +112,8 @@ public class JBPMEngine extends BPMEngine protected NodeService nodeService; protected ServiceRegistry serviceRegistry; protected PersonService personService; + protected AuthorityService authorityService; + protected AuthorityDAO authorityDAO; protected JbpmTemplate jbpmTemplate; // Company Home @@ -183,6 +189,26 @@ public class JBPMEngine extends BPMEngine this.personService = personService; } + /** + * Sets the Authority Service + * + * @param authorityService + */ + public void setAuthorityService(AuthorityService authorityService) + { + this.authorityService = authorityService; + } + + /** + * Sets the Authority DAO + * + * @param authorityDAO + */ + public void setAuthorityDAO(AuthorityDAO authorityDAO) + { + this.authorityDAO = authorityDAO; + } + /** * Sets the Service Registry * @@ -459,7 +485,7 @@ public class JBPMEngine extends BPMEngine processContext.setVariable("cancelled", false); NodeRef companyHome = getCompanyHome(); processContext.setVariable("companyhome", new JBPMNode(companyHome, serviceRegistry)); - NodeRef initiatorPerson = mapNameToAuthority(currentUserName); + NodeRef initiatorPerson = mapNameToPerson(currentUserName); if (initiatorPerson != null) { processContext.setVariable("initiator", new JBPMNode(initiatorPerson, serviceRegistry)); @@ -831,9 +857,17 @@ public class JBPMEngine extends BPMEngine { public List doInJbpm(JbpmContext context) { - // retrieve pooled tasks for specified authorities + // flatten authorities to include all parent authorities + Set flattenedAuthorities = new HashSet(); + for (String authority : authorities) + { + Set parents = authorityService.getContainingAuthorities(AuthorityType.GROUP, authority, false); + flattenedAuthorities.addAll(parents); + } + + // retrieve pooled tasks for all flattened authorities TaskMgmtSession taskSession = context.getTaskMgmtSession(); - List tasks = taskSession.findPooledTaskInstances(authorities); + List tasks = taskSession.findPooledTaskInstances(new ArrayList(flattenedAuthorities)); List workflowTasks = new ArrayList(tasks.size()); for (TaskInstance task : tasks) { @@ -1281,7 +1315,7 @@ public class JBPMEngine extends BPMEngine } /** - * Sets Properties of Task + * Gets Properties of Task * * @param instance task instance * @param properties properties to set @@ -1778,12 +1812,12 @@ public class JBPMEngine extends BPMEngine } /** - * Convert authority name to an Alfresco Authority + * Convert person name to an Alfresco Person * - * @param names the authority names to convert - * @return the Alfresco authorities + * @param names the person name to convert + * @return the Alfresco person */ - private NodeRef mapNameToAuthority(String name) + private NodeRef mapNameToPerson(String name) { NodeRef authority = null; if (name != null) @@ -1797,6 +1831,26 @@ public class JBPMEngine extends BPMEngine return authority; } + /** + * Convert authority name to an Alfresco Authority + * + * @param names the authority names to convert + * @return the Alfresco authorities + */ + private NodeRef mapNameToAuthority(String name) + { + NodeRef authority = null; + if (name != null) + { + // TODO: Should this be an exception? + if (authorityDAO.authorityExists(name)) + { + authority = authorityDAO.getAuthorityNodeRefOrNull(name); + } + } + return authority; + } + /** * Map jBPM variable name to QName * diff --git a/source/java/org/alfresco/repo/workflow/jbpm/JBPMSpringAssignmentHandler.java b/source/java/org/alfresco/repo/workflow/jbpm/JBPMSpringAssignmentHandler.java new file mode 100644 index 0000000000..a9f4f376e3 --- /dev/null +++ b/source/java/org/alfresco/repo/workflow/jbpm/JBPMSpringAssignmentHandler.java @@ -0,0 +1,54 @@ +/* + * 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 org.jbpm.taskmgmt.def.AssignmentHandler; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.access.BeanFactoryLocator; +import org.springframework.beans.factory.access.BeanFactoryReference; +import org.springmodules.workflow.jbpm31.JbpmFactoryLocator; + + +/** + * Abstract base implementation of a Jbpm Assignment Handler with access to + * Alfresco Spring beans. + * + * @author davidc + */ +public abstract class JBPMSpringAssignmentHandler implements AssignmentHandler +{ + + /** + * Construct + */ + protected JBPMSpringAssignmentHandler() + { + // The following implementation is derived from Spring Modules v0.4 + BeanFactoryLocator factoryLocator = new JbpmFactoryLocator(); + BeanFactoryReference factory = factoryLocator.useBeanFactory(null); + initialiseHandler(factory.getFactory()); + } + + /** + * Initialise Action Handler + * + * @param factory Spring bean factory for accessing Alfresco beans + */ + protected abstract void initialiseHandler(BeanFactory factory); + + +} diff --git a/source/java/org/alfresco/repo/workflow/jbpm/test_groups.xml b/source/java/org/alfresco/repo/workflow/jbpm/test_groups.xml new file mode 100644 index 0000000000..5456b9e080 --- /dev/null +++ b/source/java/org/alfresco/repo/workflow/jbpm/test_groups.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + #{bpm_groupAssignee} + + + + + + + + + + + #{people.getMembers(bpm_groupAssignee)} + reviewer + + + + + + + + #{reviewer} + + + + + + + + + + + + \ No newline at end of file