/* 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.activiti.engine.impl.persistence.deploy;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.delegate.event.ActivitiEventDispatcher;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.impl.ActivitiEventBuilder;
import org.activiti.engine.impl.ProcessDefinitionQueryImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.persistence.entity.DeploymentEntity;
import org.activiti.engine.impl.persistence.entity.DeploymentEntityManager;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.ResourceEntity;
import org.activiti.engine.impl.util.io.BytesStreamSource;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
/**
* @author Tom Baeyens
* @author Falko Menge
* @author Joram Barrez
*/
public class DeploymentManager {
protected DeploymentCache<ProcessDefinitionEntity> processDefinitionCache;
protected DeploymentCache<BpmnModel> bpmnModelCache;
protected ProcessDefinitionInfoCache processDefinitionInfoCache;
protected DeploymentCache<Object> knowledgeBaseCache; // Needs to be object to avoid an import to Drools in this core class
protected List<Deployer> deployers;
public void deploy(DeploymentEntity deployment) {
deploy(deployment, null);
}
public void deploy(DeploymentEntity deployment, Map<String, Object> deploymentSettings) {
for (Deployer deployer: deployers) {
deployer.deploy(deployment, deploymentSettings);
}
}
public ProcessDefinitionEntity findDeployedProcessDefinitionById(String processDefinitionId) {
if (processDefinitionId == null) {
throw new ActivitiIllegalArgumentException("Invalid process definition id : null");
}
// first try the cache
ProcessDefinitionEntity processDefinition = processDefinitionCache.get(processDefinitionId);
if (processDefinition == null) {
processDefinition = Context.getCommandContext()
.getProcessDefinitionEntityManager()
.findProcessDefinitionById(processDefinitionId);
if (processDefinition == null) {
throw new ActivitiObjectNotFoundException("no deployed process definition found with id '" + processDefinitionId + "'", ProcessDefinition.class);
}
processDefinition = resolveProcessDefinition(processDefinition);
}
return processDefinition;
}
public ProcessDefinitionEntity findProcessDefinitionByIdFromDatabase(String processDefinitionId) {
if (processDefinitionId == null) {
throw new ActivitiIllegalArgumentException("Invalid process definition id : null");
}
ProcessDefinitionEntity processDefinition = Context.getCommandContext()
.getProcessDefinitionEntityManager()
.findProcessDefinitionById(processDefinitionId);
if (processDefinition == null) {
throw new ActivitiObjectNotFoundException("no deployed process definition found with id '" + processDefinitionId + "'", ProcessDefinition.class);
}
return processDefinition;
}
public boolean isProcessDefinitionSuspended(String processDefinitionId) {
return findProcessDefinitionByIdFromDatabase(processDefinitionId).isSuspended();
}
public BpmnModel getBpmnModelById(String processDefinitionId) {
if (processDefinitionId == null) {
throw new ActivitiIllegalArgumentException("Invalid process definition id : null");
}
// first try the cache
BpmnModel bpmnModel = bpmnModelCache.get(processDefinitionId);
if (bpmnModel == null) {
ProcessDefinitionEntity processDefinition = findDeployedProcessDefinitionById(processDefinitionId);
if (processDefinition == null) {
throw new ActivitiObjectNotFoundException("no deployed process definition found with id '" + processDefinitionId + "'", ProcessDefinition.class);
}
// Fetch the resource
String resourceName = processDefinition.getResourceName();
ResourceEntity resource = Context.getCommandContext().getResourceEntityManager()
.findResourceByDeploymentIdAndResourceName(processDefinition.getDeploymentId(), resourceName);
if (resource == null) {
if (Context.getCommandContext().getDeploymentEntityManager().findDeploymentById(processDefinition.getDeploymentId()) == null) {
throw new ActivitiObjectNotFoundException("deployment for process definition does not exist: "
+ processDefinition.getDeploymentId(), Deployment.class);
} else {
throw new ActivitiObjectNotFoundException("no resource found with name '" + resourceName
+ "' in deployment '" + processDefinition.getDeploymentId() + "'", InputStream.class);
}
}
// Convert the bpmn 2.0 xml to a bpmn model
BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
bpmnModel = bpmnXMLConverter.convertToBpmnModel(new BytesStreamSource(resource.getBytes()), false, false);
bpmnModelCache.add(processDefinition.getId(), bpmnModel);
}
return bpmnModel;
}
public ProcessDefinitionEntity findDeployedLatestProcessDefinitionByKey(String processDefinitionKey) {
ProcessDefinitionEntity processDefinition = Context
.getCommandContext()
.getProcessDefinitionEntityManager()
.findLatestProcessDefinitionByKey(processDefinitionKey);
if (processDefinition==null) {
throw new ActivitiObjectNotFoundException("no processes deployed with key '"+processDefinitionKey+"'", ProcessDefinition.class);
}
processDefinition = resolveProcessDefinition(processDefinition);
return processDefinition;
}
public ProcessDefinitionEntity findDeployedLatestProcessDefinitionByKeyAndTenantId(String processDefinitionKey, String tenantId) {
ProcessDefinitionEntity processDefinition = Context
.getCommandContext()
.getProcessDefinitionEntityManager()
.findLatestProcessDefinitionByKeyAndTenantId(processDefinitionKey, tenantId);
if (processDefinition==null) {
throw new ActivitiObjectNotFoundException("no processes deployed with key '"+processDefinitionKey+"' for tenant identifier '" + tenantId + "'", ProcessDefinition.class);
}
processDefinition = resolveProcessDefinition(processDefinition);
return processDefinition;
}
public ProcessDefinitionEntity findDeployedProcessDefinitionByKeyAndVersion(String processDefinitionKey, Integer processDefinitionVersion) {
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) Context
.getCommandContext()
.getProcessDefinitionEntityManager()
.findProcessDefinitionByKeyAndVersion(processDefinitionKey, processDefinitionVersion);
if (processDefinition==null) {
throw new ActivitiObjectNotFoundException("no processes deployed with key = '" + processDefinitionKey + "' and version = '" + processDefinitionVersion + "'", ProcessDefinition.class);
}
processDefinition = resolveProcessDefinition(processDefinition);
return processDefinition;
}
public ProcessDefinitionEntity resolveProcessDefinition(ProcessDefinitionEntity processDefinition) {
String processDefinitionId = processDefinition.getId();
String deploymentId = processDefinition.getDeploymentId();
processDefinition = processDefinitionCache.get(processDefinitionId);
if (processDefinition==null) {
DeploymentEntity deployment = Context
.getCommandContext()
.getDeploymentEntityManager()
.findDeploymentById(deploymentId);
deployment.setNew(false);
deploy(deployment, null);
processDefinition = processDefinitionCache.get(processDefinitionId);
if (processDefinition==null) {
throw new ActivitiException("deployment '"+deploymentId+"' didn't put process definition '"+processDefinitionId+"' in the cache");
}
}
return processDefinition;
}
public void removeDeployment(String deploymentId, boolean cascade) {
DeploymentEntityManager deploymentEntityManager = Context
.getCommandContext()
.getDeploymentEntityManager();
DeploymentEntity deployment = deploymentEntityManager.findDeploymentById(deploymentId);
if(deployment == null)
throw new ActivitiObjectNotFoundException("Could not find a deployment with id '" + deploymentId + "'.", DeploymentEntity.class);
// Remove any process definition from the cache
List<ProcessDefinition> processDefinitions = new ProcessDefinitionQueryImpl(Context.getCommandContext())
.deploymentId(deploymentId)
.list();
ActivitiEventDispatcher eventDispatcher = Context.getProcessEngineConfiguration().getEventDispatcher();
for (ProcessDefinition processDefinition : processDefinitions) {
// Since all process definitions are deleted by a single query, we should dispatch the events in this loop
if (eventDispatcher.isEnabled()) {
eventDispatcher.dispatchEvent(ActivitiEventBuilder.createEntityEvent(
ActivitiEventType.ENTITY_DELETED, processDefinition));
}
}
// Delete data
deploymentEntityManager.deleteDeployment(deploymentId, cascade);
// Since we use a delete by query, delete-events are not automatically dispatched
if(eventDispatcher.isEnabled()) {
eventDispatcher.dispatchEvent(
ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_DELETED, deployment));
}
for (ProcessDefinition processDefinition : processDefinitions) {
processDefinitionCache.remove(processDefinition.getId());
}
}
// getters and setters //////////////////////////////////////////////////////
public List<Deployer> getDeployers() {
return deployers;
}
public void setDeployers(List<Deployer> deployers) {
this.deployers = deployers;
}
public DeploymentCache<ProcessDefinitionEntity> getProcessDefinitionCache() {
return processDefinitionCache;
}
public void setProcessDefinitionCache(DeploymentCache<ProcessDefinitionEntity> processDefinitionCache) {
this.processDefinitionCache = processDefinitionCache;
}
public DeploymentCache<BpmnModel> getBpmnModelCache() {
return bpmnModelCache;
}
public void setBpmnModelCache(DeploymentCache<BpmnModel> bpmnModelCache) {
this.bpmnModelCache = bpmnModelCache;
}
public ProcessDefinitionInfoCache getProcessDefinitionInfoCache() {
return processDefinitionInfoCache;
}
public void setProcessDefinitionInfoCache(ProcessDefinitionInfoCache processDefinitionInfoCache) {
this.processDefinitionInfoCache = processDefinitionInfoCache;
}
public DeploymentCache<Object> getKnowledgeBaseCache() {
return knowledgeBaseCache;
}
public void setKnowledgeBaseCache(DeploymentCache<Object> knowledgeBaseCache) {
this.knowledgeBaseCache = knowledgeBaseCache;
}
}