/**
* Copyright (c) 2015 WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* <p/>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wso2.carbon.bpmn.rest.service.runtime;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.identity.Group;
import org.activiti.engine.impl.ProcessEngineImpl;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.interceptor.CommandExecutor;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityManager;
import org.activiti.engine.impl.persistence.entity.VariableInstanceEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
import org.wso2.carbon.bpmn.core.integration.BPSGroupIdentityManager;
import org.wso2.carbon.bpmn.rest.common.CorrelationProcess;
import org.wso2.carbon.bpmn.rest.common.RestResponseFactory;
import org.wso2.carbon.bpmn.rest.common.exception.BPMNConflictException;
import org.wso2.carbon.bpmn.rest.common.exception.BPMNContentNotSupportedException;
import org.wso2.carbon.bpmn.rest.common.exception.BPMNRestException;
import org.wso2.carbon.bpmn.rest.common.exception.RestApiBasicAuthenticationException;
import org.wso2.carbon.bpmn.rest.common.utils.BPMNOSGIService;
import org.wso2.carbon.bpmn.rest.common.utils.Utils;
import org.wso2.carbon.bpmn.rest.engine.variable.QueryVariable;
import org.wso2.carbon.bpmn.rest.engine.variable.RestVariable;
import org.wso2.carbon.bpmn.rest.model.common.DataResponse;
import org.wso2.carbon.bpmn.rest.model.common.RestIdentityLink;
import org.wso2.carbon.bpmn.rest.model.correlation.CorrelationActionRequest;
import org.wso2.carbon.bpmn.rest.model.runtime.AttachmentDataHolder;
import org.wso2.carbon.bpmn.rest.model.runtime.ProcessInstanceActionRequest;
import org.wso2.carbon.bpmn.rest.model.runtime.ProcessInstanceCreateRequest;
import org.wso2.carbon.bpmn.rest.model.runtime.ProcessInstanceQueryRequest;
import org.wso2.carbon.bpmn.rest.model.runtime.ProcessInstanceResponse;
import org.wso2.carbon.bpmn.rest.model.runtime.RestVariableCollection;
import org.wso2.carbon.bpmn.rest.service.base.BaseProcessInstanceService;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.activation.DataHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
@Path("/process-instances")
public class ProcessInstanceService extends BaseProcessInstanceService {
private static final Log log = LogFactory.getLog(ProcessInstanceService.class);
@Context
UriInfo uriInfo;
@GET
@Path("/")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response getProcessInstances() {
Map<String, String> allRequestParams = allRequestParams(uriInfo);
// Populate query based on request
ProcessInstanceQueryRequest queryRequest = getQueryRequest(allRequestParams);
return Response.ok().entity(getQueryResponse(queryRequest, allRequestParams, uriInfo)).build();
}
@POST
@Path("/")
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response startInstance(ProcessInstanceCreateRequest processInstanceCreateRequest) {
if (log.isDebugEnabled()) {
log.debug("ProcessInstanceCreateRequest:" + processInstanceCreateRequest.getProcessDefinitionId());
log.debug(" processInstanceCreateRequest.getVariables().size():" + processInstanceCreateRequest.getVariables().size());
}
if (processInstanceCreateRequest.getProcessDefinitionId() == null && processInstanceCreateRequest.getProcessDefinitionKey() == null
&& processInstanceCreateRequest.getMessage() == null) {
throw new ActivitiIllegalArgumentException("Either processDefinitionId, processDefinitionKey or message is required.");
}
int paramsSet = ((processInstanceCreateRequest.getProcessDefinitionId() != null) ? 1 : 0)
+ ((processInstanceCreateRequest.getProcessDefinitionKey() != null) ? 1 : 0)
+ ((processInstanceCreateRequest.getMessage() != null) ? 1 : 0);
if (paramsSet > 1) {
throw new ActivitiIllegalArgumentException("Only one of processDefinitionId, processDefinitionKey or message should be set.");
}
if (processInstanceCreateRequest.isCustomTenantSet()) {
// Tenant-id can only be used with either key or message
if (processInstanceCreateRequest.getProcessDefinitionId() != null) {
throw new ActivitiIllegalArgumentException("TenantId can only be used with either processDefinitionKey or message.");
}
} else {
//if no tenantId, it must be from definitionId
if(processInstanceCreateRequest.getProcessDefinitionId() == null){
throw new ActivitiIllegalArgumentException("TenantId should be specified to be used with either " +
"processDefinitionKey or message.");
}
}
//Have to add the validation part here
if (!isValidUserToStartProcess(processInstanceCreateRequest)) {
throw new RestApiBasicAuthenticationException("User doesn't have the necessary permission to start the process");
}
if (processInstanceCreateRequest.getSkipInstanceCreation() || processInstanceCreateRequest.getSkipInstanceCreationIfExist()) {
ProcessInstanceQueryRequest processInstanceQueryRequest = processInstanceCreateRequest
.cloneInstanceCreationRequest();
Map<String, String> allRequestParams = allRequestParams(uriInfo);
DataResponse dataResponse = getQueryResponse(processInstanceQueryRequest, allRequestParams, uriInfo);
if (log.isDebugEnabled()) {
log.debug("ProcessInstanceCreation check:" + dataResponse.getSize());
}
int dataResponseSize = dataResponse.getSize();
if(dataResponseSize > 0){
if(processInstanceCreateRequest.getCorrelate()){
if(dataResponseSize != 1){
String responseMessage = "Correlation matching failed as there are more than one matching instance with " +
"given variables state";
throw new NotFoundException(Response.ok().entity(responseMessage).status(Response.Status
.NOT_FOUND).build());
}
//process the correlation aspect now
if(processInstanceCreateRequest.getMessageName() == null){
String responseMessage = "Correlation matching failed as messageName property is not specified";
throw new ActivitiIllegalArgumentException(responseMessage);
}
return performCorrelation(processInstanceCreateRequest);
} else {
dataResponse.setMessage("Instance information corresponding to the request");
return Response.ok().entity(dataResponse).build();
}
}
}
RestResponseFactory restResponseFactory = new RestResponseFactory();
Map<String, Object> startVariables = null;
if (processInstanceCreateRequest.getVariables() != null) {
startVariables = new HashMap<>();
for (RestVariable variable : processInstanceCreateRequest.getVariables()) {
if (variable.getName() == null) {
throw new ActivitiIllegalArgumentException("Variable name is required.");
}
startVariables.put(variable.getName(), restResponseFactory.getVariableValue(variable));
}
}
//updated the additional variables
if (processInstanceCreateRequest.getAdditionalVariables() != null) {
if(startVariables == null){
startVariables = new HashMap<>();
}
for (RestVariable variable : processInstanceCreateRequest.getAdditionalVariables()) {
if (variable.getName() == null) {
throw new ActivitiIllegalArgumentException("Additional Variable name is required.");
}
startVariables.put(variable.getName(), restResponseFactory.getVariableValue(variable));
}
}
RuntimeService runtimeService = BPMNOSGIService.getRuntimeService();
ProcessInstanceResponse processInstanceResponse;
// Actually start the instance based on key or id
try {
ProcessInstance instance;
if (processInstanceCreateRequest.getProcessDefinitionId() != null) {
instance = runtimeService.startProcessInstanceById(
processInstanceCreateRequest.getProcessDefinitionId(), processInstanceCreateRequest.getBusinessKey(), startVariables);
} else if (processInstanceCreateRequest.getProcessDefinitionKey() != null) {
if (processInstanceCreateRequest.isCustomTenantSet()) {
instance = runtimeService.startProcessInstanceByKeyAndTenantId(
processInstanceCreateRequest.getProcessDefinitionKey(), processInstanceCreateRequest.getBusinessKey(), startVariables,
processInstanceCreateRequest.getTenantId());
} else {
instance = runtimeService.startProcessInstanceByKey(
processInstanceCreateRequest.getProcessDefinitionKey(), processInstanceCreateRequest.getBusinessKey(), startVariables);
}
} else {
if (processInstanceCreateRequest.isCustomTenantSet()) {
instance = runtimeService.startProcessInstanceByMessageAndTenantId(
processInstanceCreateRequest.getMessage(), processInstanceCreateRequest.getBusinessKey(), startVariables, processInstanceCreateRequest.getTenantId());
} else {
instance = runtimeService.startProcessInstanceByMessage(
processInstanceCreateRequest.getMessage(), processInstanceCreateRequest.getBusinessKey(), startVariables);
}
}
HistoryService historyService = BPMNOSGIService.getHistoryService();
if (processInstanceCreateRequest.getReturnVariables()) {
Map<String, Object> runtimeVariableMap = null;
List<HistoricVariableInstance> historicVariableList = null;
if (instance.isEnded()) {
historicVariableList = historyService.createHistoricVariableInstanceQuery()
.processInstanceId(instance.getId())
.list();
} else {
runtimeVariableMap = runtimeService.getVariables(instance.getId());
}
processInstanceResponse = restResponseFactory.createProcessInstanceResponse(instance, true,
runtimeVariableMap, historicVariableList, uriInfo.getBaseUri().toString());
} else {
processInstanceResponse = restResponseFactory.createProcessInstanceResponse(instance, uriInfo.getBaseUri
().toString());
}
} catch (ActivitiObjectNotFoundException aonfe) {
throw new ActivitiIllegalArgumentException(aonfe.getMessage(), aonfe);
}
return Response.ok().status(Response.Status.CREATED).entity(processInstanceResponse).build();
}
@GET
@Path("/{processInstanceId}/diagram")
@Produces(MediaType.APPLICATION_JSON)
public Response getProcessInstanceDiagram(@PathParam("processInstanceId") String processInstanceId) {
ProcessInstance processInstance = getProcessInstanceFromRequest(processInstanceId);
RepositoryService repositoryService = BPMNOSGIService.getRepositoryService();
ProcessDefinition pde = repositoryService.getProcessDefinition(processInstance.getProcessDefinitionId());
if (pde != null && pde.hasGraphicalNotation()) {
RuntimeService runtimeService = BPMNOSGIService.getRuntimeService();
InputStream diagramStream = new DefaultProcessDiagramGenerator().generateDiagram(repositoryService
.getBpmnModel(pde.getId()), "png",
runtimeService.getActiveActivityIds(processInstanceId));
try {
return Response.ok().type("image/png").entity(IOUtils.toByteArray(diagramStream)).build();
} catch (Exception e) {
throw new ActivitiIllegalArgumentException("Error exporting diagram", e);
}
} else {
throw new ActivitiIllegalArgumentException("Process instance with id '" + processInstance.getId()
+ "' has no graphical notation defined.");
}
}
@GET
@Path("/{processInstanceId}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response getProcessInstance(@PathParam("processInstanceId") String processInstanceId) {
ProcessInstance processInstance = getProcessInstanceFromRequest(processInstanceId);
RestResponseFactory restResponseFactory = new RestResponseFactory();
ProcessInstanceResponse processInstanceResponse = restResponseFactory.createProcessInstanceResponse
(processInstance, uriInfo.getBaseUri().toString());
return Response.ok().entity(processInstanceResponse).build();
}
@DELETE
@Path("/{processInstanceId}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response deleteProcessInstance(@PathParam("processInstanceId") String processInstanceId) {
RuntimeService runtimeService = BPMNOSGIService.getRuntimeService();
String deleteReason = uriInfo.getQueryParameters().getFirst("deleteReason");
if (deleteReason == null) {
deleteReason = "";
}
ProcessInstance processInstance = getProcessInstanceFromRequest(processInstanceId);
runtimeService.deleteProcessInstance(processInstance.getId(), deleteReason);
return Response.ok().status(Response.Status.NO_CONTENT).build();
}
@PUT
@Path("/{processInstanceId}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response performProcessInstanceAction(@PathParam("processInstanceId") String
processInstanceId,
ProcessInstanceActionRequest actionRequest) {
ProcessInstance processInstance = getProcessInstanceFromRequest(processInstanceId);
RestResponseFactory restResponseFactory = new RestResponseFactory();
if (ProcessInstanceActionRequest.ACTION_ACTIVATE.equals(actionRequest.getAction())) {
return Response.ok().entity(activateProcessInstance(processInstance, uriInfo)).build();
} else if (ProcessInstanceActionRequest.ACTION_SUSPEND.equals(actionRequest.getAction())) {
return Response.ok().entity(suspendProcessInstance(processInstance, restResponseFactory, uriInfo)).build();
}
throw new ActivitiIllegalArgumentException("Invalid action: '" + actionRequest.getAction() + "'.");
}
@GET
@Path("/{processInstanceId}/identitylinks")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public List<RestIdentityLink> getIdentityLinks(@PathParam("processInstanceId") String processInstanceId) {
RuntimeService runtimeService = BPMNOSGIService.getRuntimeService();
ProcessInstance processInstance = getProcessInstanceFromRequest(processInstanceId);
return new RestResponseFactory().createRestIdentityLinks(runtimeService.getIdentityLinksForProcessInstance
(processInstance.getId()), uriInfo.getBaseUri().toString());
}
@POST
@Path("/{processInstanceId}/identitylinks")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response createIdentityLink(@PathParam("processInstanceId") String processInstanceId,
RestIdentityLink identityLink) {
ProcessInstance processInstance = getProcessInstanceFromRequest(processInstanceId);
if (identityLink.getGroup() != null) {
throw new ActivitiIllegalArgumentException("Only user identity links are supported on a process instance.");
}
if (identityLink.getUser() == null) {
throw new ActivitiIllegalArgumentException("The user is required.");
}
if (identityLink.getType() == null) {
throw new ActivitiIllegalArgumentException("The identity link type is required.");
}
RuntimeService runtimeService = BPMNOSGIService.getRuntimeService();
runtimeService.addUserIdentityLink(processInstance.getId(), identityLink.getUser(), identityLink.getType());
RestIdentityLink restIdentityLink = new RestResponseFactory().createRestIdentityLink(identityLink.getType(),
identityLink.getUser(), identityLink.getGroup(), null, null, processInstance.getId(), uriInfo.getBaseUri()
.toString());
return Response.ok().status(Response.Status.CREATED).entity(restIdentityLink).build();
}
@GET
@Path("/{processInstanceId}/identitylinks/users/{identityId}/{type}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response getIdentityLinK(@PathParam("processInstanceId") String processInstanceId,
@PathParam("identityId") String identityId, @PathParam("type") String type) {
ProcessInstance processInstance = getProcessInstanceFromRequest(processInstanceId);
validateIdentityLinkArguments(identityId, type);
IdentityLink link = getIdentityLink(identityId, type, processInstance.getId());
return Response.ok().entity(new RestResponseFactory().createRestIdentityLink(link, uriInfo.getBaseUri()
.toString())).build();
}
@DELETE
@Path("/{processInstanceId}/identitylinks/users/{identityId}/{type}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response deleteIdentityLink(@PathParam("processInstanceId") String processInstanceId,
@PathParam("identityId") String identityId, @PathParam("type") String type) {
ProcessInstance processInstance = getProcessInstanceFromRequest(processInstanceId);
validateIdentityLinkArguments(identityId, type);
getIdentityLink(identityId, type, processInstance.getId());
RuntimeService runtimeService = BPMNOSGIService.getRuntimeService();
runtimeService.deleteUserIdentityLink(processInstance.getId(), identityId, type);
return Response.ok().status(Response.Status.NO_CONTENT).build();
}
@GET
@Path("/{processInstanceId}/variables")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response getVariables(@PathParam("processInstanceId") String processInstanceId) {
String scope = uriInfo.getQueryParameters().getFirst("scope");
Execution execution = getExecutionInstanceFromRequest(processInstanceId);
List<RestVariable> restVariableList = processVariables(execution, scope, RestResponseFactory.VARIABLE_PROCESS);
RestVariableCollection restVariableCollection = new RestVariableCollection();
restVariableCollection.setRestVariables(restVariableList);
return Response.ok().entity(restVariableCollection).build();
}
@GET
@Path("/{processInstanceId}/variables/{variableName}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response getVariable(@PathParam("processInstanceId") String processInstanceId,
@PathParam("variableName") String variableName) {
String scope = uriInfo.getQueryParameters().getFirst("scope");
Execution execution = getExecutionInstanceFromRequest(processInstanceId);
RestVariable restVariable = getVariableFromRequest(execution, variableName, scope, false);
return Response.ok().entity(restVariable).build();
}
@PUT
@Path("/{processInstanceId}/variables/{variableName}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response updateBinaryVariable(@PathParam("processInstanceId") String processInstanceId,
@PathParam("variableName") String variableName,
MultipartBody multipartBody) {
Execution execution = getExecutionInstanceFromRequest(processInstanceId);
RestVariable result;
try {
result = setBinaryVariable(multipartBody, execution, RestResponseFactory.VARIABLE_PROCESS, false);
} catch (IOException | ServletException e) {
throw new BPMNRestException("Exception occured during creating binary execution variable", e);
}
return Response.ok().entity(result).build();
}
@PUT
@Path("/{processInstanceId}/variables/{variableName}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public RestVariable updateVariable(@PathParam("processInstanceId") String processInstanceId,
@PathParam("variableName") String variableName,
@Context HttpServletRequest httpServletRequest) {
Execution execution = getExecutionInstanceFromRequest(processInstanceId);
RestVariable restVariable = null;
if (Utils.isApplicationJsonRequest(httpServletRequest)) {
try {
restVariable = new ObjectMapper().readValue(httpServletRequest.getInputStream(), RestVariable.class);
} catch (IOException e) {
throw new ActivitiIllegalArgumentException("request body could not be transformed to a RestVariable " +
"instance.", e);
}
} else if (Utils.isApplicationXmlRequest(httpServletRequest)) {
JAXBContext jaxbContext;
try {
jaxbContext = JAXBContext.newInstance(RestVariable.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
restVariable = (RestVariable) jaxbUnmarshaller.
unmarshal(httpServletRequest.getInputStream());
} catch (JAXBException | IOException e) {
throw new ActivitiIllegalArgumentException("xml request body could not be transformed to a " +
"RestVariable " +
"instance.", e);
}
}
if (restVariable == null) {
throw new ActivitiException("Invalid body was supplied");
}
if (!restVariable.getName().equals(variableName)) {
throw new ActivitiIllegalArgumentException("Variable name in the body should be equal to the name used in the requested URL.");
}
// }
return setSimpleVariable(restVariable, execution, false);
}
@POST
@Path("/{processInstanceId}/variables")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response createBinaryExecutionVariable(@PathParam("processInstanceId") String processInstanceId, @Context
HttpServletRequest httpServletRequest, MultipartBody multipartBody) {
Execution execution = getExecutionInstanceFromRequest(processInstanceId);
Response response;
try {
response = createBinaryExecutionVariable(execution, false, RestResponseFactory
.VARIABLE_PROCESS, multipartBody);
} catch (IOException | ServletException e) {
throw new BPMNRestException("Exception occured during creating binary execution variable", e);
}
return response;
}
@POST
@Path("/{processInstanceId}/variables")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response createExecutionVariable(@PathParam("processInstanceId") String processInstanceId, @Context
HttpServletRequest httpServletRequest) {
Execution execution = getExecutionInstanceFromRequest(processInstanceId);
Response response;
try {
response = createExecutionVariable(execution, false, RestResponseFactory.VARIABLE_PROCESS,
httpServletRequest);
} catch (IOException | ServletException e) {
throw new BPMNRestException("Exception occured during creating execution variable", e);
}
return response;
}
@PUT
@Path("/{processInstanceId}/variables")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response createOrUpdateBinaryExecutionVariable(@PathParam("processInstanceId") String processInstanceId,
MultipartBody multipartBody) {
Execution execution = getExecutionInstanceFromRequest(processInstanceId);
Response response;
try {
response = createBinaryExecutionVariable(execution, true, RestResponseFactory.VARIABLE_PROCESS,
multipartBody);
} catch (IOException | ServletException e) {
throw new BPMNRestException("Exception occured during creating execution variable", e);
}
return response;
}
@PUT
@Path("/{processInstanceId}/variables")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response createOrUpdateExecutionVariable(@PathParam("processInstanceId") String processInstanceId,
@Context HttpServletRequest httpServletRequest) {
Execution execution = getExecutionInstanceFromRequest(processInstanceId);
Response result;
try {
result = createExecutionVariable(execution, true, RestResponseFactory.VARIABLE_PROCESS, httpServletRequest);
} catch (IOException | ServletException e) {
throw new BPMNRestException("Exception occured during creating execution variable", e);
}
return result;
}
/**
* Delete variables in local scope of a process instance for a given path.
* @param processInstanceId
* @return
*/
@DELETE
@Path(value="/{processInstanceId}/variables")
public Response deleteLocalVariables(@PathParam("processInstanceId") String processInstanceId) {
Execution execution = getProcessInstanceFromRequest(processInstanceId);
deleteAllLocalVariables(execution);
return Response.ok().status(Response.Status.NO_CONTENT).build();
}
@GET
@Path("/{processInstanceId}/variables/{variableName}/data")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response getVariableData(@PathParam("processInstanceId") String processInstanceId,
@PathParam("variableName") String variableName,
@Context HttpServletRequest request) {
String scope = uriInfo.getQueryParameters().getFirst("scope");
Execution execution = getExecutionInstanceFromRequest(processInstanceId);
Response.ResponseBuilder responseBuilder = Response.ok();
return responseBuilder.entity(getVariableDataByteArray(execution, variableName, scope, responseBuilder)).build();
}
@DELETE
@Path("/{processInstanceId}/variables/{variableName}")
public Response deleteVariable(@PathParam("processInstanceId") String processInstanceId,
@PathParam("variableName") String variableName) {
String scope = uriInfo.getQueryParameters().getFirst("scope");
Execution execution = getExecutionInstanceFromRequest(processInstanceId);
// Determine scope
RestVariable.RestVariableScope variableScope = RestVariable.RestVariableScope.LOCAL;
if (scope != null) {
variableScope = RestVariable.getScopeFromString(scope);
}
if (!hasVariableOnScope(execution, variableName, variableScope)) {
throw new ActivitiObjectNotFoundException("Execution '" + execution.getId() + "' doesn't have a variable '" +
variableName + "' in scope " + variableScope.name().toLowerCase(), VariableInstanceEntity.class);
}
RuntimeService runtimeService = BPMNOSGIService.getRuntimeService();
if (variableScope == RestVariable.RestVariableScope.LOCAL) {
runtimeService.removeVariableLocal(execution.getId(), variableName);
} else {
// Safe to use parentId, as the hasVariableOnScope would have stopped a global-var update on a root-execution
runtimeService.removeVariable(execution.getParentId(), variableName);
}
return Response.ok().status(Response.Status.NO_CONTENT).build();
}
protected byte[] getVariableDataByteArray(Execution execution, String variableName, String scope, Response.ResponseBuilder responseBuilder) {
try {
byte[] result;
RestVariable variable = getVariableFromRequest(execution, variableName, scope, true);
if (RestResponseFactory.BYTE_ARRAY_VARIABLE_TYPE.equals(variable.getType())) {
result = (byte[]) variable.getValue();
responseBuilder.type(MediaType.APPLICATION_OCTET_STREAM);
} else if (RestResponseFactory.SERIALIZABLE_VARIABLE_TYPE.equals(variable.getType())) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ObjectOutputStream outputStream = new ObjectOutputStream(buffer);
outputStream.writeObject(variable.getValue());
outputStream.close();
result = buffer.toByteArray();
responseBuilder.type("application/x-java-serialized-object");
} else {
throw new ActivitiObjectNotFoundException("The variable does not have a binary data stream.", null);
}
return result;
} catch (IOException ioe) {
throw new ActivitiException("Error getting variable " + variableName, ioe);
}
}
protected RestVariable setSimpleVariable(RestVariable restVariable, Execution execution, boolean isNew) {
if (restVariable.getName() == null) {
throw new ActivitiIllegalArgumentException("Variable name is required");
}
// Figure out scope, revert to local is omitted
RestVariable.RestVariableScope scope = restVariable.getVariableScope();
if (scope == null) {
scope = RestVariable.RestVariableScope.LOCAL;
}
Object actualVariableValue = new RestResponseFactory().getVariableValue(restVariable);
setVariable(execution, restVariable.getName(), actualVariableValue, scope, isNew);
return constructRestVariable(restVariable.getName(), actualVariableValue, scope,
execution.getId(), false);
}
protected Response createBinaryExecutionVariable(Execution execution, boolean override, int variableType,
MultipartBody multipartBody) throws
IOException, ServletException {
Response.ResponseBuilder responseBuilder = Response.ok();
Object result = setBinaryVariable(multipartBody, execution, variableType, !override);
responseBuilder.entity(result);
return responseBuilder.status(Response.Status.CREATED).build();
}
protected Response createExecutionVariable(Execution execution, boolean override, int variableType,
HttpServletRequest httpServletRequest) throws IOException, ServletException {
boolean debugEnabled = log.isDebugEnabled();
if (debugEnabled) {
log.debug("httpServletRequest.getContentType():" + httpServletRequest.getContentType());
}
Response.ResponseBuilder responseBuilder = Response.ok();
if (debugEnabled) {
log.debug("Processing non binary variable");
}
List<RestVariable> inputVariables = new ArrayList<>();
List<RestVariable> resultVariables = new ArrayList<>();
try {
if (Utils.isApplicationJsonRequest(httpServletRequest)) {
ObjectMapper objectMapper = new ObjectMapper();
@SuppressWarnings("unchecked")
List<Object> variableObjects = (List<Object>) objectMapper.readValue(httpServletRequest.getInputStream(), List.class);
for (Object restObject : variableObjects) {
RestVariable restVariable = objectMapper.convertValue(restObject, RestVariable.class);
inputVariables.add(restVariable);
}
} else if (Utils.isApplicationXmlRequest(httpServletRequest)) {
JAXBContext jaxbContext;
try {
jaxbContext = JAXBContext.newInstance(RestVariableCollection.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
RestVariableCollection restVariableCollection = (RestVariableCollection) jaxbUnmarshaller.
unmarshal(httpServletRequest.getInputStream());
if (restVariableCollection == null) {
throw new ActivitiIllegalArgumentException("xml request body could not be transformed to a " +
"RestVariable Collection instance.");
}
List<RestVariable> restVariableList = restVariableCollection.getRestVariables();
if (restVariableList.size() == 0) {
throw new ActivitiIllegalArgumentException("xml request body could not identify any rest " +
"variables to be updated");
}
for (RestVariable restVariable : restVariableList) {
inputVariables.add(restVariable);
}
} catch (JAXBException | IOException e) {
throw new ActivitiIllegalArgumentException("xml request body could not be transformed to a " +
"RestVariable instance.", e);
}
}
} catch (Exception e) {
throw new ActivitiIllegalArgumentException("Failed to serialize to a RestVariable instance", e);
}
if (inputVariables.size() == 0) {
throw new ActivitiIllegalArgumentException("Request didn't contain a list of variables to create.");
}
RestVariable.RestVariableScope sharedScope = null;
RestVariable.RestVariableScope varScope;
Map<String, Object> variablesToSet = new HashMap<>();
for (RestVariable var : inputVariables) {
// Validate if scopes match
varScope = var.getVariableScope();
if (var.getName() == null) {
throw new ActivitiIllegalArgumentException("Variable name is required");
}
if (varScope == null) {
varScope = RestVariable.RestVariableScope.LOCAL;
}
if (sharedScope == null) {
sharedScope = varScope;
}
if (varScope != sharedScope) {
throw new ActivitiIllegalArgumentException("Only allowed to update multiple variables in the same scope.");
}
if (!override && hasVariableOnScope(execution, var.getName(), varScope)) {
throw new BPMNConflictException("Variable '" + var.getName() + "' is already present on execution '" + execution
.getId() + "'.");
}
RestResponseFactory restResponseFactory = new RestResponseFactory();
Object actualVariableValue = restResponseFactory.getVariableValue(var);
variablesToSet.put(var.getName(), actualVariableValue);
resultVariables.add(restResponseFactory.createRestVariable(var.getName(), actualVariableValue, varScope,
execution.getId(), variableType, false, uriInfo.getBaseUri().toString()));
}
if (!variablesToSet.isEmpty()) {
RuntimeService runtimeService = BPMNOSGIService.getRuntimeService();
if (sharedScope == RestVariable.RestVariableScope.LOCAL) {
runtimeService.setVariablesLocal(execution.getId(), variablesToSet);
} else {
if (execution.getParentId() != null) {
// Explicitly set on parent, setting non-local variables on execution itself will override local-variables if exists
runtimeService.setVariables(execution.getParentId(), variablesToSet);
} else {
// Standalone task, no global variables possible
throw new ActivitiIllegalArgumentException("Cannot set global variables on execution '" + execution.getId() + "', task is not part of process.");
}
}
}
RestVariableCollection restVariableCollection = new RestVariableCollection();
restVariableCollection.setRestVariables(resultVariables);
responseBuilder.entity(restVariableCollection);
// }
return responseBuilder.status(Response.Status.CREATED).build();
}
protected RestVariable setBinaryVariable(MultipartBody multipartBody, Execution execution,
int responseVariableType, boolean isNew) throws
IOException, ServletException {
boolean debugEnabled = log.isDebugEnabled();
List<org.apache.cxf.jaxrs.ext.multipart.Attachment> attachments = multipartBody.getAllAttachments();
int attachmentSize = attachments.size();
if (attachmentSize <= 0) {
throw new ActivitiIllegalArgumentException("No Attachments found with the request body");
}
AttachmentDataHolder attachmentDataHolder = new AttachmentDataHolder();
for (int i = 0; i < attachmentSize; i++) {
org.apache.cxf.jaxrs.ext.multipart.Attachment attachment = attachments.get(i);
String contentDispositionHeaderValue = attachment.getHeader("Content-Disposition");
String contentType = attachment.getHeader("Content-Type");
if (debugEnabled) {
log.debug("Going to iterate:" + i);
log.debug("contentDisposition:" + contentDispositionHeaderValue);
}
if (contentDispositionHeaderValue != null) {
contentDispositionHeaderValue = contentDispositionHeaderValue.trim();
Map<String, String> contentDispositionHeaderValueMap = Utils.processContentDispositionHeader
(contentDispositionHeaderValue);
String dispositionName = contentDispositionHeaderValueMap.get("name");
DataHandler dataHandler = attachment.getDataHandler();
OutputStream outputStream;
if ("name".equals(dispositionName)) {
try {
outputStream = Utils.getAttachmentStream(dataHandler.getInputStream());
} catch (IOException e) {
throw new ActivitiIllegalArgumentException("Attachment Name Reading error occured", e);
}
if (outputStream != null) {
String fileName = outputStream.toString();
attachmentDataHolder.setName(fileName);
}
} else if ("type".equals(dispositionName)) {
try {
outputStream = Utils.getAttachmentStream(dataHandler.getInputStream());
} catch (IOException e) {
throw new ActivitiIllegalArgumentException("Attachment Type Reading error occured", e);
}
if (outputStream != null) {
String typeName = outputStream.toString();
attachmentDataHolder.setType(typeName);
}
} else if ("scope".equals(dispositionName)) {
try {
outputStream = Utils.getAttachmentStream(dataHandler.getInputStream());
} catch (IOException e) {
throw new ActivitiIllegalArgumentException("Attachment Description Reading error occured", e);
}
if (outputStream != null) {
String scope = outputStream.toString();
attachmentDataHolder.setScope(scope);
}
}
if (contentType != null) {
if ("file".equals(dispositionName)) {
InputStream inputStream;
try {
inputStream = dataHandler.getInputStream();
} catch (IOException e) {
throw new ActivitiIllegalArgumentException("Error Occured During processing empty body.",
e);
}
if (inputStream != null) {
attachmentDataHolder.setContentType(contentType);
byte[] attachmentArray = new byte[0];
try {
attachmentArray = IOUtils.toByteArray(inputStream);
} catch (IOException e) {
throw new ActivitiIllegalArgumentException("Processing Attachment Body Failed.", e);
}
attachmentDataHolder.setAttachmentArray(attachmentArray);
}
}
}
}
}
attachmentDataHolder.printDebug();
String variableScope = attachmentDataHolder.getScope();
String variableName = attachmentDataHolder.getName();
String variableType = attachmentDataHolder.getType();
if (attachmentDataHolder.getName() == null) {
throw new ActivitiIllegalArgumentException("Attachment name is required.");
}
if (attachmentDataHolder.getAttachmentArray() == null) {
throw new ActivitiIllegalArgumentException("Empty attachment body was found in request body after " +
"decoding the request" +
".");
}
if (debugEnabled) {
log.debug("variableScope:" + variableScope + " variableName:" + variableName + " variableType:" + variableType);
}
try {
// Validate input and set defaults
if (variableName == null) {
throw new ActivitiIllegalArgumentException("No variable name was found in request body.");
}
if (variableType != null) {
if (!RestResponseFactory.BYTE_ARRAY_VARIABLE_TYPE.equals(variableType) && !RestResponseFactory.SERIALIZABLE_VARIABLE_TYPE.equals(variableType)) {
throw new ActivitiIllegalArgumentException("Only 'binary' and 'serializable' are supported as variable type.");
}
} else {
variableType = RestResponseFactory.BYTE_ARRAY_VARIABLE_TYPE;
}
RestVariable.RestVariableScope scope = RestVariable.RestVariableScope.LOCAL;
if (variableScope != null) {
scope = RestVariable.getScopeFromString(variableScope);
}
if (variableType.equals(RestResponseFactory.BYTE_ARRAY_VARIABLE_TYPE)) {
// Use raw bytes as variable value
setVariable(execution, variableName, attachmentDataHolder.getAttachmentArray(), scope, isNew);
} else {
// Try deserializing the object
try(
InputStream inputStream = new ByteArrayInputStream(attachmentDataHolder.getAttachmentArray());
ObjectInputStream stream = new ObjectInputStream(inputStream);
) {
Object value = stream.readObject();
setVariable(execution, variableName, value, scope, isNew);
}
}
RestResponseFactory restResponseFactory = new RestResponseFactory();
if (responseVariableType == RestResponseFactory.VARIABLE_PROCESS) {
return new RestResponseFactory().createBinaryRestVariable(variableName, scope, variableType,
null, null, execution.getId(), uriInfo.getBaseUri().toString());
} else {
return restResponseFactory.createBinaryRestVariable(variableName, scope, variableType, null,
execution.getId(), null, uriInfo.getBaseUri().toString());
}
} catch (IOException ioe) {
throw new ActivitiIllegalArgumentException("Could not process multipart content", ioe);
} catch (ClassNotFoundException ioe) {
throw new BPMNContentNotSupportedException("The provided body contains a serialized object for which the " +
"class is not found: " + ioe.getMessage());
}
}
protected void setVariable(Execution execution, String name, Object value, RestVariable.RestVariableScope scope, boolean isNew) {
// Create can only be done on new variables. Existing variables should be updated using PUT
if (log.isDebugEnabled()) {
log.debug("Going to invoke has variable from set binary variable");
}
boolean hasVariable = hasVariableOnScope(execution, name, scope);
if (isNew && hasVariable) {
throw new ActivitiException("Variable '" + name + "' is already present on execution '" + execution.getId() + "'.");
}
if (!isNew && !hasVariable) {
throw new ActivitiObjectNotFoundException("Execution '" + execution.getId() + "' doesn't have a variable with name: '" + name + "'.", null);
}
RuntimeService runtimeService = BPMNOSGIService.getRuntimeService();
if (scope == RestVariable.RestVariableScope.LOCAL) {
runtimeService.setVariableLocal(execution.getId(), name, value);
} else {
if (execution.getParentId() != null) {
runtimeService.setVariable(execution.getParentId(), name, value);
} else {
runtimeService.setVariable(execution.getId(), name, value);
}
}
}
protected boolean hasVariableOnScope(Execution execution, String variableName, RestVariable.RestVariableScope scope) {
boolean logEnabled = log.isDebugEnabled();
if (logEnabled) {
log.debug("invoked hasVariableOnScope" + scope);
}
boolean variableFound = false;
RuntimeService runtimeService = BPMNOSGIService.getRuntimeService();
if (scope == RestVariable.RestVariableScope.GLOBAL) {
boolean test = false;
if (execution.getParentId() != null) {
test = true;
}
if (logEnabled) {
log.debug("Execution has parentID:" + test);
}
if (execution.getParentId() != null && runtimeService.hasVariable(execution.getParentId(), variableName)) {
variableFound = true;
}
} else if (scope == RestVariable.RestVariableScope.LOCAL) {
if (runtimeService.hasVariableLocal(execution.getId(), variableName)) {
variableFound = true;
}
}
if (logEnabled) {
log.debug("variableFound:" + variableFound);
}
return variableFound;
}
public RestVariable getVariableFromRequest(Execution execution, String variableName, String scope,
boolean includeBinary) {
boolean variableFound = false;
Object value = null;
if (execution == null) {
throw new ActivitiObjectNotFoundException("Could not find an execution", Execution.class);
}
RuntimeService runtimeService = BPMNOSGIService.getRuntimeService();
RestVariable.RestVariableScope variableScope = RestVariable.getScopeFromString(scope);
if (variableScope == null) {
// First, check local variables (which have precedence when no scope is supplied)
if (runtimeService.hasVariableLocal(execution.getId(), variableName)) {
value = runtimeService.getVariableLocal(execution.getId(), variableName);
variableScope = RestVariable.RestVariableScope.LOCAL;
variableFound = true;
} else {
if (execution.getParentId() != null) {
value = runtimeService.getVariable(execution.getParentId(), variableName);
variableScope = RestVariable.RestVariableScope.GLOBAL;
variableFound = true;
}
}
} else if (variableScope == RestVariable.RestVariableScope.GLOBAL) {
// Use parent to get variables
if (execution.getParentId() != null) {
value = runtimeService.getVariable(execution.getParentId(), variableName);
variableScope = RestVariable.RestVariableScope.GLOBAL;
variableFound = true;
}
} else if (variableScope == RestVariable.RestVariableScope.LOCAL) {
value = runtimeService.getVariableLocal(execution.getId(), variableName);
variableScope = RestVariable.RestVariableScope.LOCAL;
variableFound = true;
}
if (!variableFound) {
throw new ActivitiObjectNotFoundException("Execution '" + execution.getId() +
"' doesn't have a variable with name: '" + variableName + "'.", VariableInstanceEntity.class);
} else {
return constructRestVariable(variableName, value, variableScope, execution.getId(), includeBinary);
}
}
protected List<RestVariable> processVariables(Execution execution, String scope, int variableType) {
List<RestVariable> result = new ArrayList<RestVariable>();
Map<String, RestVariable> variableMap = new HashMap<>();
// Check if it's a valid execution to get the variables for
RestVariable.RestVariableScope variableScope = RestVariable.getScopeFromString(scope);
if (variableScope == null) {
// Use both local and global variables
addLocalVariables(execution, variableType, variableMap);
addGlobalVariables(execution, variableType, variableMap);
} else if (variableScope == RestVariable.RestVariableScope.GLOBAL) {
addGlobalVariables(execution, variableType, variableMap);
} else if (variableScope == RestVariable.RestVariableScope.LOCAL) {
addLocalVariables(execution, variableType, variableMap);
}
// Get unique variables from map
result.addAll(variableMap.values());
return result;
}
protected void addLocalVariables(Execution execution, int variableType, Map<String, RestVariable> variableMap) {
RuntimeService runtimeService = BPMNOSGIService.getRuntimeService();
Map<String, Object> rawLocalvariables = runtimeService.getVariablesLocal(execution.getId());
List<RestVariable> localVariables = new RestResponseFactory().createRestVariables(rawLocalvariables,
execution.getId(), variableType, RestVariable.RestVariableScope.LOCAL, uriInfo.getBaseUri().toString());
for (RestVariable var : localVariables) {
variableMap.put(var.getName(), var);
}
}
protected void addGlobalVariables(Execution execution, int variableType, Map<String, RestVariable> variableMap) {
RuntimeService runtimeService = BPMNOSGIService.getRuntimeService();
Map<String, Object> rawVariables = runtimeService.getVariables(execution.getId());
List<RestVariable> globalVariables = new RestResponseFactory().createRestVariables(rawVariables,
execution.getId(), variableType, RestVariable.RestVariableScope.GLOBAL, uriInfo.getBaseUri().toString());
// Overlay global variables over local ones. In case they are present the values are not overridden,
// since local variables get precedence over global ones at all times.
for (RestVariable var : globalVariables) {
if (!variableMap.containsKey(var.getName())) {
variableMap.put(var.getName(), var);
}
}
}
protected RestVariable constructRestVariable(String variableName, Object value,
RestVariable.RestVariableScope variableScope, String executionId, boolean includeBinary) {
return new RestResponseFactory().createRestVariable(variableName, value, variableScope, executionId,
RestResponseFactory.VARIABLE_EXECUTION, includeBinary, uriInfo.getBaseUri().toString());
}
private boolean isValidUserToStartProcess(ProcessInstanceCreateRequest processInstanceCreateRequest) {
//check whether the users/groups exist
String processDefinitionId = processInstanceCreateRequest.getProcessDefinitionId();
RepositoryService repositoryService = BPMNOSGIService.getRepositoryService();
if (processDefinitionId == null) {
final String processDefinitionKey = processInstanceCreateRequest.getProcessDefinitionKey();
final String tenantId = processInstanceCreateRequest.getTenantId();
ProcessEngine processEngine = BPMNOSGIService.getBPMNEngineService().getProcessEngine();
if (processEngine != null) {
if(processDefinitionKey != null){
if (((ProcessEngineImpl) processEngine).getProcessEngineConfiguration() != null) {
CommandExecutor commandExecutor = ((ProcessEngineImpl) processEngine).getProcessEngineConfiguration().getCommandExecutor();
if (commandExecutor != null) {
processDefinitionId =
(String) commandExecutor.execute(new Command<Object>() {
public Object execute(CommandContext commandContext) {
ProcessDefinitionEntityManager processDefinitionEntityManager = commandContext.
getSession(ProcessDefinitionEntityManager.class);
ProcessDefinitionEntity processDefinitionEntity = processDefinitionEntityManager.
findLatestProcessDefinitionByKeyAndTenantId(processDefinitionKey, tenantId);
if (processDefinitionEntity != null && processDefinitionEntity
.getProcessDefinition() != null) {
return processDefinitionEntity.getProcessDefinition().getId();
}
return null;
}
});
}
}
if (processDefinitionId == null) {
return false;
}
}
String messageName = processInstanceCreateRequest.getMessage();
if(messageName != null && !messageName.isEmpty()){
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
.messageEventSubscriptionName(messageName);
if(processDefinitionQuery != null){
processDefinitionQuery = processDefinitionQuery.processDefinitionTenantId
(processInstanceCreateRequest.getTenantId());
if(processDefinitionQuery != null && processDefinitionQuery.count() > 1){
processDefinitionQuery = processDefinitionQuery.latestVersion();
}
}
if(processDefinitionQuery != null){
ProcessDefinition processDefinition = processDefinitionQuery.singleResult();
if(processDefinition != null){
processDefinitionId = processDefinition.getId();
}
}
if (processDefinitionId == null) {
return false;
}
}
}
}
PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
String userName = carbonContext.getUsername();
String tenantDomain = carbonContext.getTenantDomain();
String userNameWithTenantDomain = userName + "@" + tenantDomain;
BPSGroupIdentityManager bpsGroupIdentityManager = BPMNOSGIService.getGroupIdentityManager();
List<Group> groupList = bpsGroupIdentityManager.findGroupsByUser(userName);
List<IdentityLink> identityLinkList = repositoryService.getIdentityLinksForProcessDefinition
(processDefinitionId);
boolean valueExistsForUserId = false;
boolean valueExistsForGroupId = false;
for (IdentityLink identityLink : identityLinkList) {
String userId = identityLink.getUserId();
if (userId != null) {
valueExistsForUserId = true;
if (userId.contains("$")) {
userId = resolveVariable(processInstanceCreateRequest, userId);
}
if ( !userId.isEmpty() && ( userId.equals(userName) || userId.equals(userNameWithTenantDomain)) ) {
return true;
}
continue;
}
String groupId = identityLink.getGroupId();
if (groupId != null) {
valueExistsForGroupId = true;
if (groupId.contains("$")) {
groupId = resolveVariable(processInstanceCreateRequest, groupId);
}
for (Group identityGroup:groupList){
if(!groupId.isEmpty() && identityGroup.getId() != null && identityGroup.getId().equals(groupId)){
return true;
}
}
}
}
if (!valueExistsForGroupId && !valueExistsForUserId) {
return true;
}
return false;
}
private String resolveVariable(ProcessInstanceCreateRequest processInstanceCreateRequest, String resolvingName) {
int initialIndex = resolvingName.indexOf("{");
int lastIndex = resolvingName.indexOf("}");
String variableName = null;
if (initialIndex != -1 && lastIndex != -1 && initialIndex < lastIndex) {
variableName = resolvingName.substring(initialIndex + 1, lastIndex);
}
List<RestVariable> variableList = processInstanceCreateRequest.getVariables();
if(variableList != null && variableName != null){
for (RestVariable restVariable:variableList){
if(restVariable.getName().equals(variableName)){
return restVariable.getValue().toString();
}
}
}
variableList = processInstanceCreateRequest.getAdditionalVariables();
if(variableList != null && variableName != null){
for (RestVariable restVariable:variableList){
if(restVariable.getName().equals(variableName)){
return restVariable.getValue().toString();
}
}
}
return "";
}
private Response performCorrelation(ProcessInstanceCreateRequest processInstanceCreateRequest){
CorrelationActionRequest correlationActionRequest = new CorrelationActionRequest();
String requestValue = processInstanceCreateRequest.getProcessDefinitionId();
if( requestValue != null){
correlationActionRequest.setProcessDefinitionId(processInstanceCreateRequest.getProcessDefinitionId());
}
requestValue = processInstanceCreateRequest.getProcessDefinitionKey();
if(requestValue != null){
correlationActionRequest.setProcessDefinitionKey(requestValue);
}
if(processInstanceCreateRequest.isCustomTenantSet()){
correlationActionRequest.setTenantId(processInstanceCreateRequest.getTenantId());
}
requestValue = processInstanceCreateRequest.getMessageName();
if(requestValue != null){
correlationActionRequest.setMessageName(requestValue);
}
List<RestVariable> variables = processInstanceCreateRequest.getVariables();
if(variables != null){
RestResponseFactory restResponseFactory = new RestResponseFactory();
List<QueryVariable> correlationVariableList = new ArrayList<>();
for (RestVariable variable:variables){
QueryVariable correlationVariable = new QueryVariable();
correlationVariable.setName(variable.getName());
correlationVariable.setOperation("equals");
correlationVariable.setType(variable.getType());
correlationVariable.setValue(restResponseFactory.getVariableValue(variable));
correlationVariableList.add(correlationVariable);
}
correlationActionRequest.setCorrelationVariables(correlationVariableList);
}
variables = processInstanceCreateRequest.getAdditionalVariables();
if(variables != null){
correlationActionRequest.setVariables(variables);
}
correlationActionRequest.setAction(CorrelationActionRequest.ACTION_MESSAGE_EVENT_RECEIVED);
return new CorrelationProcess().getQueryResponse(correlationActionRequest, uriInfo);
}
/**
* Delete all variables in local scope of a process instance.
* @param execution
*/
protected void deleteAllLocalVariables(Execution execution) {
RuntimeService runtimeService = BPMNOSGIService.getRuntimeService();
Collection<String> currentVariables = runtimeService.getVariablesLocal(execution.getId()).keySet();
runtimeService.removeVariablesLocal(execution.getId(), currentVariables);
}
}