/* * JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jbpm.pvm.internal.repository; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.List; import java.util.Map; import org.jbpm.api.ProcessDefinition; import org.jbpm.api.ProcessDefinitionQuery; import org.jbpm.internal.log.Log; import org.jbpm.pvm.internal.env.EnvironmentImpl; import org.jbpm.pvm.internal.migration.InstanceMigrator; import org.jbpm.pvm.internal.migration.MigrationDescriptor; import org.jbpm.pvm.internal.model.ProcessDefinitionImpl; import org.jbpm.pvm.internal.session.RepositorySession; import org.jbpm.pvm.internal.xml.Parse; import org.jbpm.pvm.internal.xml.Parser; /** * @author Tom Baeyens */ public class ProcessDeployer implements Deployer { private static final Log log = Log.getLog(ProcessDeployer.class.getName()); protected String extension; protected Parser parser; public ProcessDeployer(String extension, Parser parser) { this.extension = extension; this.parser = parser; } @SuppressWarnings("unchecked") public void deploy(DeploymentImpl deployment) { for (String resourceName: deployment.getResourceNames()) { if (resourceName.endsWith(extension)) { byte[] bytes = deployment.getBytes(resourceName); InputStream inputStream = new ByteArrayInputStream(bytes); Parse parse = parser.createParse(); parse.contextMapPut(Parse.CONTEXT_KEY_DEPLOYMENT, deployment); parse.setProblems(deployment.getProblems()); parse.setInputStream(inputStream); parse.execute(); List processDefinitions = (List) parse.getDocumentObject(); if (processDefinitions!=null) { for (ProcessDefinitionImpl processDefinition : processDefinitions) { if ((processDefinition != null) && (processDefinition.getName() != null)) { String processDefinitionName = processDefinition.getName(); processDefinition.setSuspended(deployment.isSuspended()); String imageResourceName = resourceName.substring(0, resourceName.lastIndexOf(extension)) + ".png"; if (deployment.getResourceNames().contains(imageResourceName)) { processDefinition.setImageResourceName(imageResourceName); } processDefinition.setDeploymentDbid(deployment.getDbid()); if (deployment.hasObjectProperties(processDefinitionName)) { String key = deployment.getProcessDefinitionKey(processDefinitionName); String id = deployment.getProcessDefinitionId(processDefinitionName); Long version = deployment.getProcessDefinitionVersion(processDefinitionName); processDefinition.setId(id); processDefinition.setKey(key); processDefinition.setVersion(version.intValue()); } else { checkKey(processDefinition, deployment); checkVersion(processDefinition, deployment); checkId(processDefinition, deployment); deployment.setProcessDefinitionId(processDefinitionName, processDefinition.getId()); deployment.setProcessDefinitionKey(processDefinitionName, processDefinition.getKey()); deployment.setProcessDefinitionVersion(processDefinitionName, new Long(processDefinition.getVersion())); //execute migration Map migrations = (Map)parse.contextMapGet(Parse.CONTEXT_KEY_MIGRATIONS); if (migrations != null) { MigrationDescriptor migrationDescriptor = migrations.get(processDefinition); if (migrationDescriptor != null) { InstanceMigrator.migrateAll(processDefinition, migrationDescriptor); } } } deployment.addObject(processDefinitionName, processDefinition); } } } } } } protected void checkKey(ProcessDefinitionImpl processDefinition, DeploymentImpl deployment) { String processDefinitionName = processDefinition.getName(); String processDefinitionKey = processDefinition.getKey(); // if no key was specified in the jpdl process file if (processDefinitionKey==null) { // derive the key from the name // replace any non-word character with an underscore processDefinitionKey = processDefinitionName.replaceAll("\\W", "_"); processDefinition.setKey(processDefinitionKey); } RepositorySession repositorySession = EnvironmentImpl.getFromCurrent(RepositorySession.class); List existingProcesses = repositorySession.createProcessDefinitionQuery() .processDefinitionName(processDefinitionName) .list(); for (ProcessDefinition existingProcess: existingProcesses) { if (!processDefinitionKey.equals(existingProcess.getKey())) { deployment.addProblem("invalid key '"+processDefinitionKey+"' in process "+processDefinition.getName()+". Existing process has name '"+processDefinitionName+"' and key '"+processDefinitionKey+"'"); } } existingProcesses = repositorySession.createProcessDefinitionQuery() .processDefinitionKey(processDefinitionKey) .list(); for (ProcessDefinition existingProcess: existingProcesses) { if (!processDefinitionName.equals(existingProcess.getName())) { deployment.addProblem("invalid name '"+processDefinitionName+"' in process "+processDefinition.getName()+". Existing process has name '"+processDefinitionName+"' and key '"+processDefinitionKey+"'"); } } } protected void checkId(ProcessDefinitionImpl processDefinition, DeploymentImpl deployment) { String id = processDefinition.getId(); if (id==null) { id = processDefinition.getKey()+"-"+processDefinition.getVersion(); if (log.isTraceEnabled()) log.trace("created id '"+id+"' for "+processDefinition); processDefinition.setId(id); } RepositorySession repositorySession = EnvironmentImpl.getFromCurrent(RepositorySession.class); ProcessDefinition existingProcessDefinition = repositorySession.createProcessDefinitionQuery() .processDefinitionId(id) .uniqueResult(); if (existingProcessDefinition != null) { deployment.addProblem("process '" + id + "' already exists"); } } protected void checkVersion(ProcessDefinitionImpl processDefinition, DeploymentImpl deployment) { int version = processDefinition.getVersion(); String key = processDefinition.getKey(); if (version==ProcessDefinitionImpl.UNASSIGNED_VERSION) { RepositorySession repositorySession = EnvironmentImpl.getFromCurrent(RepositorySession.class); ProcessDefinition latestDeployedVersion = repositorySession .createProcessDefinitionQuery() .processDefinitionKey(key) .orderDesc(ProcessDefinitionQuery.PROPERTY_VERSION) .page(0, 1) .uniqueResult(); if (latestDeployedVersion!=null) { version = latestDeployedVersion.getVersion() + 1; } else { version = 1; } if (log.isTraceEnabled()) log.trace("assigning version "+version+" to process definition "+key); processDefinition.setVersion(version); } } public void updateResource(DeploymentImpl deployment, String resourceName, byte[] bytes) { deployment.addResourceFromInputStream(resourceName, new ByteArrayInputStream(bytes)); } }