Merged 5.1.N (5.1.2) to 5.2.N (5.2.1)

125605 rmunteanu: Merged 5.1.1 (5.1.1) to 5.1.N (5.1.2)
      125498 slanglois: MNT-16155 Update source headers - remove svn:eol-style property on Java and JSP source files


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@125783 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Raluca Munteanu
2016-04-26 13:03:25 +00:00
parent 8674e2bfc8
commit dc6b2852d0
830 changed files with 142585 additions and 142585 deletions

View File

@@ -1,245 +1,245 @@
package org.alfresco.repo.workflow.jbpm;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.jscript.ScriptNode;
import org.alfresco.repo.security.authority.AuthorityDAO;
import org.alfresco.repo.workflow.WorkflowNotificationUtils;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.alfresco.service.namespace.QName;
import org.dom4j.Element;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.taskmgmt.exe.Assignable;
import org.springframework.beans.factory.BeanFactory;
/**
* Assignment Handler for assigning Alfresco People and Groups to Tasks
* and Swimlanes
*
* @author davidc
*/
public class AlfrescoAssignment extends JBPMSpringAssignmentHandler
{
private static final long serialVersionUID = 1025667849552265719L;
private ServiceRegistry services;
private DictionaryService dictionaryService;
private AuthorityDAO authorityDAO;
private WorkflowNotificationUtils workflowNotificationUtils;
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);
dictionaryService = services.getDictionaryService();
authorityDAO = (AuthorityDAO)factory.getBean("authorityDAO");
workflowNotificationUtils = (WorkflowNotificationUtils)factory.getBean("workflowNotification");
}
/* (non-Javadoc)
* @see org.jbpm.taskmgmt.def.AssignmentHandler#assign(org.jbpm.taskmgmt.exe.Assignable, org.jbpm.graph.exe.ExecutionContext)
*/
public void assign(Assignable assignable, ExecutionContext executionContext) throws Exception
{
if (actor == null && pooledactors == null)
{
throw new WorkflowException("no actor or pooled actors has been specified");
}
//
// extract actor
//
String assignedActor = null;
if (actor != null)
{
String actorValStr = actor.getTextTrim();
if (actorValStr != null && actorValStr.length() > 0)
{
if (actorValStr.startsWith("#{"))
{
String expression = actorValStr.substring(2, actorValStr.length() -1);
Object eval = AlfrescoJavaScript.executeScript(executionContext, services, expression, null, null);
if (eval == null)
{
throw new WorkflowException("actor expression '" + actorValStr + "' evaluates to null");
}
String theActor = null;
if (eval instanceof String)
{
theActor = (String)eval;
}
else if (eval instanceof JBPMNode)
{
theActor = mapAuthorityToName((JBPMNode)eval, false);
}
if (theActor == null)
{
throw new WorkflowException("actor expression must evaluate to a person");
}
assignedActor = theActor;
}
else
{
assignedActor = actorValStr;
}
}
}
//
// extract pooled actors
//
String[] assignedPooledActors = null;
if (pooledactors != null)
{
String pooledactorValStr = pooledactors.getTextTrim();
if (pooledactorValStr != null && pooledactorValStr.length() > 0)
{
if (pooledactorValStr.startsWith("#{"))
{
String expression = pooledactorValStr.substring(2, pooledactorValStr.length() -1);
Object eval = AlfrescoJavaScript.executeScript(executionContext, services, expression, null, null);
if (eval == null)
{
throw new WorkflowException("pooledactors expression '" + pooledactorValStr + "' evaluates to null");
}
if (eval instanceof ScriptNode[])
{
ScriptNode[] nodes = (ScriptNode[])eval;
assignedPooledActors = new String[nodes.length];
int i = 0;
for (ScriptNode node : nodes)
{
String theActor = mapAuthorityToName(node, true);
if (theActor == null)
{
throw new WorkflowException("pooledactors expression does not evaluate to a collection of authorities");
}
assignedPooledActors[i++] = theActor;
}
}
if (eval instanceof Collection)
{
List<String> actors = new ArrayList<String>();
Collection<?> nodes = (Collection<?>)eval;
for (Object node : nodes)
{
if (node instanceof ScriptNode)
{
String theActor = mapAuthorityToName((ScriptNode)node, true);
if (theActor == null)
{
throw new WorkflowException("pooledactors expression does not evaluate to a collection of authorities");
}
actors.add(theActor);
}
}
assignedPooledActors = new String[actors.size()];
actors.toArray(assignedPooledActors);
}
else if (eval instanceof ScriptNode)
{
ScriptNode node = (ScriptNode)eval;
String theActor = mapAuthorityToName(node, true);
if (theActor == null)
{
throw new WorkflowException("pooledactors expression does not evaluate to a collection of authorities");
}
assignedPooledActors = new String[] {theActor};
}
else if (eval instanceof String)
{
assignedPooledActors = new String[] {(String)eval};
}
else
{
throw new WorkflowException("pooledactors expression does not evaluate to a collection of authorities");
}
}
else
{
assignedPooledActors = new String[] {pooledactorValStr};
}
}
}
//Determine whether we need to send email notifications of not
Boolean sendEMailNotification = (Boolean)executionContext.getVariable(WorkflowNotificationUtils.PROP_SEND_EMAIL_NOTIFICATIONS);
//
// make the assignment
//
if (assignedActor != null)
{
assignable.setActorId(assignedActor);
if (Boolean.TRUE.equals(sendEMailNotification) == true)
{
// Send the notification
workflowNotificationUtils.sendWorkflowAssignedNotificationEMail(
JBPMEngine.ENGINE_ID + "$" + executionContext.getTaskInstance().getId(), null,
assignedActor,
false);
}
}
if (assignedPooledActors != null)
{
assignable.setPooledActors(assignedPooledActors);
if (Boolean.TRUE.equals(sendEMailNotification) == true)
{
// Send the notification
workflowNotificationUtils.sendWorkflowAssignedNotificationEMail(
JBPMEngine.ENGINE_ID + "$" + executionContext.getTaskInstance().getId(), null,
assignedPooledActors,
true);
}
}
}
/**
* Convert Alfresco authority to actor id
*
* @param authority ScriptNode
* @param allowGroup boolean
* @return actor id
*/
private String mapAuthorityToName(ScriptNode authority, boolean allowGroup)
{
String name = null;
QName type = authority.getQNameType();
if (dictionaryService.isSubClass(type, ContentModel.TYPE_PERSON))
{
name = (String)authority.getProperties().get(ContentModel.PROP_USERNAME);
}
else if (allowGroup && dictionaryService.isSubClass(type, ContentModel.TYPE_AUTHORITY_CONTAINER))
{
name = authorityDAO.getAuthorityName(authority.getNodeRef());
}
else if (type.equals(ContentModel.TYPE_AUTHORITY))
{
name = authorityDAO.getAuthorityName(authority.getNodeRef());
}
return name;
}
}
package org.alfresco.repo.workflow.jbpm;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.jscript.ScriptNode;
import org.alfresco.repo.security.authority.AuthorityDAO;
import org.alfresco.repo.workflow.WorkflowNotificationUtils;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.alfresco.service.namespace.QName;
import org.dom4j.Element;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.taskmgmt.exe.Assignable;
import org.springframework.beans.factory.BeanFactory;
/**
* Assignment Handler for assigning Alfresco People and Groups to Tasks
* and Swimlanes
*
* @author davidc
*/
public class AlfrescoAssignment extends JBPMSpringAssignmentHandler
{
private static final long serialVersionUID = 1025667849552265719L;
private ServiceRegistry services;
private DictionaryService dictionaryService;
private AuthorityDAO authorityDAO;
private WorkflowNotificationUtils workflowNotificationUtils;
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);
dictionaryService = services.getDictionaryService();
authorityDAO = (AuthorityDAO)factory.getBean("authorityDAO");
workflowNotificationUtils = (WorkflowNotificationUtils)factory.getBean("workflowNotification");
}
/* (non-Javadoc)
* @see org.jbpm.taskmgmt.def.AssignmentHandler#assign(org.jbpm.taskmgmt.exe.Assignable, org.jbpm.graph.exe.ExecutionContext)
*/
public void assign(Assignable assignable, ExecutionContext executionContext) throws Exception
{
if (actor == null && pooledactors == null)
{
throw new WorkflowException("no actor or pooled actors has been specified");
}
//
// extract actor
//
String assignedActor = null;
if (actor != null)
{
String actorValStr = actor.getTextTrim();
if (actorValStr != null && actorValStr.length() > 0)
{
if (actorValStr.startsWith("#{"))
{
String expression = actorValStr.substring(2, actorValStr.length() -1);
Object eval = AlfrescoJavaScript.executeScript(executionContext, services, expression, null, null);
if (eval == null)
{
throw new WorkflowException("actor expression '" + actorValStr + "' evaluates to null");
}
String theActor = null;
if (eval instanceof String)
{
theActor = (String)eval;
}
else if (eval instanceof JBPMNode)
{
theActor = mapAuthorityToName((JBPMNode)eval, false);
}
if (theActor == null)
{
throw new WorkflowException("actor expression must evaluate to a person");
}
assignedActor = theActor;
}
else
{
assignedActor = actorValStr;
}
}
}
//
// extract pooled actors
//
String[] assignedPooledActors = null;
if (pooledactors != null)
{
String pooledactorValStr = pooledactors.getTextTrim();
if (pooledactorValStr != null && pooledactorValStr.length() > 0)
{
if (pooledactorValStr.startsWith("#{"))
{
String expression = pooledactorValStr.substring(2, pooledactorValStr.length() -1);
Object eval = AlfrescoJavaScript.executeScript(executionContext, services, expression, null, null);
if (eval == null)
{
throw new WorkflowException("pooledactors expression '" + pooledactorValStr + "' evaluates to null");
}
if (eval instanceof ScriptNode[])
{
ScriptNode[] nodes = (ScriptNode[])eval;
assignedPooledActors = new String[nodes.length];
int i = 0;
for (ScriptNode node : nodes)
{
String theActor = mapAuthorityToName(node, true);
if (theActor == null)
{
throw new WorkflowException("pooledactors expression does not evaluate to a collection of authorities");
}
assignedPooledActors[i++] = theActor;
}
}
if (eval instanceof Collection)
{
List<String> actors = new ArrayList<String>();
Collection<?> nodes = (Collection<?>)eval;
for (Object node : nodes)
{
if (node instanceof ScriptNode)
{
String theActor = mapAuthorityToName((ScriptNode)node, true);
if (theActor == null)
{
throw new WorkflowException("pooledactors expression does not evaluate to a collection of authorities");
}
actors.add(theActor);
}
}
assignedPooledActors = new String[actors.size()];
actors.toArray(assignedPooledActors);
}
else if (eval instanceof ScriptNode)
{
ScriptNode node = (ScriptNode)eval;
String theActor = mapAuthorityToName(node, true);
if (theActor == null)
{
throw new WorkflowException("pooledactors expression does not evaluate to a collection of authorities");
}
assignedPooledActors = new String[] {theActor};
}
else if (eval instanceof String)
{
assignedPooledActors = new String[] {(String)eval};
}
else
{
throw new WorkflowException("pooledactors expression does not evaluate to a collection of authorities");
}
}
else
{
assignedPooledActors = new String[] {pooledactorValStr};
}
}
}
//Determine whether we need to send email notifications of not
Boolean sendEMailNotification = (Boolean)executionContext.getVariable(WorkflowNotificationUtils.PROP_SEND_EMAIL_NOTIFICATIONS);
//
// make the assignment
//
if (assignedActor != null)
{
assignable.setActorId(assignedActor);
if (Boolean.TRUE.equals(sendEMailNotification) == true)
{
// Send the notification
workflowNotificationUtils.sendWorkflowAssignedNotificationEMail(
JBPMEngine.ENGINE_ID + "$" + executionContext.getTaskInstance().getId(), null,
assignedActor,
false);
}
}
if (assignedPooledActors != null)
{
assignable.setPooledActors(assignedPooledActors);
if (Boolean.TRUE.equals(sendEMailNotification) == true)
{
// Send the notification
workflowNotificationUtils.sendWorkflowAssignedNotificationEMail(
JBPMEngine.ENGINE_ID + "$" + executionContext.getTaskInstance().getId(), null,
assignedPooledActors,
true);
}
}
}
/**
* Convert Alfresco authority to actor id
*
* @param authority ScriptNode
* @param allowGroup boolean
* @return actor id
*/
private String mapAuthorityToName(ScriptNode authority, boolean allowGroup)
{
String name = null;
QName type = authority.getQNameType();
if (dictionaryService.isSubClass(type, ContentModel.TYPE_PERSON))
{
name = (String)authority.getProperties().get(ContentModel.PROP_USERNAME);
}
else if (allowGroup && dictionaryService.isSubClass(type, ContentModel.TYPE_AUTHORITY_CONTAINER))
{
name = authorityDAO.getAuthorityName(authority.getNodeRef());
}
else if (type.equals(ContentModel.TYPE_AUTHORITY))
{
name = authorityDAO.getAuthorityName(authority.getNodeRef());
}
return name;
}
}

View File

@@ -1,88 +1,88 @@
package org.alfresco.repo.workflow.jbpm;
import java.util.Calendar;
import java.util.Date;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.jbpm.calendar.BusinessCalendar;
import org.jbpm.calendar.Duration;
import org.jbpm.graph.def.GraphElement;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.job.Timer;
import org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator;
import org.jbpm.scheduler.def.CreateTimerAction;
/**
* Extended Create Timer action for supporting Alfresco implemented timers.
*
* Alfresco timer supports ability to provide due date expression that can
* evaluate to a date.
*
* @author davidc
*/
public class AlfrescoCreateTimerAction extends CreateTimerAction
{
private static final long serialVersionUID = -7427571820130058416L;
protected static BusinessCalendar businessCalendar = new BusinessCalendar();
/* (non-Javadoc)
* @see org.jbpm.scheduler.def.CreateTimerAction#createTimer(org.jbpm.graph.exe.ExecutionContext)
*/
@Override
protected Timer createTimer(ExecutionContext executionContext)
{
Date dueDate = null;
String dueDateExpression = getDueDate();
if (dueDateExpression.startsWith("#{"))
{
Object result = JbpmExpressionEvaluator.evaluate(dueDateExpression, executionContext);
if (result instanceof Date)
{
dueDate = (Date)result;
}
else if(result instanceof Calendar)
{
dueDate = ((Calendar)result).getTime();
}
else
{
throw new WorkflowException("duedate expression must evaluate to a date");
}
}
else
{
Duration duration = new Duration(getDueDate());
dueDate = businessCalendar.add(new Date(), duration);
}
Timer timer = new AlfrescoTimer(executionContext.getToken());
timer.setName(getTimerName());
timer.setRepeat(getRepeat());
timer.setDueDate(dueDate);
timer.setAction(getTimerAction());
timer.setTransitionName(getTransitionName());
timer.setGraphElement(executionContext.getEventSource());
timer.setTaskInstance(executionContext.getTaskInstance());
// if this action was executed for a graph element
if ((getEvent() != null) && (getEvent().getGraphElement() != null))
{
GraphElement graphElement = getEvent().getGraphElement();
try
{
executionContext.setTimer(timer);
// fire the create timer event on the same graph element
graphElement.fireEvent("timer-create", executionContext);
}
finally
{
executionContext.setTimer(null);
}
}
return timer;
}
}
package org.alfresco.repo.workflow.jbpm;
import java.util.Calendar;
import java.util.Date;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.jbpm.calendar.BusinessCalendar;
import org.jbpm.calendar.Duration;
import org.jbpm.graph.def.GraphElement;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.job.Timer;
import org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator;
import org.jbpm.scheduler.def.CreateTimerAction;
/**
* Extended Create Timer action for supporting Alfresco implemented timers.
*
* Alfresco timer supports ability to provide due date expression that can
* evaluate to a date.
*
* @author davidc
*/
public class AlfrescoCreateTimerAction extends CreateTimerAction
{
private static final long serialVersionUID = -7427571820130058416L;
protected static BusinessCalendar businessCalendar = new BusinessCalendar();
/* (non-Javadoc)
* @see org.jbpm.scheduler.def.CreateTimerAction#createTimer(org.jbpm.graph.exe.ExecutionContext)
*/
@Override
protected Timer createTimer(ExecutionContext executionContext)
{
Date dueDate = null;
String dueDateExpression = getDueDate();
if (dueDateExpression.startsWith("#{"))
{
Object result = JbpmExpressionEvaluator.evaluate(dueDateExpression, executionContext);
if (result instanceof Date)
{
dueDate = (Date)result;
}
else if(result instanceof Calendar)
{
dueDate = ((Calendar)result).getTime();
}
else
{
throw new WorkflowException("duedate expression must evaluate to a date");
}
}
else
{
Duration duration = new Duration(getDueDate());
dueDate = businessCalendar.add(new Date(), duration);
}
Timer timer = new AlfrescoTimer(executionContext.getToken());
timer.setName(getTimerName());
timer.setRepeat(getRepeat());
timer.setDueDate(dueDate);
timer.setAction(getTimerAction());
timer.setTransitionName(getTransitionName());
timer.setGraphElement(executionContext.getEventSource());
timer.setTaskInstance(executionContext.getTaskInstance());
// if this action was executed for a graph element
if ((getEvent() != null) && (getEvent().getGraphElement() != null))
{
GraphElement graphElement = getEvent().getGraphElement();
try
{
executionContext.setTimer(timer);
// fire the create timer event on the same graph element
graphElement.fireEvent("timer-create", executionContext);
}
finally
{
executionContext.setTimer(null);
}
}
return timer;
}
}

View File

@@ -1,472 +1,472 @@
package org.alfresco.repo.workflow.jbpm;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.ScriptService;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.dom4j.Element;
import org.jbpm.context.def.VariableAccess;
import org.jbpm.context.exe.ContextInstance;
import org.jbpm.graph.def.Node;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.graph.exe.Token;
import org.jbpm.jpdl.xml.JpdlXmlReader;
import org.jbpm.taskmgmt.def.Task;
import org.jbpm.taskmgmt.exe.TaskInstance;
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:
* <script>
* <expression>
* the script to execute
* </expression>
* <variable name="watcha" access="write"/>
* </script>
*
* 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 ServiceRegistry services;
private NodeRef companyHome;
private Element script;
private String runas;
/**
* {@inheritDoc}
*/
@Override
protected void initialiseHandler(BeanFactory factory)
{
this.services = (ServiceRegistry)factory.getBean(ServiceRegistry.SERVICE_REGISTRY);
Repository repositoryHelper = (Repository)factory.getBean("repositoryHelper");
this.companyHome = repositoryHelper.getCompanyHome();
}
/* (non-Javadoc)
* @see org.jbpm.graph.def.ActionHandler#execute(org.jbpm.graph.exe.ExecutionContext)
*/
public void execute(final ExecutionContext executionContext) throws Exception
{
// validate script
if (script == null)
{
throw new WorkflowException("Script has not been provided");
}
boolean isTextOnly = isScriptOnlyText();
List<VariableAccess> variableAccesses = getVariableAccessors(isTextOnly);
String expression = getExpression(isTextOnly);
// execute
Object result = executeExpression(expression, executionContext, variableAccesses);
// 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);
}
}
private Object executeExpression(String expression, ExecutionContext executionContext, List<VariableAccess> variableAccesses)
{
boolean userChanged = checkFullyAuthenticatedUser(executionContext);
Object result = executeScript(expression, executionContext, variableAccesses);
if(userChanged)
{
AuthenticationUtil.clearCurrentSecurityContext();
}
return result;
}
private Object executeScript(String expression,
ExecutionContext executionContext,
List<VariableAccess> variableAccesses)
{
String user = AuthenticationUtil.getFullyAuthenticatedUser();
if (runas == null && user !=null)
{
return executeScript(executionContext, services, expression, variableAccesses, companyHome);
}
else
{
String runAsUser = runas;
if(runAsUser == null)
{
runAsUser = AuthenticationUtil.getSystemUserName();
}
else
{
validateRunAsUser();
}
return executeScriptAs(runAsUser, expression, executionContext, variableAccesses);
}
}
private Object executeScriptAs(String runAsUser,
final String expression,
final ExecutionContext executionContext,
final List<VariableAccess> variableAccesses)
{
// execute as specified runAsUser
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
{
public Object doWork() throws Exception
{
return executeScript(executionContext, services, expression, variableAccesses,companyHome);
}
}, runAsUser);
}
/**
* Checks a valid Fully Authenticated User is set.
* If none is set then attempts to set the task assignee as the Fully Authenticated User.
* @param executionContext
* @return <code>true</code> if the Fully Authenticated User was changes, otherwise <code>false</code>.
*/
private boolean checkFullyAuthenticatedUser(final ExecutionContext executionContext)
{
if(AuthenticationUtil.getFullyAuthenticatedUser()!= null)
return false;
TaskInstance taskInstance = executionContext.getTaskInstance();
if(taskInstance!=null)
{
String userName = taskInstance.getActorId();
if (userName != null)
{
AuthenticationUtil.setFullyAuthenticatedUser(userName);
return true;
}
}
return false;
}
/**
* Checks that the specified 'runas' field
* specifies a valid username.
*/
private void validateRunAsUser()
{
Boolean runAsExists = AuthenticationUtil.runAs(new RunAsWork<Boolean>()
{
// Validate using System user to ensure sufficient permissions available to access person node.
public Boolean doWork() throws Exception
{
return services.getPersonService().personExists(runas);
}
}, AuthenticationUtil.getSystemUserName());
if (!runAsExists)
{
throw new WorkflowException("runas user '" + runas + "' does not exist.");
}
}
/**
* Gets the expression {@link String} from the script.
* @param isTextOnly Is the script text only or is it XML?
* @return the expression {@link String}.
*/
private String getExpression(boolean isTextOnly)
{
if (isTextOnly)
{
return script.getText().trim();
}
else
{
Element expressionElement = script.element("expression");
if (expressionElement == null)
{
throw new WorkflowException("Script expression has not been provided");
}
return expressionElement.getText().trim();
}
}
@SuppressWarnings("unchecked")
private List<VariableAccess> getVariableAccessors(boolean isTextOnly)
{
if (isTextOnly)
{
return null;
}
else
{
return jpdlReader.readVariableAccesses(script);
}
}
/**
* Is the script specified as text only, or as explicit expression, variable elements
* @return boolean
*/
@SuppressWarnings("unchecked")
private boolean isScriptOnlyText()
{
Iterator<Element> iter = script.elementIterator();
while (iter.hasNext())
{
Element element = iter.next();
if (element.getNodeType() == org.dom4j.Node.ELEMENT_NODE)
{
return false;
}
}
return true;
}
/**
* 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)
* @param companyHome TODO
* @return script result
*/
public static Object executeScript(ExecutionContext context, ServiceRegistry services, String expression, List<VariableAccess> variableAccesses, NodeRef companyHome)
{
Map<String, Object> inputMap = createInputMap(services, companyHome, context, variableAccesses);
ScriptService scriptService = services.getScriptService();
scriptService.buildCoreModel(inputMap);
Object result = scriptService.executeScriptString(expression, inputMap);
result = convertForJBPM(result, services);
return result;
}
/**
* Convert values for JBPM Context
*
* @param value Object
* @param services ServiceRegistry
* @return Object
*/
@SuppressWarnings("unchecked")
private static Object convertForJBPM(Object value, ServiceRegistry services)
{
if (value == null)
{
return null;
}
else if (value instanceof NodeRef)
{
value = new JBPMNode(((NodeRef)value), services);
}
else if (value instanceof Collection)
{
// recursively convert each value in the collection
Collection<Object> collection = (Collection<Object>)value;
// Note: this needs to be cleaned up - we need to create appropriate collection type based
// on collection contents
boolean isNodeCollection = false;
for (Object obj : collection)
{
if (obj instanceof NodeRef)
{
isNodeCollection = true;
break;
}
}
if (isNodeCollection)
{
JBPMNodeList converted = new JBPMNodeList();
for (Object obj : collection)
{
if (!(obj instanceof NodeRef))
{
throw new WorkflowException("Unable to convert script collection to JBPM value - mixed node/non-node collection");
}
converted.add((JBPMNode)convertForJBPM(obj, services));
}
value = converted;
}
else
{
Collection<Object> converted = new ArrayList<Object>();
for (Object obj : collection)
{
converted.add(convertForJBPM(obj, services));
}
value = converted;
}
}
return value;
}
/**
* Construct map of arguments to pass to script
*
* Based on the <variable> elements of the action configuration.
* @param companyHome TODO
* @param executionContext the execution context
* @param variableAccesses the variable configuration
*
* @return the map of script arguments
*/
private static Map<String, Object> createInputMap(ServiceRegistry services, NodeRef companyHome, ExecutionContext executionContext, List<VariableAccess> variableAccesses)
{
ScriptService scriptService = services.getScriptService();
// initialise global script variables
NodeRef person = getPersonNode(services);
NodeRef userHome = null;
if (person != null)
{
NodeService nodeService = services.getNodeService();
userHome = (NodeRef)nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
}
Map<String, Object> inputMap = scriptService.buildDefaultModel(person, companyHome, userHome, null, null, null);
// initialise process variables
Token token = executionContext.getToken();
inputMap.put("executionContext", executionContext);
inputMap.put("token", token);
Node node = executionContext.getNode();
if (node != null)
{
inputMap.put("node", node);
}
Task task = executionContext.getTask();
if (task != null)
{
inputMap.put("task", task);
}
TaskInstance taskInstance = executionContext.getTaskInstance();
if (taskInstance != null)
{
inputMap.put("taskInstance", taskInstance);
}
// 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;
}
private static NodeRef getPersonNode(ServiceRegistry services)
{
String userName = AuthenticationUtil.getFullyAuthenticatedUser();
if (userName != null)
{
NodeRef person = services.getPersonService().getPerson(userName);
return person;
}
return null;
}
/**
* Determine if there are variables to read from the process context
*
* @param variableAccesses the variables configuration
* @return true => there are variables to read
*/
private static boolean hasReadableVariable(List<VariableAccess> 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 static VariableAccess getWritableVariable(List<VariableAccess> variableAccesses)
{
VariableAccess writable = null;
if (variableAccesses != null)
{
for (VariableAccess variableAccess : variableAccesses)
{
if (variableAccess.isWritable())
{
if (writable != null)
{
throw new WorkflowException("AlfrescoJavaScript supports only one writable variable");
}
writable = variableAccess;
}
}
}
return writable;
}
public void setScript(Element script)
{
this.script = script;
}
public void setRunas(String runas)
{
this.runas = runas;
}
}
package org.alfresco.repo.workflow.jbpm;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.ScriptService;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.dom4j.Element;
import org.jbpm.context.def.VariableAccess;
import org.jbpm.context.exe.ContextInstance;
import org.jbpm.graph.def.Node;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.graph.exe.Token;
import org.jbpm.jpdl.xml.JpdlXmlReader;
import org.jbpm.taskmgmt.def.Task;
import org.jbpm.taskmgmt.exe.TaskInstance;
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:
* <script>
* <expression>
* the script to execute
* </expression>
* <variable name="watcha" access="write"/>
* </script>
*
* 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 ServiceRegistry services;
private NodeRef companyHome;
private Element script;
private String runas;
/**
* {@inheritDoc}
*/
@Override
protected void initialiseHandler(BeanFactory factory)
{
this.services = (ServiceRegistry)factory.getBean(ServiceRegistry.SERVICE_REGISTRY);
Repository repositoryHelper = (Repository)factory.getBean("repositoryHelper");
this.companyHome = repositoryHelper.getCompanyHome();
}
/* (non-Javadoc)
* @see org.jbpm.graph.def.ActionHandler#execute(org.jbpm.graph.exe.ExecutionContext)
*/
public void execute(final ExecutionContext executionContext) throws Exception
{
// validate script
if (script == null)
{
throw new WorkflowException("Script has not been provided");
}
boolean isTextOnly = isScriptOnlyText();
List<VariableAccess> variableAccesses = getVariableAccessors(isTextOnly);
String expression = getExpression(isTextOnly);
// execute
Object result = executeExpression(expression, executionContext, variableAccesses);
// 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);
}
}
private Object executeExpression(String expression, ExecutionContext executionContext, List<VariableAccess> variableAccesses)
{
boolean userChanged = checkFullyAuthenticatedUser(executionContext);
Object result = executeScript(expression, executionContext, variableAccesses);
if(userChanged)
{
AuthenticationUtil.clearCurrentSecurityContext();
}
return result;
}
private Object executeScript(String expression,
ExecutionContext executionContext,
List<VariableAccess> variableAccesses)
{
String user = AuthenticationUtil.getFullyAuthenticatedUser();
if (runas == null && user !=null)
{
return executeScript(executionContext, services, expression, variableAccesses, companyHome);
}
else
{
String runAsUser = runas;
if(runAsUser == null)
{
runAsUser = AuthenticationUtil.getSystemUserName();
}
else
{
validateRunAsUser();
}
return executeScriptAs(runAsUser, expression, executionContext, variableAccesses);
}
}
private Object executeScriptAs(String runAsUser,
final String expression,
final ExecutionContext executionContext,
final List<VariableAccess> variableAccesses)
{
// execute as specified runAsUser
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
{
public Object doWork() throws Exception
{
return executeScript(executionContext, services, expression, variableAccesses,companyHome);
}
}, runAsUser);
}
/**
* Checks a valid Fully Authenticated User is set.
* If none is set then attempts to set the task assignee as the Fully Authenticated User.
* @param executionContext
* @return <code>true</code> if the Fully Authenticated User was changes, otherwise <code>false</code>.
*/
private boolean checkFullyAuthenticatedUser(final ExecutionContext executionContext)
{
if(AuthenticationUtil.getFullyAuthenticatedUser()!= null)
return false;
TaskInstance taskInstance = executionContext.getTaskInstance();
if(taskInstance!=null)
{
String userName = taskInstance.getActorId();
if (userName != null)
{
AuthenticationUtil.setFullyAuthenticatedUser(userName);
return true;
}
}
return false;
}
/**
* Checks that the specified 'runas' field
* specifies a valid username.
*/
private void validateRunAsUser()
{
Boolean runAsExists = AuthenticationUtil.runAs(new RunAsWork<Boolean>()
{
// Validate using System user to ensure sufficient permissions available to access person node.
public Boolean doWork() throws Exception
{
return services.getPersonService().personExists(runas);
}
}, AuthenticationUtil.getSystemUserName());
if (!runAsExists)
{
throw new WorkflowException("runas user '" + runas + "' does not exist.");
}
}
/**
* Gets the expression {@link String} from the script.
* @param isTextOnly Is the script text only or is it XML?
* @return the expression {@link String}.
*/
private String getExpression(boolean isTextOnly)
{
if (isTextOnly)
{
return script.getText().trim();
}
else
{
Element expressionElement = script.element("expression");
if (expressionElement == null)
{
throw new WorkflowException("Script expression has not been provided");
}
return expressionElement.getText().trim();
}
}
@SuppressWarnings("unchecked")
private List<VariableAccess> getVariableAccessors(boolean isTextOnly)
{
if (isTextOnly)
{
return null;
}
else
{
return jpdlReader.readVariableAccesses(script);
}
}
/**
* Is the script specified as text only, or as explicit expression, variable elements
* @return boolean
*/
@SuppressWarnings("unchecked")
private boolean isScriptOnlyText()
{
Iterator<Element> iter = script.elementIterator();
while (iter.hasNext())
{
Element element = iter.next();
if (element.getNodeType() == org.dom4j.Node.ELEMENT_NODE)
{
return false;
}
}
return true;
}
/**
* 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)
* @param companyHome TODO
* @return script result
*/
public static Object executeScript(ExecutionContext context, ServiceRegistry services, String expression, List<VariableAccess> variableAccesses, NodeRef companyHome)
{
Map<String, Object> inputMap = createInputMap(services, companyHome, context, variableAccesses);
ScriptService scriptService = services.getScriptService();
scriptService.buildCoreModel(inputMap);
Object result = scriptService.executeScriptString(expression, inputMap);
result = convertForJBPM(result, services);
return result;
}
/**
* Convert values for JBPM Context
*
* @param value Object
* @param services ServiceRegistry
* @return Object
*/
@SuppressWarnings("unchecked")
private static Object convertForJBPM(Object value, ServiceRegistry services)
{
if (value == null)
{
return null;
}
else if (value instanceof NodeRef)
{
value = new JBPMNode(((NodeRef)value), services);
}
else if (value instanceof Collection)
{
// recursively convert each value in the collection
Collection<Object> collection = (Collection<Object>)value;
// Note: this needs to be cleaned up - we need to create appropriate collection type based
// on collection contents
boolean isNodeCollection = false;
for (Object obj : collection)
{
if (obj instanceof NodeRef)
{
isNodeCollection = true;
break;
}
}
if (isNodeCollection)
{
JBPMNodeList converted = new JBPMNodeList();
for (Object obj : collection)
{
if (!(obj instanceof NodeRef))
{
throw new WorkflowException("Unable to convert script collection to JBPM value - mixed node/non-node collection");
}
converted.add((JBPMNode)convertForJBPM(obj, services));
}
value = converted;
}
else
{
Collection<Object> converted = new ArrayList<Object>();
for (Object obj : collection)
{
converted.add(convertForJBPM(obj, services));
}
value = converted;
}
}
return value;
}
/**
* Construct map of arguments to pass to script
*
* Based on the <variable> elements of the action configuration.
* @param companyHome TODO
* @param executionContext the execution context
* @param variableAccesses the variable configuration
*
* @return the map of script arguments
*/
private static Map<String, Object> createInputMap(ServiceRegistry services, NodeRef companyHome, ExecutionContext executionContext, List<VariableAccess> variableAccesses)
{
ScriptService scriptService = services.getScriptService();
// initialise global script variables
NodeRef person = getPersonNode(services);
NodeRef userHome = null;
if (person != null)
{
NodeService nodeService = services.getNodeService();
userHome = (NodeRef)nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
}
Map<String, Object> inputMap = scriptService.buildDefaultModel(person, companyHome, userHome, null, null, null);
// initialise process variables
Token token = executionContext.getToken();
inputMap.put("executionContext", executionContext);
inputMap.put("token", token);
Node node = executionContext.getNode();
if (node != null)
{
inputMap.put("node", node);
}
Task task = executionContext.getTask();
if (task != null)
{
inputMap.put("task", task);
}
TaskInstance taskInstance = executionContext.getTaskInstance();
if (taskInstance != null)
{
inputMap.put("taskInstance", taskInstance);
}
// 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;
}
private static NodeRef getPersonNode(ServiceRegistry services)
{
String userName = AuthenticationUtil.getFullyAuthenticatedUser();
if (userName != null)
{
NodeRef person = services.getPersonService().getPerson(userName);
return person;
}
return null;
}
/**
* Determine if there are variables to read from the process context
*
* @param variableAccesses the variables configuration
* @return true => there are variables to read
*/
private static boolean hasReadableVariable(List<VariableAccess> 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 static VariableAccess getWritableVariable(List<VariableAccess> variableAccesses)
{
VariableAccess writable = null;
if (variableAccesses != null)
{
for (VariableAccess variableAccess : variableAccesses)
{
if (variableAccess.isWritable())
{
if (writable != null)
{
throw new WorkflowException("AlfrescoJavaScript supports only one writable variable");
}
writable = variableAccess;
}
}
}
return writable;
}
public void setScript(Element script)
{
this.script = script;
}
public void setRunas(String runas)
{
this.runas = runas;
}
}

View File

@@ -1,203 +1,203 @@
package org.alfresco.repo.workflow.jbpm;
import java.io.InputStream;
import org.hibernate.SessionFactory;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.configuration.ObjectFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springmodules.workflow.jbpm31.JbpmFactoryLocator;
/**
* Implementation of Spring Module's JbpmConfigurationFactoryBean for Jbpm 3.2.
*
* @author Costin Leau
* @author davidc
*/
public class AlfrescoJbpmConfigurationFactoryBean implements InitializingBean, FactoryBean<JbpmConfiguration>,
BeanFactoryAware, BeanNameAware, DisposableBean
{
private JbpmConfiguration jbpmConfiguration;
private ObjectFactory objectFactory;
private Resource configuration;
private SessionFactory sessionFactory;
private String contextName = JbpmContext.DEFAULT_JBPM_CONTEXT_NAME;
/**
* FactoryLocator
*/
private final AlfrescoJbpmFactoryLocator factoryLocator = new AlfrescoJbpmFactoryLocator();
/*
* (non-Javadoc)
* @see
* org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org
* .springframework.beans.factory.BeanFactory)
*/
public void setBeanFactory(final BeanFactory beanFactory) throws BeansException
{
// TODO Added to get the build working. A better solution is needed
// long-term.
this.factoryLocator.destroy();
this.factoryLocator.setBeanFactory(beanFactory);
}
/**
* {@inheritDoc}
*/
public void setBeanName(final String name)
{
this.factoryLocator.setBeanName(name);
}
/**
* {@inheritDoc}
*/
public void afterPropertiesSet() throws Exception
{
if (this.configuration == null) { throw new IllegalArgumentException(
"configuration or objectFactory property need to be not null"); }
// 1. Construct Jbpm Configuration
// NOTE: Jbpm 3.2 adds a JbpmConfiguration value to its context
final InputStream stream = this.configuration.getInputStream();
this.jbpmConfiguration = JbpmConfiguration.parseInputStream(stream);
// 2. inject the HB session factory if it is the case
if (this.sessionFactory != null)
{
final JbpmContext context = this.jbpmConfiguration.createJbpmContext(this.contextName);
try
{
context.setSessionFactory(this.sessionFactory);
}
finally
{
context.close();
}
}
}
/**
* {@inheritDoc}
*/
public JbpmConfiguration getObject() throws Exception
{
return this.jbpmConfiguration;
}
/**
* {@inheritDoc}
*/
public Class<JbpmConfiguration> getObjectType()
{
return JbpmConfiguration.class;
}
/**
* {@inheritDoc}
*/
public boolean isSingleton()
{
return true;
}
/**
* @return Returns the configuration.
*/
public Resource getConfiguration()
{
return this.configuration;
}
/**
* @param configuration The configuration to set
*/
public void setConfiguration(final Resource configuration)
{
this.configuration = configuration;
}
/**
* @return Returns the objectFactory.
*/
public ObjectFactory getObjectFactory()
{
return this.objectFactory;
}
/**
* @param objectFactory The objectFactory to set
*/
public void setObjectFactory(final ObjectFactory objectFactory)
{
this.objectFactory = objectFactory;
}
/**
* @return Returns the contextName.
*/
public String getContextName()
{
return this.contextName;
}
/**
* @param contextName The contextName to set
*/
public void setContextName(final String contextName)
{
this.contextName = contextName;
}
/**
* @return Returns the sessionFactory.
*/
public SessionFactory getSessionFactory()
{
return this.sessionFactory;
}
/**
* @param sessionFactory The sessionFactory to set
*/
public void setSessionFactory(final SessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
/**
* {@inheritDoc}
*/
public void destroy() throws Exception
{
this.factoryLocator.destroy();
}
private static class AlfrescoJbpmFactoryLocator extends JbpmFactoryLocator
{
public void destroy()
{
JbpmFactoryLocator.beanFactories.clear();
JbpmFactoryLocator.beanFactoriesNames.clear();
JbpmFactoryLocator.referenceCounter.clear();
JbpmFactoryLocator.canUseDefaultBeanFactory = true;
JbpmFactoryLocator.defaultFactory = null;
}
}
}
package org.alfresco.repo.workflow.jbpm;
import java.io.InputStream;
import org.hibernate.SessionFactory;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.configuration.ObjectFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springmodules.workflow.jbpm31.JbpmFactoryLocator;
/**
* Implementation of Spring Module's JbpmConfigurationFactoryBean for Jbpm 3.2.
*
* @author Costin Leau
* @author davidc
*/
public class AlfrescoJbpmConfigurationFactoryBean implements InitializingBean, FactoryBean<JbpmConfiguration>,
BeanFactoryAware, BeanNameAware, DisposableBean
{
private JbpmConfiguration jbpmConfiguration;
private ObjectFactory objectFactory;
private Resource configuration;
private SessionFactory sessionFactory;
private String contextName = JbpmContext.DEFAULT_JBPM_CONTEXT_NAME;
/**
* FactoryLocator
*/
private final AlfrescoJbpmFactoryLocator factoryLocator = new AlfrescoJbpmFactoryLocator();
/*
* (non-Javadoc)
* @see
* org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org
* .springframework.beans.factory.BeanFactory)
*/
public void setBeanFactory(final BeanFactory beanFactory) throws BeansException
{
// TODO Added to get the build working. A better solution is needed
// long-term.
this.factoryLocator.destroy();
this.factoryLocator.setBeanFactory(beanFactory);
}
/**
* {@inheritDoc}
*/
public void setBeanName(final String name)
{
this.factoryLocator.setBeanName(name);
}
/**
* {@inheritDoc}
*/
public void afterPropertiesSet() throws Exception
{
if (this.configuration == null) { throw new IllegalArgumentException(
"configuration or objectFactory property need to be not null"); }
// 1. Construct Jbpm Configuration
// NOTE: Jbpm 3.2 adds a JbpmConfiguration value to its context
final InputStream stream = this.configuration.getInputStream();
this.jbpmConfiguration = JbpmConfiguration.parseInputStream(stream);
// 2. inject the HB session factory if it is the case
if (this.sessionFactory != null)
{
final JbpmContext context = this.jbpmConfiguration.createJbpmContext(this.contextName);
try
{
context.setSessionFactory(this.sessionFactory);
}
finally
{
context.close();
}
}
}
/**
* {@inheritDoc}
*/
public JbpmConfiguration getObject() throws Exception
{
return this.jbpmConfiguration;
}
/**
* {@inheritDoc}
*/
public Class<JbpmConfiguration> getObjectType()
{
return JbpmConfiguration.class;
}
/**
* {@inheritDoc}
*/
public boolean isSingleton()
{
return true;
}
/**
* @return Returns the configuration.
*/
public Resource getConfiguration()
{
return this.configuration;
}
/**
* @param configuration The configuration to set
*/
public void setConfiguration(final Resource configuration)
{
this.configuration = configuration;
}
/**
* @return Returns the objectFactory.
*/
public ObjectFactory getObjectFactory()
{
return this.objectFactory;
}
/**
* @param objectFactory The objectFactory to set
*/
public void setObjectFactory(final ObjectFactory objectFactory)
{
this.objectFactory = objectFactory;
}
/**
* @return Returns the contextName.
*/
public String getContextName()
{
return this.contextName;
}
/**
* @param contextName The contextName to set
*/
public void setContextName(final String contextName)
{
this.contextName = contextName;
}
/**
* @return Returns the sessionFactory.
*/
public SessionFactory getSessionFactory()
{
return this.sessionFactory;
}
/**
* @param sessionFactory The sessionFactory to set
*/
public void setSessionFactory(final SessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
/**
* {@inheritDoc}
*/
public void destroy() throws Exception
{
this.factoryLocator.destroy();
}
private static class AlfrescoJbpmFactoryLocator extends JbpmFactoryLocator
{
public void destroy()
{
JbpmFactoryLocator.beanFactories.clear();
JbpmFactoryLocator.beanFactoriesNames.clear();
JbpmFactoryLocator.referenceCounter.clear();
JbpmFactoryLocator.canUseDefaultBeanFactory = true;
JbpmFactoryLocator.defaultFactory = null;
}
}
}

View File

@@ -1,101 +1,101 @@
package org.alfresco.repo.workflow.jbpm;
import org.alfresco.repo.lock.JobLockService;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jbpm.JbpmConfiguration;
import org.jbpm.job.executor.JobExecutor;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springmodules.workflow.jbpm31.JbpmFactoryLocator;
/**
* jBPM Job Executor
*
* @author davidc
*/
public class AlfrescoJobExecutor extends JobExecutor
{
private static final long serialVersionUID = -4576396495395482111L;
private static Log log = LogFactory.getLog(JobExecutor.class);
private TransactionService transactionService;
private JbpmConfiguration jbpmConfiguration;
private JobLockService jobLockService;
private boolean jobExecutorLockEnabled = true;
public void setJobExecutorLockEnabled(boolean jobExecutorLockEnabled)
{
this.jobExecutorLockEnabled = jobExecutorLockEnabled;
}
/**
* Is Alfresco Job Executor Lock Enabled
*
* @return true if only one executor thread allowed (including across cluster)
*
* @since 3.2
*/
public boolean getJobExecutorLockEnabled()
{
return this.jobExecutorLockEnabled;
}
/**
* Gets Transaction Service
*
* @return transaction service
*/
public TransactionService getTransactionService()
{
return transactionService;
}
/**
* Gets Job Lock Service
*
* @return job lock service
*
* @since 3.2
*/
public JobLockService getJobLockService()
{
return jobLockService;
}
/**
* Constructor
*/
public AlfrescoJobExecutor()
{
BeanFactoryLocator factoryLocator = new JbpmFactoryLocator();
BeanFactoryReference factory = factoryLocator.useBeanFactory(null);
transactionService = (TransactionService)factory.getFactory().getBean(ServiceRegistry.TRANSACTION_SERVICE.getLocalName());
jobLockService = (JobLockService)factory.getFactory().getBean(ServiceRegistry.JOB_LOCK_SERVICE.getLocalName());
jbpmConfiguration = (JbpmConfiguration)factory.getFactory().getBean("jbpm_configuration");
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
protected synchronized void startThread()
{
String threadName = getNextThreadName();
Thread thread = new AlfrescoJobExecutorThread(threadName, this, jbpmConfiguration, getIdleInterval(), getMaxIdleInterval(), getMaxLockTime(), getHistoryMaxSize());
getThreads().put(threadName, thread);
log.debug("starting new job executor thread '" + threadName + "'");
thread.setDaemon(true);
thread.start();
}
}
package org.alfresco.repo.workflow.jbpm;
import org.alfresco.repo.lock.JobLockService;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jbpm.JbpmConfiguration;
import org.jbpm.job.executor.JobExecutor;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springmodules.workflow.jbpm31.JbpmFactoryLocator;
/**
* jBPM Job Executor
*
* @author davidc
*/
public class AlfrescoJobExecutor extends JobExecutor
{
private static final long serialVersionUID = -4576396495395482111L;
private static Log log = LogFactory.getLog(JobExecutor.class);
private TransactionService transactionService;
private JbpmConfiguration jbpmConfiguration;
private JobLockService jobLockService;
private boolean jobExecutorLockEnabled = true;
public void setJobExecutorLockEnabled(boolean jobExecutorLockEnabled)
{
this.jobExecutorLockEnabled = jobExecutorLockEnabled;
}
/**
* Is Alfresco Job Executor Lock Enabled
*
* @return true if only one executor thread allowed (including across cluster)
*
* @since 3.2
*/
public boolean getJobExecutorLockEnabled()
{
return this.jobExecutorLockEnabled;
}
/**
* Gets Transaction Service
*
* @return transaction service
*/
public TransactionService getTransactionService()
{
return transactionService;
}
/**
* Gets Job Lock Service
*
* @return job lock service
*
* @since 3.2
*/
public JobLockService getJobLockService()
{
return jobLockService;
}
/**
* Constructor
*/
public AlfrescoJobExecutor()
{
BeanFactoryLocator factoryLocator = new JbpmFactoryLocator();
BeanFactoryReference factory = factoryLocator.useBeanFactory(null);
transactionService = (TransactionService)factory.getFactory().getBean(ServiceRegistry.TRANSACTION_SERVICE.getLocalName());
jobLockService = (JobLockService)factory.getFactory().getBean(ServiceRegistry.JOB_LOCK_SERVICE.getLocalName());
jbpmConfiguration = (JbpmConfiguration)factory.getFactory().getBean("jbpm_configuration");
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
protected synchronized void startThread()
{
String threadName = getNextThreadName();
Thread thread = new AlfrescoJobExecutorThread(threadName, this, jbpmConfiguration, getIdleInterval(), getMaxIdleInterval(), getMaxLockTime(), getHistoryMaxSize());
getThreads().put(threadName, thread);
log.debug("starting new job executor thread '" + threadName + "'");
thread.setDaemon(true);
thread.start();
}
}

View File

@@ -1,448 +1,448 @@
package org.alfresco.repo.workflow.jbpm;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import org.alfresco.repo.lock.LockAcquisitionException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.DoNotRetryException;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.db.JobSession;
import org.jbpm.job.Job;
import org.jbpm.job.executor.JobExecutorThread;
import org.jbpm.persistence.JbpmPersistenceException;
import org.jbpm.svc.Services;
import org.jbpm.taskmgmt.exe.TaskInstance;
/**
* Alfresco Job Executor Thread
*
* @author davidc, janv
*/
public class AlfrescoJobExecutorThread extends JobExecutorThread
{
/**
* The name of the lock used to ensure that job executor does not run on
* more than one node at the same time.
*/
private static final QName LOCK_QNAME = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI,
"AlfrescoJbpmJobExecutor");
private static Log logger = LogFactory.getLog(AlfrescoJobExecutorThread.class);
private AlfrescoJobExecutor alfrescoJobExecutor;
private boolean isActive = true;
private long jbpmMaxLockTime;
private long jobLockTTL = 0;
private String jobLockToken = null;
private JbpmConfiguration jbpmConfiguration;
@Override
public void setActive(boolean isActive)
{
this.isActive = isActive;
}
/**
* Constructor
*/
public AlfrescoJobExecutorThread(String name, AlfrescoJobExecutor jobExecutor, JbpmConfiguration jbpmConfiguration,
int idleInterval, int maxIdleInterval, long maxLockTime, int maxHistory)
{
super(name, jobExecutor, jbpmConfiguration, idleInterval, maxIdleInterval, maxLockTime, maxHistory);
this.alfrescoJobExecutor = jobExecutor;
this.jbpmMaxLockTime = maxLockTime;
this.jobLockTTL = jbpmMaxLockTime + (1000 * 60 * 10);
this.jbpmConfiguration = jbpmConfiguration;
}
@SuppressWarnings("rawtypes")
@Override
protected Collection acquireJobs()
{
Collection jobs = Collections.EMPTY_LIST;
if ((isActive) && (!alfrescoJobExecutor.getTransactionService().isReadOnly()))
{
try
{
jobs = alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper()
.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Collection>()
{
public Collection execute() throws Throwable
{
if (jobLockToken != null)
{
refreshExecutorLock(jobLockToken);
}
else
{
jobLockToken = getExecutorLock();
}
try
{
return AlfrescoJobExecutorThread.super.acquireJobs();
}
catch (Throwable t)
{
logger.error("Failed to acquire jobs");
releaseExecutorLock(jobLockToken);
jobLockToken = null;
throw t;
}
}
});
if (jobs != null)
{
if (logger.isDebugEnabled() && (!logger.isTraceEnabled()) && (!jobs.isEmpty()))
{
logger.debug("acquired " + jobs.size() + " job" + ((jobs.size() != 1) ? "s" : ""));
}
if (logger.isTraceEnabled())
{
logger.trace("acquired " + jobs.size() + " job" + ((jobs.size() != 1) ? "s" : "")
+ ((jobs.size() > 0) ? ": " + jobs.toString() : ""));
}
if (jobs.size() == 0)
{
releaseExecutorLock(jobLockToken);
jobLockToken = null;
}
}
}
catch (LockAcquisitionException e)
{
// ignore
jobLockToken = null;
}
}
return jobs;
}
@Override
protected Date getNextDueDate()
{
if (!isActive)
{
return null;
}
return alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper()
.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Date>()
{
public Date execute() throws Throwable
{
return AlfrescoJobExecutorThread.super.getNextDueDate();
}
}, true);
}
/**
* {@inheritDoc}
*/
@Override
protected void executeJob(final Job jobIn)
{
// execute the job as System (ALF-10776) so transaction commit level
// operations have a security context.
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
public Void doWork() throws Exception
{
executeJobImpl(jobIn);
return null;
}
}, getActorId(jobIn));
// clear authentication context for this thread
AuthenticationUtil.clearCurrentSecurityContext();
}
private String getActorId(final Job jobIn)
{
TaskInstance taskInstance = jobIn.getTaskInstance();
if (taskInstance != null)
{
String actorId = taskInstance.getActorId();
if (actorId != null && actorId.length() > 0)
{
return actorId;
}
}
return AuthenticationUtil.getSystemUserName();
}
private void executeJobImpl(final Job jobIn)
{
if ((!isActive) || (alfrescoJobExecutor.getTransactionService().isReadOnly()))
{
return;
}
// based on JBPM 3.3.1 (JobExecutorThread.executeJob)
// - wrap executeJob / deleteJob in Alfresco retries
// - add setRollbackOnly warnings
// - if Alfresco retries fail, attempt to set JBPM job exception/retries
try
{
RetryingTransactionHelper tranHelper = alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper();
tranHelper.doInTransaction(new RetryingTransactionCallback<Object>()
{
public Object execute() throws Throwable
{
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try
{
JobSession jobSession = jbpmContext.getJobSession();
Job job = jobSession.loadJob(jobIn.getId());
if (logger.isTraceEnabled())
{
logger.trace("executing " + job);
}
if (job.execute(jbpmContext))
{
jobSession.deleteJob(job);
if (logger.isDebugEnabled())
{
logger.debug("executed and deleted: " + job);
}
}
// if this job is locked too long
long totalLockTimeInMillis = System.currentTimeMillis() - job.getLockTime().getTime();
if (totalLockTimeInMillis > jbpmMaxLockTime)
{
logger.warn("setRollbackOnly: exceeded maxLockTime (" + jbpmMaxLockTime + ") " + job);
jbpmContext.setRollbackOnly();
}
}
catch(Exception e)
{
if(isPersistenceException(e))
{
throw new AlfrescoJbpmPersistenceException(e);
}
else
{
throw e;
}
}
finally
{
jbpmContext.getSession().flush();
jbpmContext.close();
}
return null;
}
});
}
catch (LockAcquisitionException e)
{
// ignore
jobLockToken = null;
}
catch(JbpmPersistenceException pe)
{
if(Services.isCausedByStaleState(pe))
{
if (logger.isDebugEnabled())
{
logger.debug("optimistic locking failed, couldn't complete job "+ jobIn, pe);
}
}
else handleException(jobIn, pe);
}
catch (final Exception e)
{
handleException(jobIn, e);
}
}
private void handleException(final Job jobIn, final Exception e)
{
if (logger.isErrorEnabled())
{
logger.error("failed to execute " + jobIn, e);
}
try
{
RetryingTransactionHelper tranHelper = alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper();
tranHelper.doInTransaction(new RetryingTransactionCallback<Object>()
{
public Object execute() throws Throwable
{
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try
{
JobSession jobSession = jbpmContext.getJobSession();
Job job = jobSession.loadJob(jobIn.getId());
StringWriter memoryWriter = new StringWriter();
e.printStackTrace(new PrintWriter(memoryWriter));
job.setException(memoryWriter.toString());
if (logger.isDebugEnabled())
{
logger.debug("attempting to update exception/retries: " + job);
}
int retries = 0;
if (isPersistenceException(e) ==false)
{
retries = job.getRetries() -1;
}
job.setRetries(retries);
if (logger.isInfoEnabled())
{
String msg = "updated job exception and set to " + job.getRetries() + " retries: " + jobIn;
logger.info(msg);
}
}
finally
{
jbpmContext.getSession().flush();
jbpmContext.close();
}
return null;
}
});
}
catch (Exception e2)
{
if (logger.isErrorEnabled())
{
logger.error("failed to update job exception/retries " + jobIn, e2);
}
}
}
private String getExecutorLock()
{
String lockToken = null;
if (alfrescoJobExecutor.getJobExecutorLockEnabled())
{
try
{
lockToken = alfrescoJobExecutor.getJobLockService().getLock(LOCK_QNAME, jobLockTTL, 3000, 10);
if (logger.isTraceEnabled())
{
logger.trace(Thread.currentThread().getName() + " got lock token: " + lockToken);
}
}
catch (LockAcquisitionException e)
{
if (logger.isTraceEnabled())
{
logger.trace("Failed to get Alfresco Job Executor lock - may already running in another thread");
}
throw e;
}
}
return lockToken;
}
private void refreshExecutorLock(String lockToken)
{
if (lockToken != null)
{
try
{
alfrescoJobExecutor.getJobLockService().refreshLock(lockToken, LOCK_QNAME, jobLockTTL);
if (logger.isTraceEnabled())
{
logger.trace(Thread.currentThread().getName() + " refreshed lock token: " + lockToken);
}
}
catch (LockAcquisitionException e)
{
if (logger.isTraceEnabled())
{
logger.trace("Failed to refresh Alfresco Job Executor lock - may no longer exist (" + lockToken
+ ")");
}
throw e;
}
}
}
private void releaseExecutorLock(String lockToken)
{
if (lockToken != null)
{
try
{
alfrescoJobExecutor.getJobLockService().releaseLock(lockToken, LOCK_QNAME);
if (logger.isTraceEnabled())
{
logger.trace(Thread.currentThread().getName() + " released lock token: " + lockToken);
}
}
catch (LockAcquisitionException e)
{
if (logger.isTraceEnabled())
{
logger.trace("Failed to release Alfresco Job Executor lock - may no longer exist (" + lockToken
+ ")");
}
throw e;
}
}
}
private boolean isPersistenceException(Throwable throwable)
{
do
{
if (throwable instanceof HibernateException)
{
return true;
}
throwable = throwable.getCause();
}
while (throwable != null);
return false;
}
public static class AlfrescoJbpmPersistenceException extends Exception implements DoNotRetryException
{
private static final long serialVersionUID = -2233119713831272158L;
public AlfrescoJbpmPersistenceException(Throwable cause) {
super(cause);
}
}
}
package org.alfresco.repo.workflow.jbpm;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import org.alfresco.repo.lock.LockAcquisitionException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.DoNotRetryException;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.db.JobSession;
import org.jbpm.job.Job;
import org.jbpm.job.executor.JobExecutorThread;
import org.jbpm.persistence.JbpmPersistenceException;
import org.jbpm.svc.Services;
import org.jbpm.taskmgmt.exe.TaskInstance;
/**
* Alfresco Job Executor Thread
*
* @author davidc, janv
*/
public class AlfrescoJobExecutorThread extends JobExecutorThread
{
/**
* The name of the lock used to ensure that job executor does not run on
* more than one node at the same time.
*/
private static final QName LOCK_QNAME = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI,
"AlfrescoJbpmJobExecutor");
private static Log logger = LogFactory.getLog(AlfrescoJobExecutorThread.class);
private AlfrescoJobExecutor alfrescoJobExecutor;
private boolean isActive = true;
private long jbpmMaxLockTime;
private long jobLockTTL = 0;
private String jobLockToken = null;
private JbpmConfiguration jbpmConfiguration;
@Override
public void setActive(boolean isActive)
{
this.isActive = isActive;
}
/**
* Constructor
*/
public AlfrescoJobExecutorThread(String name, AlfrescoJobExecutor jobExecutor, JbpmConfiguration jbpmConfiguration,
int idleInterval, int maxIdleInterval, long maxLockTime, int maxHistory)
{
super(name, jobExecutor, jbpmConfiguration, idleInterval, maxIdleInterval, maxLockTime, maxHistory);
this.alfrescoJobExecutor = jobExecutor;
this.jbpmMaxLockTime = maxLockTime;
this.jobLockTTL = jbpmMaxLockTime + (1000 * 60 * 10);
this.jbpmConfiguration = jbpmConfiguration;
}
@SuppressWarnings("rawtypes")
@Override
protected Collection acquireJobs()
{
Collection jobs = Collections.EMPTY_LIST;
if ((isActive) && (!alfrescoJobExecutor.getTransactionService().isReadOnly()))
{
try
{
jobs = alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper()
.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Collection>()
{
public Collection execute() throws Throwable
{
if (jobLockToken != null)
{
refreshExecutorLock(jobLockToken);
}
else
{
jobLockToken = getExecutorLock();
}
try
{
return AlfrescoJobExecutorThread.super.acquireJobs();
}
catch (Throwable t)
{
logger.error("Failed to acquire jobs");
releaseExecutorLock(jobLockToken);
jobLockToken = null;
throw t;
}
}
});
if (jobs != null)
{
if (logger.isDebugEnabled() && (!logger.isTraceEnabled()) && (!jobs.isEmpty()))
{
logger.debug("acquired " + jobs.size() + " job" + ((jobs.size() != 1) ? "s" : ""));
}
if (logger.isTraceEnabled())
{
logger.trace("acquired " + jobs.size() + " job" + ((jobs.size() != 1) ? "s" : "")
+ ((jobs.size() > 0) ? ": " + jobs.toString() : ""));
}
if (jobs.size() == 0)
{
releaseExecutorLock(jobLockToken);
jobLockToken = null;
}
}
}
catch (LockAcquisitionException e)
{
// ignore
jobLockToken = null;
}
}
return jobs;
}
@Override
protected Date getNextDueDate()
{
if (!isActive)
{
return null;
}
return alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper()
.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Date>()
{
public Date execute() throws Throwable
{
return AlfrescoJobExecutorThread.super.getNextDueDate();
}
}, true);
}
/**
* {@inheritDoc}
*/
@Override
protected void executeJob(final Job jobIn)
{
// execute the job as System (ALF-10776) so transaction commit level
// operations have a security context.
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
public Void doWork() throws Exception
{
executeJobImpl(jobIn);
return null;
}
}, getActorId(jobIn));
// clear authentication context for this thread
AuthenticationUtil.clearCurrentSecurityContext();
}
private String getActorId(final Job jobIn)
{
TaskInstance taskInstance = jobIn.getTaskInstance();
if (taskInstance != null)
{
String actorId = taskInstance.getActorId();
if (actorId != null && actorId.length() > 0)
{
return actorId;
}
}
return AuthenticationUtil.getSystemUserName();
}
private void executeJobImpl(final Job jobIn)
{
if ((!isActive) || (alfrescoJobExecutor.getTransactionService().isReadOnly()))
{
return;
}
// based on JBPM 3.3.1 (JobExecutorThread.executeJob)
// - wrap executeJob / deleteJob in Alfresco retries
// - add setRollbackOnly warnings
// - if Alfresco retries fail, attempt to set JBPM job exception/retries
try
{
RetryingTransactionHelper tranHelper = alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper();
tranHelper.doInTransaction(new RetryingTransactionCallback<Object>()
{
public Object execute() throws Throwable
{
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try
{
JobSession jobSession = jbpmContext.getJobSession();
Job job = jobSession.loadJob(jobIn.getId());
if (logger.isTraceEnabled())
{
logger.trace("executing " + job);
}
if (job.execute(jbpmContext))
{
jobSession.deleteJob(job);
if (logger.isDebugEnabled())
{
logger.debug("executed and deleted: " + job);
}
}
// if this job is locked too long
long totalLockTimeInMillis = System.currentTimeMillis() - job.getLockTime().getTime();
if (totalLockTimeInMillis > jbpmMaxLockTime)
{
logger.warn("setRollbackOnly: exceeded maxLockTime (" + jbpmMaxLockTime + ") " + job);
jbpmContext.setRollbackOnly();
}
}
catch(Exception e)
{
if(isPersistenceException(e))
{
throw new AlfrescoJbpmPersistenceException(e);
}
else
{
throw e;
}
}
finally
{
jbpmContext.getSession().flush();
jbpmContext.close();
}
return null;
}
});
}
catch (LockAcquisitionException e)
{
// ignore
jobLockToken = null;
}
catch(JbpmPersistenceException pe)
{
if(Services.isCausedByStaleState(pe))
{
if (logger.isDebugEnabled())
{
logger.debug("optimistic locking failed, couldn't complete job "+ jobIn, pe);
}
}
else handleException(jobIn, pe);
}
catch (final Exception e)
{
handleException(jobIn, e);
}
}
private void handleException(final Job jobIn, final Exception e)
{
if (logger.isErrorEnabled())
{
logger.error("failed to execute " + jobIn, e);
}
try
{
RetryingTransactionHelper tranHelper = alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper();
tranHelper.doInTransaction(new RetryingTransactionCallback<Object>()
{
public Object execute() throws Throwable
{
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try
{
JobSession jobSession = jbpmContext.getJobSession();
Job job = jobSession.loadJob(jobIn.getId());
StringWriter memoryWriter = new StringWriter();
e.printStackTrace(new PrintWriter(memoryWriter));
job.setException(memoryWriter.toString());
if (logger.isDebugEnabled())
{
logger.debug("attempting to update exception/retries: " + job);
}
int retries = 0;
if (isPersistenceException(e) ==false)
{
retries = job.getRetries() -1;
}
job.setRetries(retries);
if (logger.isInfoEnabled())
{
String msg = "updated job exception and set to " + job.getRetries() + " retries: " + jobIn;
logger.info(msg);
}
}
finally
{
jbpmContext.getSession().flush();
jbpmContext.close();
}
return null;
}
});
}
catch (Exception e2)
{
if (logger.isErrorEnabled())
{
logger.error("failed to update job exception/retries " + jobIn, e2);
}
}
}
private String getExecutorLock()
{
String lockToken = null;
if (alfrescoJobExecutor.getJobExecutorLockEnabled())
{
try
{
lockToken = alfrescoJobExecutor.getJobLockService().getLock(LOCK_QNAME, jobLockTTL, 3000, 10);
if (logger.isTraceEnabled())
{
logger.trace(Thread.currentThread().getName() + " got lock token: " + lockToken);
}
}
catch (LockAcquisitionException e)
{
if (logger.isTraceEnabled())
{
logger.trace("Failed to get Alfresco Job Executor lock - may already running in another thread");
}
throw e;
}
}
return lockToken;
}
private void refreshExecutorLock(String lockToken)
{
if (lockToken != null)
{
try
{
alfrescoJobExecutor.getJobLockService().refreshLock(lockToken, LOCK_QNAME, jobLockTTL);
if (logger.isTraceEnabled())
{
logger.trace(Thread.currentThread().getName() + " refreshed lock token: " + lockToken);
}
}
catch (LockAcquisitionException e)
{
if (logger.isTraceEnabled())
{
logger.trace("Failed to refresh Alfresco Job Executor lock - may no longer exist (" + lockToken
+ ")");
}
throw e;
}
}
}
private void releaseExecutorLock(String lockToken)
{
if (lockToken != null)
{
try
{
alfrescoJobExecutor.getJobLockService().releaseLock(lockToken, LOCK_QNAME);
if (logger.isTraceEnabled())
{
logger.trace(Thread.currentThread().getName() + " released lock token: " + lockToken);
}
}
catch (LockAcquisitionException e)
{
if (logger.isTraceEnabled())
{
logger.trace("Failed to release Alfresco Job Executor lock - may no longer exist (" + lockToken
+ ")");
}
throw e;
}
}
}
private boolean isPersistenceException(Throwable throwable)
{
do
{
if (throwable instanceof HibernateException)
{
return true;
}
throwable = throwable.getCause();
}
while (throwable != null);
return false;
}
public static class AlfrescoJbpmPersistenceException extends Exception implements DoNotRetryException
{
private static final long serialVersionUID = -2233119713831272158L;
public AlfrescoJbpmPersistenceException(Throwable cause) {
super(cause);
}
}
}

View File

@@ -1,74 +1,74 @@
package org.alfresco.repo.workflow.jbpm;
import org.jbpm.JbpmContext;
import org.jbpm.graph.exe.Token;
import org.jbpm.job.Timer;
import org.jbpm.taskmgmt.exe.TaskInstance;
/**
* Extended JBPM Timer that provides Alfresco context.
*
* NOTE: The action triggered by the timer is executed as the user assigned
* to the task associated with the timer. If not associated with a
* task, the timer is executed unauthenticated.
*
* @author davidc
* @author Nick Smith
*/
public class AlfrescoTimer extends Timer
{
private static final long serialVersionUID = -6618486175822866286L;
/**
* Construct
*/
public AlfrescoTimer()
{
super();
}
/**
* Construct
*
* @param token Token
*/
public AlfrescoTimer(Token token)
{
super(token);
}
/**
* {@inheritDoc}
*/
@Override
public boolean execute(final JbpmContext jbpmContext)
throws Exception
{
// establish authentication context
final TaskInstance taskInstance = getTaskInstance();
// execute timer
boolean deleteTimer = AlfrescoTimer.super.execute(jbpmContext);
// End the task if timer does not repeat.
// Note the order is a little odd here as the task will be ended
// after the token has been signalled to move to the next node.
if (deleteTimer
&& taskInstance != null
&& taskInstance.isOpen())
{
taskInstance.setSignalling(false);
String transitionName = getTransitionName();
if (transitionName==null)
{
taskInstance.end();
}
else
{
taskInstance.end(transitionName);
}
}
return deleteTimer;
}
}
package org.alfresco.repo.workflow.jbpm;
import org.jbpm.JbpmContext;
import org.jbpm.graph.exe.Token;
import org.jbpm.job.Timer;
import org.jbpm.taskmgmt.exe.TaskInstance;
/**
* Extended JBPM Timer that provides Alfresco context.
*
* NOTE: The action triggered by the timer is executed as the user assigned
* to the task associated with the timer. If not associated with a
* task, the timer is executed unauthenticated.
*
* @author davidc
* @author Nick Smith
*/
public class AlfrescoTimer extends Timer
{
private static final long serialVersionUID = -6618486175822866286L;
/**
* Construct
*/
public AlfrescoTimer()
{
super();
}
/**
* Construct
*
* @param token Token
*/
public AlfrescoTimer(Token token)
{
super(token);
}
/**
* {@inheritDoc}
*/
@Override
public boolean execute(final JbpmContext jbpmContext)
throws Exception
{
// establish authentication context
final TaskInstance taskInstance = getTaskInstance();
// execute timer
boolean deleteTimer = AlfrescoTimer.super.execute(jbpmContext);
// End the task if timer does not repeat.
// Note the order is a little odd here as the task will be ended
// after the token has been signalled to move to the next node.
if (deleteTimer
&& taskInstance != null
&& taskInstance.isOpen())
{
taskInstance.setSignalling(false);
String transitionName = getTransitionName();
if (transitionName==null)
{
taskInstance.end();
}
else
{
taskInstance.end(transitionName);
}
}
return deleteTimer;
}
}

View File

@@ -1,243 +1,243 @@
package org.alfresco.repo.workflow.jbpm;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.dom4j.Element;
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.springframework.beans.factory.BeanFactory;
/**
* For each "item in collection", create a fork.
*/
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.
*
* @param executionContext ExecutionContext
* @throws Exception
*/
public void execute(final ExecutionContext executionContext)
throws Exception
{
//
// process action handler arguments
//
if (foreach == null)
{
throw new WorkflowException("forEach has not been provided");
}
// Collection<?> forEachColl = buildForEachCollection(executionContext);
if (var == null || var.length() == 0)
{
throw new WorkflowException("forEach variable name has not been provided");
}
//
// create forked paths
//
Node node = executionContext.getNode();
List<ForkedTransition> forkTransitions = new ArrayList<ForkedTransition>();
Collection<?> forEachColl = buildForEachCollection(executionContext);
// Create a new token and execution context for each node transition and item in list
List<Transition> nodeTransitions = node.getLeavingTransitions();
for (Transition noderansition : nodeTransitions)
{
int iVar = 0;
for (Object item: forEachColl)
{
// create child token to represent new path
Token loopToken = buildChildToken(executionContext, noderansition, iVar);
iVar++;
// assign variable within path
final ExecutionContext newExecutionContext = new ExecutionContext(loopToken);
newExecutionContext.getContextInstance().createVariable(var, item, loopToken);
// record path & transition
ForkedTransition forkTransition = new ForkedTransition();
forkTransition.executionContext = newExecutionContext;
forkTransition.transition = noderansition;
forkTransitions.add(forkTransition);
}
}
//
// let each new token leave the node.
//
for (ForkedTransition forkTransition : forkTransitions)
{
node.leave(forkTransition.executionContext, forkTransition.transition);
}
}
private Token buildChildToken(final ExecutionContext executionContext, Transition noderansition,
int iVar)
{
Token rootToken = executionContext.getToken();
String tokenName = getTokenName(rootToken, noderansition.getName(), iVar);
Token loopToken = new Token(rootToken, tokenName);
loopToken.setTerminationImplicit(true);
executionContext.getJbpmContext().getSession().save(loopToken);
return loopToken;
}
private Collection<?> buildForEachCollection(final ExecutionContext executionContext)
{
// build "for each" collection
String text = foreach.getTextTrim();
if (text != null && text.startsWith("#{"))
{
return evaluateForEachExpression(executionContext, text);
}
return (Collection<?>) FieldInstantiator.getValue(List.class, foreach);
}
private Collection<?> evaluateForEachExpression(final ExecutionContext executionContext, String forEachText)
{
String expression = forEachText.substring(2, forEachText.length() -1);
Object result = AlfrescoJavaScript.executeScript(executionContext, services, expression, null, null);
if (result == null)
{
throw new WorkflowException("forEach expression '" + forEachText + "' evaluates to null");
}
// expression evaluates to string
if (result instanceof String)
{
return buildStrings((String)result);
}
// expression evaluates to Node array
else if (result instanceof Serializable[])
{
return buildJbpmNodes((Serializable[]) result);
}
// expression evaluates to collection
else if (result instanceof Collection<?>)
{
return (Collection<?>)result;
}
else return null;
}
private List<?> buildStrings(String result)
{
String[] results = result.trim().split(",");
return Arrays.asList(results);
}
private List<?> buildJbpmNodes(Serializable[] nodes)
{
List<JBPMNode> jbpmNodes = new ArrayList<JBPMNode>(nodes.length);
for (Serializable node : nodes)
{
if (node instanceof NodeRef)
{
JBPMNode jbpmNode = new JBPMNode((NodeRef)node, services);
jbpmNodes.add(jbpmNode);
}
}
return jbpmNodes;
}
/**
* Create a token name
*
* @param parent Token
* @param transitionName String
* @param loopIndex int
* @return String
*/
protected String getTokenName(Token parent, String transitionName, int loopIndex)
{
String suffix = "." + loopIndex;
if (transitionName == null || transitionName.isEmpty())
{
// No transition name
int size = (parent.getChildren() != null) ? parent.getChildren().size() + 1 : 1;
return buildTokenName("FOREACHFORK", suffix, size);
}
return findFirstAvailableTokenName(parent, transitionName, suffix);
}
private String findFirstAvailableTokenName(Token parent, String transitionName, String suffix)
{
int i = 1;
while (true)
{
String tokenName = buildTokenName(transitionName, suffix, i);
if(!parent.hasChild(tokenName))
{
return tokenName;
}
i++;
}
}
private String buildTokenName(String prefix, String suffix, int count)
{
String countStr = count<2 ? "": Integer.toString(count);
return prefix + countStr + suffix;
}
/**
* Sets the list of objects to be iterated over.
* @param foreach the list of objects to set
*/
public void setForeach(Element foreach)
{
this.foreach = foreach;
}
/**
* Set the name of the variable to which the eleements of <code>foreach</code> are assigned.
* @param var the variable name to set
*/
public void setVar(String var)
{
this.var = var;
}
/**
* Fork Transition
*/
private class ForkedTransition
{
private ExecutionContext executionContext;
private Transition transition;
}
}
package org.alfresco.repo.workflow.jbpm;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.dom4j.Element;
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.springframework.beans.factory.BeanFactory;
/**
* For each "item in collection", create a fork.
*/
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.
*
* @param executionContext ExecutionContext
* @throws Exception
*/
public void execute(final ExecutionContext executionContext)
throws Exception
{
//
// process action handler arguments
//
if (foreach == null)
{
throw new WorkflowException("forEach has not been provided");
}
// Collection<?> forEachColl = buildForEachCollection(executionContext);
if (var == null || var.length() == 0)
{
throw new WorkflowException("forEach variable name has not been provided");
}
//
// create forked paths
//
Node node = executionContext.getNode();
List<ForkedTransition> forkTransitions = new ArrayList<ForkedTransition>();
Collection<?> forEachColl = buildForEachCollection(executionContext);
// Create a new token and execution context for each node transition and item in list
List<Transition> nodeTransitions = node.getLeavingTransitions();
for (Transition noderansition : nodeTransitions)
{
int iVar = 0;
for (Object item: forEachColl)
{
// create child token to represent new path
Token loopToken = buildChildToken(executionContext, noderansition, iVar);
iVar++;
// assign variable within path
final ExecutionContext newExecutionContext = new ExecutionContext(loopToken);
newExecutionContext.getContextInstance().createVariable(var, item, loopToken);
// record path & transition
ForkedTransition forkTransition = new ForkedTransition();
forkTransition.executionContext = newExecutionContext;
forkTransition.transition = noderansition;
forkTransitions.add(forkTransition);
}
}
//
// let each new token leave the node.
//
for (ForkedTransition forkTransition : forkTransitions)
{
node.leave(forkTransition.executionContext, forkTransition.transition);
}
}
private Token buildChildToken(final ExecutionContext executionContext, Transition noderansition,
int iVar)
{
Token rootToken = executionContext.getToken();
String tokenName = getTokenName(rootToken, noderansition.getName(), iVar);
Token loopToken = new Token(rootToken, tokenName);
loopToken.setTerminationImplicit(true);
executionContext.getJbpmContext().getSession().save(loopToken);
return loopToken;
}
private Collection<?> buildForEachCollection(final ExecutionContext executionContext)
{
// build "for each" collection
String text = foreach.getTextTrim();
if (text != null && text.startsWith("#{"))
{
return evaluateForEachExpression(executionContext, text);
}
return (Collection<?>) FieldInstantiator.getValue(List.class, foreach);
}
private Collection<?> evaluateForEachExpression(final ExecutionContext executionContext, String forEachText)
{
String expression = forEachText.substring(2, forEachText.length() -1);
Object result = AlfrescoJavaScript.executeScript(executionContext, services, expression, null, null);
if (result == null)
{
throw new WorkflowException("forEach expression '" + forEachText + "' evaluates to null");
}
// expression evaluates to string
if (result instanceof String)
{
return buildStrings((String)result);
}
// expression evaluates to Node array
else if (result instanceof Serializable[])
{
return buildJbpmNodes((Serializable[]) result);
}
// expression evaluates to collection
else if (result instanceof Collection<?>)
{
return (Collection<?>)result;
}
else return null;
}
private List<?> buildStrings(String result)
{
String[] results = result.trim().split(",");
return Arrays.asList(results);
}
private List<?> buildJbpmNodes(Serializable[] nodes)
{
List<JBPMNode> jbpmNodes = new ArrayList<JBPMNode>(nodes.length);
for (Serializable node : nodes)
{
if (node instanceof NodeRef)
{
JBPMNode jbpmNode = new JBPMNode((NodeRef)node, services);
jbpmNodes.add(jbpmNode);
}
}
return jbpmNodes;
}
/**
* Create a token name
*
* @param parent Token
* @param transitionName String
* @param loopIndex int
* @return String
*/
protected String getTokenName(Token parent, String transitionName, int loopIndex)
{
String suffix = "." + loopIndex;
if (transitionName == null || transitionName.isEmpty())
{
// No transition name
int size = (parent.getChildren() != null) ? parent.getChildren().size() + 1 : 1;
return buildTokenName("FOREACHFORK", suffix, size);
}
return findFirstAvailableTokenName(parent, transitionName, suffix);
}
private String findFirstAvailableTokenName(Token parent, String transitionName, String suffix)
{
int i = 1;
while (true)
{
String tokenName = buildTokenName(transitionName, suffix, i);
if(!parent.hasChild(tokenName))
{
return tokenName;
}
i++;
}
}
private String buildTokenName(String prefix, String suffix, int count)
{
String countStr = count<2 ? "": Integer.toString(count);
return prefix + countStr + suffix;
}
/**
* Sets the list of objects to be iterated over.
* @param foreach the list of objects to set
*/
public void setForeach(Element foreach)
{
this.foreach = foreach;
}
/**
* Set the name of the variable to which the eleements of <code>foreach</code> are assigned.
* @param var the variable name to set
*/
public void setVar(String var)
{
this.var = var;
}
/**
* Fork Transition
*/
private class ForkedTransition
{
private ExecutionContext executionContext;
private Transition transition;
}
}

View File

@@ -1,61 +1,61 @@
package org.alfresco.repo.workflow.jbpm;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.jpdl.JpdlException;
import org.jbpm.jpdl.par.ProcessArchive;
import org.jbpm.jpdl.par.ProcessArchiveParser;
import org.jbpm.jpdl.xml.JpdlXmlReader;
import org.xml.sax.InputSource;
/**
* Alfresco specific process archive parser to allow for extensions
* to jPDL.
*
* @author davidc
*/
public class JBPMJpdlArchiveParser implements ProcessArchiveParser
{
private static final long serialVersionUID = 1L;
/* (non-Javadoc)
* @see org.jbpm.jpdl.par.ProcessArchiveParser#readFromArchive(org.jbpm.jpdl.par.ProcessArchive, org.jbpm.graph.def.ProcessDefinition)
*/
public ProcessDefinition readFromArchive(ProcessArchive processArchive, ProcessDefinition processDefinition)
throws JpdlException
{
// NOTE: This method implementation is a copy from the JpdlXmlReader class
// with the difference of constructing an AlfrescoCreateTimerAction.
// It may need to be updated whenever a jbpm library upgrade is performed.
try
{
byte[] processBytes = processArchive.getEntry("processdefinition.xml");
if (processBytes == null)
{
throw new JpdlException("no processdefinition.xml inside process archive");
}
// creating the JpdlXmlReader
InputStream processInputStream = new ByteArrayInputStream(processBytes);
InputSource processInputSource = new InputSource(processInputStream);
JpdlXmlReader jpdlXmlReader = new JBPMJpdlXmlReader(processInputSource, processArchive);
processDefinition = jpdlXmlReader.readProcessDefinition();
// close all the streams
jpdlXmlReader.close();
processInputStream.close();
}
catch (IOException e)
{
throw new JpdlException("io problem while reading processdefinition.xml: " + e.getMessage(), e);
}
return processDefinition;
}
}
package org.alfresco.repo.workflow.jbpm;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.jpdl.JpdlException;
import org.jbpm.jpdl.par.ProcessArchive;
import org.jbpm.jpdl.par.ProcessArchiveParser;
import org.jbpm.jpdl.xml.JpdlXmlReader;
import org.xml.sax.InputSource;
/**
* Alfresco specific process archive parser to allow for extensions
* to jPDL.
*
* @author davidc
*/
public class JBPMJpdlArchiveParser implements ProcessArchiveParser
{
private static final long serialVersionUID = 1L;
/* (non-Javadoc)
* @see org.jbpm.jpdl.par.ProcessArchiveParser#readFromArchive(org.jbpm.jpdl.par.ProcessArchive, org.jbpm.graph.def.ProcessDefinition)
*/
public ProcessDefinition readFromArchive(ProcessArchive processArchive, ProcessDefinition processDefinition)
throws JpdlException
{
// NOTE: This method implementation is a copy from the JpdlXmlReader class
// with the difference of constructing an AlfrescoCreateTimerAction.
// It may need to be updated whenever a jbpm library upgrade is performed.
try
{
byte[] processBytes = processArchive.getEntry("processdefinition.xml");
if (processBytes == null)
{
throw new JpdlException("no processdefinition.xml inside process archive");
}
// creating the JpdlXmlReader
InputStream processInputStream = new ByteArrayInputStream(processBytes);
InputSource processInputSource = new InputSource(processInputStream);
JpdlXmlReader jpdlXmlReader = new JBPMJpdlXmlReader(processInputSource, processArchive);
processDefinition = jpdlXmlReader.readProcessDefinition();
// close all the streams
jpdlXmlReader.close();
processInputStream.close();
}
catch (IOException e)
{
throw new JpdlException("io problem while reading processdefinition.xml: " + e.getMessage(), e);
}
return processDefinition;
}
}

View File

@@ -1,155 +1,155 @@
package org.alfresco.repo.workflow.jbpm;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;
import org.dom4j.Element;
import org.jbpm.graph.def.Action;
import org.jbpm.graph.def.Event;
import org.jbpm.graph.def.Node;
import org.jbpm.instantiation.Delegation;
import org.jbpm.jpdl.xml.JpdlXmlReader;
import org.jbpm.jpdl.xml.Problem;
import org.jbpm.jpdl.xml.ProblemListener;
import org.jbpm.scheduler.def.CancelTimerAction;
import org.jbpm.scheduler.def.CreateTimerAction;
import org.jbpm.taskmgmt.def.Task;
import org.xml.sax.InputSource;
/**
* Extended JpdlXmlReader with access to problems encountered during compile.
*
* Provides extension to Timers (to allow for absolute date).
*
* @author davidc
*/
public class JBPMJpdlXmlReader extends JpdlXmlReader
{
private static final long serialVersionUID = -753730152120696221L;
/*
* Construct
*/
public JBPMJpdlXmlReader(InputStream inputStream)
{
super(new InputSource(inputStream));
}
/*
* Construct
*/
public JBPMJpdlXmlReader(InputSource inputSource, ProblemListener problemListener)
{
super(inputSource, problemListener);
}
/*
* Construct
*/
public JBPMJpdlXmlReader(InputSource inputSource)
{
super(inputSource);
}
/*
* Construct
*/
public JBPMJpdlXmlReader(Reader reader)
{
super(reader);
}
/**
* {@inheritDoc}
*/
@Override
protected void readNodeTimer(Element timerElement, Node node)
{
// NOTE: This method implementation is a copy from the JpdlXmlReader class
// with the difference of constructing an AlfrescoCreateTimerAction.
// It may need to be updated whenever a jbpm library upgrade is performed.
String name = timerElement.attributeValue("name", node.getName());
CreateTimerAction createTimerAction = new AlfrescoCreateTimerAction();
createTimerAction.read(timerElement, this);
createTimerAction.setTimerName(name);
createTimerAction.setTimerAction(readSingleAction(timerElement));
addAction(node, Event.EVENTTYPE_NODE_ENTER, createTimerAction);
CancelTimerAction cancelTimerAction = new CancelTimerAction();
cancelTimerAction.setTimerName(name);
addAction(node, Event.EVENTTYPE_NODE_LEAVE, cancelTimerAction);
}
/**
* {@inheritDoc}
*/
@Override
protected void readTaskTimer(Element timerElement, Task task)
{
// NOTE: This method implementation is a copy from the JpdlXmlReader class
// with the difference of constructing an AlfrescoCreateTimerAction.
// It may need to be updated whenever a jbpm library upgrade is performed.
String name = timerElement.attributeValue("name", task.getName());
if (name == null)
name = "timer-for-task-" + task.getId();
CreateTimerAction createTimerAction = new AlfrescoCreateTimerAction();
createTimerAction.read(timerElement, this);
createTimerAction.setTimerName(name);
Action action = null;
if ("timer".equals(timerElement.getName()))
{
action = readSingleAction(timerElement);
}
else
{
Delegation delegation = createMailDelegation("task-reminder", null, null, null, null);
action = new Action(delegation);
}
createTimerAction.setTimerAction(action);
addAction(task, Event.EVENTTYPE_TASK_CREATE, createTimerAction);
// read the cancel-event types
Collection<String> cancelEventTypes = new ArrayList<String>();
String cancelEventTypeText = timerElement.attributeValue("cancel-event");
if (cancelEventTypeText != null)
{
// cancel-event is a comma separated list of events
StringTokenizer tokenizer = new StringTokenizer(cancelEventTypeText, ",");
while (tokenizer.hasMoreTokens())
{
cancelEventTypes.add(tokenizer.nextToken().trim());
}
}
else
{
// set the default
cancelEventTypes.add(Event.EVENTTYPE_TASK_END);
}
for (String cancelEventType : cancelEventTypes)
{
CancelTimerAction cancelTimerAction = new CancelTimerAction();
cancelTimerAction.setTimerName(name);
addAction(task, cancelEventType, cancelTimerAction);
}
}
/**
* Gets the problems
*
* @return problems
*/
@SuppressWarnings("unchecked")
public List<Problem> getProblems()
{
return problems;
}
}
package org.alfresco.repo.workflow.jbpm;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;
import org.dom4j.Element;
import org.jbpm.graph.def.Action;
import org.jbpm.graph.def.Event;
import org.jbpm.graph.def.Node;
import org.jbpm.instantiation.Delegation;
import org.jbpm.jpdl.xml.JpdlXmlReader;
import org.jbpm.jpdl.xml.Problem;
import org.jbpm.jpdl.xml.ProblemListener;
import org.jbpm.scheduler.def.CancelTimerAction;
import org.jbpm.scheduler.def.CreateTimerAction;
import org.jbpm.taskmgmt.def.Task;
import org.xml.sax.InputSource;
/**
* Extended JpdlXmlReader with access to problems encountered during compile.
*
* Provides extension to Timers (to allow for absolute date).
*
* @author davidc
*/
public class JBPMJpdlXmlReader extends JpdlXmlReader
{
private static final long serialVersionUID = -753730152120696221L;
/*
* Construct
*/
public JBPMJpdlXmlReader(InputStream inputStream)
{
super(new InputSource(inputStream));
}
/*
* Construct
*/
public JBPMJpdlXmlReader(InputSource inputSource, ProblemListener problemListener)
{
super(inputSource, problemListener);
}
/*
* Construct
*/
public JBPMJpdlXmlReader(InputSource inputSource)
{
super(inputSource);
}
/*
* Construct
*/
public JBPMJpdlXmlReader(Reader reader)
{
super(reader);
}
/**
* {@inheritDoc}
*/
@Override
protected void readNodeTimer(Element timerElement, Node node)
{
// NOTE: This method implementation is a copy from the JpdlXmlReader class
// with the difference of constructing an AlfrescoCreateTimerAction.
// It may need to be updated whenever a jbpm library upgrade is performed.
String name = timerElement.attributeValue("name", node.getName());
CreateTimerAction createTimerAction = new AlfrescoCreateTimerAction();
createTimerAction.read(timerElement, this);
createTimerAction.setTimerName(name);
createTimerAction.setTimerAction(readSingleAction(timerElement));
addAction(node, Event.EVENTTYPE_NODE_ENTER, createTimerAction);
CancelTimerAction cancelTimerAction = new CancelTimerAction();
cancelTimerAction.setTimerName(name);
addAction(node, Event.EVENTTYPE_NODE_LEAVE, cancelTimerAction);
}
/**
* {@inheritDoc}
*/
@Override
protected void readTaskTimer(Element timerElement, Task task)
{
// NOTE: This method implementation is a copy from the JpdlXmlReader class
// with the difference of constructing an AlfrescoCreateTimerAction.
// It may need to be updated whenever a jbpm library upgrade is performed.
String name = timerElement.attributeValue("name", task.getName());
if (name == null)
name = "timer-for-task-" + task.getId();
CreateTimerAction createTimerAction = new AlfrescoCreateTimerAction();
createTimerAction.read(timerElement, this);
createTimerAction.setTimerName(name);
Action action = null;
if ("timer".equals(timerElement.getName()))
{
action = readSingleAction(timerElement);
}
else
{
Delegation delegation = createMailDelegation("task-reminder", null, null, null, null);
action = new Action(delegation);
}
createTimerAction.setTimerAction(action);
addAction(task, Event.EVENTTYPE_TASK_CREATE, createTimerAction);
// read the cancel-event types
Collection<String> cancelEventTypes = new ArrayList<String>();
String cancelEventTypeText = timerElement.attributeValue("cancel-event");
if (cancelEventTypeText != null)
{
// cancel-event is a comma separated list of events
StringTokenizer tokenizer = new StringTokenizer(cancelEventTypeText, ",");
while (tokenizer.hasMoreTokens())
{
cancelEventTypes.add(tokenizer.nextToken().trim());
}
}
else
{
// set the default
cancelEventTypes.add(Event.EVENTTYPE_TASK_END);
}
for (String cancelEventType : cancelEventTypes)
{
CancelTimerAction cancelTimerAction = new CancelTimerAction();
cancelTimerAction.setTimerName(name);
addAction(task, cancelEventType, cancelTimerAction);
}
}
/**
* Gets the problems
*
* @return problems
*/
@SuppressWarnings("unchecked")
public List<Problem> getProblems()
{
return problems;
}
}

View File

@@ -1,82 +1,82 @@
package org.alfresco.repo.workflow.jbpm;
import java.io.Serializable;
import java.util.Date;
import org.alfresco.repo.jscript.ScriptNode;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
/**
* Scriptable Node suitable for JBPM Beanshell access
*
* TODO: This implementation derives from the JavaScript Alfresco Node. At
* some point we should look to having a script-independent node with various
* script-specific sub-types (and value conversions).
*
* @author davidc
*/
public class JBPMNode extends ScriptNode
{
private static final long serialVersionUID = -826970280203254365L;
/**
* Construct
*
* @param nodeRef node reference
* @param services services
*/
public JBPMNode(NodeRef nodeRef, ServiceRegistry services)
{
super(nodeRef, services, NullScope.instance());
}
/**
* {@inheritDoc}
*/
@Override
protected NodeValueConverter createValueConverter()
{
return new JBPMNodeConverter();
}
/**
* Value converter for beanshell.
*/
private class JBPMNodeConverter extends NodeValueConverter
{
@Override
public Serializable convertValueForRepo(Serializable value)
{
if (value instanceof Date)
{
return value;
}
else
{
return super.convertValueForRepo(value);
}
}
@Override
public Serializable convertValueForScript(ServiceRegistry serviceRegistry, Scriptable theScope, QName qname, Serializable value)
{
if (value instanceof NodeRef)
{
return new JBPMNode(((NodeRef)value), serviceRegistry);
}
else if (value instanceof Date)
{
return value;
}
else
{
return super.convertValueForScript(serviceRegistry, theScope, qname, value);
}
}
}
}
package org.alfresco.repo.workflow.jbpm;
import java.io.Serializable;
import java.util.Date;
import org.alfresco.repo.jscript.ScriptNode;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
/**
* Scriptable Node suitable for JBPM Beanshell access
*
* TODO: This implementation derives from the JavaScript Alfresco Node. At
* some point we should look to having a script-independent node with various
* script-specific sub-types (and value conversions).
*
* @author davidc
*/
public class JBPMNode extends ScriptNode
{
private static final long serialVersionUID = -826970280203254365L;
/**
* Construct
*
* @param nodeRef node reference
* @param services services
*/
public JBPMNode(NodeRef nodeRef, ServiceRegistry services)
{
super(nodeRef, services, NullScope.instance());
}
/**
* {@inheritDoc}
*/
@Override
protected NodeValueConverter createValueConverter()
{
return new JBPMNodeConverter();
}
/**
* Value converter for beanshell.
*/
private class JBPMNodeConverter extends NodeValueConverter
{
@Override
public Serializable convertValueForRepo(Serializable value)
{
if (value instanceof Date)
{
return value;
}
else
{
return super.convertValueForRepo(value);
}
}
@Override
public Serializable convertValueForScript(ServiceRegistry serviceRegistry, Scriptable theScope, QName qname, Serializable value)
{
if (value instanceof NodeRef)
{
return new JBPMNode(((NodeRef)value), serviceRegistry);
}
else if (value instanceof Date)
{
return value;
}
else
{
return super.convertValueForScript(serviceRegistry, theScope, qname, value);
}
}
}
}

View File

@@ -1,15 +1,15 @@
package org.alfresco.repo.workflow.jbpm;
import java.util.ArrayList;
/**
* List of jBPM Nodes
*
* @author davidc
*/
public class JBPMNodeList extends ArrayList<JBPMNode>
{
private static final long serialVersionUID = 1376915749912156471L;
}
package org.alfresco.repo.workflow.jbpm;
import java.util.ArrayList;
/**
* List of jBPM Nodes
*
* @author davidc
*/
public class JBPMNodeList extends ArrayList<JBPMNode>
{
private static final long serialVersionUID = 1376915749912156471L;
}

View File

@@ -1,57 +1,57 @@
package org.alfresco.repo.workflow.jbpm;
import org.jbpm.job.executor.JobExecutor;
import org.springframework.context.ApplicationEvent;
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
import org.springmodules.workflow.jbpm31.JbpmTemplate;
/**
* JBPM Scheduler
*
* Manages lifecycle of Jbpm Job Executor.
*
* @author davidc
*/
public class JBPMScheduler extends AbstractLifecycleBean
{
private JobExecutor executor = null;
private JbpmTemplate jbpmTemplate;
private boolean JbpmEngineEnabled = false;
/**
* @param jbpmTemplate JbpmTemplate
*/
public void setJBPMTemplate(JbpmTemplate jbpmTemplate)
{
this.jbpmTemplate = jbpmTemplate;
}
/**
* @param jbpmEngineEnabled whether or not the JBPM-Engine is enables. Please note that we are
* not using the WorklfowAdminService since this is only initialized later in the sequence.
*/
public void setJBPMEngineEnabled(boolean jbpmEngineEnabled) {
JbpmEngineEnabled = jbpmEngineEnabled;
}
@Override
protected void onBootstrap(ApplicationEvent event)
{
if(JbpmEngineEnabled)
{
executor = jbpmTemplate.getJbpmConfiguration().getJobExecutor();
executor.start();
}
}
@Override
protected void onShutdown(ApplicationEvent event)
{
if(JbpmEngineEnabled && executor.isStarted())
{
executor.stop();
}
}
}
package org.alfresco.repo.workflow.jbpm;
import org.jbpm.job.executor.JobExecutor;
import org.springframework.context.ApplicationEvent;
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
import org.springmodules.workflow.jbpm31.JbpmTemplate;
/**
* JBPM Scheduler
*
* Manages lifecycle of Jbpm Job Executor.
*
* @author davidc
*/
public class JBPMScheduler extends AbstractLifecycleBean
{
private JobExecutor executor = null;
private JbpmTemplate jbpmTemplate;
private boolean JbpmEngineEnabled = false;
/**
* @param jbpmTemplate JbpmTemplate
*/
public void setJBPMTemplate(JbpmTemplate jbpmTemplate)
{
this.jbpmTemplate = jbpmTemplate;
}
/**
* @param jbpmEngineEnabled whether or not the JBPM-Engine is enables. Please note that we are
* not using the WorklfowAdminService since this is only initialized later in the sequence.
*/
public void setJBPMEngineEnabled(boolean jbpmEngineEnabled) {
JbpmEngineEnabled = jbpmEngineEnabled;
}
@Override
protected void onBootstrap(ApplicationEvent event)
{
if(JbpmEngineEnabled)
{
executor = jbpmTemplate.getJbpmConfiguration().getJobExecutor();
executor.start();
}
}
@Override
protected void onShutdown(ApplicationEvent event)
{
if(JbpmEngineEnabled && executor.isStarted())
{
executor.stop();
}
}
}

View File

@@ -1,53 +1,53 @@
package org.alfresco.repo.workflow.jbpm;
import org.alfresco.repo.workflow.BPMEngineRegistry;
import org.jbpm.graph.def.ActionHandler;
import org.jbpm.graph.exe.ExecutionContext;
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 Action Hander with access to
* Alfresco Spring beans.
*
* @author davidc
*/
public abstract class JBPMSpringActionHandler implements ActionHandler
{
private static final long serialVersionUID = 6848343645482681529L;
/**
* Construct
*/
protected JBPMSpringActionHandler()
{
// 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);
/**
* Gets the workflow instance id of the currently executing workflow
*
* @param context jBPM execution context
* @return workflow instance id
*/
protected String getWorkflowInstanceId(ExecutionContext context)
{
String id = new Long(context.getProcessInstance().getId()).toString();
return BPMEngineRegistry.createGlobalId(JBPMEngine.ENGINE_ID, id);
}
}
package org.alfresco.repo.workflow.jbpm;
import org.alfresco.repo.workflow.BPMEngineRegistry;
import org.jbpm.graph.def.ActionHandler;
import org.jbpm.graph.exe.ExecutionContext;
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 Action Hander with access to
* Alfresco Spring beans.
*
* @author davidc
*/
public abstract class JBPMSpringActionHandler implements ActionHandler
{
private static final long serialVersionUID = 6848343645482681529L;
/**
* Construct
*/
protected JBPMSpringActionHandler()
{
// 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);
/**
* Gets the workflow instance id of the currently executing workflow
*
* @param context jBPM execution context
* @return workflow instance id
*/
protected String getWorkflowInstanceId(ExecutionContext context)
{
String id = new Long(context.getProcessInstance().getId()).toString();
return BPMEngineRegistry.createGlobalId(JBPMEngine.ENGINE_ID, id);
}
}

View File

@@ -1,39 +1,39 @@
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
{
private static final long serialVersionUID = -2233750219905283562L;
/**
* 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);
}
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
{
private static final long serialVersionUID = -2233750219905283562L;
/**
* 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);
}

View File

@@ -1,47 +1,47 @@
package org.alfresco.repo.workflow.jbpm;
import org.alfresco.service.descriptor.DescriptorService;
import org.jbpm.graph.exe.ExecutionContext;
import org.springframework.beans.factory.BeanFactory;
/**
* Test Spring based Jbpm Action Handler
*
* @author davidc
*/
public class JBPMTestSpringActionHandler extends JBPMSpringActionHandler
{
private static final long serialVersionUID = -7659883022289711381L;
private DescriptorService descriptorService;
private String value;
/**
* Setter accessible from jBPM jPDL
* @param value String
*/
public void setValue(String value)
{
this.value = value;
}
/*
* (non-Javadoc)
* @see org.jbpm.graph.def.ActionHandler#execute(org.jbpm.graph.exe.ExecutionContext)
*/
public void execute(ExecutionContext arg0) throws Exception
{
String result = "Repo: " + descriptorService.getServerDescriptor().getVersion();
result += ", Value: " + value + ", Node: " + arg0.getNode().getName() + ", Token: " + arg0.getToken().getFullName();
arg0.getContextInstance().setVariable("jbpm.test.action.result", result);
}
@Override
protected void initialiseHandler(BeanFactory factory)
{
descriptorService = factory.getBean("DescriptorService", DescriptorService.class);
}
}
package org.alfresco.repo.workflow.jbpm;
import org.alfresco.service.descriptor.DescriptorService;
import org.jbpm.graph.exe.ExecutionContext;
import org.springframework.beans.factory.BeanFactory;
/**
* Test Spring based Jbpm Action Handler
*
* @author davidc
*/
public class JBPMTestSpringActionHandler extends JBPMSpringActionHandler
{
private static final long serialVersionUID = -7659883022289711381L;
private DescriptorService descriptorService;
private String value;
/**
* Setter accessible from jBPM jPDL
* @param value String
*/
public void setValue(String value)
{
this.value = value;
}
/*
* (non-Javadoc)
* @see org.jbpm.graph.def.ActionHandler#execute(org.jbpm.graph.exe.ExecutionContext)
*/
public void execute(ExecutionContext arg0) throws Exception
{
String result = "Repo: " + descriptorService.getServerDescriptor().getVersion();
result += ", Value: " + value + ", Node: " + arg0.getNode().getName() + ", Token: " + arg0.getToken().getFullName();
arg0.getContextInstance().setVariable("jbpm.test.action.result", result);
}
@Override
protected void initialiseHandler(BeanFactory factory)
{
descriptorService = factory.getBean("DescriptorService", DescriptorService.class);
}
}

View File

@@ -1,211 +1,211 @@
package org.alfresco.repo.workflow.jbpm;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.TransactionListener;
import org.alfresco.util.GUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
import org.springmodules.workflow.jbpm31.JbpmTemplate;
/**
* JBPM Template that manages JBPM Context at the Alfresco Transaction level
*
* @author davidc
*/
public class JBPMTransactionTemplate extends JbpmTemplate
implements TransactionListener
{
// Logging support
private static Log logger = LogFactory.getLog("org.alfresco.repo.workflow");
/** Id used in equals and hash */
private String id = GUID.generate();
// JBPM Template Keys
private static final String JBPM_CONTEXT_KEY = JBPMTransactionTemplate.class.getName() + ".context";
/** Use local or transaction bound JBPM Context */
private boolean localContext = true;
/*
* Constructor
*/
public JBPMTransactionTemplate()
{
super();
}
/*
* Constructor
*/
public JBPMTransactionTemplate(JbpmConfiguration jbpmConfiguration, ProcessDefinition processDefinition)
{
super(jbpmConfiguration, processDefinition);
}
/*
* Constructor
*/
public JBPMTransactionTemplate(JbpmConfiguration jbpmConfiguration)
{
super(jbpmConfiguration);
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("synthetic-access")
@Override
public void afterPropertiesSet() throws Exception
{
try
{
JBPMTransactionTemplate.super.afterPropertiesSet();
}
finally
{
localContext = false;
}
}
/**
* {@inheritDoc}
*/
@Override
protected JbpmContext getContext()
{
if (localContext)
{
return super.getContext();
}
else
{
JbpmContext context = (JbpmContext)AlfrescoTransactionSupport.getResource(JBPM_CONTEXT_KEY);
if (context == null)
{
context = super.getContext();
AlfrescoTransactionSupport.bindResource(JBPM_CONTEXT_KEY, context);
AlfrescoTransactionSupport.bindListener(this);
if (logger.isDebugEnabled())
logger.debug("Attached JBPM Context to transaction " + AlfrescoTransactionSupport.getTransactionId());
}
return context;
}
}
/**
* {@inheritDoc}
*/
@Override
protected void releaseContext(JbpmContext jbpmContext)
{
if (localContext)
{
jbpmContext.close();
}
else
{
// NOTE: Defer release to end of transaction
}
}
/**
* {@inheritDoc}
*/
public void flush()
{
//NOOP
}
/**
* {@inheritDoc}
*/
public void beforeCommit(boolean readOnly)
{
//NOOP
}
/**
* {@inheritDoc}
*/
public void beforeCompletion()
{
//NOOP
}
/**
* {@inheritDoc}
*/
public void afterCommit()
{
JbpmContext context = (JbpmContext)AlfrescoTransactionSupport.getResource(JBPM_CONTEXT_KEY);
if (context != null)
{
super.releaseContext(context);
if (logger.isDebugEnabled())
logger.debug("Detached (commit) JBPM Context from transaction " + AlfrescoTransactionSupport.getTransactionId());
}
}
/**
* {@inheritDoc}
*/
public void afterRollback()
{
JbpmContext context = (JbpmContext)AlfrescoTransactionSupport.getResource(JBPM_CONTEXT_KEY);
if (context != null)
{
super.releaseContext(context);
if (logger.isDebugEnabled())
logger.debug("Detached (rollback) JBPM Context from transaction " + AlfrescoTransactionSupport.getTransactionId());
}
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode()
{
return this.id.hashCode();
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj instanceof JBPMTransactionTemplate)
{
JBPMTransactionTemplate that = (JBPMTransactionTemplate) obj;
return (this.id.equals(that.id));
}
else
{
return false;
}
}
}
package org.alfresco.repo.workflow.jbpm;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.TransactionListener;
import org.alfresco.util.GUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
import org.springmodules.workflow.jbpm31.JbpmTemplate;
/**
* JBPM Template that manages JBPM Context at the Alfresco Transaction level
*
* @author davidc
*/
public class JBPMTransactionTemplate extends JbpmTemplate
implements TransactionListener
{
// Logging support
private static Log logger = LogFactory.getLog("org.alfresco.repo.workflow");
/** Id used in equals and hash */
private String id = GUID.generate();
// JBPM Template Keys
private static final String JBPM_CONTEXT_KEY = JBPMTransactionTemplate.class.getName() + ".context";
/** Use local or transaction bound JBPM Context */
private boolean localContext = true;
/*
* Constructor
*/
public JBPMTransactionTemplate()
{
super();
}
/*
* Constructor
*/
public JBPMTransactionTemplate(JbpmConfiguration jbpmConfiguration, ProcessDefinition processDefinition)
{
super(jbpmConfiguration, processDefinition);
}
/*
* Constructor
*/
public JBPMTransactionTemplate(JbpmConfiguration jbpmConfiguration)
{
super(jbpmConfiguration);
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("synthetic-access")
@Override
public void afterPropertiesSet() throws Exception
{
try
{
JBPMTransactionTemplate.super.afterPropertiesSet();
}
finally
{
localContext = false;
}
}
/**
* {@inheritDoc}
*/
@Override
protected JbpmContext getContext()
{
if (localContext)
{
return super.getContext();
}
else
{
JbpmContext context = (JbpmContext)AlfrescoTransactionSupport.getResource(JBPM_CONTEXT_KEY);
if (context == null)
{
context = super.getContext();
AlfrescoTransactionSupport.bindResource(JBPM_CONTEXT_KEY, context);
AlfrescoTransactionSupport.bindListener(this);
if (logger.isDebugEnabled())
logger.debug("Attached JBPM Context to transaction " + AlfrescoTransactionSupport.getTransactionId());
}
return context;
}
}
/**
* {@inheritDoc}
*/
@Override
protected void releaseContext(JbpmContext jbpmContext)
{
if (localContext)
{
jbpmContext.close();
}
else
{
// NOTE: Defer release to end of transaction
}
}
/**
* {@inheritDoc}
*/
public void flush()
{
//NOOP
}
/**
* {@inheritDoc}
*/
public void beforeCommit(boolean readOnly)
{
//NOOP
}
/**
* {@inheritDoc}
*/
public void beforeCompletion()
{
//NOOP
}
/**
* {@inheritDoc}
*/
public void afterCommit()
{
JbpmContext context = (JbpmContext)AlfrescoTransactionSupport.getResource(JBPM_CONTEXT_KEY);
if (context != null)
{
super.releaseContext(context);
if (logger.isDebugEnabled())
logger.debug("Detached (commit) JBPM Context from transaction " + AlfrescoTransactionSupport.getTransactionId());
}
}
/**
* {@inheritDoc}
*/
public void afterRollback()
{
JbpmContext context = (JbpmContext)AlfrescoTransactionSupport.getResource(JBPM_CONTEXT_KEY);
if (context != null)
{
super.releaseContext(context);
if (logger.isDebugEnabled())
logger.debug("Detached (rollback) JBPM Context from transaction " + AlfrescoTransactionSupport.getTransactionId());
}
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode()
{
return this.id.hashCode();
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj instanceof JBPMTransactionTemplate)
{
JBPMTransactionTemplate that = (JBPMTransactionTemplate) obj;
return (this.id.equals(that.id));
}
else
{
return false;
}
}
}

View File

@@ -1,50 +1,50 @@
package org.alfresco.repo.workflow.jbpm;
import org.dom4j.Element;
import org.jbpm.graph.def.Action;
import org.jbpm.graph.def.Event;
import org.jbpm.instantiation.Delegation;
import org.jbpm.jpdl.xml.JpdlXmlReader;
/**
* Implementation of Join which ends child tokens / tasks for nOutM cases.
*
* @author davidc
*
*/
public class Join extends org.jbpm.graph.node.Join
{
private static final long serialVersionUID = 6417483503439714897L;
/**
* Constructor
*/
public Join()
{
super();
}
/**
* Constructor
*/
public Join(String name)
{
super(name);
}
/**
* {@inheritDoc}
*/
@Override
public void read(Element element, JpdlXmlReader jpdlReader)
{
// Add "on node leave" event handler which ends child tokens / tasks
Delegation delegation = new Delegation(JoinEndForkedTokens.class.getName());
Action theAction = new Action(delegation);
Event event = new Event(Event.EVENTTYPE_NODE_LEAVE);
event.addAction(theAction);
addEvent(event);
}
}
package org.alfresco.repo.workflow.jbpm;
import org.dom4j.Element;
import org.jbpm.graph.def.Action;
import org.jbpm.graph.def.Event;
import org.jbpm.instantiation.Delegation;
import org.jbpm.jpdl.xml.JpdlXmlReader;
/**
* Implementation of Join which ends child tokens / tasks for nOutM cases.
*
* @author davidc
*
*/
public class Join extends org.jbpm.graph.node.Join
{
private static final long serialVersionUID = 6417483503439714897L;
/**
* Constructor
*/
public Join()
{
super();
}
/**
* Constructor
*/
public Join(String name)
{
super(name);
}
/**
* {@inheritDoc}
*/
@Override
public void read(Element element, JpdlXmlReader jpdlReader)
{
// Add "on node leave" event handler which ends child tokens / tasks
Delegation delegation = new Delegation(JoinEndForkedTokens.class.getName());
Action theAction = new Action(delegation);
Event event = new Event(Event.EVENTTYPE_NODE_LEAVE);
event.addAction(theAction);
addEvent(event);
}
}

View File

@@ -1,94 +1,94 @@
package org.alfresco.repo.workflow.jbpm;
import java.util.Collection;
import java.util.Map;
import org.jbpm.graph.def.ActionHandler;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.graph.exe.Token;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.jbpm.taskmgmt.exe.TaskMgmtInstance;
/**
* Action Handler for ending child tokens / tasks
*
* @author davidc
*/
public class JoinEndForkedTokens implements ActionHandler
{
private static final long serialVersionUID = 8679390550752208189L;
/**
* Constructor
*/
public JoinEndForkedTokens()
{
super();
}
/**
* {@inheritDoc}
*/
public void execute(ExecutionContext executionContext)
{
Token token = executionContext.getToken();
Map<?, ?> childTokens = token.getActiveChildren();
for (Object childToken : childTokens.values())
{
cancelToken(executionContext, (Token)childToken);
}
}
/**
* Cancel token
*
* @param executionContext ExecutionContext
* @param token Token
*/
protected void cancelToken(ExecutionContext executionContext, Token token)
{
// visit child tokens
Map<?, ?> childTokens = token.getActiveChildren();
for (Object childToken : childTokens.values())
{
cancelToken(executionContext, (Token)childToken);
}
// end token
if (!token.hasEnded())
{
token.end(false);
}
// end any associated tasks
cancelTokenTasks(executionContext, token);
}
/**
* Cancel tasks associated with a token
*
* @param executionContext ExecutionContext
* @param token Token
*/
protected void cancelTokenTasks(ExecutionContext executionContext, Token token)
{
TaskMgmtInstance tms = executionContext.getTaskMgmtInstance();
Collection<TaskInstance> tasks = tms.getUnfinishedTasks(token);
for (Object task : tasks)
{
TaskInstance taskInstance = (TaskInstance)task;
if (taskInstance.isBlocking())
{
taskInstance.setBlocking(false);
}
if (taskInstance.isSignalling())
{
taskInstance.setSignalling(false);
}
if (!taskInstance.hasEnded())
{
taskInstance.cancel();
}
}
}
}
package org.alfresco.repo.workflow.jbpm;
import java.util.Collection;
import java.util.Map;
import org.jbpm.graph.def.ActionHandler;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.graph.exe.Token;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.jbpm.taskmgmt.exe.TaskMgmtInstance;
/**
* Action Handler for ending child tokens / tasks
*
* @author davidc
*/
public class JoinEndForkedTokens implements ActionHandler
{
private static final long serialVersionUID = 8679390550752208189L;
/**
* Constructor
*/
public JoinEndForkedTokens()
{
super();
}
/**
* {@inheritDoc}
*/
public void execute(ExecutionContext executionContext)
{
Token token = executionContext.getToken();
Map<?, ?> childTokens = token.getActiveChildren();
for (Object childToken : childTokens.values())
{
cancelToken(executionContext, (Token)childToken);
}
}
/**
* Cancel token
*
* @param executionContext ExecutionContext
* @param token Token
*/
protected void cancelToken(ExecutionContext executionContext, Token token)
{
// visit child tokens
Map<?, ?> childTokens = token.getActiveChildren();
for (Object childToken : childTokens.values())
{
cancelToken(executionContext, (Token)childToken);
}
// end token
if (!token.hasEnded())
{
token.end(false);
}
// end any associated tasks
cancelTokenTasks(executionContext, token);
}
/**
* Cancel tasks associated with a token
*
* @param executionContext ExecutionContext
* @param token Token
*/
protected void cancelTokenTasks(ExecutionContext executionContext, Token token)
{
TaskMgmtInstance tms = executionContext.getTaskMgmtInstance();
Collection<TaskInstance> tasks = tms.getUnfinishedTasks(token);
for (Object task : tasks)
{
TaskInstance taskInstance = (TaskInstance)task;
if (taskInstance.isBlocking())
{
taskInstance.setBlocking(false);
}
if (taskInstance.isSignalling())
{
taskInstance.setSignalling(false);
}
if (!taskInstance.hasEnded())
{
taskInstance.cancel();
}
}
}
}

View File

@@ -1,63 +1,63 @@
package org.alfresco.repo.workflow.jbpm;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.jbpm.context.exe.Converter;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springmodules.workflow.jbpm31.JbpmFactoryLocator;
/**
* jBPM Converter for transforming Alfresco Node to string and back
*
* @author davidc
*/
public class NodeConverter implements Converter
{
private static final long serialVersionUID = 1L;
private static BeanFactoryLocator jbpmFactoryLocator = new JbpmFactoryLocator();
/* (non-Javadoc)
* @see org.jbpm.context.exe.Converter#supports(java.lang.Object)
*/
public boolean supports(Object value)
{
if (value == null)
{
return true;
}
return (value.getClass() == JBPMNode.class);
}
/* (non-Javadoc)
* @see org.jbpm.context.exe.Converter#convert(java.lang.Object)
*/
public Object convert(Object o)
{
Object converted = null;
if (o != null)
{
converted = ((JBPMNode)o).getNodeRef().toString();
}
return converted;
}
/* (non-Javadoc)
* @see org.jbpm.context.exe.Converter#revert(java.lang.Object)
*/
public Object revert(Object o)
{
Object reverted = null;
if (o != null)
{
BeanFactoryReference factory = jbpmFactoryLocator.useBeanFactory(null);
ServiceRegistry serviceRegistry = (ServiceRegistry)factory.getFactory().getBean(ServiceRegistry.SERVICE_REGISTRY);
reverted = new JBPMNode(new NodeRef((String)o), serviceRegistry);
}
return reverted;
}
}
package org.alfresco.repo.workflow.jbpm;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.jbpm.context.exe.Converter;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springmodules.workflow.jbpm31.JbpmFactoryLocator;
/**
* jBPM Converter for transforming Alfresco Node to string and back
*
* @author davidc
*/
public class NodeConverter implements Converter
{
private static final long serialVersionUID = 1L;
private static BeanFactoryLocator jbpmFactoryLocator = new JbpmFactoryLocator();
/* (non-Javadoc)
* @see org.jbpm.context.exe.Converter#supports(java.lang.Object)
*/
public boolean supports(Object value)
{
if (value == null)
{
return true;
}
return (value.getClass() == JBPMNode.class);
}
/* (non-Javadoc)
* @see org.jbpm.context.exe.Converter#convert(java.lang.Object)
*/
public Object convert(Object o)
{
Object converted = null;
if (o != null)
{
converted = ((JBPMNode)o).getNodeRef().toString();
}
return converted;
}
/* (non-Javadoc)
* @see org.jbpm.context.exe.Converter#revert(java.lang.Object)
*/
public Object revert(Object o)
{
Object reverted = null;
if (o != null)
{
BeanFactoryReference factory = jbpmFactoryLocator.useBeanFactory(null);
ServiceRegistry serviceRegistry = (ServiceRegistry)factory.getFactory().getBean(ServiceRegistry.SERVICE_REGISTRY);
reverted = new JBPMNode(new NodeRef((String)o), serviceRegistry);
}
return reverted;
}
}

View File

@@ -1,110 +1,110 @@
package org.alfresco.repo.workflow.jbpm;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.jbpm.context.exe.converter.SerializableToByteArrayConverter;
import org.jbpm.graph.def.ProcessDefinition;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springmodules.workflow.jbpm31.JbpmFactoryLocator;
/**
* jBPM Converter for transforming Alfresco Node to string and back
*
* @author davidc
* @author Nick Smith
*/
public class NodeListConverter extends SerializableToByteArrayConverter
{
private static final long serialVersionUID = 1L;
private static BeanFactoryLocator jbpmFactoryLocator = new JbpmFactoryLocator();
/**
* {@inheritDoc}
*/
@Override
public boolean supports(Object value)
{
if (value == null)
{
return true;
}
return (value.getClass() == JBPMNodeList.class);
}
/**
* {@inheritDoc}
*/
@Override
public Object convert(Object o)
{
Object converted = null;
if (o != null)
{
JBPMNodeList nodes = (JBPMNodeList)o;
List<NodeRef> values = new ArrayList<NodeRef>(nodes.size());
for (JBPMNode node : nodes)
{
values.add(node.getNodeRef());
}
converted = super.convert(values);
}
return converted;
}
/**
* {@inheritDoc}
*/
@Override
public Object revert(Object o)
{
Object reverted = null;
if (o != null)
{
Object nodeRefs = super.revert(o);
reverted = revertNodes(nodeRefs);
}
return reverted;
}
/**
* {@inheritDoc}
*/
@Override
public Object revert(Object o, ProcessDefinition processDefinition)
{
Object reverted = null;
if (o != null)
{
Object nodeRefs = super.revert(o, processDefinition);
reverted = revertNodes(nodeRefs);
}
return reverted;
}
/**
* @param value Object
* @return JBPMNodeList
*/
@SuppressWarnings("unchecked")
private JBPMNodeList revertNodes(Object value)
{
BeanFactoryReference factory = jbpmFactoryLocator.useBeanFactory(null);
ServiceRegistry serviceRegistry = (ServiceRegistry)factory.getFactory().getBean(ServiceRegistry.SERVICE_REGISTRY);
JBPMNodeList nodes = new JBPMNodeList();
Collection<NodeRef> nodeRefs = (Collection<NodeRef>) value;
for (NodeRef nodeRef : nodeRefs)
{
nodes.add(new JBPMNode(nodeRef, serviceRegistry));
}
return nodes;
}
}
package org.alfresco.repo.workflow.jbpm;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.jbpm.context.exe.converter.SerializableToByteArrayConverter;
import org.jbpm.graph.def.ProcessDefinition;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springmodules.workflow.jbpm31.JbpmFactoryLocator;
/**
* jBPM Converter for transforming Alfresco Node to string and back
*
* @author davidc
* @author Nick Smith
*/
public class NodeListConverter extends SerializableToByteArrayConverter
{
private static final long serialVersionUID = 1L;
private static BeanFactoryLocator jbpmFactoryLocator = new JbpmFactoryLocator();
/**
* {@inheritDoc}
*/
@Override
public boolean supports(Object value)
{
if (value == null)
{
return true;
}
return (value.getClass() == JBPMNodeList.class);
}
/**
* {@inheritDoc}
*/
@Override
public Object convert(Object o)
{
Object converted = null;
if (o != null)
{
JBPMNodeList nodes = (JBPMNodeList)o;
List<NodeRef> values = new ArrayList<NodeRef>(nodes.size());
for (JBPMNode node : nodes)
{
values.add(node.getNodeRef());
}
converted = super.convert(values);
}
return converted;
}
/**
* {@inheritDoc}
*/
@Override
public Object revert(Object o)
{
Object reverted = null;
if (o != null)
{
Object nodeRefs = super.revert(o);
reverted = revertNodes(nodeRefs);
}
return reverted;
}
/**
* {@inheritDoc}
*/
@Override
public Object revert(Object o, ProcessDefinition processDefinition)
{
Object reverted = null;
if (o != null)
{
Object nodeRefs = super.revert(o, processDefinition);
reverted = revertNodes(nodeRefs);
}
return reverted;
}
/**
* @param value Object
* @return JBPMNodeList
*/
@SuppressWarnings("unchecked")
private JBPMNodeList revertNodes(Object value)
{
BeanFactoryReference factory = jbpmFactoryLocator.useBeanFactory(null);
ServiceRegistry serviceRegistry = (ServiceRegistry)factory.getFactory().getBean(ServiceRegistry.SERVICE_REGISTRY);
JBPMNodeList nodes = new JBPMNodeList();
Collection<NodeRef> nodeRefs = (Collection<NodeRef>) value;
for (NodeRef nodeRef : nodeRefs)
{
nodes.add(new JBPMNode(nodeRef, serviceRegistry));
}
return nodes;
}
}

View File

@@ -1,131 +1,131 @@
package org.alfresco.repo.workflow.jbpm;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.alfresco.service.namespace.QName;
import org.jbpm.graph.def.Transition;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springmodules.workflow.jbpm31.JbpmFactoryLocator;
/**
* Alfresco specific implementation of a jBPM task instance
*
* @author davidc
*/
public class WorkflowTaskInstance extends TaskInstance
{
private static final long serialVersionUID = 6824116036569411964L;
/**
* Used to look up the Alfresco JBPM Engine.
*/
private String jbpmEngineName = null;
/** Alfresco JBPM Engine */
private static JBPMEngine jbpmEngine = null;
/**
* Construct
*/
public WorkflowTaskInstance()
{
super();
}
/**
* Construct
*
* @param taskName String
* @param actorId String
*/
public WorkflowTaskInstance(String taskName, String actorId)
{
super(taskName, actorId);
}
/**
* Sets jbpmEngineName which is used to get the JBPMEngine instance from a
* BeanFactory
*
* @param jbpmEngineName the jbpmEngineName to set
*/
public void setJbpmEngineName(String jbpmEngineName)
{
this.jbpmEngineName = jbpmEngineName;
}
/**
* Gets the JBPM Engine instance
*
* @return JBPM Engine
*/
private JBPMEngine getJBPMEngine()
{
if (jbpmEngine == null)
{
BeanFactoryLocator factoryLocator = new JbpmFactoryLocator();
BeanFactoryReference factory = factoryLocator.useBeanFactory(null);
if (jbpmEngineName == null) jbpmEngineName = "jbpm_engine";
jbpmEngine = (JBPMEngine) factory.getFactory().getBean(jbpmEngineName);
if (jbpmEngine == null) { throw new WorkflowException(
"Failed to retrieve JBPMEngine component"); }
}
return jbpmEngine;
}
@Override
public void create(ExecutionContext executionContext)
{
super.create(executionContext);
getJBPMEngine().setDefaultTaskProperties(this);
}
@Override
public void end(Transition transition)
{
// Force assignment of task if transition is taken, but no owner has yet
// been assigned
if (actorId == null)
{
actorId = AuthenticationUtil.getFullyAuthenticatedUser();
}
// Set task properties on completion of task
// NOTE: Set properties first, so they're available during the
// submission of
// task variables to the process context
Map<QName, Serializable> taskProperties = new HashMap<QName, Serializable>();
Transition outcome = (transition == null) ? token.getNode().getDefaultLeavingTransition()
: transition;
if (outcome != null)
{
taskProperties.put(WorkflowModel.PROP_OUTCOME, outcome.getName());
}
taskProperties.put(WorkflowModel.PROP_STATUS, "Completed");
getJBPMEngine().setTaskProperties(this, taskProperties);
// perform transition
super.end(transition);
if (getTask().getStartState() != null)
{
// if ending a start task, push start task properties to process
// context, if not
// already done
getJBPMEngine().setDefaultWorkflowProperties(this);
// set task description
getJBPMEngine().setDefaultStartTaskDescription(this);
}
}
}
package org.alfresco.repo.workflow.jbpm;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.alfresco.service.namespace.QName;
import org.jbpm.graph.def.Transition;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springmodules.workflow.jbpm31.JbpmFactoryLocator;
/**
* Alfresco specific implementation of a jBPM task instance
*
* @author davidc
*/
public class WorkflowTaskInstance extends TaskInstance
{
private static final long serialVersionUID = 6824116036569411964L;
/**
* Used to look up the Alfresco JBPM Engine.
*/
private String jbpmEngineName = null;
/** Alfresco JBPM Engine */
private static JBPMEngine jbpmEngine = null;
/**
* Construct
*/
public WorkflowTaskInstance()
{
super();
}
/**
* Construct
*
* @param taskName String
* @param actorId String
*/
public WorkflowTaskInstance(String taskName, String actorId)
{
super(taskName, actorId);
}
/**
* Sets jbpmEngineName which is used to get the JBPMEngine instance from a
* BeanFactory
*
* @param jbpmEngineName the jbpmEngineName to set
*/
public void setJbpmEngineName(String jbpmEngineName)
{
this.jbpmEngineName = jbpmEngineName;
}
/**
* Gets the JBPM Engine instance
*
* @return JBPM Engine
*/
private JBPMEngine getJBPMEngine()
{
if (jbpmEngine == null)
{
BeanFactoryLocator factoryLocator = new JbpmFactoryLocator();
BeanFactoryReference factory = factoryLocator.useBeanFactory(null);
if (jbpmEngineName == null) jbpmEngineName = "jbpm_engine";
jbpmEngine = (JBPMEngine) factory.getFactory().getBean(jbpmEngineName);
if (jbpmEngine == null) { throw new WorkflowException(
"Failed to retrieve JBPMEngine component"); }
}
return jbpmEngine;
}
@Override
public void create(ExecutionContext executionContext)
{
super.create(executionContext);
getJBPMEngine().setDefaultTaskProperties(this);
}
@Override
public void end(Transition transition)
{
// Force assignment of task if transition is taken, but no owner has yet
// been assigned
if (actorId == null)
{
actorId = AuthenticationUtil.getFullyAuthenticatedUser();
}
// Set task properties on completion of task
// NOTE: Set properties first, so they're available during the
// submission of
// task variables to the process context
Map<QName, Serializable> taskProperties = new HashMap<QName, Serializable>();
Transition outcome = (transition == null) ? token.getNode().getDefaultLeavingTransition()
: transition;
if (outcome != null)
{
taskProperties.put(WorkflowModel.PROP_OUTCOME, outcome.getName());
}
taskProperties.put(WorkflowModel.PROP_STATUS, "Completed");
getJBPMEngine().setTaskProperties(this, taskProperties);
// perform transition
super.end(transition);
if (getTask().getStartState() != null)
{
// if ending a start task, push start task properties to process
// context, if not
// already done
getJBPMEngine().setDefaultWorkflowProperties(this);
// set task description
getJBPMEngine().setDefaultStartTaskDescription(this);
}
}
}

View File

@@ -1,39 +1,39 @@
package org.alfresco.repo.workflow.jbpm;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.taskmgmt.TaskInstanceFactory;
import org.jbpm.taskmgmt.exe.TaskInstance;
/**
* jBPM factory for creating Alfresco derived Task Instances
*
* @author davidc
*/
public class WorkflowTaskInstanceFactory implements TaskInstanceFactory
{
private static final long serialVersionUID = -8097108150047415711L;
private String jbpmEngineName;
/**
* @param jbpmEngine the jbpmEngine to set
*/
public void setJbpmEngine(String jbpmEngine)
{
this.jbpmEngineName = jbpmEngine;
}
/*
* (non-Javadoc)
* @see
* org.jbpm.taskmgmt.TaskInstanceFactory#createTaskInstance(org.jbpm.graph
* .exe.ExecutionContext)
*/
public TaskInstance createTaskInstance(ExecutionContext executionContext)
{
WorkflowTaskInstance taskInstance = new WorkflowTaskInstance();
taskInstance.setJbpmEngineName(jbpmEngineName);
return taskInstance;
}
}
package org.alfresco.repo.workflow.jbpm;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.taskmgmt.TaskInstanceFactory;
import org.jbpm.taskmgmt.exe.TaskInstance;
/**
* jBPM factory for creating Alfresco derived Task Instances
*
* @author davidc
*/
public class WorkflowTaskInstanceFactory implements TaskInstanceFactory
{
private static final long serialVersionUID = -8097108150047415711L;
private String jbpmEngineName;
/**
* @param jbpmEngine the jbpmEngine to set
*/
public void setJbpmEngine(String jbpmEngine)
{
this.jbpmEngineName = jbpmEngine;
}
/*
* (non-Javadoc)
* @see
* org.jbpm.taskmgmt.TaskInstanceFactory#createTaskInstance(org.jbpm.graph
* .exe.ExecutionContext)
*/
public TaskInstance createTaskInstance(ExecutionContext executionContext)
{
WorkflowTaskInstance taskInstance = new WorkflowTaskInstance();
taskInstance.setJbpmEngineName(jbpmEngineName);
return taskInstance;
}
}