/*
* Copyright (c) 2015. WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.management;
import org.activiti.engine.*;
import org.activiti.engine.impl.JobQueryProperty;
import org.activiti.engine.management.TableMetaData;
import org.activiti.engine.management.TablePage;
import org.activiti.engine.management.TablePageQuery;
import org.activiti.engine.query.QueryProperty;
import org.activiti.engine.runtime.Job;
import org.activiti.engine.runtime.JobQuery;
import org.wso2.carbon.bpmn.rest.common.RequestUtil;
import org.wso2.carbon.bpmn.rest.common.RestResponseFactory;
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.runtime.*;
import javax.ws.rs.*;
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.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ManagementService {
@Context
UriInfo uriInfo;
private static final String EXECUTE_ACTION = "execute";
protected static final Integer DEFAULT_RESULT_SIZE = 10;
protected static Map<String, QueryProperty> properties;
protected static final List<String> jobPropertiesList = new ArrayList<>();
static {
jobPropertiesList.add("id");
jobPropertiesList.add("processInstanceId");
jobPropertiesList.add("executionId");
jobPropertiesList.add("processDefinitionId");
jobPropertiesList.add("dueBefore");
jobPropertiesList.add("dueAfter");
jobPropertiesList.add("exceptionMessage");
jobPropertiesList.add("tenantId");
jobPropertiesList.add("tenantIdLike");
jobPropertiesList.add("withRetriesLeft");
jobPropertiesList.add("executable");
jobPropertiesList.add("timersOnly");
jobPropertiesList.add("messagesOnly");
jobPropertiesList.add("withException");
jobPropertiesList.add("withoutTenantId");
}
static {
properties = new HashMap<String, QueryProperty>();
properties.put("id", JobQueryProperty.JOB_ID);
properties.put("dueDate", JobQueryProperty.DUEDATE);
properties.put("executionId", JobQueryProperty.EXECUTION_ID);
properties.put("processInstanceId", JobQueryProperty.PROCESS_INSTANCE_ID);
properties.put("retries", JobQueryProperty.RETRIES);
properties.put("tenantId", JobQueryProperty.TENANT_ID);
}
protected RestResponseFactory restResponseFactory = new RestResponseFactory();
protected org.activiti.engine.ManagementService managementService = BPMNOSGIService.getManagementService();
@GET
@Path("/jobs")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public DataResponse getJobs() {
JobQuery query = managementService.createJobQuery();
Map<String, String> allRequestParams = Utils.populateRequestParams(jobPropertiesList, uriInfo);
allRequestParams = Utils.prepareCommonParameters(allRequestParams, uriInfo);
if (allRequestParams.containsKey("id")) {
query.jobId(allRequestParams.get("id"));
}
if (allRequestParams.containsKey("processInstanceId")) {
query.processInstanceId(allRequestParams.get("processInstanceId"));
}
if (allRequestParams.containsKey("executionId")) {
query.executionId(allRequestParams.get("executionId"));
}
if (allRequestParams.containsKey("processDefinitionId")) {
query.processDefinitionId(allRequestParams.get("processDefinitionId"));
}
if (allRequestParams.containsKey("withRetriesLeft")) {
if (Boolean.valueOf(allRequestParams.get("withRetriesLeft"))) {
query.withRetriesLeft();
}
}
if (allRequestParams.containsKey("executable")) {
if (Boolean.valueOf(allRequestParams.get("executable"))) {
query.executable();
}
}
if (allRequestParams.containsKey("timersOnly")) {
if (allRequestParams.containsKey("messagesOnly")) {
throw new ActivitiIllegalArgumentException("Only one of 'timersOnly' or 'messagesOnly' can be provided.");
}
if (Boolean.valueOf(allRequestParams.get("timersOnly"))) {
query.timers();
}
}
if (allRequestParams.containsKey("messagesOnly")) {
if (Boolean.valueOf(allRequestParams.get("messagesOnly"))) {
query.messages();
}
}
if (allRequestParams.containsKey("dueBefore")) {
query.duedateLowerThan(RequestUtil.getDate(allRequestParams, "dueBefore"));
}
if (allRequestParams.containsKey("dueAfter")) {
query.duedateHigherThan(RequestUtil.getDate(allRequestParams, "dueAfter"));
}
if (allRequestParams.containsKey("withException")) {
if (Boolean.valueOf(allRequestParams.get("withException"))) {
query.withException();
}
}
if (allRequestParams.containsKey("exceptionMessage")) {
query.exceptionMessage(allRequestParams.get("exceptionMessage"));
}
if (allRequestParams.containsKey("tenantId")) {
query.jobTenantId(allRequestParams.get("tenantId"));
}
if (allRequestParams.containsKey("tenantIdLike")) {
query.jobTenantIdLike(allRequestParams.get("tenantIdLike"));
}
if (allRequestParams.containsKey("withoutTenantId")) {
if (Boolean.valueOf(allRequestParams.get("withoutTenantId"))) {
query.jobWithoutTenantId();
}
}
return new JobPaginateList(restResponseFactory, uriInfo)
.paginateList(allRequestParams, query, "id", properties);
}
@GET
@Path("/jobs/{jobId}/exception-stacktrace")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public String getJobStacktrace(@PathParam("jobId") String jobId) {
Job job = getJobFromResponse(jobId);
String stackTrace = managementService.getJobExceptionStacktrace(job.getId());
if (stackTrace == null) {
throw new ActivitiObjectNotFoundException("Job with id '" + job.getId() + "' doesn't have an exception stacktrace.", String.class);
}
Response.ok(stackTrace, "plain");
return stackTrace;
}
protected Job getJobFromResponse(String jobId) {
Job job = managementService.createJobQuery().jobId(jobId).singleResult();
if (job == null) {
throw new ActivitiObjectNotFoundException("Could not find a job with id '" + jobId + "'.", Job.class);
}
return job;
}
@GET
@Path("/jobs/{jobId}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public JobResponse getJob(@PathParam("jobId") String jobId) {
Job job = getJobFromResponse(jobId);
return restResponseFactory.createJobResponse(job, uriInfo.getBaseUri().toString());
}
@DELETE
@Path("/jobs/{jobId}")
public void deleteJob(@PathParam("jobId") String jobId) {
try {
managementService.deleteJob(jobId);
} catch(ActivitiObjectNotFoundException aonfe) {
// Re-throw to have consistent error-messaging acrosse REST-api
throw new ActivitiObjectNotFoundException("Could not find a job with id '" + jobId + "'.", Job.class);
}
Response.noContent().build();
}
@POST
@Path("/jobs/{jobId}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public void executeJobAction(@PathParam("jobId") String jobId, RestActionRequest actionRequest) {
if (actionRequest == null || ! EXECUTE_ACTION.equals(actionRequest.getAction())) {
throw new ActivitiIllegalArgumentException("Invalid action, only 'execute' is supported.");
}
try {
managementService.executeJob(jobId);
} catch(ActivitiObjectNotFoundException aonfe) {
// Re-throw to have consistent error-messaging acrosse REST-api
throw new ActivitiObjectNotFoundException("Could not find a job with id '" + jobId + "'.", Job.class);
}
Response.noContent().build();
}
@GET
@Path("/engine")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public ProcessEngineInfoResponse getEngineInfo() {
ProcessEngineInfoResponse response = new ProcessEngineInfoResponse();
ProcessEngine engine = BPMNOSGIService.getBPMNEngineService().getProcessEngine();
try {
ProcessEngineInfo engineInfo = ProcessEngines.getProcessEngineInfo(engine.getName());
if (engineInfo != null) {
response.setName(engineInfo.getName());
response.setResourceUrl(engineInfo.getResourceUrl());
response.setException(engineInfo.getException());
} else {
// Revert to using process-engine directly
response.setName(engine.getName());
}
} catch (Exception e) {
throw new ActivitiException("Error retrieving process info", e);
}
response.setVersion(ProcessEngine.VERSION);
return response;
}
@GET
@Path("/properties")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Map<String, String> getProperties() {
return managementService.getProperties();
}
@GET
@Path("/tables")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public List<TableResponse> getTables() {
return restResponseFactory.createTableResponseList(managementService.getTableCount(), uriInfo.getBaseUri().toString());
}
@GET
@Path("/tables/{tableName}/columns")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public TableMetaData getTableMetaData(@PathParam("tableName") String tableName) {
TableMetaData response = managementService.getTableMetaData(tableName);
if (response == null) {
throw new ActivitiObjectNotFoundException("Could not find a table with name '" + tableName + "'.", String.class);
}
return response;
}
@GET
@Path("/tables/{tableName}/data")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public DataResponse getTableData(@PathParam("tableName") String tableName) {
Map<String,String> allRequestParams = new HashMap<>();
// Check if table exists before continuing
if (managementService.getTableMetaData(tableName) == null) {
throw new ActivitiObjectNotFoundException("Could not find a table with name '" + tableName + "'.", String.class);
}
String orderAsc = uriInfo.getQueryParameters().getFirst("orderAscendingColumn");
String orderDesc = uriInfo.getQueryParameters().getFirst("orderDescendingColumn");
if (orderAsc != null && orderDesc != null) {
throw new ActivitiIllegalArgumentException("Only one of 'orderAscendingColumn' or 'orderDescendingColumn' can be supplied.");
}
allRequestParams = Utils.prepareCommonParameters(allRequestParams, uriInfo);
Integer start = null;
if (allRequestParams.containsKey("start")) {
start = Integer.valueOf(allRequestParams.get("start"));
}
if (start == null) {
start = 0;
}
Integer size = null;
if (allRequestParams.containsKey("size")) {
size = Integer.valueOf(allRequestParams.get("size"));
}
if (size == null) {
size = DEFAULT_RESULT_SIZE;
}
DataResponse response = new DataResponse();
TablePageQuery tablePageQuery = managementService.createTablePageQuery().tableName(tableName);
if (orderAsc != null) {
allRequestParams.put("orderAscendingColumn", orderAsc);
tablePageQuery.orderAsc(orderAsc);
response.setOrder("asc");
response.setSort(orderAsc);
}
if (orderDesc != null) {
allRequestParams.put("orderDescendingColumn", orderDesc);
tablePageQuery.orderDesc(orderDesc);
response.setOrder("desc");
response.setSort(orderDesc);
}
TablePage listPage = tablePageQuery.listPage(start, size);
response.setSize(((Long) listPage.getSize()).intValue());
response.setStart(((Long) listPage.getFirstResult()).intValue());
response.setTotal(listPage.getTotal());
response.setData((List)listPage.getRows());
return response;
}
@GET
@Path("/tables/{tableName}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public TableResponse getTable(@PathParam("tableName") String tableName) {
Map<String, Long> tableCounts = managementService.getTableCount();
TableResponse response = null;
for (Map.Entry<String, Long> entry : tableCounts.entrySet()) {
if (entry.getKey().equals(tableName)) {
response = restResponseFactory.createTableResponse(entry.getKey(), entry.getValue(), uriInfo.getBaseUri().toString());
break;
}
}
if (response == null) {
throw new ActivitiObjectNotFoundException("Could not find a table with name '" + tableName + "'.", String.class);
}
return response;
}
}