http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowDefinitionTO.java ---------------------------------------------------------------------- diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowDefinitionTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowDefinitionTO.java new file mode 100644 index 0000000..804d75c --- /dev/null +++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowDefinitionTO.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.common.lib.to; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import org.apache.syncope.common.lib.AbstractBaseBean; + +@XmlRootElement(name = "workflowDefinition") +@XmlType +public class WorkflowDefinitionTO extends AbstractBaseBean { + + private static final long serialVersionUID = -7044543391316529128L; + + private String key; + + private String modelId; + + private String name; + + private boolean main; + + public String getKey() { + return key; + } + + public void setKey(final String key) { + this.key = key; + } + + public String getModelId() { + return modelId; + } + + public void setModelId(final String modelId) { + this.modelId = modelId; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public boolean isMain() { + return main; + } + + public void setMain(final boolean main) { + this.main = main; + } + +}
http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java ---------------------------------------------------------------------- diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java index 8f70ba1..aa3fd17 100644 --- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java +++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java @@ -160,9 +160,13 @@ public final class StandardEntitlement { public static final String POLICY_DELETE = "POLICY_DELETE"; - public static final String WORKFLOW_DEF_READ = "WORKFLOW_DEF_READ"; + public static final String WORKFLOW_DEF_LIST = "WORKFLOW_DEF_LIST"; - public static final String WORKFLOW_DEF_UPDATE = "WORKFLOW_DEF_UPDATE"; + public static final String WORKFLOW_DEF_GET = "WORKFLOW_DEF_GET"; + + public static final String WORKFLOW_DEF_SET = "WORKFLOW_DEF_SET"; + + public static final String WORKFLOW_DEF_DELETE = "WORKFLOW_DEF_DELETE"; public static final String WORKFLOW_TASK_LIST = "WORKFLOW_TASK_LIST"; http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/WorkflowService.java ---------------------------------------------------------------------- diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/WorkflowService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/WorkflowService.java index 28b8932..cb1cc4a 100644 --- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/WorkflowService.java +++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/WorkflowService.java @@ -18,8 +18,10 @@ */ package org.apache.syncope.common.rest.api.service; +import java.util.List; import javax.validation.constraints.NotNull; import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; @@ -27,7 +29,7 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import org.apache.syncope.common.lib.types.AnyTypeKind; +import org.apache.syncope.common.lib.to.WorkflowDefinitionTO; import org.apache.syncope.common.rest.api.RESTHeaders; /** @@ -37,36 +39,68 @@ import org.apache.syncope.common.rest.api.RESTHeaders; public interface WorkflowService extends JAXRSService { /** - * Exports workflow definition for matching kind. + * Lists the available workflow definitions, for the given any object type. * - * @param anyTypeKind any object type - * @return workflow definition for matching kind + * @param anyType any object type + * @return available workflow definitions, for the given any object type */ @GET - @Path("{anyTypeKind}") + @Path("{anyType}") @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - Response exportDefinition(@NotNull @PathParam("anyTypeKind") AnyTypeKind anyTypeKind); + List<WorkflowDefinitionTO> list(@NotNull @PathParam("anyType") String anyType); /** - * Exports workflow diagram representation. + * Exports the workflow definition for matching any object type and key. * - * @param anyTypeKind any object type + * @param anyType any object type + * @param key workflow definition key + * @return workflow definition for matching any object type and key + */ + @GET + @Path("{anyType}/{key}") + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + Response get( + @NotNull @PathParam("anyType") String anyType, + @NotNull @PathParam("key") String key); + + /** + * Exports the workflow diagram representation (if available), for matching any object type and key. + * + * @param anyType any object type + * @param key workflow definition key * @return workflow diagram representation */ @GET - @Path("{anyTypeKind}/diagram.png") + @Path("{anyType}/{key}/diagram.png") @Produces({ RESTHeaders.MEDIATYPE_IMAGE_PNG }) - Response exportDiagram(@NotNull @PathParam("anyTypeKind") AnyTypeKind anyTypeKind); + Response exportDiagram( + @NotNull @PathParam("anyType") String anyType, + @NotNull @PathParam("key") String key); /** - * Imports workflow definition for matching kind. + * Imports the workflow definition for matching any object type, under the provided key. * - * @param anyTypeKind any object type + * @param anyType any object type + * @param key workflow definition key * @param definition workflow definition for matching kind */ @PUT - @Path("{anyTypeKind}") + @Path("{anyType}/{key}") @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - void importDefinition(@NotNull @PathParam("anyTypeKind") AnyTypeKind anyTypeKind, @NotNull String definition); + void set( + @NotNull @PathParam("anyType") String anyType, + @NotNull @PathParam("key") String key, + @NotNull String definition); + /** + * Removes the workflow definition for matching any object type, under the provided key. + * + * @param anyType any object type + * @param key workflow definition key + */ + @DELETE + @Path("{anyType}/{key}") + void delete( + @NotNull @PathParam("anyType") String anyType, + @NotNull @PathParam("key") String key); } http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/logic/src/main/java/org/apache/syncope/core/logic/WorkflowLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/WorkflowLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/WorkflowLogic.java index 8b6d530..4f3e512 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/WorkflowLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/WorkflowLogic.java @@ -20,13 +20,16 @@ package org.apache.syncope.core.logic; import java.io.OutputStream; import java.lang.reflect.Method; -import javax.ws.rs.core.MediaType; -import org.apache.syncope.common.lib.AbstractBaseBean; +import java.util.List; +import org.apache.syncope.common.lib.to.WorkflowDefinitionTO; import org.apache.syncope.common.lib.types.StandardEntitlement; -import org.apache.syncope.core.workflow.api.AnyObjectWorkflowAdapter; -import org.apache.syncope.core.workflow.api.GroupWorkflowAdapter; -import org.apache.syncope.core.workflow.api.UserWorkflowAdapter; -import org.apache.syncope.core.workflow.api.WorkflowAdapter; +import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO; +import org.apache.syncope.core.persistence.api.dao.NotFoundException; +import org.apache.syncope.core.persistence.api.entity.AnyType; +import org.apache.syncope.core.workflow.api.AnyObjectWorkflowDefinitionAdapter; +import org.apache.syncope.core.workflow.api.GroupWorkflowDefinitionAdapter; +import org.apache.syncope.core.workflow.api.UserWorkflowDefinitionAdapter; +import org.apache.syncope.core.workflow.api.WorkflowDefinitionAdapter; import org.apache.syncope.core.workflow.api.WorkflowDefinitionFormat; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; @@ -34,94 +37,77 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @Component -public class WorkflowLogic extends AbstractTransactionalLogic<AbstractBaseBean> { +public class WorkflowLogic extends AbstractTransactionalLogic<WorkflowDefinitionTO> { @Autowired - private AnyObjectWorkflowAdapter awfAdapter; + private AnyTypeDAO anyTypeDAO; @Autowired - private UserWorkflowAdapter uwfAdapter; + private AnyObjectWorkflowDefinitionAdapter awfAdapter; @Autowired - private GroupWorkflowAdapter gwfAdapter; + private UserWorkflowDefinitionAdapter uwfAdapter; - private void exportDefinition( - final WorkflowAdapter adapter, final WorkflowDefinitionFormat format, final OutputStream os) { - - adapter.exportDefinition(format, os); - } - - private WorkflowDefinitionFormat getFormat(final MediaType format) { - return format.equals(MediaType.APPLICATION_JSON_TYPE) - ? WorkflowDefinitionFormat.JSON - : WorkflowDefinitionFormat.XML; - } - - @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_DEF_READ + "')") - @Transactional(readOnly = true) - public void exportAnyObjectDefinition(final MediaType format, final OutputStream os) { - exportDefinition(awfAdapter, getFormat(format), os); + @Autowired + private GroupWorkflowDefinitionAdapter gwfAdapter; + + private WorkflowDefinitionAdapter getAdapter(final String anyTypeKey) { + AnyType anyType = anyTypeDAO.find(anyTypeKey); + if (anyType == null) { + LOG.error("Could not find anyType '" + anyTypeKey + "'"); + throw new NotFoundException(anyTypeKey); + } + + switch (anyType.getKind()) { + case ANY_OBJECT: + return awfAdapter; + + case GROUP: + return gwfAdapter; + + case USER: + default: + return uwfAdapter; + } } - @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_DEF_READ + "')") + @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_DEF_LIST + "')") @Transactional(readOnly = true) - public void exportUserDefinition(final MediaType format, final OutputStream os) { - exportDefinition(uwfAdapter, getFormat(format), os); + public List<WorkflowDefinitionTO> list(final String anyType) { + return getAdapter(anyType).getDefinitions(); } - @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_DEF_READ + "')") + @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_DEF_GET + "')") @Transactional(readOnly = true) - public void exportGroupDefinition(final MediaType format, final OutputStream os) { - exportDefinition(gwfAdapter, getFormat(format), os); - } + public void exportDefinition( + final String anyType, final String key, final WorkflowDefinitionFormat format, final OutputStream os) { - private void exportDiagram(final WorkflowAdapter adapter, final OutputStream os) { - adapter.exportDiagram(os); + getAdapter(anyType).exportDefinition(key, format, os); } - @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_DEF_READ + "')") + @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_DEF_GET + "')") @Transactional(readOnly = true) - public void exportAnyObjectDiagram(final OutputStream os) { - exportDiagram(awfAdapter, os); + public void exportDiagram(final String anyType, final String key, final OutputStream os) { + getAdapter(anyType).exportDiagram(key, os); } - @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_DEF_READ + "')") - @Transactional(readOnly = true) - public void exportUserDiagram(final OutputStream os) { - exportDiagram(uwfAdapter, os); - } + @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_DEF_GET + "')") + public void importDefinition( + final String anyType, final String key, final WorkflowDefinitionFormat format, final String definition) { - @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_DEF_READ + "')") - @Transactional(readOnly = true) - public void exportGroupDiagram(final OutputStream os) { - exportDiagram(gwfAdapter, os); + getAdapter(anyType).importDefinition(key, format, definition); } - private void importDefinition( - final WorkflowAdapter adapter, final WorkflowDefinitionFormat format, final String definition) { - - adapter.importDefinition(format, definition); - } - - @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_DEF_UPDATE + "')") - public void importAnyObjectDefinition(final MediaType format, final String definition) { - importDefinition(awfAdapter, getFormat(format), definition); - } - - @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_DEF_UPDATE + "')") - public void importUserDefinition(final MediaType format, final String definition) { - importDefinition(uwfAdapter, getFormat(format), definition); - } - - @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_DEF_UPDATE + "')") - public void importGroupDefinition(final MediaType format, final String definition) { - importDefinition(gwfAdapter, getFormat(format), definition); + @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_DEF_DELETE + "')") + public void delete(final String anyType, final String key) { + getAdapter(anyType).deleteDefinition(key); } @Override - protected AbstractBaseBean resolveReference(final Method method, final Object... args) + protected WorkflowDefinitionTO resolveReference(final Method method, final Object... args) throws UnresolvedReferenceException { throw new UnresolvedReferenceException(); } + } http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/WorkflowServiceImpl.java ---------------------------------------------------------------------- diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/WorkflowServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/WorkflowServiceImpl.java index 5b82db0..2642853 100644 --- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/WorkflowServiceImpl.java +++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/WorkflowServiceImpl.java @@ -20,13 +20,15 @@ package org.apache.syncope.core.rest.cxf.service; import java.io.IOException; import java.io.OutputStream; +import java.util.List; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.StreamingOutput; -import org.apache.syncope.common.lib.types.AnyTypeKind; +import org.apache.syncope.common.lib.to.WorkflowDefinitionTO; import org.apache.syncope.common.rest.api.RESTHeaders; import org.apache.syncope.common.rest.api.service.WorkflowService; import org.apache.syncope.core.logic.WorkflowLogic; +import org.apache.syncope.core.workflow.api.WorkflowDefinitionFormat; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -37,44 +39,38 @@ public class WorkflowServiceImpl extends AbstractServiceImpl implements Workflow private WorkflowLogic logic; @Override - public Response exportDefinition(final AnyTypeKind kind) { - final MediaType accept = + public List<WorkflowDefinitionTO> list(final String anyType) { + return logic.list(anyType); + } + + @Override + public Response get(final String anyType, final String key) { + final WorkflowDefinitionFormat format = messageContext.getHttpHeaders().getAcceptableMediaTypes().contains(MediaType.APPLICATION_JSON_TYPE) - ? MediaType.APPLICATION_JSON_TYPE - : MediaType.APPLICATION_XML_TYPE; + ? WorkflowDefinitionFormat.JSON + : WorkflowDefinitionFormat.XML; StreamingOutput sout = new StreamingOutput() { @Override public void write(final OutputStream os) throws IOException { - if (kind == AnyTypeKind.USER) { - logic.exportUserDefinition(accept, os); - } else if (kind == AnyTypeKind.ANY_OBJECT) { - logic.exportAnyObjectDefinition(accept, os); - } else { - logic.exportGroupDefinition(accept, os); - } + logic.exportDefinition(anyType, key, format, os); } }; return Response.ok(sout). - type(accept). + type(format == WorkflowDefinitionFormat.JSON + ? MediaType.APPLICATION_JSON_TYPE : MediaType.APPLICATION_XHTML_XML_TYPE). build(); } @Override - public Response exportDiagram(final AnyTypeKind kind) { + public Response exportDiagram(final String anyType, final String key) { StreamingOutput sout = new StreamingOutput() { @Override public void write(final OutputStream os) throws IOException { - if (kind == AnyTypeKind.USER) { - logic.exportUserDiagram(os); - } else if (kind == AnyTypeKind.ANY_OBJECT) { - logic.exportAnyObjectDiagram(os); - } else { - logic.exportGroupDiagram(os); - } + logic.exportDiagram(anyType, key, os); } }; @@ -84,19 +80,18 @@ public class WorkflowServiceImpl extends AbstractServiceImpl implements Workflow } @Override - public void importDefinition(final AnyTypeKind kind, final String definition) { - final MediaType contentType = + public void set(final String anyType, final String key, final String definition) { + WorkflowDefinitionFormat format = messageContext.getHttpHeaders().getMediaType().equals(MediaType.APPLICATION_JSON_TYPE) - ? MediaType.APPLICATION_JSON_TYPE - : MediaType.APPLICATION_XML_TYPE; + ? WorkflowDefinitionFormat.JSON + : WorkflowDefinitionFormat.XML; - if (kind == AnyTypeKind.USER) { - logic.importUserDefinition(contentType, definition); - } else if (kind == AnyTypeKind.ANY_OBJECT) { - logic.importAnyObjectDefinition(contentType, definition); - } else { - logic.importGroupDefinition(contentType, definition); - } + logic.importDefinition(anyType, key, format, definition); + } + + @Override + public void delete(final String anyType, final String key) { + logic.delete(anyType, key); } } http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiDefinitionLoader.java ---------------------------------------------------------------------- diff --git a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiDefinitionLoader.java b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiDefinitionLoader.java index e91f595..9521213 100644 --- a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiDefinitionLoader.java +++ b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiDefinitionLoader.java @@ -18,17 +18,13 @@ */ package org.apache.syncope.core.workflow.activiti; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Map; import javax.annotation.Resource; -import org.activiti.editor.constants.ModelDataJsonConstants; import org.activiti.engine.ProcessEngine; -import org.activiti.engine.repository.Model; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.spring.SpringProcessEngineConfiguration; import org.apache.commons.io.IOUtils; @@ -65,7 +61,7 @@ public class ActivitiDefinitionLoader implements SyncopeLoader { wfIn = userWorkflowDef.getResource().getInputStream(); wfDef = IOUtils.toByteArray(wfIn); } catch (IOException e) { - LOG.error("While loading " + ActivitiUserWorkflowAdapter.WF_PROCESS_RESOURCE, e); + LOG.error("While loading " + userWorkflowDef.getResource().getFilename(), e); } finally { IOUtils.closeQuietly(wfIn); } @@ -79,21 +75,13 @@ public class ActivitiDefinitionLoader implements SyncopeLoader { // Only loads process definition from file if not found in repository if (processes.isEmpty()) { entry.getValue().getRepositoryService().createDeployment().addInputStream( - ActivitiUserWorkflowAdapter.WF_PROCESS_RESOURCE, new ByteArrayInputStream(wfDef)).deploy(); + userWorkflowDef.getResource().getFilename(), new ByteArrayInputStream(wfDef)).deploy(); ProcessDefinition procDef = entry.getValue().getRepositoryService().createProcessDefinitionQuery(). processDefinitionKey(ActivitiUserWorkflowAdapter.WF_PROCESS_ID).latestVersion(). singleResult(); - Model model = entry.getValue().getRepositoryService().newModel(); - ObjectNode modelObjectNode = new ObjectMapper().createObjectNode(); - modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, procDef.getName()); - modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1); - modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, procDef.getDescription()); - model.setMetaInfo(modelObjectNode.toString()); - model.setName(procDef.getName()); - model.setDeploymentId(procDef.getDeploymentId()); - ActivitiImportUtils.fromJSON(entry.getValue(), procDef, model); + ActivitiDeployUtils.deployModel(entry.getValue(), procDef); LOG.debug("Activiti Workflow definition loaded for domain {}", entry.getKey()); } http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiDeployUtils.java ---------------------------------------------------------------------- diff --git a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiDeployUtils.java b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiDeployUtils.java new file mode 100644 index 0000000..965e03c --- /dev/null +++ b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiDeployUtils.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.workflow.activiti; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import org.activiti.bpmn.converter.BpmnXMLConverter; +import org.activiti.bpmn.model.BpmnModel; +import org.activiti.editor.constants.ModelDataJsonConstants; +import org.activiti.editor.language.json.converter.BpmnJsonConverter; +import org.activiti.engine.ActivitiException; +import org.activiti.engine.ProcessEngine; +import org.activiti.engine.repository.Deployment; +import org.activiti.engine.repository.Model; +import org.activiti.engine.repository.ProcessDefinition; +import org.apache.commons.io.IOUtils; +import org.apache.syncope.core.workflow.api.WorkflowException; + +public final class ActivitiDeployUtils { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + public static Deployment deployDefinition( + final ProcessEngine engine, final String resourceName, final byte[] definition) { + + try { + return engine.getRepositoryService().createDeployment(). + addInputStream(resourceName, new ByteArrayInputStream(definition)).deploy(); + } catch (ActivitiException e) { + throw new WorkflowException("While importing " + resourceName, e); + } + } + + public static void deployModel(final ProcessEngine engine, final ProcessDefinition procDef) { + InputStream bpmnStream = null; + InputStreamReader isr = null; + XMLStreamReader xtr = null; + try { + bpmnStream = engine.getRepositoryService().getResourceAsStream( + procDef.getDeploymentId(), procDef.getResourceName()); + isr = new InputStreamReader(bpmnStream); + xtr = XMLInputFactory.newInstance().createXMLStreamReader(isr); + BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr); + + Model model = engine.getRepositoryService().newModel(); + ObjectNode modelObjectNode = OBJECT_MAPPER.createObjectNode(); + modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, procDef.getName()); + model.setMetaInfo(modelObjectNode.toString()); + model.setName(procDef.getName()); + model.setDeploymentId(procDef.getDeploymentId()); + model.setVersion(procDef.getVersion()); + + engine.getRepositoryService().saveModel(model); + engine.getRepositoryService().addModelEditorSource( + model.getId(), + new BpmnJsonConverter().convertToJson(bpmnModel).toString().getBytes()); + } catch (Exception e) { + throw new WorkflowException("While importing " + procDef.getResourceName(), e); + } finally { + if (xtr != null) { + try { + xtr.close(); + } catch (XMLStreamException e) { + // ignore + } + } + IOUtils.closeQuietly(isr); + IOUtils.closeQuietly(bpmnStream); + } + } + + private ActivitiDeployUtils() { + // private constructor for static utility class + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiImportUtils.java ---------------------------------------------------------------------- diff --git a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiImportUtils.java b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiImportUtils.java deleted file mode 100644 index 5df8ac4..0000000 --- a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiImportUtils.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.syncope.core.workflow.activiti; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.io.InputStreamReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; -import org.activiti.bpmn.converter.BpmnXMLConverter; -import org.activiti.bpmn.model.BpmnModel; -import org.activiti.editor.language.json.converter.BpmnJsonConverter; -import org.activiti.engine.ActivitiException; -import org.activiti.engine.ProcessEngine; -import org.activiti.engine.repository.Model; -import org.activiti.engine.repository.ProcessDefinition; -import org.apache.commons.io.IOUtils; -import org.apache.syncope.core.workflow.api.WorkflowException; - -public final class ActivitiImportUtils { - - public static void fromXML(final ProcessEngine engine, final byte[] definition) { - try { - engine.getRepositoryService().createDeployment(). - addInputStream(ActivitiUserWorkflowAdapter.WF_PROCESS_RESOURCE, - new ByteArrayInputStream(definition)).deploy(); - } catch (ActivitiException e) { - throw new WorkflowException("While updating process " + ActivitiUserWorkflowAdapter.WF_PROCESS_RESOURCE, e); - } - } - - public static void fromJSON( - final ProcessEngine engine, final byte[] definition, final ProcessDefinition procDef, final Model model) { - - try { - model.setVersion(procDef.getVersion()); - model.setDeploymentId(procDef.getDeploymentId()); - engine.getRepositoryService().saveModel(model); - - engine.getRepositoryService().addModelEditorSource(model.getId(), definition); - } catch (Exception e) { - throw new WorkflowException("While updating process " + ActivitiUserWorkflowAdapter.WF_PROCESS_RESOURCE, e); - } - } - - public static void fromJSON(final ProcessEngine engine, final ProcessDefinition procDef, final Model model) { - InputStream bpmnStream = null; - InputStreamReader isr = null; - XMLStreamReader xtr = null; - try { - bpmnStream = engine.getRepositoryService().getResourceAsStream( - procDef.getDeploymentId(), procDef.getResourceName()); - isr = new InputStreamReader(bpmnStream); - xtr = XMLInputFactory.newInstance().createXMLStreamReader(isr); - BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr); - - fromJSON(engine, new BpmnJsonConverter().convertToJson(bpmnModel).toString().getBytes(), procDef, model); - } catch (Exception e) { - throw new WorkflowException("While updating process " + ActivitiUserWorkflowAdapter.WF_PROCESS_RESOURCE, e); - } finally { - if (xtr != null) { - try { - xtr.close(); - } catch (XMLStreamException e) { - // ignore - } - } - IOUtils.closeQuietly(isr); - IOUtils.closeQuietly(bpmnStream); - } - } - - private ActivitiImportUtils() { - // private constructor for static utility class - } -} http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java ---------------------------------------------------------------------- diff --git a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java index 8f4fe93..569dce1 100644 --- a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java +++ b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java @@ -32,7 +32,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.Resource; -import javax.ws.rs.NotFoundException; import org.activiti.bpmn.converter.BpmnXMLConverter; import org.activiti.bpmn.model.BpmnModel; import org.activiti.editor.constants.ModelDataJsonConstants; @@ -46,11 +45,13 @@ import org.activiti.engine.history.HistoricDetail; import org.activiti.engine.history.HistoricTaskInstance; import org.activiti.engine.impl.persistence.entity.HistoricFormPropertyEntity; import org.activiti.engine.query.Query; +import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.Model; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Transformer; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -59,6 +60,7 @@ import org.apache.syncope.common.lib.SyncopeClientException; import org.apache.syncope.common.lib.patch.PasswordPatch; import org.apache.syncope.common.lib.patch.UserPatch; import org.apache.syncope.common.lib.to.UserTO; +import org.apache.syncope.common.lib.to.WorkflowDefinitionTO; import org.apache.syncope.common.lib.to.WorkflowFormPropertyTO; import org.apache.syncope.common.lib.to.WorkflowFormTO; import org.apache.syncope.core.provisioning.api.PropagationByResource; @@ -68,6 +70,7 @@ import org.apache.syncope.core.spring.security.AuthContextUtils; import org.apache.syncope.core.spring.BeanUtils; import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidEntityException; import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException; +import org.apache.syncope.core.persistence.api.dao.NotFoundException; import org.apache.syncope.core.persistence.api.entity.user.User; import org.apache.syncope.core.provisioning.api.WorkflowResult; import org.apache.syncope.core.provisioning.api.utils.EntityUtils; @@ -83,14 +86,12 @@ import org.springframework.transaction.annotation.Transactional; */ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter { + protected static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + protected static final String[] PROPERTY_IGNORE_PROPS = { "type" }; public static final String WF_PROCESS_ID = "userWorkflow"; - public static final String WF_PROCESS_RESOURCE = "userWorkflow.bpmn20.xml"; - - public static final String WF_DGRM_RESOURCE = "userWorkflow.userWorkflow.png"; - public static final String USER = "user"; public static final String WF_EXECUTOR = "wfExecutor"; @@ -464,112 +465,6 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter { return new WorkflowResult<>(updated.getKey(), null, performedTasks); } - protected ProcessDefinition getProcessDefinition() { - try { - return engine.getRepositoryService().createProcessDefinitionQuery().processDefinitionKey( - ActivitiUserWorkflowAdapter.WF_PROCESS_ID).latestVersion().singleResult(); - } catch (ActivitiException e) { - throw new WorkflowException("While accessing process " + ActivitiUserWorkflowAdapter.WF_PROCESS_ID, e); - } - - } - - protected Model getModel(final ProcessDefinition procDef) { - try { - Model model = engine.getRepositoryService().createModelQuery(). - deploymentId(procDef.getDeploymentId()).singleResult(); - if (model == null) { - throw new NotFoundException("Could not find Model for deployment " + procDef.getDeploymentId()); - } - return model; - } catch (Exception e) { - throw new WorkflowException("While accessing process " + ActivitiUserWorkflowAdapter.WF_PROCESS_ID, e); - } - } - - protected void exportProcessResource(final String resourceName, final OutputStream os) { - ProcessDefinition procDef = getProcessDefinition(); - - InputStream procDefIS = engine.getRepositoryService().getResourceAsStream(procDef.getDeploymentId(), - resourceName); - try { - IOUtils.copy(procDefIS, os); - } catch (IOException e) { - LOG.error("While exporting workflow definition {}", procDef.getKey(), e); - } finally { - IOUtils.closeQuietly(procDefIS); - } - } - - protected void exportProcessModel(final OutputStream os) { - Model model = getModel(getProcessDefinition()); - - ObjectMapper objectMapper = new ObjectMapper(); - try { - ObjectNode modelNode = (ObjectNode) objectMapper.readTree(model.getMetaInfo()); - modelNode.put(ModelDataJsonConstants.MODEL_ID, model.getId()); - modelNode.replace(MODEL_DATA_JSON_MODEL, - objectMapper.readTree(engine.getRepositoryService().getModelEditorSource(model.getId()))); - - os.write(modelNode.toString().getBytes()); - } catch (IOException e) { - LOG.error("While exporting workflow definition {}", model.getId(), e); - } - } - - @Override - public void exportDefinition(final WorkflowDefinitionFormat format, final OutputStream os) { - switch (format) { - case JSON: - exportProcessModel(os); - break; - - case XML: - default: - exportProcessResource(WF_PROCESS_RESOURCE, os); - } - } - - @Override - public void exportDiagram(final OutputStream os) { - exportProcessResource(WF_DGRM_RESOURCE, os); - } - - @Override - public void importDefinition(final WorkflowDefinitionFormat format, final String definition) { - Model model = getModel(getProcessDefinition()); - switch (format) { - case JSON: - JsonNode definitionNode; - try { - definitionNode = new ObjectMapper().readTree(definition); - if (definitionNode.has(MODEL_DATA_JSON_MODEL)) { - definitionNode = definitionNode.get(MODEL_DATA_JSON_MODEL); - } - if (!definitionNode.has(BpmnJsonConverter.EDITOR_CHILD_SHAPES)) { - throw new IllegalArgumentException( - "Could not find JSON node " + BpmnJsonConverter.EDITOR_CHILD_SHAPES); - } - - BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(definitionNode); - ActivitiImportUtils.fromXML(engine, new BpmnXMLConverter().convertToXML(bpmnModel)); - } catch (Exception e) { - throw new WorkflowException("While updating process " - + ActivitiUserWorkflowAdapter.WF_PROCESS_RESOURCE, e); - } - - ActivitiImportUtils.fromJSON( - engine, definitionNode.toString().getBytes(), getProcessDefinition(), model); - break; - - case XML: - default: - ActivitiImportUtils.fromXML(engine, definition.getBytes()); - - ActivitiImportUtils.fromJSON(engine, getProcessDefinition(), model); - } - } - protected WorkflowFormPropertyType fromActivitiFormType(final FormType activitiFormType) { WorkflowFormPropertyType result = WorkflowFormPropertyType.String; @@ -884,4 +779,173 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter { return new WorkflowResult<>(userPatch, propByRes, postTasks); } + + protected Model getModel(final ProcessDefinition procDef) { + try { + Model model = engine.getRepositoryService().createModelQuery(). + deploymentId(procDef.getDeploymentId()).singleResult(); + if (model == null) { + throw new NotFoundException("Could not find Model for deployment " + procDef.getDeploymentId()); + } + return model; + } catch (Exception e) { + throw new WorkflowException("While accessing process " + procDef.getKey(), e); + } + } + + @Override + public List<WorkflowDefinitionTO> getDefinitions() { + try { + return CollectionUtils.collect( + engine.getRepositoryService().createProcessDefinitionQuery().latestVersion().list(), + new Transformer<ProcessDefinition, WorkflowDefinitionTO>() { + + @Override + public WorkflowDefinitionTO transform(final ProcessDefinition procDef) { + WorkflowDefinitionTO defTO = new WorkflowDefinitionTO(); + defTO.setKey(procDef.getKey()); + defTO.setName(procDef.getName()); + + try { + defTO.setModelId(getModel(procDef).getId()); + } catch (NotFoundException e) { + LOG.warn("No model found for definition {}, ignoring", procDef.getDeploymentId(), e); + } + + defTO.setMain(WF_PROCESS_ID.equals(procDef.getKey())); + + return defTO; + } + }, new ArrayList<WorkflowDefinitionTO>()); + } catch (ActivitiException e) { + throw new WorkflowException("While listing available process definitions", e); + } + } + + protected ProcessDefinition getProcessDefinitionByKey(final String key) { + try { + return engine.getRepositoryService().createProcessDefinitionQuery(). + processDefinitionKey(key).latestVersion().singleResult(); + } catch (ActivitiException e) { + throw new WorkflowException("While accessing process " + key, e); + } + + } + + protected ProcessDefinition getProcessDefinitionByDeploymentId(final String deploymentId) { + try { + return engine.getRepositoryService().createProcessDefinitionQuery(). + deploymentId(deploymentId).latestVersion().singleResult(); + } catch (ActivitiException e) { + throw new WorkflowException("While accessing deployment " + deploymentId, e); + } + + } + + protected void exportProcessModel(final String key, final OutputStream os) { + Model model = getModel(getProcessDefinitionByKey(key)); + + try { + ObjectNode modelNode = (ObjectNode) OBJECT_MAPPER.readTree(model.getMetaInfo()); + modelNode.put(ModelDataJsonConstants.MODEL_ID, model.getId()); + modelNode.replace(MODEL_DATA_JSON_MODEL, + OBJECT_MAPPER.readTree(engine.getRepositoryService().getModelEditorSource(model.getId()))); + + os.write(modelNode.toString().getBytes()); + } catch (IOException e) { + LOG.error("While exporting workflow definition {}", model.getId(), e); + } + } + + protected void exportProcessResource(final String deploymentId, final String resourceName, final OutputStream os) { + InputStream procDefIS = engine.getRepositoryService(). + getResourceAsStream(deploymentId, resourceName); + try { + IOUtils.copy(procDefIS, os); + } catch (IOException e) { + LOG.error("While exporting {}", resourceName, e); + } finally { + IOUtils.closeQuietly(procDefIS); + } + } + + @Override + public void exportDefinition(final String key, final WorkflowDefinitionFormat format, final OutputStream os) { + switch (format) { + case JSON: + exportProcessModel(key, os); + break; + + case XML: + default: + ProcessDefinition procDef = getProcessDefinitionByKey(key); + exportProcessResource(procDef.getDeploymentId(), procDef.getResourceName(), os); + } + } + + @Override + public void exportDiagram(final String key, final OutputStream os) { + ProcessDefinition procDef = getProcessDefinitionByKey(key); + if (procDef == null) { + throw new NotFoundException("Workflow process definition for " + key); + } + exportProcessResource(procDef.getDeploymentId(), procDef.getDiagramResourceName(), os); + } + + @Override + public void importDefinition(final String key, final WorkflowDefinitionFormat format, final String definition) { + ProcessDefinition procDef = getProcessDefinitionByKey(key); + String resourceName = procDef == null ? key + ".bpmn20.xml" : procDef.getResourceName(); + Deployment deployment; + switch (format) { + case JSON: + JsonNode definitionNode; + try { + definitionNode = OBJECT_MAPPER.readTree(definition); + if (definitionNode.has(MODEL_DATA_JSON_MODEL)) { + definitionNode = definitionNode.get(MODEL_DATA_JSON_MODEL); + } + if (!definitionNode.has(BpmnJsonConverter.EDITOR_CHILD_SHAPES)) { + throw new IllegalArgumentException( + "Could not find JSON node " + BpmnJsonConverter.EDITOR_CHILD_SHAPES); + } + + BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(definitionNode); + deployment = ActivitiDeployUtils.deployDefinition( + engine, + resourceName, + new BpmnXMLConverter().convertToXML(bpmnModel)); + } catch (Exception e) { + throw new WorkflowException("While creating or updating process " + key, e); + } + break; + + case XML: + default: + deployment = ActivitiDeployUtils.deployDefinition( + engine, + resourceName, + definition.getBytes()); + } + + procDef = getProcessDefinitionByDeploymentId(deployment.getId()); + if (!key.equals(procDef.getKey())) { + throw new WorkflowException("Mismatching key: expected " + key + ", found " + procDef.getKey()); + } + ActivitiDeployUtils.deployModel(engine, procDef); + } + + @Override + public void deleteDefinition(final String key) { + ProcessDefinition procDef = getProcessDefinitionByKey(key); + if (WF_PROCESS_ID.equals(procDef.getKey())) { + throw new WorkflowException("Cannot delete the main process " + WF_PROCESS_ID); + } + + try { + engine.getRepositoryService().deleteDeployment(procDef.getDeploymentId()); + } catch (Exception e) { + throw new WorkflowException("While deleting " + key, e); + } + } } http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/AnyObjectWorkflowDefinitionAdapter.java ---------------------------------------------------------------------- diff --git a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/AnyObjectWorkflowDefinitionAdapter.java b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/AnyObjectWorkflowDefinitionAdapter.java new file mode 100644 index 0000000..43fb0dd --- /dev/null +++ b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/AnyObjectWorkflowDefinitionAdapter.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.workflow.api; + +public interface AnyObjectWorkflowDefinitionAdapter extends WorkflowDefinitionAdapter { +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/GroupWorkflowDefinitionAdapter.java ---------------------------------------------------------------------- diff --git a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/GroupWorkflowDefinitionAdapter.java b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/GroupWorkflowDefinitionAdapter.java new file mode 100644 index 0000000..6dc2241 --- /dev/null +++ b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/GroupWorkflowDefinitionAdapter.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.workflow.api; + +public interface GroupWorkflowDefinitionAdapter extends WorkflowDefinitionAdapter { +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowDefinitionAdapter.java ---------------------------------------------------------------------- diff --git a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowDefinitionAdapter.java b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowDefinitionAdapter.java new file mode 100644 index 0000000..93b3969 --- /dev/null +++ b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowDefinitionAdapter.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.workflow.api; + +public interface UserWorkflowDefinitionAdapter extends WorkflowDefinitionAdapter { +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java ---------------------------------------------------------------------- diff --git a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java index b6fab8f..881c4dc 100644 --- a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java +++ b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java @@ -18,7 +18,6 @@ */ package org.apache.syncope.core.workflow.api; -import java.io.OutputStream; import java.util.List; import org.apache.syncope.common.lib.patch.AnyPatch; import org.apache.syncope.common.lib.to.WorkflowFormTO; @@ -37,29 +36,6 @@ public interface WorkflowAdapter { String getPrefix(); /** - * Export workflow definition. - * - * @param format export format - * @param os export stream - */ - void exportDefinition(WorkflowDefinitionFormat format, OutputStream os); - - /** - * Export workflow graphical representation (if available). - * - * @param os export stream - */ - void exportDiagram(OutputStream os); - - /** - * Update workflow definition. - * - * @param format import format - * @param definition definition - */ - void importDefinition(WorkflowDefinitionFormat format, String definition); - - /** * Get all defined forms for current workflow process instances. * * @return list of defined forms http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowDefinitionAdapter.java ---------------------------------------------------------------------- diff --git a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowDefinitionAdapter.java b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowDefinitionAdapter.java new file mode 100644 index 0000000..ea84598 --- /dev/null +++ b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowDefinitionAdapter.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.workflow.api; + +import java.io.OutputStream; +import java.util.List; +import org.apache.syncope.common.lib.to.WorkflowDefinitionTO; + +public interface WorkflowDefinitionAdapter { + + /** + * @return all available workflow definitions. + */ + List<WorkflowDefinitionTO> getDefinitions(); + + /** + * Export the workflow definition for the given key, in the requested format. + * + * @param key definition key + * @param format export format + * @param os export stream + */ + void exportDefinition(String key, WorkflowDefinitionFormat format, OutputStream os); + + /** + * Export the workflow graphical representation for the given key (if available). + * + * @param key definition key + * @param os export stream + */ + void exportDiagram(String key, OutputStream os); + + /** + * Import the workflow definition for the given key. + * + * @param key definition key + * @param format import format + * @param definition definition + */ + void importDefinition(String key, WorkflowDefinitionFormat format, String definition); + + /** + * Remove the workflow definition for the given key. + * + * @param key definition key + */ + void deleteDefinition(String key); +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowException.java ---------------------------------------------------------------------- diff --git a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowException.java b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowException.java index 74abc21..7b3805d 100644 --- a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowException.java +++ b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowException.java @@ -25,11 +25,12 @@ package org.apache.syncope.core.workflow.api; */ public class WorkflowException extends RuntimeException { - /** - * Generated serialVersionUID. - */ private static final long serialVersionUID = -6261173250078013869L; + public WorkflowException(final String message) { + super(message); + } + /** * Return a new instance wrapping the original workflow exception. * http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableDefinitionLoader.java ---------------------------------------------------------------------- diff --git a/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableDefinitionLoader.java b/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableDefinitionLoader.java index 18f4b37..d918ecc 100644 --- a/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableDefinitionLoader.java +++ b/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableDefinitionLoader.java @@ -18,17 +18,13 @@ */ package org.apache.syncope.core.workflow.flowable; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Map; import javax.annotation.Resource; -import org.activiti.editor.constants.ModelDataJsonConstants; import org.activiti.engine.ProcessEngine; -import org.activiti.engine.repository.Model; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.spring.SpringProcessEngineConfiguration; import org.apache.commons.io.IOUtils; @@ -65,7 +61,7 @@ public class FlowableDefinitionLoader implements SyncopeLoader { wfIn = userWorkflowDef.getResource().getInputStream(); wfDef = IOUtils.toByteArray(wfIn); } catch (IOException e) { - LOG.error("While loading " + FlowableUserWorkflowAdapter.WF_PROCESS_RESOURCE, e); + LOG.error("While loading " + userWorkflowDef.getResource().getFilename(), e); } finally { IOUtils.closeQuietly(wfIn); } @@ -74,28 +70,20 @@ public class FlowableDefinitionLoader implements SyncopeLoader { List<ProcessDefinition> processes = entry.getValue().getRepositoryService(). createProcessDefinitionQuery().processDefinitionKey(FlowableUserWorkflowAdapter.WF_PROCESS_ID). list(); - LOG.debug(FlowableUserWorkflowAdapter.WF_PROCESS_ID + " Flowable processes in repository: {}", processes); + LOG.debug(FlowableUserWorkflowAdapter.WF_PROCESS_ID + " Activiti processes in repository: {}", processes); // Only loads process definition from file if not found in repository if (processes.isEmpty()) { entry.getValue().getRepositoryService().createDeployment().addInputStream( - FlowableUserWorkflowAdapter.WF_PROCESS_RESOURCE, new ByteArrayInputStream(wfDef)).deploy(); + userWorkflowDef.getResource().getFilename(), new ByteArrayInputStream(wfDef)).deploy(); ProcessDefinition procDef = entry.getValue().getRepositoryService().createProcessDefinitionQuery(). processDefinitionKey(FlowableUserWorkflowAdapter.WF_PROCESS_ID).latestVersion(). singleResult(); - Model model = entry.getValue().getRepositoryService().newModel(); - ObjectNode modelObjectNode = new ObjectMapper().createObjectNode(); - modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, procDef.getName()); - modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1); - modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, procDef.getDescription()); - model.setMetaInfo(modelObjectNode.toString()); - model.setName(procDef.getName()); - model.setDeploymentId(procDef.getDeploymentId()); - FlowableImportUtils.fromJSON(entry.getValue(), procDef, model); + FlowableDeployUtils.deployModel(entry.getValue(), procDef); - LOG.debug("Flowable Workflow definition loaded for domain {}", entry.getKey()); + LOG.debug("Activiti Workflow definition loaded for domain {}", entry.getKey()); } // jump to the next ID block http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableDeployUtils.java ---------------------------------------------------------------------- diff --git a/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableDeployUtils.java b/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableDeployUtils.java new file mode 100644 index 0000000..4d28cd2 --- /dev/null +++ b/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableDeployUtils.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.workflow.flowable; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import org.activiti.bpmn.converter.BpmnXMLConverter; +import org.activiti.bpmn.model.BpmnModel; +import org.activiti.editor.constants.ModelDataJsonConstants; +import org.activiti.editor.language.json.converter.BpmnJsonConverter; +import org.activiti.engine.ActivitiException; +import org.activiti.engine.ProcessEngine; +import org.activiti.engine.repository.Deployment; +import org.activiti.engine.repository.Model; +import org.activiti.engine.repository.ProcessDefinition; +import org.apache.commons.io.IOUtils; +import org.apache.syncope.core.workflow.api.WorkflowException; + +public final class FlowableDeployUtils { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + public static Deployment deployDefinition( + final ProcessEngine engine, final String resourceName, final byte[] definition) { + + try { + return engine.getRepositoryService().createDeployment(). + addInputStream(resourceName, new ByteArrayInputStream(definition)).deploy(); + } catch (ActivitiException e) { + throw new WorkflowException("While importing " + resourceName, e); + } + } + + public static void deployModel(final ProcessEngine engine, final ProcessDefinition procDef) { + InputStream bpmnStream = null; + InputStreamReader isr = null; + XMLStreamReader xtr = null; + try { + bpmnStream = engine.getRepositoryService().getResourceAsStream( + procDef.getDeploymentId(), procDef.getResourceName()); + isr = new InputStreamReader(bpmnStream); + xtr = XMLInputFactory.newInstance().createXMLStreamReader(isr); + BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr); + + Model model = engine.getRepositoryService().newModel(); + ObjectNode modelObjectNode = OBJECT_MAPPER.createObjectNode(); + modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, procDef.getName()); + model.setMetaInfo(modelObjectNode.toString()); + model.setName(procDef.getName()); + model.setDeploymentId(procDef.getDeploymentId()); + model.setVersion(procDef.getVersion()); + + engine.getRepositoryService().saveModel(model); + engine.getRepositoryService().addModelEditorSource( + model.getId(), + new BpmnJsonConverter().convertToJson(bpmnModel).toString().getBytes()); + } catch (Exception e) { + throw new WorkflowException("While importing " + procDef.getResourceName(), e); + } finally { + if (xtr != null) { + try { + xtr.close(); + } catch (XMLStreamException e) { + // ignore + } + } + IOUtils.closeQuietly(isr); + IOUtils.closeQuietly(bpmnStream); + } + } + + private FlowableDeployUtils() { + // private constructor for static utility class + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7a440618/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableImportUtils.java ---------------------------------------------------------------------- diff --git a/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableImportUtils.java b/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableImportUtils.java deleted file mode 100644 index 6d0aae5..0000000 --- a/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableImportUtils.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.syncope.core.workflow.flowable; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.io.InputStreamReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; -import org.activiti.bpmn.converter.BpmnXMLConverter; -import org.activiti.bpmn.model.BpmnModel; -import org.activiti.editor.language.json.converter.BpmnJsonConverter; -import org.activiti.engine.ActivitiException; -import org.activiti.engine.ProcessEngine; -import org.activiti.engine.repository.Model; -import org.activiti.engine.repository.ProcessDefinition; -import org.apache.commons.io.IOUtils; -import org.apache.syncope.core.workflow.api.WorkflowException; - -public final class FlowableImportUtils { - - public static void fromXML(final ProcessEngine engine, final byte[] definition) { - try { - engine.getRepositoryService().createDeployment(). - addInputStream(FlowableUserWorkflowAdapter.WF_PROCESS_RESOURCE, - new ByteArrayInputStream(definition)).deploy(); - } catch (ActivitiException e) { - throw new WorkflowException("While updating process " + FlowableUserWorkflowAdapter.WF_PROCESS_RESOURCE, e); - } - } - - public static void fromJSON( - final ProcessEngine engine, final byte[] definition, final ProcessDefinition procDef, final Model model) { - - try { - model.setVersion(procDef.getVersion()); - model.setDeploymentId(procDef.getDeploymentId()); - engine.getRepositoryService().saveModel(model); - - engine.getRepositoryService().addModelEditorSource(model.getId(), definition); - } catch (Exception e) { - throw new WorkflowException("While updating process " + FlowableUserWorkflowAdapter.WF_PROCESS_RESOURCE, e); - } - } - - public static void fromJSON(final ProcessEngine engine, final ProcessDefinition procDef, final Model model) { - InputStream bpmnStream = null; - InputStreamReader isr = null; - XMLStreamReader xtr = null; - try { - bpmnStream = engine.getRepositoryService().getResourceAsStream( - procDef.getDeploymentId(), procDef.getResourceName()); - isr = new InputStreamReader(bpmnStream); - xtr = XMLInputFactory.newInstance().createXMLStreamReader(isr); - BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr); - - fromJSON(engine, new BpmnJsonConverter().convertToJson(bpmnModel).toString().getBytes(), procDef, model); - } catch (Exception e) { - throw new WorkflowException("While updating process " + FlowableUserWorkflowAdapter.WF_PROCESS_RESOURCE, e); - } finally { - if (xtr != null) { - try { - xtr.close(); - } catch (XMLStreamException e) { - // ignore - } - } - IOUtils.closeQuietly(isr); - IOUtils.closeQuietly(bpmnStream); - } - } - - private FlowableImportUtils() { - // private constructor for static utility class - } -}
