diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml
index 0da6b3f999..c03d087d7b 100644
--- a/config/alfresco/bootstrap-context.xml
+++ b/config/alfresco/bootstrap-context.xml
@@ -216,7 +216,12 @@
/${spaces.company_home.childname}/${spaces.dictionary.childname}
alfresco/bootstrap/customWebClientExtensionSpace.xml
-
+
+
+ /${spaces.company_home.childname}/${spaces.dictionary.childname}
+ alfresco/bootstrap/customWorkflowDefsSpace.acp
+
+
diff --git a/config/alfresco/bootstrap/customWorkflowDefsSpace.acp b/config/alfresco/bootstrap/customWorkflowDefsSpace.acp
new file mode 100644
index 0000000000..e0750a5037
Binary files /dev/null and b/config/alfresco/bootstrap/customWorkflowDefsSpace.acp differ
diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties
index 64df8f28c0..cc0251fb47 100644
--- a/config/alfresco/messages/patch-service.properties
+++ b/config/alfresco/messages/patch-service.properties
@@ -174,4 +174,6 @@ patch.AVMProperties.result=Properties were moved.
patch.customModels.description=Adds Models space to Data Dictionary.
patch.customMessages.description=Adds Messages space to Data Dictionary.
-patch.customWebClientExtension.description=Adds Web Client Extension space to Data Dictionary.
+patch.customWebClientExtension.description=Adds Web Client Extension space to Data Dictionary.
+
+patch.customWorkflowDefs.description=Adds Workflow Definitions space to Data Dictionary.
diff --git a/config/alfresco/model/bpmModel.xml b/config/alfresco/model/bpmModel.xml
index a8ac800697..7911884dbf 100644
--- a/config/alfresco/model/bpmModel.xml
+++ b/config/alfresco/model/bpmModel.xml
@@ -269,6 +269,32 @@
+
+
+
+
+
+
+ Workflow Process Definition
+ cm:content
+
+
+ Workflow Name
+ d:text
+
+
+ Workflow Engine Id
+ d:text
+ true
+ jbpm
+
+
+ Workflow Deployed
+ d:boolean
+ false
+
+
+
diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml
index d00b1b5825..dca8aef4fe 100644
--- a/config/alfresco/patch/patch-services-context.xml
+++ b/config/alfresco/patch/patch-services-context.xml
@@ -1017,4 +1017,25 @@
+
+ patch.customWorkflowDefs
+ patch.customWorkflowDefs.description
+ 0
+ 105
+ 106
+
+
+
+
+
+ /${spaces.company_home.childname}/${spaces.dictionary.childname}/app:workflow_defs
+
+
+
+ /${spaces.company_home.childname}/${spaces.dictionary.childname}
+ alfresco/bootstrap/customWorkflowDefsSpace.acp
+
+
+
+
diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties
index 6b17d748b2..ebff9289bb 100644
--- a/config/alfresco/version.properties
+++ b/config/alfresco/version.properties
@@ -19,4 +19,4 @@ version.build=@build-number@
# Schema number
-version.schema=105
+version.schema=106
diff --git a/config/alfresco/workflow-context.xml b/config/alfresco/workflow-context.xml
index 2194d39088..6a7e9d07e3 100644
--- a/config/alfresco/workflow-context.xml
+++ b/config/alfresco/workflow-context.xml
@@ -21,6 +21,8 @@
+
+
@@ -106,5 +108,12 @@
-
+
+
+
+
+
+
+
+
diff --git a/source/java/org/alfresco/repo/workflow/WorkflowDefinitionType.java b/source/java/org/alfresco/repo/workflow/WorkflowDefinitionType.java
new file mode 100644
index 0000000000..b1abbe05f0
--- /dev/null
+++ b/source/java/org/alfresco/repo/workflow/WorkflowDefinitionType.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program 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 General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.workflow;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.content.ContentServicePolicies;
+import org.alfresco.repo.node.NodeServicePolicies;
+import org.alfresco.repo.policy.JavaBehaviour;
+import org.alfresco.repo.policy.PolicyComponent;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.workflow.WorkflowDefinition;
+import org.alfresco.service.cmr.workflow.WorkflowDeployment;
+import org.alfresco.service.cmr.workflow.WorkflowService;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Workflow Definition type behaviour.
+ *
+ * @author JanV
+ */
+public class WorkflowDefinitionType implements ContentServicePolicies.OnContentUpdatePolicy,
+ NodeServicePolicies.OnUpdatePropertiesPolicy,
+ NodeServicePolicies.BeforeDeleteNodePolicy
+{
+ // logger
+ private static Log logger = LogFactory.getLog(WorkflowDefinitionType.class);
+
+ /** The node service */
+ private NodeService nodeService;
+
+ /** The policy component */
+ private PolicyComponent policyComponent;
+
+ /** The workflow service */
+ private WorkflowService workflowService;
+
+
+
+ /**
+ * Set the node service
+ *
+ * @param nodeService the node service
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * Set the policy component
+ *
+ * @param policyComponent the policy component
+ */
+ public void setPolicyComponent(PolicyComponent policyComponent)
+ {
+ this.policyComponent = policyComponent;
+ }
+
+ /**
+ * Set the workflow service
+ *
+ * @param workflowService the workflow service
+ */
+ public void setWorkflowService(WorkflowService workflowService)
+ {
+ this.workflowService = workflowService;
+ }
+
+
+ /**
+ * The initialise method
+ */
+ public void init()
+ {
+ // Register interest in the onContentUpdate policy for the workflow definition type
+ policyComponent.bindClassBehaviour(
+ ContentServicePolicies.ON_CONTENT_UPDATE,
+ WorkflowModel.TYPE_WORKFLOW_DEF,
+ new JavaBehaviour(this, "onContentUpdate"));
+
+ // Register interest in the onPropertyUpdate policy for the workflow definition type
+ policyComponent.bindClassBehaviour(
+ QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),
+ WorkflowModel.TYPE_WORKFLOW_DEF,
+ new JavaBehaviour(this, "onUpdateProperties"));
+
+ // Register interest in the node delete policy
+ policyComponent.bindClassBehaviour(
+ QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
+ WorkflowModel.TYPE_WORKFLOW_DEF,
+ new JavaBehaviour(this, "beforeDeleteNode"));
+ }
+
+ /**
+ * On content update behaviour implementation
+ *
+ * @param nodeRef the node reference whose content has been updated
+ */
+ public void onContentUpdate(NodeRef nodeRef, boolean newContent)
+ {
+ deploy(nodeRef);
+ }
+
+ /**
+ * On update properties behaviour implementation
+ *
+ * @param nodeRef the node reference
+ * @param before the values of the properties before update
+ * @param after the values of the properties after the update
+ */
+ public void onUpdateProperties(
+ NodeRef nodeRef,
+ Map before,
+ Map after)
+ {
+ Boolean beforeValue = (Boolean)before.get(WorkflowModel.PROP_WORKFLOW_DEF_DEPLOYED);
+ Boolean afterValue = (Boolean)after.get(WorkflowModel.PROP_WORKFLOW_DEF_DEPLOYED);
+
+ if (afterValue != null &&
+ (beforeValue == null || (beforeValue != null && afterValue != null && beforeValue.equals(afterValue) == false)))
+ {
+ if (afterValue.booleanValue() == true)
+ {
+ deploy(nodeRef);
+ }
+ else
+ {
+ undeploy(nodeRef);
+ }
+ }
+ else if (afterValue == null && beforeValue != null)
+ {
+ // Undeploy the definition since the value has been cleared
+ undeploy(nodeRef);
+ }
+
+ }
+
+ public void beforeDeleteNode(NodeRef nodeRef)
+ {
+ // Ignore if the node is a working copy
+ if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY) == false)
+ {
+ undeploy(nodeRef);
+ }
+ }
+
+ private void deploy(NodeRef nodeRef)
+ {
+ // deploy / re-deploy
+ WorkflowDeployment deployment = workflowService.deployDefinition(nodeRef);
+
+ if (deployment != null)
+ {
+ WorkflowDefinition def = deployment.definition;
+
+ // Update the meta data for the model
+ Map props = nodeService.getProperties(nodeRef);
+
+ props.put(WorkflowModel.PROP_WORKFLOW_DEF_NAME, def.getName());
+
+ // TODO - ability to return and handle deployment problems / warnings
+ if (deployment.problems.length > 0)
+ {
+ for (String problem : deployment.problems)
+ {
+ logger.warn(problem);
+ }
+ }
+
+ nodeService.setProperties(nodeRef, props);
+ }
+ }
+
+ private void undeploy(NodeRef nodeRef)
+ {
+ String defName = (String)nodeService.getProperty(nodeRef, WorkflowModel.PROP_WORKFLOW_DEF_NAME);
+ if (defName != null)
+ {
+ // Undeploy the workflow definition - all versions in JBPM
+ List defs = workflowService.getAllDefinitionsByName(defName);
+ for (WorkflowDefinition def: defs)
+ {
+ logger.info("Undeploying workflow '" + defName + "' ...");
+ workflowService.undeployDefinition(def.getId());
+ logger.info("... undeployed '" + def.getId() + "' v" + def.getVersion());
+ }
+ }
+ }
+}
diff --git a/source/java/org/alfresco/repo/workflow/WorkflowModel.java b/source/java/org/alfresco/repo/workflow/WorkflowModel.java
index 030a359f5f..b914a2d362 100644
--- a/source/java/org/alfresco/repo/workflow/WorkflowModel.java
+++ b/source/java/org/alfresco/repo/workflow/WorkflowModel.java
@@ -74,4 +74,10 @@ public interface WorkflowModel
static final QName PROP_WORKFLOW_DEFINITION_NAME = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowDefinitionName");
static final QName PROP_WORKFLOW_INSTANCE_ID = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowInstanceId");
+ // workflow definition
+ static final QName TYPE_WORKFLOW_DEF = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowDefinition");
+ static final QName PROP_WORKFLOW_DEF_ENGINE_ID = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "engineId");
+ static final QName PROP_WORKFLOW_DEF_NAME = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "definitionName");
+ static final QName PROP_WORKFLOW_DEF_DEPLOYED = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "definitionDeployed");
+
}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java b/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java
index 9b84b16ba8..33678171a1 100644
--- a/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java
+++ b/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java
@@ -32,7 +32,11 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.alfresco.model.ContentModel;
+import org.alfresco.service.cmr.repository.ContentReader;
+import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
@@ -66,6 +70,8 @@ public class WorkflowServiceImpl implements WorkflowService
private AuthorityService authorityService;
private BPMEngineRegistry registry;
private WorkflowPackageComponent workflowPackageComponent;
+ private NodeService nodeService;
+ private ContentService contentService;
/**
@@ -98,6 +104,26 @@ public class WorkflowServiceImpl implements WorkflowService
this.workflowPackageComponent = workflowPackageComponent;
}
+ /**
+ * Sets the Node Service
+ *
+ * @param nodeService
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * Sets the Content Service
+ *
+ * @param contentService
+ */
+ public void setContentService(ContentService contentService)
+ {
+ this.contentService = contentService;
+ }
+
/* (non-Javadoc)
* @see org.alfresco.service.cmr.workflow.WorkflowService#deployDefinition(java.lang.String, java.io.InputStream, java.lang.String)
@@ -132,8 +158,15 @@ public class WorkflowServiceImpl implements WorkflowService
*/
public WorkflowDeployment deployDefinition(NodeRef definitionContent)
{
- // TODO
- throw new UnsupportedOperationException();
+ if (! nodeService.getType(definitionContent).equals(WorkflowModel.TYPE_WORKFLOW_DEF))
+ {
+ throw new WorkflowException("Node " + definitionContent + " is not of type 'bpm:workflowDefinition'");
+ }
+
+ String engineId = (String)nodeService.getProperty(definitionContent, WorkflowModel.PROP_WORKFLOW_DEF_ENGINE_ID);
+ ContentReader contentReader = contentService.getReader(definitionContent, ContentModel.PROP_CONTENT);
+
+ return deployDefinition(engineId, contentReader.getContentInputStream(), contentReader.getMimetype());
}
/* (non-Javadoc)
diff --git a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java
index e1d83a3b15..0243edae7d 100644
--- a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java
+++ b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java
@@ -321,7 +321,7 @@ public class JBPMEngine extends BPMEngine
}
catch(JbpmException e)
{
- throw new WorkflowException("Failed to deploy workflow definition", e);
+ throw new WorkflowException("Failed to deploy workflow definition - " + e.getMessage(), e);
}
}
@@ -380,7 +380,7 @@ public class JBPMEngine extends BPMEngine
}
catch(JbpmException e)
{
- throw new WorkflowException("Failed to undeploy workflow definition", e);
+ throw new WorkflowException("Failed to undeploy workflow definition - " + e.getMessage(), e);
}
}
@@ -1801,8 +1801,13 @@ public class JBPMEngine extends BPMEngine
throw new JbpmException("Failed to parse process definition from jBPM xml stream", e);
}
}
+
+ else
+ {
+ throw new JbpmException("Failed to parse process definition - unsupported mime type '" + mimetype + "'");
+ }
- if (tenantService.isEnabled())
+ if ((compiledDef != null) && tenantService.isEnabled())
{
compiledDef.def.setName(tenantService.getName(compiledDef.def.getName()));
}