/** * 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.repository; import org.activiti.engine.ActivitiException; import org.activiti.engine.ActivitiIllegalArgumentException; import org.activiti.engine.ActivitiObjectNotFoundException; import org.activiti.engine.RepositoryService; import org.activiti.engine.impl.ProcessDefinitionQueryProperty; import org.activiti.engine.query.QueryProperty; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.repository.ProcessDefinitionQuery; import org.activiti.engine.task.IdentityLink; import org.activiti.engine.task.IdentityLinkType; import org.apache.commons.io.IOUtils; import org.wso2.carbon.bpmn.rest.common.RestResponseFactory; import org.wso2.carbon.bpmn.rest.common.RestUrls; import org.wso2.carbon.bpmn.rest.common.utils.BPMNOSGIService; import org.wso2.carbon.bpmn.rest.common.utils.Utils; import org.wso2.carbon.bpmn.rest.model.common.DataResponse; import org.wso2.carbon.bpmn.rest.model.repository.ProcessDefinitionResponse; import org.wso2.carbon.bpmn.rest.model.repository.ProcessDefinitionsPaginateList; import javax.ws.rs.GET; 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 java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @Path("/process-definitions") public class ProcessDefinitionService { @Context UriInfo uriInfo; private static final Map<String, QueryProperty> properties = new HashMap<>(); private static final List<String> allPropertiesList = new ArrayList<>(); static { properties.put("id", ProcessDefinitionQueryProperty.PROCESS_DEFINITION_ID); properties.put("key", ProcessDefinitionQueryProperty.PROCESS_DEFINITION_KEY); properties.put("category", ProcessDefinitionQueryProperty.PROCESS_DEFINITION_CATEGORY); properties.put("name", ProcessDefinitionQueryProperty.PROCESS_DEFINITION_NAME); properties.put("version", ProcessDefinitionQueryProperty.PROCESS_DEFINITION_VERSION); properties.put("deploymentId", ProcessDefinitionQueryProperty.DEPLOYMENT_ID); properties.put("tenantId", ProcessDefinitionQueryProperty.PROCESS_DEFINITION_TENANT_ID); } static { allPropertiesList.add("version"); allPropertiesList.add("name"); allPropertiesList.add("nameLike"); allPropertiesList.add("key"); allPropertiesList.add("keyLike"); allPropertiesList.add("resourceName"); allPropertiesList.add("resourceNameLike"); allPropertiesList.add("category"); allPropertiesList.add("categoryLike"); allPropertiesList.add("categoryNotEquals"); allPropertiesList.add("deploymentId"); allPropertiesList.add("startableByUser"); allPropertiesList.add("latest"); allPropertiesList.add("suspended"); allPropertiesList.add("tenantId"); allPropertiesList.add("start"); allPropertiesList.add("size"); allPropertiesList.add("order"); allPropertiesList.add("sort"); } @GET @Path("/") @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Response getProcessDefinitions() { RepositoryService repositoryService = BPMNOSGIService.getRepositoryService(); Map<String, String> allRequestParams = new HashMap<>(); for (String property : allPropertiesList) { String value = uriInfo.getQueryParameters().getFirst(property); if (value != null) { allRequestParams.put(property, value); } } ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery(); // Populate filter-parameters if (allRequestParams.containsKey("category")) { processDefinitionQuery.processDefinitionCategory(allRequestParams.get("category")); } if (allRequestParams.containsKey("categoryLike")) { processDefinitionQuery.processDefinitionCategoryLike(allRequestParams.get("categoryLike")); } if (allRequestParams.containsKey("categoryNotEquals")) { processDefinitionQuery.processDefinitionCategoryNotEquals(allRequestParams.get("categoryNotEquals")); } if (allRequestParams.containsKey("key")) { processDefinitionQuery.processDefinitionKey(allRequestParams.get("key")); } if (allRequestParams.containsKey("keyLike")) { processDefinitionQuery.processDefinitionKeyLike(allRequestParams.get("keyLike")); } if (allRequestParams.containsKey("name")) { processDefinitionQuery.processDefinitionName(allRequestParams.get("name")); } if (allRequestParams.containsKey("nameLike")) { processDefinitionQuery.processDefinitionNameLike(allRequestParams.get("nameLike")); } if (allRequestParams.containsKey("resourceName")) { processDefinitionQuery.processDefinitionResourceName(allRequestParams.get("resourceName")); } if (allRequestParams.containsKey("resourceNameLike")) { processDefinitionQuery.processDefinitionResourceNameLike(allRequestParams.get("resourceNameLike")); } if (allRequestParams.containsKey("version")) { processDefinitionQuery.processDefinitionVersion(Integer.valueOf(allRequestParams.get("version"))); } if (allRequestParams.containsKey("suspended")) { Boolean suspended = Boolean.valueOf(allRequestParams.get("suspended")); if (suspended != null) { if (suspended) { processDefinitionQuery.suspended(); } else { processDefinitionQuery.active(); } } } if (allRequestParams.containsKey("latest")) { Boolean latest = Boolean.valueOf(allRequestParams.get("latest")); if (latest != null && latest) { processDefinitionQuery.latestVersion(); } } if (allRequestParams.containsKey("deploymentId")) { processDefinitionQuery.deploymentId(allRequestParams.get("deploymentId")); } if (allRequestParams.containsKey("startableByUser")) { processDefinitionQuery.startableByUser(allRequestParams.get("startableByUser")); } if (allRequestParams.containsKey("tenantId")) { processDefinitionQuery.processDefinitionTenantId(allRequestParams.get("tenantId")); } if (allRequestParams.containsKey("tenantIdLike")) { processDefinitionQuery.processDefinitionTenantIdLike(allRequestParams.get("tenantIdLike")); } DataResponse response = new ProcessDefinitionsPaginateList(new RestResponseFactory(), uriInfo) .paginateList(allRequestParams, processDefinitionQuery, "name", properties); return Response.ok().entity(response).build(); } @GET @Path("/{processDefinitionId}") @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public ProcessDefinitionResponse getProcessDefinition(@PathParam("processDefinitionId") String processDefinitionId) { ProcessDefinition processDefinition = getProcessDefinitionFromRequest(processDefinitionId); return new RestResponseFactory().createProcessDefinitionResponse(processDefinition, uriInfo.getBaseUri().toString()); } @GET @Path("/{processDefinitionId}/resourcedata") @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Response getProcessDefinitionResource(@PathParam("processDefinitionId") String processDefinitionId) { RepositoryService repositoryService = BPMNOSGIService.getRepositoryService(); ProcessDefinition processDefinition = getProcessDefinitionFromRequest(processDefinitionId); String resourceID = processDefinition.getResourceName(); String contentType = Utils.resolveContentType(processDefinition.getResourceName()); return Response.ok().type(contentType).entity(getDeploymentResourceData(processDefinition.getDeploymentId(), resourceID, repositoryService)).build(); } @GET @Path("/{processDefinitionId}/identitylinks") @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Response getIdentityLinks(@PathParam("processDefinitionId") String processDefinitionId) { RepositoryService repositoryService = BPMNOSGIService.getRepositoryService(); ProcessDefinition processDefinition = getProcessDefinitionFromRequest(processDefinitionId); return Response.ok().entity(new RestResponseFactory().createRestIdentityLinks(repositoryService .getIdentityLinksForProcessDefinition(processDefinition.getId()), uriInfo.getBaseUri().toString())).build(); } @GET @Path("/{processDefinitionId}/identitylinks/{family}/{identityId}") @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Response getIdentityLink(@PathParam("processDefinitionId") String processDefinitionId, @PathParam("family") String family, @PathParam("identityId") String identityId) { ProcessDefinition processDefinition = getProcessDefinitionFromRequest(processDefinitionId); validateIdentityLinkArguments(family, identityId); RepositoryService repositoryService = BPMNOSGIService.getRepositoryService(); // Check if identitylink to get exists IdentityLink link = getIdentityLink(family, identityId, processDefinition.getId(), repositoryService); return Response.ok().entity(new RestResponseFactory().createRestIdentityLink(link, uriInfo.getBaseUri().toString())) .build(); } private ProcessDefinition getProcessDefinitionFromRequest(String processDefinitionId) { RepositoryService repositoryService = BPMNOSGIService.getRepositoryService(); ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); if (processDefinition == null) { throw new ActivitiObjectNotFoundException("Could not find a process definition with id '" + processDefinitionId + "'.", ProcessDefinition.class); } return processDefinition; } private byte[] getDeploymentResourceData(String deploymentId, String resourceId, RepositoryService repositoryService) { if (deploymentId == null) { throw new ActivitiIllegalArgumentException("No deployment id provided"); } if (resourceId == null) { throw new ActivitiIllegalArgumentException("No resource id provided"); } // Check if deployment exists Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult(); if (deployment == null) { throw new ActivitiObjectNotFoundException("Could not find a deployment with id '" + deploymentId + "'.", Deployment.class); } List<String> resourceList = repositoryService.getDeploymentResourceNames(deploymentId); if (resourceList.contains(resourceId)) { final InputStream resourceStream = repositoryService.getResourceAsStream(deploymentId, resourceId); try { return IOUtils.toByteArray(resourceStream); } catch (Exception e) { throw new ActivitiException("Error converting resource stream", e); } } else { // Resource not found in deployment throw new ActivitiObjectNotFoundException("Could not find a resource with id '" + resourceId + "' in deployment '" + deploymentId + "'.", String.class); } } protected void validateIdentityLinkArguments(String family, String identityId) { if (family == null || (!RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_GROUPS.equals(family) && !RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS.equals(family))) { throw new ActivitiIllegalArgumentException("Identity link family should be 'users' or 'groups'."); } if (identityId == null) { throw new ActivitiIllegalArgumentException("IdentityId is required."); } } protected IdentityLink getIdentityLink(String family, String identityId, String processDefinitionId, RepositoryService repositoryService) { boolean isUser = family.equals(RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS); // Perhaps it would be better to offer getting a single identitylink from // the API List<IdentityLink> allLinks = repositoryService.getIdentityLinksForProcessDefinition(processDefinitionId); for (IdentityLink link : allLinks) { boolean rightIdentity; if (isUser) { rightIdentity = identityId.equals(link.getUserId()); } else { rightIdentity = identityId.equals(link.getGroupId()); } if (rightIdentity && link.getType().equals(IdentityLinkType.CANDIDATE)) { return link; } } throw new ActivitiObjectNotFoundException("Could not find the requested identity link.", IdentityLink.class); } }