提交 ecd6cee5 编写于 作者: J Joram Barrez

Merge branch 'stpm-activiti6-bpmn-deployer-refactoring' into activiti6

/* 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.bpmn.deployer;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.DeploymentEntity;
import org.activiti.engine.impl.persistence.entity.IdentityLinkEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityManager;
import org.activiti.engine.task.IdentityLinkType;
import org.apache.commons.lang3.StringUtils;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* Methods for working with deployments. Much of the actual work of {@link BpmnDeployer} is
* done by orchestrating the different pieces of work this class does; by having them here,
* we allow other deployers to make use of them.
*/
public class BpmnDeploymentHelper {
protected TimerManager timerManager;
protected EventSubscriptionManager eventSubscriptionManager;
/**
* Verifies that no two process definitions share the same key, to prevent database unique
* index violation.
*
* @throws ActivitiException if any two processes have the same key
*/
public void verifyProcessDefinitionsDoNotShareKeys(
Collection<ProcessDefinitionEntity> processDefinitions) {
Set<String> keySet = new LinkedHashSet<String>();
for (ProcessDefinitionEntity processDefinition : processDefinitions) {
if (keySet.contains(processDefinition.getKey())) {
throw new ActivitiException(
"The deployment contains process definitions with the same key (process id attribute), this is not allowed");
}
keySet.add(processDefinition.getKey());
}
}
/**
* Updates all the process definition entities to match the deployment's values for tenant,
* engine version, and deployment id.
*/
public void copyDeploymentValuesToProcessDefinitions(DeploymentEntity deployment,
List<ProcessDefinitionEntity> processDefinitions) {
String engineVersion = deployment.getEngineVersion();
String tenantId = deployment.getTenantId();
String deploymentId = deployment.getId();
for (ProcessDefinitionEntity processDefinition : processDefinitions) {
// Backwards compatibility
if (engineVersion != null) {
processDefinition.setEngineVersion(engineVersion);
}
// process definition inherits the tenant id
if (tenantId != null) {
processDefinition.setTenantId(tenantId);
}
processDefinition.setDeploymentId(deploymentId);
}
}
/**
* Updates all the process definition entities to have the correct resource names.
*/
public void setResourceNamesOnProcessDefinitions(ParsedDeployment parsedDeployment) {
for (ProcessDefinitionEntity processDefinition : parsedDeployment.getAllProcessDefinitions()) {
String resourceName = parsedDeployment.getResourceForProcessDefinition(processDefinition).getName();
processDefinition.setResourceName(resourceName);
}
}
/**
* Gets the most recent persisted process definition that matches this one for tenant and key.
* If none is found, returns null. This method assumes that the tenant and key are properly
* set on the process definition entity.
*/
public ProcessDefinitionEntity getMostRecentVersionOfProcessDefinition(ProcessDefinitionEntity processDefinition) {
String key = processDefinition.getKey();
String tenantId = processDefinition.getTenantId();
ProcessDefinitionEntityManager processDefinitionManager
= Context.getCommandContext().getProcessEngineConfiguration().getProcessDefinitionEntityManager();
ProcessDefinitionEntity existingDefinition = null;
if (tenantId != null && !tenantId.equals(ProcessEngineConfiguration.NO_TENANT_ID)) {
existingDefinition = processDefinitionManager.findLatestProcessDefinitionByKeyAndTenantId(key, tenantId);
} else {
existingDefinition = processDefinitionManager.findLatestProcessDefinitionByKey(key);
}
return existingDefinition;
}
/**
* Gets the persisted version of the already-deployed process definition. Note that this is
* different from {@link #getMostRecentVersionOfProcessDefinition} as it looks specifically for
* a process definition that is already persisted and attached to a particular deployment,
* rather than the latest version across all deployments.
*/
public ProcessDefinitionEntity getPersistedInstanceOfProcessDefinition(ProcessDefinitionEntity processDefinition) {
String deploymentId = processDefinition.getDeploymentId();
if (StringUtils.isEmpty(processDefinition.getDeploymentId())) {
throw new IllegalStateException("Provided process definition must have a deployment id.");
}
ProcessDefinitionEntityManager processDefinitionManager
= Context.getCommandContext().getProcessEngineConfiguration().getProcessDefinitionEntityManager();
ProcessDefinitionEntity persistedProcessDefinition = null;
if (processDefinition.getTenantId() == null || ProcessEngineConfiguration.NO_TENANT_ID.equals(processDefinition.getTenantId())) {
persistedProcessDefinition = processDefinitionManager.findProcessDefinitionByDeploymentAndKey(deploymentId, processDefinition.getKey());
} else {
persistedProcessDefinition = processDefinitionManager.findProcessDefinitionByDeploymentAndKeyAndTenantId(deploymentId, processDefinition.getKey(), processDefinition.getTenantId());
}
return persistedProcessDefinition;
}
/**
* Updates all timers and events for the process definition. This removes obsolete message and signal
* subscriptions and timers, and adds new ones.
*/
public void updateTimersAndEvents(ProcessDefinitionEntity processDefinition,
ProcessDefinitionEntity previousProcessDefinition, ParsedDeployment parsedDeployment) {
Process process = parsedDeployment.getProcessModelForProcessDefinition(processDefinition);
BpmnModel bpmnModel = parsedDeployment.getBpmnModelForProcessDefinition(processDefinition);
eventSubscriptionManager.removeObsoleteMessageEventSubscriptions(previousProcessDefinition);
eventSubscriptionManager.addMessageEventSubscriptions(processDefinition, process, bpmnModel);
eventSubscriptionManager.removeObsoleteSignalEventSubScription(previousProcessDefinition);
eventSubscriptionManager.addSignalEventSubscriptions(Context.getCommandContext(), processDefinition, process, bpmnModel);
timerManager.removeObsoleteTimers(processDefinition);
timerManager.scheduleTimers(processDefinition, process);
}
enum ExprType {
USER, GROUP
}
/**
* @param processDefinition
*/
public void addAuthorizationsForNewProcessDefinition(ProcessDefinitionEntity processDefinition) {
CommandContext commandContext = Context.getCommandContext();
addAuthorizationsFromIterator(commandContext, processDefinition.getCandidateStarterUserIdExpressions(), processDefinition, ExprType.USER);
addAuthorizationsFromIterator(commandContext, processDefinition.getCandidateStarterGroupIdExpressions(), processDefinition, ExprType.GROUP);
}
protected void addAuthorizationsFromIterator(CommandContext commandContext,
Set<Expression> expressions,
ProcessDefinitionEntity processDefinition,
ExprType expressionType) {
if (expressions != null) {
Iterator<Expression> iterator = expressions.iterator();
while (iterator.hasNext()) {
@SuppressWarnings("cast")
Expression expr = (Expression) iterator.next();
IdentityLinkEntity identityLink = commandContext.getIdentityLinkEntityManager().create();
identityLink.setProcessDef(processDefinition);
if (expressionType.equals(ExprType.USER)) {
identityLink.setUserId(expr.toString());
} else if (expressionType.equals(ExprType.GROUP)) {
identityLink.setGroupId(expr.toString());
}
identityLink.setType(IdentityLinkType.CANDIDATE);
commandContext.getIdentityLinkEntityManager().insert(identityLink);
}
}
}
public TimerManager getTimerManager() {
return timerManager;
}
public void setTimerManager(TimerManager timerManager) {
this.timerManager = timerManager;
}
public EventSubscriptionManager getEventSubscriptionManager() {
return eventSubscriptionManager;
}
public void setEventSubscriptionManager(EventSubscriptionManager eventSubscriptionManager) {
this.eventSubscriptionManager = eventSubscriptionManager;
}
}
/* 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.bpmn.deployer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.deploy.DeploymentCache;
import org.activiti.engine.impl.persistence.deploy.DeploymentManager;
import org.activiti.engine.impl.persistence.deploy.ProcessDefinitionCacheEntry;
import org.activiti.engine.impl.persistence.deploy.ProcessDefinitionInfoCacheObject;
import org.activiti.engine.impl.persistence.entity.DeploymentEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionInfoEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionInfoEntityManager;
/**
* Updates caches and artifacts for a deployment, its process definitions,
* and its process definition infos.
*/
public class CachingAndArtifactsManager {
/**
* Ensures that the process definition is cached in the appropriate places, including the
* deployment's collection of deployed artifacts and the deployment manager's cache, as well
* as caching any ProcessDefinitionInfos.
*/
public void updateCachingAndArtifacts(ParsedDeployment parsedDeployment) {
CommandContext commandContext = Context.getCommandContext();
final ProcessEngineConfigurationImpl processEngineConfiguration = Context.getProcessEngineConfiguration();
DeploymentCache<ProcessDefinitionCacheEntry> processDefinitionCache
= processEngineConfiguration.getDeploymentManager().getProcessDefinitionCache();
DeploymentEntity deployment = parsedDeployment.getDeployment();
for (ProcessDefinitionEntity processDefinition : parsedDeployment.getAllProcessDefinitions()) {
BpmnModel bpmnModel = parsedDeployment.getBpmnModelForProcessDefinition(processDefinition);
Process process = parsedDeployment.getProcessModelForProcessDefinition(processDefinition);
ProcessDefinitionCacheEntry cacheEntry = new ProcessDefinitionCacheEntry(processDefinition, bpmnModel, process);
processDefinitionCache.add(processDefinition.getId(), cacheEntry);
addDefinitionInfoToCache(processDefinition, processEngineConfiguration, commandContext);
// Add to deployment for further usage
deployment.addDeployedArtifact(processDefinition);
}
}
protected void addDefinitionInfoToCache(ProcessDefinitionEntity processDefinition,
ProcessEngineConfigurationImpl processEngineConfiguration, CommandContext commandContext) {
if (processEngineConfiguration.isEnableProcessDefinitionInfoCache() == false) {
return;
}
DeploymentManager deploymentManager = processEngineConfiguration.getDeploymentManager();
ProcessDefinitionInfoEntityManager definitionInfoEntityManager = commandContext.getProcessDefinitionInfoEntityManager();
ObjectMapper objectMapper = commandContext.getProcessEngineConfiguration().getObjectMapper();
ProcessDefinitionInfoEntity definitionInfoEntity = definitionInfoEntityManager.findProcessDefinitionInfoByProcessDefinitionId(processDefinition.getId());
ObjectNode infoNode = null;
if (definitionInfoEntity != null && definitionInfoEntity.getInfoJsonId() != null) {
byte[] infoBytes = definitionInfoEntityManager.findInfoJsonById(definitionInfoEntity.getInfoJsonId());
if (infoBytes != null) {
try {
infoNode = (ObjectNode) objectMapper.readTree(infoBytes);
} catch (Exception e) {
throw new ActivitiException("Error deserializing json info for process definition " + processDefinition.getId());
}
}
}
ProcessDefinitionInfoCacheObject definitionCacheObject = new ProcessDefinitionInfoCacheObject();
if (definitionInfoEntity == null) {
definitionCacheObject.setRevision(0);
} else {
definitionCacheObject.setId(definitionInfoEntity.getId());
definitionCacheObject.setRevision(definitionInfoEntity.getRevision());
}
if (infoNode == null) {
infoNode = objectMapper.createObjectNode();
}
definitionCacheObject.setInfoNode(infoNode);
deploymentManager.getProcessDefinitionInfoCache().add(processDefinition.getId(), definitionCacheObject);
}
}
/* 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.bpmn.deployer;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.EventDefinition;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.Message;
import org.activiti.bpmn.model.MessageEventDefinition;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.Signal;
import org.activiti.bpmn.model.SignalEventDefinition;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.event.MessageEventHandler;
import org.activiti.engine.impl.event.SignalEventHandler;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.EventSubscriptionEntity;
import org.activiti.engine.impl.persistence.entity.EventSubscriptionEntityManager;
import org.activiti.engine.impl.persistence.entity.MessageEventSubscriptionEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.SignalEventSubscriptionEntity;
import org.apache.commons.collections.CollectionUtils;
import java.util.List;
/**
* Manages event subscriptions for newly-deployed process definitions and their previous versions.
*/
public class EventSubscriptionManager {
protected void removeObsoleteEventSubscriptionsImpl(ProcessDefinitionEntity processDefinition, String eventHandlerType) {
// remove all subscriptions for the previous version
EventSubscriptionEntityManager eventSubscriptionEntityManager = Context.getCommandContext().getEventSubscriptionEntityManager();
List<EventSubscriptionEntity> subscriptionsToDelete = eventSubscriptionEntityManager.findEventSubscriptionsByConfiguration(eventHandlerType,
processDefinition.getId(), processDefinition.getTenantId());
for (EventSubscriptionEntity eventSubscriptionEntity : subscriptionsToDelete) {
eventSubscriptionEntityManager.delete(eventSubscriptionEntity);
}
}
protected void removeObsoleteMessageEventSubscriptions(ProcessDefinitionEntity previousProcessDefinition) {
// remove all subscriptions for the previous version
if (previousProcessDefinition != null) {
removeObsoleteEventSubscriptionsImpl(previousProcessDefinition, MessageEventHandler.EVENT_HANDLER_TYPE);
}
}
protected void removeObsoleteSignalEventSubScription(ProcessDefinitionEntity previousProcessDefinition) {
// remove all subscriptions for the previous version
if (previousProcessDefinition != null) {
removeObsoleteEventSubscriptionsImpl(previousProcessDefinition, SignalEventHandler.EVENT_HANDLER_TYPE);
}
}
protected void addMessageEventSubscriptions(ProcessDefinitionEntity processDefinition, Process process, BpmnModel bpmnModel) {
if (CollectionUtils.isNotEmpty(process.getFlowElements())) {
for (FlowElement element : process.getFlowElements()) {
if (element instanceof StartEvent) {
StartEvent startEvent = (StartEvent) element;
if (CollectionUtils.isNotEmpty(startEvent.getEventDefinitions())) {
EventDefinition eventDefinition = startEvent.getEventDefinitions().get(0);
if (eventDefinition instanceof MessageEventDefinition) {
MessageEventDefinition messageEventDefinition = (MessageEventDefinition) eventDefinition;
insertMessageEvent(messageEventDefinition, startEvent, processDefinition, bpmnModel);
}
}
}
}
}
}
protected void insertMessageEvent(MessageEventDefinition messageEventDefinition, StartEvent startEvent, ProcessDefinitionEntity processDefinition, BpmnModel bpmnModel) {
CommandContext commandContext = Context.getCommandContext();
if (bpmnModel.containsMessageId(messageEventDefinition.getMessageRef())) {
Message message = bpmnModel.getMessage(messageEventDefinition.getMessageRef());
messageEventDefinition.setMessageRef(message.getName());
}
// look for subscriptions for the same name in db:
List<EventSubscriptionEntity> subscriptionsForSameMessageName = commandContext.getEventSubscriptionEntityManager()
.findEventSubscriptionsByName(MessageEventHandler.EVENT_HANDLER_TYPE, messageEventDefinition.getMessageRef(), processDefinition.getTenantId());
for (EventSubscriptionEntity eventSubscriptionEntity : subscriptionsForSameMessageName) {
// throw exception only if there's already a subscription as start event
if (eventSubscriptionEntity.getProcessInstanceId() == null || eventSubscriptionEntity.getProcessInstanceId().isEmpty()) { // processInstanceId != null or not empty -> it's a message related to an execution
// the event subscription has no instance-id, so it's a message start event
throw new ActivitiException("Cannot deploy process definition '" + processDefinition.getResourceName()
+ "': there already is a message event subscription for the message with name '" + messageEventDefinition.getMessageRef() + "'.");
}
}
MessageEventSubscriptionEntity newSubscription = commandContext.getEventSubscriptionEntityManager().createMessageEventSubscription();
newSubscription.setEventName(messageEventDefinition.getMessageRef());
newSubscription.setActivityId(startEvent.getId());
newSubscription.setConfiguration(processDefinition.getId());
newSubscription.setProcessDefinitionId(processDefinition.getId());
if (processDefinition.getTenantId() != null) {
newSubscription.setTenantId(processDefinition.getTenantId());
}
commandContext.getEventSubscriptionEntityManager().insert(newSubscription);
}
protected void addSignalEventSubscriptions(CommandContext commandContext, ProcessDefinitionEntity processDefinition, org.activiti.bpmn.model.Process process, BpmnModel bpmnModel) {
if (CollectionUtils.isNotEmpty(process.getFlowElements())) {
for (FlowElement element : process.getFlowElements()) {
if (element instanceof StartEvent) {
StartEvent startEvent = (StartEvent) element;
if (CollectionUtils.isNotEmpty(startEvent.getEventDefinitions())) {
EventDefinition eventDefinition = startEvent.getEventDefinitions().get(0);
if (eventDefinition instanceof SignalEventDefinition) {
SignalEventDefinition signalEventDefinition = (SignalEventDefinition) eventDefinition;
SignalEventSubscriptionEntity subscriptionEntity = commandContext.getEventSubscriptionEntityManager().createSignalEventSubscription();
Signal signal = bpmnModel.getSignal(signalEventDefinition.getSignalRef());
if (signal != null) {
subscriptionEntity.setEventName(signal.getName());
} else {
subscriptionEntity.setEventName(signalEventDefinition.getSignalRef());
}
subscriptionEntity.setActivityId(startEvent.getId());
subscriptionEntity.setProcessDefinitionId(processDefinition.getId());
if (processDefinition.getTenantId() != null) {
subscriptionEntity.setTenantId(processDefinition.getTenantId());
}
Context.getCommandContext().getEventSubscriptionEntityManager().insert(subscriptionEntity);
}
}
}
}
}
}
}
/* 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.bpmn.deployer;
import java.util.List;
import java.util.Map;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.impl.bpmn.parser.BpmnParse;
import org.activiti.engine.impl.persistence.entity.DeploymentEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.ResourceEntity;
/**
* An intermediate representation of a DeploymentEntity which keeps track of all of the entity's
* ProcessDefinitionEntities and resources, and BPMN parses, models, and processes associated
* with each ProcessDefinitionEntity - all produced by parsing the deployment.
*
* The ProcessDefinitionEntities are expected to be "not fully set-up" - they may be inconsistent with the
* DeploymentEntity and/or the persisted versions, and if the deployment is new, they will not yet be persisted.
*/
public class ParsedDeployment {
protected DeploymentEntity deploymentEntity;
protected List<ProcessDefinitionEntity> processDefinitions;
protected Map<ProcessDefinitionEntity, BpmnParse> mapProcessDefinitionsToParses;
protected Map<ProcessDefinitionEntity, ResourceEntity> mapProcessDefinitionsToResources;
public ParsedDeployment(
DeploymentEntity entity, List<ProcessDefinitionEntity> processDefinitions,
Map<ProcessDefinitionEntity, BpmnParse> mapProcessDefinitionsToParses,
Map<ProcessDefinitionEntity, ResourceEntity> mapProcessDefinitionsToResources) {
this.deploymentEntity = entity;
this.processDefinitions = processDefinitions;
this.mapProcessDefinitionsToParses = mapProcessDefinitionsToParses;
this.mapProcessDefinitionsToResources = mapProcessDefinitionsToResources;
}
public DeploymentEntity getDeployment() {
return deploymentEntity;
}
public List<ProcessDefinitionEntity> getAllProcessDefinitions() {
return processDefinitions;
}
public ResourceEntity getResourceForProcessDefinition(ProcessDefinitionEntity processDefinition) {
return mapProcessDefinitionsToResources.get(processDefinition);
}
public BpmnParse getBpmnParseForProcessDefinition(ProcessDefinitionEntity processDefinition) {
return mapProcessDefinitionsToParses.get(processDefinition);
}
public BpmnModel getBpmnModelForProcessDefinition(ProcessDefinitionEntity processDefinition) {
BpmnParse parse = getBpmnParseForProcessDefinition(processDefinition);
return (parse == null ? null : parse.getBpmnModel());
}
public Process getProcessModelForProcessDefinition(ProcessDefinitionEntity processDefinition) {
BpmnModel model = getBpmnModelForProcessDefinition(processDefinition);
return (model == null ? null : model.getProcessById(processDefinition.getKey()));
}
}
/* 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.bpmn.deployer;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.activiti.engine.impl.bpmn.parser.BpmnParse;
import org.activiti.engine.impl.bpmn.parser.BpmnParser;
import org.activiti.engine.impl.cmd.DeploymentSettings;
import org.activiti.engine.impl.persistence.entity.DeploymentEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.ResourceEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ParsedDeploymentBuilder {
private static final Logger log = LoggerFactory.getLogger(ParsedDeploymentBuilder.class);
protected DeploymentEntity deployment;
protected BpmnParser bpmnParser;
protected Map<String, Object> deploymentSettings;
public ParsedDeploymentBuilder(DeploymentEntity deployment,
BpmnParser bpmnParser, Map<String, Object> deploymentSettings) {
this.deployment = deployment;
this.bpmnParser = bpmnParser;
this.deploymentSettings = deploymentSettings;
}
public ParsedDeployment build() {
List<ProcessDefinitionEntity> processDefinitions = new ArrayList<ProcessDefinitionEntity>();
Map<ProcessDefinitionEntity, BpmnParse> processDefinitionsToBpmnParseMap
= new LinkedHashMap<ProcessDefinitionEntity, BpmnParse>();
Map<ProcessDefinitionEntity, ResourceEntity> processDefinitionsToResourceMap
= new LinkedHashMap<ProcessDefinitionEntity, ResourceEntity>();
for (ResourceEntity resource : deployment.getResources().values()) {
if (isBpmnResource(resource.getName())) {
log.debug("Processing BPMN resource {}", resource.getName());
BpmnParse parse = createBpmnParseFromResource(resource);
for (ProcessDefinitionEntity processDefinition : parse.getProcessDefinitions()) {
processDefinitions.add(processDefinition);
processDefinitionsToBpmnParseMap.put(processDefinition, parse);
processDefinitionsToResourceMap.put(processDefinition, resource);
}
}
}
return new ParsedDeployment(deployment, processDefinitions,
processDefinitionsToBpmnParseMap, processDefinitionsToResourceMap);
}
protected BpmnParse createBpmnParseFromResource(ResourceEntity resource) {
String resourceName = resource.getName();
ByteArrayInputStream inputStream = new ByteArrayInputStream(resource.getBytes());
BpmnParse bpmnParse = bpmnParser.createParse()
.sourceInputStream(inputStream)
.setSourceSystemId(resourceName)
.deployment(deployment)
.name(resourceName);
if (deploymentSettings != null) {
// Schema validation if needed
if (deploymentSettings.containsKey(DeploymentSettings.IS_BPMN20_XSD_VALIDATION_ENABLED)) {
bpmnParse.setValidateSchema((Boolean) deploymentSettings.get(DeploymentSettings.IS_BPMN20_XSD_VALIDATION_ENABLED));
}
// Process validation if needed
if (deploymentSettings.containsKey(DeploymentSettings.IS_PROCESS_VALIDATION_ENABLED)) {
bpmnParse.setValidateProcess((Boolean) deploymentSettings.get(DeploymentSettings.IS_PROCESS_VALIDATION_ENABLED));
}
} else {
// On redeploy, we assume it is validated at the first deploy
bpmnParse.setValidateSchema(false);
bpmnParse.setValidateProcess(false);
}
bpmnParse.execute();
return bpmnParse;
}
protected boolean isBpmnResource(String resourceName) {
for (String suffix : ResourceNameUtil.BPMN_RESOURCE_SUFFIXES) {
if (resourceName.endsWith(suffix)) {
return true;
}
}
return false;
}
}
\ No newline at end of file
/* 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.bpmn.deployer;
import java.util.Map;
import org.activiti.engine.impl.bpmn.parser.BpmnParser;
import org.activiti.engine.impl.persistence.entity.DeploymentEntity;
public class ParsedDeploymentBuilderFactory {
protected BpmnParser bpmnParser;
public BpmnParser getBpmnParser() {
return bpmnParser;
}
public void setBpmnParser(BpmnParser bpmnParser) {
this.bpmnParser = bpmnParser;
}
public ParsedDeploymentBuilder getBuilderForDeployment(DeploymentEntity deployment) {
return getBuilderForDeploymentAndSettings(deployment, null);
}
public ParsedDeploymentBuilder getBuilderForDeploymentAndSettings(DeploymentEntity deployment,
Map<String, Object> deploymentSettings) {
return new ParsedDeploymentBuilder(deployment, bpmnParser, deploymentSettings);
}
}
\ No newline at end of file
/* 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.bpmn.deployer;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.impl.bpmn.parser.BpmnParse;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.persistence.entity.DeploymentEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.ResourceEntity;
import org.activiti.engine.impl.util.IoUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Creates diagrams from process definitions.
*/
public class ProcessDefinitionDiagramHelper {
private static final Logger log = LoggerFactory.getLogger(ProcessDefinitionDiagramHelper.class);
/**
* Generates a diagram resource for a ProcessDefinitionEntity and associated BpmnParse. The
* returned resource has not yet been persisted, nor attached to the ProcessDefinitionEntity.
* This requires that the ProcessDefinitionEntity have its key and resource name already set.
*
* The caller must determine whether creating a diagram for this process definition is appropriate or not,
* for example see {@link #shouldCreateDiagram(ProcessDefinitionEntity, DeploymentEntity)}.
*/
public ResourceEntity createDiagramForProcessDefinition(ProcessDefinitionEntity processDefinition, BpmnParse bpmnParse) {
if (StringUtils.isEmpty(processDefinition.getKey()) || StringUtils.isEmpty(processDefinition.getResourceName())) {
throw new IllegalStateException("Provided process definition must have both key and resource name set.");
}
ResourceEntity resource = createResourceEntity();
ProcessEngineConfiguration processEngineConfiguration = Context.getCommandContext().getProcessEngineConfiguration();
try {
byte[] diagramBytes = IoUtil.readInputStream(
processEngineConfiguration.getProcessDiagramGenerator().generateDiagram(bpmnParse.getBpmnModel(), "png",
processEngineConfiguration.getActivityFontName(),
processEngineConfiguration.getLabelFontName(),
processEngineConfiguration.getClassLoader()), null);
String diagramResourceName = ResourceNameUtil.getProcessDiagramResourceName(
processDefinition.getResourceName(), processDefinition.getKey(), "png");
resource.setName(diagramResourceName);
resource.setBytes(diagramBytes);
resource.setDeploymentId(processDefinition.getDeploymentId());
// Mark the resource as 'generated'
resource.setGenerated(true);
} catch (Throwable t) { // if anything goes wrong, we don't store the image (the process will still be executable).
log.warn("Error while generating process diagram, image will not be stored in repository", t);
resource = null;
}
return resource;
}
protected ResourceEntity createResourceEntity() {
return Context.getCommandContext().getProcessEngineConfiguration().getResourceEntityManager().create();
}
public boolean shouldCreateDiagram(ProcessDefinitionEntity processDefinition, DeploymentEntity deployment) {
if (deployment.isNew()
&& processDefinition.isGraphicalNotationDefined()
&& Context.getCommandContext().getProcessEngineConfiguration().isCreateDiagramOnDeploy()) {
// If the 'getProcessDiagramResourceNameFromDeployment' call returns null, it means
// no diagram image for the process definition was provided in the deployment resources.
return ResourceNameUtil.getProcessDiagramResourceNameFromDeployment(processDefinition, deployment.getResources()) == null;
}
return false;
}
}
/* 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.bpmn.deployer;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.ResourceEntity;
import org.apache.commons.lang3.StringUtils;
import java.util.Map;
/**
* Static methods for working with BPMN and image resource names.
*/
public class ResourceNameUtil {
public static final String[] BPMN_RESOURCE_SUFFIXES = new String[] { "bpmn20.xml", "bpmn" };
public static final String[] DIAGRAM_SUFFIXES = new String[] { "png", "jpg", "gif", "svg" };
public static String stripBpmnFileSuffix(String bpmnFileResource) {
for (String suffix : BPMN_RESOURCE_SUFFIXES) {
if (bpmnFileResource.endsWith(suffix)) {
return bpmnFileResource.substring(0, bpmnFileResource.length() - suffix.length());
}
}
return bpmnFileResource;
}
public static String getProcessDiagramResourceName(String bpmnFileResource, String processKey, String diagramSuffix) {
String bpmnFileResourceBase = ResourceNameUtil.stripBpmnFileSuffix(bpmnFileResource);
return bpmnFileResourceBase + processKey + "." + diagramSuffix;
}
/**
* Finds the name of a resource for the diagram for a process definition. Assumes that the
* process definition's key and (BPMN) resource name are already set.
*
* <p>It will first look for an image resource which matches the process specifically, before
* resorting to an image resource which matches the BPMN 2.0 xml file resource.
*
* <p>Example: if the deployment contains a BPMN 2.0 xml resource called 'abc.bpmn20.xml'
* containing only one process with key 'myProcess', then this method will look for an image resources
* called'abc.myProcess.png' (or .jpg, or .gif, etc.) or 'abc.png' if the previous one wasn't
* found.
*
* <p>Example 2: if the deployment contains a BPMN 2.0 xml resource called 'abc.bpmn20.xml'
* containing three processes (with keys a, b and c), then this method will first look for an image resource
* called 'abc.a.png' before looking for 'abc.png' (likewise for b and c). Note that if abc.a.png,
* abc.b.png and abc.c.png don't exist, all processes will have the same image: abc.png.
*
* @return name of an existing resource, or null if no matching image resource is found in the resources.
*/
public static String getProcessDiagramResourceNameFromDeployment(
ProcessDefinitionEntity processDefinition, Map<String, ResourceEntity> resources) {
if (StringUtils.isEmpty(processDefinition.getResourceName())) {
throw new IllegalStateException("Provided process definition must have its resource name set.");
}
String bpmnResourceBase = stripBpmnFileSuffix(processDefinition.getResourceName());
String key = processDefinition.getKey();
for (String diagramSuffix : DIAGRAM_SUFFIXES) {
String possibleName = bpmnResourceBase + key + "." + diagramSuffix;
if (resources.containsKey(possibleName)) {
return possibleName;
}
possibleName = bpmnResourceBase + diagramSuffix;
if (resources.containsKey(possibleName)) {
return possibleName;
}
}
return null;
}
}
/* 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.bpmn.deployer;
import org.activiti.bpmn.model.EventDefinition;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.bpmn.model.TimerEventDefinition;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.impl.cmd.CancelJobsCmd;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.jobexecutor.TimerEventHandler;
import org.activiti.engine.impl.jobexecutor.TimerStartEventJobHandler;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.TimerEntity;
import org.activiti.engine.impl.util.TimerUtil;
import org.activiti.engine.runtime.Job;
import org.apache.commons.collections.CollectionUtils;
import org.activiti.bpmn.model.Process;
import java.util.ArrayList;
import java.util.List;
/**
* Manages timers for newly-deployed process definitions and their previous versions.
*/
public class TimerManager {
protected void removeObsoleteTimers(ProcessDefinitionEntity processDefinition) {
List<Job> jobsToDelete = null;
if (processDefinition.getTenantId() != null && !ProcessEngineConfiguration.NO_TENANT_ID.equals(processDefinition.getTenantId())) {
jobsToDelete = Context.getCommandContext().getJobEntityManager().findJobsByTypeAndProcessDefinitionKeyAndTenantId(
TimerStartEventJobHandler.TYPE, processDefinition.getKey(), processDefinition.getTenantId());
} else {
jobsToDelete = Context.getCommandContext().getJobEntityManager()
.findJobsByTypeAndProcessDefinitionKeyNoTenantId(TimerStartEventJobHandler.TYPE, processDefinition.getKey());
}
if (jobsToDelete != null) {
for (Job job :jobsToDelete) {
new CancelJobsCmd(job.getId()).execute(Context.getCommandContext());
}
}
}
protected void scheduleTimers(ProcessDefinitionEntity processDefinition, Process process) {
List<TimerEntity> timers = getTimerDeclarations(processDefinition, process);
for (TimerEntity timer : timers) {
Context.getCommandContext().getJobEntityManager().schedule(timer);
}
}
protected List<TimerEntity> getTimerDeclarations(ProcessDefinitionEntity processDefinition, Process process) {
List<TimerEntity> timers = new ArrayList<TimerEntity>();
if (CollectionUtils.isNotEmpty(process.getFlowElements())) {
for (FlowElement element : process.getFlowElements()) {
if (element instanceof StartEvent) {
StartEvent startEvent = (StartEvent) element;
if (CollectionUtils.isNotEmpty(startEvent.getEventDefinitions())) {
EventDefinition eventDefinition = startEvent.getEventDefinitions().get(0);
if (eventDefinition instanceof TimerEventDefinition) {
TimerEventDefinition timerEventDefinition = (TimerEventDefinition) eventDefinition;
TimerEntity timer = TimerUtil.createTimerEntityForTimerEventDefinition(timerEventDefinition, false, null, TimerStartEventJobHandler.TYPE,
TimerEventHandler.createConfiguration(startEvent.getId(), timerEventDefinition.getEndDate()));
if (timer != null) {
timer.setProcessDefinitionId(processDefinition.getId());
if (processDefinition.getTenantId() != null) {
timer.setTenantId(processDefinition.getTenantId());
}
timers.add(timer);
}
}
}
}
}
}
return timers;
}
}
......@@ -27,6 +27,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.Set;
......@@ -67,6 +68,12 @@ import org.activiti.engine.impl.TaskServiceImpl;
import org.activiti.engine.impl.asyncexecutor.DefaultAsyncJobExecutor;
import org.activiti.engine.impl.bpmn.data.ItemInstance;
import org.activiti.engine.impl.bpmn.deployer.BpmnDeployer;
import org.activiti.engine.impl.bpmn.deployer.BpmnDeploymentHelper;
import org.activiti.engine.impl.bpmn.deployer.CachingAndArtifactsManager;
import org.activiti.engine.impl.bpmn.deployer.EventSubscriptionManager;
import org.activiti.engine.impl.bpmn.deployer.ParsedDeploymentBuilderFactory;
import org.activiti.engine.impl.bpmn.deployer.ProcessDefinitionDiagramHelper;
import org.activiti.engine.impl.bpmn.deployer.TimerManager;
import org.activiti.engine.impl.bpmn.parser.BpmnParseHandlers;
import org.activiti.engine.impl.bpmn.parser.BpmnParser;
import org.activiti.engine.impl.bpmn.parser.factory.AbstractBehaviorFactory;
......@@ -304,7 +311,6 @@ import org.activiti.engine.runtime.Clock;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.activiti.validation.ProcessValidator;
import org.activiti.validation.ProcessValidatorFactory;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
......@@ -445,6 +451,12 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
protected BpmnDeployer bpmnDeployer;
protected BpmnParser bpmnParser;
protected ParsedDeploymentBuilderFactory parsedDeploymentBuilderFactory;
protected TimerManager timerManager;
protected EventSubscriptionManager eventSubscriptionManager;
protected BpmnDeploymentHelper bpmnDeploymentHelper;
protected CachingAndArtifactsManager cachingAndArtifactsManager;
protected ProcessDefinitionDiagramHelper processDefinitionDiagramHelper;
protected List<Deployer> customPreDeployers;
protected List<Deployer> customPostDeployers;
protected List<Deployer> deployers;
......@@ -611,6 +623,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
// buildProcessEngine
// ///////////////////////////////////////////////////////
@Override
public ProcessEngine buildProcessEngine() {
init();
ProcessEngineImpl processEngine = new ProcessEngineImpl(this);
......@@ -935,7 +948,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
properties.put("limitBetween", DbSqlSessionFactory.databaseSpecificLimitBetweenStatements.get(databaseType));
properties.put("limitOuterJoinBetween", DbSqlSessionFactory.databaseOuterJoinLimitBetweenStatements.get(databaseType));
properties.put("orderBy", DbSqlSessionFactory.databaseSpecificOrderByStatements.get(databaseType));
properties.put("limitBeforeNativeQuery", ObjectUtils.toString(DbSqlSessionFactory.databaseSpecificLimitBeforeNativeQueryStatements.get(databaseType)));
properties.put("limitBeforeNativeQuery", Objects.toString(DbSqlSessionFactory.databaseSpecificLimitBeforeNativeQueryStatements.get(databaseType)));
}
Configuration configuration = initMybatisConfiguration(environment, reader, properties);
......@@ -973,7 +986,8 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
}
}
protected Configuration parseMybatisConfiguration(Configuration configuration, XMLConfigBuilder parser) {
protected Configuration parseMybatisConfiguration(
@SuppressWarnings("unused") Configuration configuration, XMLConfigBuilder parser) {
return parseCustomMybatisXMLMappers(parser.parse());
}
......@@ -1357,16 +1371,56 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
}
}
protected void initBpmnDeployerDependencies() {
if (parsedDeploymentBuilderFactory == null) {
parsedDeploymentBuilderFactory = new ParsedDeploymentBuilderFactory();
}
if (parsedDeploymentBuilderFactory.getBpmnParser() == null) {
parsedDeploymentBuilderFactory.setBpmnParser(bpmnParser);
}
if (timerManager == null) {
timerManager = new TimerManager();
}
if (eventSubscriptionManager == null) {
eventSubscriptionManager = new EventSubscriptionManager();
}
if (bpmnDeploymentHelper == null) {
bpmnDeploymentHelper = new BpmnDeploymentHelper();
}
if (bpmnDeploymentHelper.getTimerManager() == null) {
bpmnDeploymentHelper.setTimerManager(timerManager);
}
if (bpmnDeploymentHelper.getEventSubscriptionManager() == null) {
bpmnDeploymentHelper.setEventSubscriptionManager(eventSubscriptionManager);
}
if (cachingAndArtifactsManager == null) {
cachingAndArtifactsManager = new CachingAndArtifactsManager();
}
if (processDefinitionDiagramHelper == null) {
processDefinitionDiagramHelper = new ProcessDefinitionDiagramHelper();
}
}
protected Collection<? extends Deployer> getDefaultDeployers() {
List<Deployer> defaultDeployers = new ArrayList<Deployer>();
if (bpmnDeployer == null) {
bpmnDeployer = new BpmnDeployer();
}
bpmnDeployer.setExpressionManager(expressionManager);
initBpmnDeployerDependencies();
bpmnDeployer.setIdGenerator(idGenerator);
bpmnDeployer.setBpmnParser(bpmnParser);
bpmnDeployer.setParsedDeploymentBuilderFactory(parsedDeploymentBuilderFactory);
bpmnDeployer.setBpmnDeploymentHelper(bpmnDeploymentHelper);
bpmnDeployer.setCachingAndArtifactsManager(cachingAndArtifactsManager);
bpmnDeployer.setProcessDefinitionDiagramHelper(processDefinitionDiagramHelper);
defaultDeployers.add(bpmnDeployer);
return defaultDeployers;
......@@ -2043,6 +2097,57 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
return this;
}
public ParsedDeploymentBuilderFactory getParsedDeploymentBuilderFactory() {
return parsedDeploymentBuilderFactory;
}
public ProcessEngineConfigurationImpl setParsedDeploymentBuilderFactory(ParsedDeploymentBuilderFactory parsedDeploymentBuilderFactory) {
this.parsedDeploymentBuilderFactory = parsedDeploymentBuilderFactory;
return this;
}
public TimerManager getTimerManager() {
return timerManager;
}
public void setTimerManager(TimerManager timerManager) {
this.timerManager = timerManager;
}
public EventSubscriptionManager getEventSubscriptionManager() {
return eventSubscriptionManager;
}
public void setEventSubscriptionManager(EventSubscriptionManager eventSubscriptionManager) {
this.eventSubscriptionManager = eventSubscriptionManager;
}
public BpmnDeploymentHelper getBpmnDeploymentHelper() {
return bpmnDeploymentHelper;
}
public ProcessEngineConfigurationImpl setBpmnDeploymentHelper(BpmnDeploymentHelper bpmnDeploymentHelper) {
this.bpmnDeploymentHelper = bpmnDeploymentHelper;
return this;
}
public CachingAndArtifactsManager getCachingAndArtifactsManager() {
return cachingAndArtifactsManager;
}
public void setCachingAndArtifactsManager(CachingAndArtifactsManager cachingAndArtifactsManager) {
this.cachingAndArtifactsManager = cachingAndArtifactsManager;
}
public ProcessDefinitionDiagramHelper getProcessDefinitionDiagramHelper() {
return processDefinitionDiagramHelper;
}
public ProcessEngineConfigurationImpl setProcessDefinitionDiagramHelper(ProcessDefinitionDiagramHelper processDefinitionDiagramHelper) {
this.processDefinitionDiagramHelper = processDefinitionDiagramHelper;
return this;
}
public List<Deployer> getDeployers() {
return deployers;
}
......
......@@ -26,7 +26,7 @@ import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.impl.ProcessEngineImpl;
import org.activiti.engine.impl.bpmn.deployer.BpmnDeployer;
import org.activiti.engine.impl.bpmn.deployer.ResourceNameUtil;
import org.activiti.engine.impl.bpmn.parser.factory.ActivityBehaviorFactory;
import org.activiti.engine.impl.db.DbSqlSession;
import org.activiti.engine.impl.interceptor.Command;
......@@ -191,7 +191,7 @@ public abstract class TestHelper {
* parameter: <code>BpmnDeployer.BPMN_RESOURCE_SUFFIXES</code>. The first resource matching a suffix will be returned.
*/
public static String getBpmnProcessDefinitionResource(Class<?> type, String name) {
for (String suffix : BpmnDeployer.BPMN_RESOURCE_SUFFIXES) {
for (String suffix : ResourceNameUtil.BPMN_RESOURCE_SUFFIXES) {
String resource = type.getName().replace('.', '/') + "." + name + "." + suffix;
InputStream inputStream = ReflectUtil.getResourceAsStream(resource);
if (inputStream == null) {
......@@ -200,7 +200,7 @@ public abstract class TestHelper {
return resource;
}
}
return type.getName().replace('.', '/') + "." + name + "." + BpmnDeployer.BPMN_RESOURCE_SUFFIXES[0];
return type.getName().replace('.', '/') + "." + name + "." + ResourceNameUtil.BPMN_RESOURCE_SUFFIXES[0];
}
// Engine startup and shutdown helpers
......
/* 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.test.bpmn.deployment;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.MatcherAssert.assertThat;
import java.util.List;
import org.activiti.engine.impl.bpmn.deployer.ParsedDeployment;
import org.activiti.engine.impl.bpmn.deployer.ParsedDeploymentBuilder;
import org.activiti.engine.impl.bpmn.deployer.ParsedDeploymentBuilderFactory;
import org.activiti.engine.impl.bpmn.deployer.ResourceNameUtil;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.persistence.entity.DeploymentEntity;
import org.activiti.engine.impl.persistence.entity.DeploymentEntityImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.ResourceEntity;
import org.activiti.engine.impl.persistence.entity.ResourceEntityImpl;
import org.activiti.engine.impl.test.PluggableActivitiTestCase;
public class ParsedDeploymentTest extends PluggableActivitiTestCase {
private static final String NAMESPACE = "xmlns='http://www.omg.org/spec/BPMN/20100524/MODEL'";
private static final String TARGET_NAMESPACE = "targetNamespace='http://activiti.org/BPMN20'";
private static final String ID1_ID = "id1";
private static final String ID2_ID = "id2";
private static final String IDR_PROCESS_XML = aseembleXmlResourceString(
"<process id='" + ID1_ID + "' name='Insurance Damage Report 1' />",
"<process id='" + ID2_ID + "' name='Insurance Damager Report 2' />");
private static final String IDR_XML_NAME = "idr." + ResourceNameUtil.BPMN_RESOURCE_SUFFIXES[0];
private static final String EN1_ID = "en1";
private static final String EN2_ID = "en2";
private static final String EN_PROCESS_XML = aseembleXmlResourceString(
"<process id='" + EN1_ID + "' name='Expense Note 1' />",
"<process id='" + EN2_ID + "' name='Expense Note 2' />");
private static final String EN_XML_NAME = "en." + ResourceNameUtil.BPMN_RESOURCE_SUFFIXES[1];
@Override
public void setUp() {
Context.setCommandContext(processEngineConfiguration.getCommandContextFactory().createCommandContext(null));
}
@Override
public void tearDown() {
Context.removeCommandContext();
}
public void testCreateAndQuery() {
DeploymentEntity entity = assembleUnpersistedDeploymentEntity();
ParsedDeploymentBuilderFactory builderFactory = processEngineConfiguration.getParsedDeploymentBuilderFactory();
ParsedDeploymentBuilder builder = builderFactory.getBuilderForDeployment(entity);
ParsedDeployment parsedDeployment = builder.build();
List<ProcessDefinitionEntity> processDefinitions = parsedDeployment.getAllProcessDefinitions();
assertThat(parsedDeployment.getDeployment(), sameInstance(entity));
assertThat(processDefinitions.size(), equalTo(4));
ProcessDefinitionEntity id1 = getProcessDefinitionEntityFromList(processDefinitions, ID1_ID);
ProcessDefinitionEntity id2 = getProcessDefinitionEntityFromList(processDefinitions, ID2_ID);
assertThat(parsedDeployment.getBpmnParseForProcessDefinition(id1),
sameInstance(parsedDeployment.getBpmnParseForProcessDefinition(id2)));
assertThat(parsedDeployment.getBpmnModelForProcessDefinition(id1), sameInstance(parsedDeployment.getBpmnParseForProcessDefinition(id1).getBpmnModel()));
assertThat(parsedDeployment.getProcessModelForProcessDefinition(id1), sameInstance(parsedDeployment.getBpmnParseForProcessDefinition(id1).getBpmnModel().getProcessById(id1.getKey())));
assertThat(parsedDeployment.getResourceForProcessDefinition(id1).getName(), equalTo(IDR_XML_NAME));
assertThat(parsedDeployment.getResourceForProcessDefinition(id2).getName(), equalTo(IDR_XML_NAME));
ProcessDefinitionEntity en1 = getProcessDefinitionEntityFromList(processDefinitions, EN1_ID);
ProcessDefinitionEntity en2 = getProcessDefinitionEntityFromList(processDefinitions, EN2_ID);
assertThat(parsedDeployment.getBpmnParseForProcessDefinition(en1),
sameInstance(parsedDeployment.getBpmnParseForProcessDefinition(en2)));
assertThat(parsedDeployment.getBpmnParseForProcessDefinition(en1), not(equalTo(parsedDeployment.getBpmnParseForProcessDefinition(id2))));
assertThat(parsedDeployment.getResourceForProcessDefinition(en1).getName(), equalTo(EN_XML_NAME));
assertThat(parsedDeployment.getResourceForProcessDefinition(en2).getName(), equalTo(EN_XML_NAME));
}
private ProcessDefinitionEntity getProcessDefinitionEntityFromList(List<ProcessDefinitionEntity> list, String idString) {
for (ProcessDefinitionEntity possible : list) {
if (possible.getKey().equals(idString)) {
return possible;
}
}
return null;
}
private DeploymentEntity assembleUnpersistedDeploymentEntity() {
DeploymentEntity entity = new DeploymentEntityImpl();
entity.addResource(buildResource(IDR_XML_NAME, IDR_PROCESS_XML));
entity.addResource(buildResource(EN_XML_NAME, EN_PROCESS_XML));
return entity;
}
private ResourceEntity buildResource(String name, String text) {
ResourceEntityImpl result = new ResourceEntityImpl();
result.setName(name);
result.setBytes(text.getBytes(UTF_8));
return result;
}
private static String aseembleXmlResourceString(String... definitions) {
StringBuilder builder = new StringBuilder("<definitions ");
builder = builder.append(NAMESPACE).append(" ").append(TARGET_NAMESPACE).append(">\n");
for (String definition : definitions) {
builder = builder.append(definition).append("\n");
}
builder = builder.append("</definitions>\n");
return builder.toString();
}
}
......@@ -19,7 +19,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.activiti.engine.impl.bpmn.deployer.BpmnDeployer;
import org.activiti.engine.impl.bpmn.deployer.ResourceNameUtil;
import org.activiti.engine.impl.test.PluggableActivitiTestCase;
import org.activiti.engine.repository.ProcessDefinition;
......@@ -148,7 +148,7 @@ public class ProcessDefinitionsTest extends PluggableActivitiTestCase {
}
private String deployProcessString(String processString) {
String resourceName = "xmlString." + BpmnDeployer.BPMN_RESOURCE_SUFFIXES[0];
String resourceName = "xmlString." + ResourceNameUtil.BPMN_RESOURCE_SUFFIXES[0];
return repositoryService.createDeployment().addString(resourceName, processString).deploy().getId();
}
......
......@@ -34,7 +34,7 @@ import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.history.HistoricVariableUpdate;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.bpmn.deployer.BpmnDeployer;
import org.activiti.engine.impl.bpmn.deployer.ResourceNameUtil;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
......@@ -200,7 +200,7 @@ public class RestResponseFactory {
// Determine type
String type = "resource";
for (String suffix : BpmnDeployer.BPMN_RESOURCE_SUFFIXES) {
for (String suffix : ResourceNameUtil.BPMN_RESOURCE_SUFFIXES) {
if (resourceId.endsWith(suffix)) {
type = "processDefinition";
break;
......
......@@ -50,7 +50,7 @@ package org.activiti5.engine;
public interface ProcessEngine {
/** the version of the activiti library */
public static String VERSION = "6.0.0.0";
public static String VERSION = "6.0.0.1";
/** The name as specified in 'process-engine-name' in
* the activiti.cfg.xml configuration file.
......
......@@ -20,13 +20,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import junit.framework.AssertionFailedError;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.impl.ProcessEngineImpl;
import org.activiti.engine.impl.bpmn.deployer.BpmnDeployer;
import org.activiti.engine.impl.bpmn.deployer.ResourceNameUtil;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.db.DbSqlSession;
import org.activiti.engine.impl.interceptor.Command;
......@@ -45,6 +43,8 @@ import org.activiti5.engine.test.mock.NoOpServiceTasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import junit.framework.AssertionFailedError;
/**
* @author Tom Baeyens
......@@ -209,7 +209,7 @@ public abstract class TestHelper {
* The first resource matching a suffix will be returned.
*/
public static String getBpmnProcessDefinitionResource(Class< ? > type, String name) {
for (String suffix : BpmnDeployer.BPMN_RESOURCE_SUFFIXES) {
for (String suffix : ResourceNameUtil.BPMN_RESOURCE_SUFFIXES) {
String resource = type.getName().replace('.', '/') + "." + name + "." + suffix;
InputStream inputStream = ReflectUtil.getResourceAsStream(resource);
if (inputStream == null) {
......@@ -218,7 +218,7 @@ public abstract class TestHelper {
return resource;
}
}
return type.getName().replace('.', '/') + "." + name + "." + BpmnDeployer.BPMN_RESOURCE_SUFFIXES[0];
return type.getName().replace('.', '/') + "." + name + "." + ResourceNameUtil.BPMN_RESOURCE_SUFFIXES[0];
}
......
......@@ -19,7 +19,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.activiti.engine.impl.bpmn.deployer.BpmnDeployer;
import org.activiti.engine.impl.bpmn.deployer.ResourceNameUtil;
import org.activiti.engine.repository.DeploymentProperties;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti5.engine.impl.test.PluggableActivitiTestCase;
......@@ -160,7 +160,7 @@ public class ProcessDefinitionsTest extends PluggableActivitiTestCase {
}
private String deployProcessString(String processString) {
String resourceName = "xmlString." + BpmnDeployer.BPMN_RESOURCE_SUFFIXES[0];
String resourceName = "xmlString." + ResourceNameUtil.BPMN_RESOURCE_SUFFIXES[0];
return repositoryService.createDeployment().addString(resourceName, processString)
.deploymentProperty(DeploymentProperties.DEPLOY_AS_ACTIVITI5_PROCESS_DEFINITION, Boolean.TRUE)
.deploy().getId();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册