From 810d3b29b3678cbe4b9a6af8e281757c6e820ee4 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sat, 15 Feb 2020 12:12:18 +0100 Subject: [PATCH] Make core runtime features independent of Spring. --- dep/org.argeo.slc.dep.backend/pom.xml | 9 + dep/org.argeo.slc.dep.minimal/pom.xml | 10 + lib/pom.xml | 25 +- .../META-INF/spring/jcr-osgi.xml | 2 +- .../META-INF/spring/jcr.xml | 5 +- .../execution/FlowConfigurationException.java | 2 +- org.argeo.slc.jcr/bnd.bnd | 1 + org.argeo.slc.jcr/pom.xml | 29 +- .../org/argeo/slc/jcr/execution/JcrAgent.java | 4 +- .../JcrExecutionModulesListener.java | 0 .../jcr/execution/JcrExecutionProcess.java | 2 +- .../slc/jcr/execution/JcrProcessThread.java | 2 +- .../slc/jcr/execution/JcrRealizedFlow.java | 56 ++-- org.argeo.slc.runtime/.classpath | 7 + org.argeo.slc.runtime/.gitignore | 2 + org.argeo.slc.runtime/.project | 28 ++ org.argeo.slc.runtime/META-INF/.gitignore | 1 + org.argeo.slc.runtime/bnd.bnd | 2 + org.argeo.slc.runtime/build.properties | 4 + org.argeo.slc.runtime/pom.xml | 21 ++ .../AbstractExecutionModulesManager.java | 2 +- .../org/argeo/slc/runtime/DefaultAgent.java | 221 +++++++++++++++ .../argeo/slc/runtime/DefaultAgentCli.java | 238 ++++++++++++++++ .../slc/runtime/DefaultExecutionFlow.java | 260 ++++++++++++++++++ .../slc/runtime/DefaultExecutionSpec.java | 82 ++++++ .../slc/runtime}/DefaultExecutionStack.java | 2 +- .../argeo/slc/runtime}/DefaultProcess.java | 2 +- .../argeo/slc/runtime}/ExecutionThread.java | 6 +- .../slc/runtime}/InstantiationManager.java | 4 +- .../org/argeo/slc/runtime}/ProcessThread.java | 2 +- .../slc/runtime}/ProcessThreadGroup.java | 2 +- .../slc/core/execution/DefaultAgent.java | 203 +------------- .../slc/core/execution/DefaultAgentCli.java | 233 +--------------- .../core/execution/DefaultExecutionFlow.java | 251 +---------------- ...faultExecutionFlowDescriptorConverter.java | 1 + .../core/execution/DefaultExecutionSpec.java | 70 ++--- .../ExecutionParameterPostProcessor.java | 1 + .../slc/core/execution/ExecutionScope.java | 1 + .../slc/core/execution/ParameterRef.java | 1 + .../org/argeo/slc/core/execution/runtime.xml | 4 +- .../org/argeo/slc/core/execution/specs.xml | 4 +- .../jcr/execution/JcrAttachmentUploader.java | 37 --- .../slc/osgi/OsgiExecutionModulesManager.java | 2 +- org.argeo.slc.support/pom.xml | 5 + .../argeo/slc/log4j/SlcExecutionAppender.java | 28 +- pom.xml | 1 + 46 files changed, 1007 insertions(+), 868 deletions(-) rename {org.argeo.slc.spring/src/org/argeo/slc/core => org.argeo.slc.api/src/org/argeo/slc}/execution/FlowConfigurationException.java (89%) rename {org.argeo.slc.spring => org.argeo.slc.jcr}/src/org/argeo/slc/jcr/execution/JcrAgent.java (97%) rename {org.argeo.slc.spring => org.argeo.slc.jcr}/src/org/argeo/slc/jcr/execution/JcrExecutionModulesListener.java (100%) rename {org.argeo.slc.spring => org.argeo.slc.jcr}/src/org/argeo/slc/jcr/execution/JcrExecutionProcess.java (99%) rename {org.argeo.slc.spring => org.argeo.slc.jcr}/src/org/argeo/slc/jcr/execution/JcrProcessThread.java (98%) rename {org.argeo.slc.spring => org.argeo.slc.jcr}/src/org/argeo/slc/jcr/execution/JcrRealizedFlow.java (75%) create mode 100644 org.argeo.slc.runtime/.classpath create mode 100644 org.argeo.slc.runtime/.gitignore create mode 100644 org.argeo.slc.runtime/.project create mode 100644 org.argeo.slc.runtime/META-INF/.gitignore create mode 100644 org.argeo.slc.runtime/bnd.bnd create mode 100644 org.argeo.slc.runtime/build.properties create mode 100644 org.argeo.slc.runtime/pom.xml rename {org.argeo.slc.spring/src/org/argeo/slc/core/execution => org.argeo.slc.runtime/src/org/argeo/slc/runtime}/AbstractExecutionModulesManager.java (99%) create mode 100644 org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultAgent.java create mode 100644 org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultAgentCli.java create mode 100644 org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultExecutionFlow.java create mode 100644 org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultExecutionSpec.java rename {org.argeo.slc.spring/src/org/argeo/slc/core/execution => org.argeo.slc.runtime/src/org/argeo/slc/runtime}/DefaultExecutionStack.java (99%) rename {org.argeo.slc.spring/src/org/argeo/slc/core/execution => org.argeo.slc.runtime/src/org/argeo/slc/runtime}/DefaultProcess.java (96%) rename {org.argeo.slc.spring/src/org/argeo/slc/core/execution => org.argeo.slc.runtime/src/org/argeo/slc/runtime}/ExecutionThread.java (96%) rename {org.argeo.slc.spring/src/org/argeo/slc/core/execution => org.argeo.slc.runtime/src/org/argeo/slc/runtime}/InstantiationManager.java (95%) rename {org.argeo.slc.spring/src/org/argeo/slc/core/execution => org.argeo.slc.runtime/src/org/argeo/slc/runtime}/ProcessThread.java (99%) rename {org.argeo.slc.spring/src/org/argeo/slc/core/execution => org.argeo.slc.runtime/src/org/argeo/slc/runtime}/ProcessThreadGroup.java (98%) delete mode 100644 org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrAttachmentUploader.java diff --git a/dep/org.argeo.slc.dep.backend/pom.xml b/dep/org.argeo.slc.dep.backend/pom.xml index 4bbe5394d..b96c01b36 100644 --- a/dep/org.argeo.slc.dep.backend/pom.xml +++ b/dep/org.argeo.slc.dep.backend/pom.xml @@ -77,6 +77,15 @@ 2.1.17-SNAPSHOT + + + org.argeo.commons + org.argeo.osgi.boot + 2.1.86-SNAPSHOT + test + + org.argeo.slc.legacy.commons diff --git a/dep/org.argeo.slc.dep.minimal/pom.xml b/dep/org.argeo.slc.dep.minimal/pom.xml index e51826248..c319e986c 100644 --- a/dep/org.argeo.slc.dep.minimal/pom.xml +++ b/dep/org.argeo.slc.dep.minimal/pom.xml @@ -25,6 +25,16 @@ org.argeo.slc.api 2.1.17-SNAPSHOT + + org.argeo.slc + org.argeo.slc.runtime + 2.1.17-SNAPSHOT + + + org.argeo.slc + org.argeo.slc.jcr + 2.1.17-SNAPSHOT + diff --git a/lib/pom.xml b/lib/pom.xml index 5cfb7fc6a..d5fb06fe7 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -46,20 +46,21 @@ default - org.springframework.cglib.proxy, - org.springframework.cglib.core, - org.springframework.cglib.reflect, - org.aopalliance.aop, - org.argeo.slc.core.execution, - org.argeo.slc.core.execution.tasks, + org.springframework.cglib.proxy;resolution:="optional", + org.springframework.cglib.core;resolution:="optional", + org.springframework.cglib.reflect;resolution:="optional", + org.aopalliance.aop;resolution:="optional", + org.argeo.slc.runtime, + org.argeo.slc.core.execution;resolution:="optional", + org.argeo.slc.core.execution.tasks;resolution:="optional", org.argeo.slc.execution, - org.argeo.slc.osgi, + org.argeo.slc.osgi;resolution:="optional", org.argeo.slc.test, - org.springframework.aop, - org.springframework.aop.framework, - org.springframework.aop.scope, - org.springframework.beans.factory.config, - org.springframework.core.io, + org.springframework.aop;resolution:="optional", + org.springframework.aop.framework;resolution:="optional", + org.springframework.aop.scope;resolution:="optional", + org.springframework.beans.factory.config;resolution:="optional", + org.springframework.core.io;resolution:="optional", ${additionalImports.slc-lib}, * diff --git a/org.argeo.slc.agent.jcr/META-INF/spring/jcr-osgi.xml b/org.argeo.slc.agent.jcr/META-INF/spring/jcr-osgi.xml index b5f913eb8..848879f8c 100644 --- a/org.argeo.slc.agent.jcr/META-INF/spring/jcr-osgi.xml +++ b/org.argeo.slc.agent.jcr/META-INF/spring/jcr-osgi.xml @@ -20,7 +20,7 @@ interface="org.argeo.slc.execution.ExecutionModulesManager" /> - + diff --git a/org.argeo.slc.agent.jcr/META-INF/spring/jcr.xml b/org.argeo.slc.agent.jcr/META-INF/spring/jcr.xml index 6d31ddd11..b15866d49 100644 --- a/org.argeo.slc.agent.jcr/META-INF/spring/jcr.xml +++ b/org.argeo.slc.agent.jcr/META-INF/spring/jcr.xml @@ -28,9 +28,8 @@ - - - + + org.argeo.slc.jcr SLC JCR implementations - - - - org.apache.maven.plugins - maven-surefire-plugin - - true - - - - + + + org.argeo.slc + org.argeo.slc.api + 2.1.17-SNAPSHOT + + + org.argeo.slc + org.argeo.slc.runtime + 2.1.17-SNAPSHOT + + org.argeo.commons @@ -49,11 +50,5 @@ ${version.argeo-commons} - - - org.argeo.slc - org.argeo.slc.api - 2.1.17-SNAPSHOT - \ No newline at end of file diff --git a/org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrAgent.java b/org.argeo.slc.jcr/src/org/argeo/slc/jcr/execution/JcrAgent.java similarity index 97% rename from org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrAgent.java rename to org.argeo.slc.jcr/src/org/argeo/slc/jcr/execution/JcrAgent.java index 89b4530ac..c75863ade 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrAgent.java +++ b/org.argeo.slc.jcr/src/org/argeo/slc/jcr/execution/JcrAgent.java @@ -30,11 +30,11 @@ import org.argeo.slc.SlcConstants; import org.argeo.slc.SlcException; import org.argeo.slc.SlcNames; import org.argeo.slc.SlcTypes; -import org.argeo.slc.core.execution.DefaultAgent; -import org.argeo.slc.core.execution.ProcessThread; +import org.argeo.slc.runtime.DefaultAgent; import org.argeo.slc.execution.ExecutionModulesManager; import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.jcr.SlcJcrConstants; +import org.argeo.slc.runtime.ProcessThread; /** SLC VM agent synchronizing with a JCR repository. */ public class JcrAgent extends DefaultAgent implements SlcNames { diff --git a/org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrExecutionModulesListener.java b/org.argeo.slc.jcr/src/org/argeo/slc/jcr/execution/JcrExecutionModulesListener.java similarity index 100% rename from org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrExecutionModulesListener.java rename to org.argeo.slc.jcr/src/org/argeo/slc/jcr/execution/JcrExecutionModulesListener.java diff --git a/org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrExecutionProcess.java b/org.argeo.slc.jcr/src/org/argeo/slc/jcr/execution/JcrExecutionProcess.java similarity index 99% rename from org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrExecutionProcess.java rename to org.argeo.slc.jcr/src/org/argeo/slc/jcr/execution/JcrExecutionProcess.java index e1ad69e3b..137d28c77 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrExecutionProcess.java +++ b/org.argeo.slc.jcr/src/org/argeo/slc/jcr/execution/JcrExecutionProcess.java @@ -33,11 +33,11 @@ import org.argeo.slc.NameVersion; import org.argeo.slc.SlcException; import org.argeo.slc.SlcNames; import org.argeo.slc.SlcTypes; -import org.argeo.slc.core.execution.ProcessThread; import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.execution.ExecutionStep; import org.argeo.slc.execution.RealizedFlow; import org.argeo.slc.jcr.SlcJcrUtils; +import org.argeo.slc.runtime.ProcessThread; /** Execution process implementation based on a JCR node. */ public class JcrExecutionProcess implements ExecutionProcess, SlcNames { diff --git a/org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrProcessThread.java b/org.argeo.slc.jcr/src/org/argeo/slc/jcr/execution/JcrProcessThread.java similarity index 98% rename from org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrProcessThread.java rename to org.argeo.slc.jcr/src/org/argeo/slc/jcr/execution/JcrProcessThread.java index a73e1a94a..56b97d02e 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrProcessThread.java +++ b/org.argeo.slc.jcr/src/org/argeo/slc/jcr/execution/JcrProcessThread.java @@ -25,10 +25,10 @@ import javax.jcr.Session; import org.argeo.jcr.JcrUtils; import org.argeo.slc.SlcException; import org.argeo.slc.SlcNames; -import org.argeo.slc.core.execution.ProcessThread; import org.argeo.slc.execution.ExecutionModulesManager; import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.execution.RealizedFlow; +import org.argeo.slc.runtime.ProcessThread; /** Where the actual execution takes place */ public class JcrProcessThread extends ProcessThread implements SlcNames { diff --git a/org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrRealizedFlow.java b/org.argeo.slc.jcr/src/org/argeo/slc/jcr/execution/JcrRealizedFlow.java similarity index 75% rename from org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrRealizedFlow.java rename to org.argeo.slc.jcr/src/org/argeo/slc/jcr/execution/JcrRealizedFlow.java index 5c8738b3f..e8f0145f0 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/jcr/execution/JcrRealizedFlow.java +++ b/org.argeo.slc.jcr/src/org/argeo/slc/jcr/execution/JcrRealizedFlow.java @@ -11,7 +11,6 @@ import javax.jcr.RepositoryException; import org.argeo.slc.SlcException; import org.argeo.slc.SlcNames; import org.argeo.slc.SlcTypes; -import org.argeo.slc.core.execution.DefaultExecutionSpec; import org.argeo.slc.execution.ExecutionFlowDescriptor; import org.argeo.slc.execution.ExecutionSpecAttribute; import org.argeo.slc.execution.RealizedFlow; @@ -19,6 +18,7 @@ import org.argeo.slc.execution.RefSpecAttribute; import org.argeo.slc.jcr.SlcJcrUtils; import org.argeo.slc.primitive.PrimitiveSpecAttribute; import org.argeo.slc.primitive.PrimitiveUtils; +import org.argeo.slc.runtime.DefaultExecutionSpec; public class JcrRealizedFlow extends RealizedFlow implements SlcNames { private static final long serialVersionUID = -3709453850260712001L; @@ -33,26 +33,20 @@ public class JcrRealizedFlow extends RealizedFlow implements SlcNames { } } - protected void loadFromNode(Node realizedFlowNode) - throws RepositoryException { + protected void loadFromNode(Node realizedFlowNode) throws RepositoryException { if (realizedFlowNode.hasNode(SLC_ADDRESS)) { - String flowPath = realizedFlowNode.getNode(SLC_ADDRESS) - .getProperty(Property.JCR_PATH).getString(); + String flowPath = realizedFlowNode.getNode(SLC_ADDRESS).getProperty(Property.JCR_PATH).getString(); // TODO: convert to local path if remote // FIXME start related module Node flowNode = realizedFlowNode.getSession().getNode(flowPath); String flowName = flowNode.getProperty(SLC_NAME).getString(); String description = null; if (flowNode.hasProperty(Property.JCR_DESCRIPTION)) - description = flowNode.getProperty(Property.JCR_DESCRIPTION) - .getString(); + description = flowNode.getProperty(Property.JCR_DESCRIPTION).getString(); - Node executionModuleNode = flowNode.getSession().getNode( - SlcJcrUtils.modulePath(flowPath)); - String executionModuleName = executionModuleNode.getProperty( - SLC_NAME).getString(); - String executionModuleVersion = executionModuleNode.getProperty( - SLC_VERSION).getString(); + Node executionModuleNode = flowNode.getSession().getNode(SlcJcrUtils.modulePath(flowPath)); + String executionModuleName = executionModuleNode.getProperty(SLC_NAME).getString(); + String executionModuleVersion = executionModuleNode.getProperty(SLC_VERSION).getString(); RealizedFlow realizedFlow = this; realizedFlow.setModuleName(executionModuleName); @@ -65,10 +59,8 @@ public class JcrRealizedFlow extends RealizedFlow implements SlcNames { // set execution spec name if (flowNode.hasProperty(SlcNames.SLC_SPEC)) { - Node executionSpecNode = flowNode.getProperty(SLC_SPEC) - .getNode(); - executionSpec.setBeanName(executionSpecNode.getProperty( - SLC_NAME).getString()); + Node executionSpecNode = flowNode.getProperty(SLC_SPEC).getNode(); + executionSpec.setName(executionSpecNode.getProperty(SLC_NAME).getString()); } // explicitly retrieve values @@ -79,41 +71,32 @@ public class JcrRealizedFlow extends RealizedFlow implements SlcNames { values.put(attrName, value); } - ExecutionFlowDescriptor efd = new ExecutionFlowDescriptor(flowName, - description, values, executionSpec); + ExecutionFlowDescriptor efd = new ExecutionFlowDescriptor(flowName, description, values, executionSpec); realizedFlow.setFlowDescriptor(efd); } else { - throw new SlcException("Unsupported realized flow " - + realizedFlowNode); + throw new SlcException("Unsupported realized flow " + realizedFlowNode); } } - protected Map readExecutionSpecAttributes( - Node node) { + protected Map readExecutionSpecAttributes(Node node) { try { Map attrs = new HashMap(); for (NodeIterator nit = node.getNodes(); nit.hasNext();) { Node specAttrNode = nit.nextNode(); - if (specAttrNode - .isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE)) { - String type = specAttrNode.getProperty(SLC_TYPE) - .getString(); + if (specAttrNode.isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE)) { + String type = specAttrNode.getProperty(SLC_TYPE).getString(); Object value = null; if (specAttrNode.hasProperty(SLC_VALUE)) { - String valueStr = specAttrNode.getProperty(SLC_VALUE) - .getString(); + String valueStr = specAttrNode.getProperty(SLC_VALUE).getString(); value = PrimitiveUtils.convert(type, valueStr); } - PrimitiveSpecAttribute specAttr = new PrimitiveSpecAttribute( - type, value); + PrimitiveSpecAttribute specAttr = new PrimitiveSpecAttribute(type, value); attrs.put(specAttrNode.getName(), specAttr); - } else if (specAttrNode - .isNodeType(SlcTypes.SLC_REF_SPEC_ATTRIBUTE)) { + } else if (specAttrNode.isNodeType(SlcTypes.SLC_REF_SPEC_ATTRIBUTE)) { if (!specAttrNode.hasProperty(SLC_VALUE)) { continue; } - Integer value = (int) specAttrNode.getProperty(SLC_VALUE) - .getLong(); + Integer value = (int) specAttrNode.getProperty(SLC_VALUE).getLong(); RefSpecAttribute specAttr = new RefSpecAttribute(); NodeIterator children = specAttrNode.getNodes(); int index = 0; @@ -132,8 +115,7 @@ public class JcrRealizedFlow extends RealizedFlow implements SlcNames { } return attrs; } catch (RepositoryException e) { - throw new SlcException("Cannot read spec attributes from " + node, - e); + throw new SlcException("Cannot read spec attributes from " + node, e); } } diff --git a/org.argeo.slc.runtime/.classpath b/org.argeo.slc.runtime/.classpath new file mode 100644 index 000000000..e801ebfb4 --- /dev/null +++ b/org.argeo.slc.runtime/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.argeo.slc.runtime/.gitignore b/org.argeo.slc.runtime/.gitignore new file mode 100644 index 000000000..09e3bc9b2 --- /dev/null +++ b/org.argeo.slc.runtime/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/target/ diff --git a/org.argeo.slc.runtime/.project b/org.argeo.slc.runtime/.project new file mode 100644 index 000000000..10ad5dafd --- /dev/null +++ b/org.argeo.slc.runtime/.project @@ -0,0 +1,28 @@ + + + org.argeo.slc.runtime + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.slc.runtime/META-INF/.gitignore b/org.argeo.slc.runtime/META-INF/.gitignore new file mode 100644 index 000000000..4854a41b9 --- /dev/null +++ b/org.argeo.slc.runtime/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/org.argeo.slc.runtime/bnd.bnd b/org.argeo.slc.runtime/bnd.bnd new file mode 100644 index 000000000..9384c2ac5 --- /dev/null +++ b/org.argeo.slc.runtime/bnd.bnd @@ -0,0 +1,2 @@ +Import-Package: org.argeo.slc.deploy,\ +* \ No newline at end of file diff --git a/org.argeo.slc.runtime/build.properties b/org.argeo.slc.runtime/build.properties new file mode 100644 index 000000000..34d2e4d2d --- /dev/null +++ b/org.argeo.slc.runtime/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/org.argeo.slc.runtime/pom.xml b/org.argeo.slc.runtime/pom.xml new file mode 100644 index 000000000..ac599097d --- /dev/null +++ b/org.argeo.slc.runtime/pom.xml @@ -0,0 +1,21 @@ + + 4.0.0 + + org.argeo.slc + argeo-slc + 2.1.17-SNAPSHOT + .. + + org.argeo.slc.runtime + SLC Runtime + + + + org.argeo.slc + org.argeo.slc.api + 2.1.17-SNAPSHOT + + + \ No newline at end of file diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/AbstractExecutionModulesManager.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/AbstractExecutionModulesManager.java similarity index 99% rename from org.argeo.slc.spring/src/org/argeo/slc/core/execution/AbstractExecutionModulesManager.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/AbstractExecutionModulesManager.java index 1d401c6b0..3b9da2a76 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/AbstractExecutionModulesManager.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/AbstractExecutionModulesManager.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.slc.core.execution; +package org.argeo.slc.runtime; import java.util.Map; diff --git a/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultAgent.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultAgent.java new file mode 100644 index 000000000..d9037fa4b --- /dev/null +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultAgent.java @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.slc.runtime; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URLDecoder; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.argeo.slc.DefaultNameVersion; +import org.argeo.slc.NameVersion; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionModuleDescriptor; +import org.argeo.slc.execution.ExecutionModulesManager; +import org.argeo.slc.execution.ExecutionProcess; +import org.argeo.slc.execution.SlcAgent; + +/** Implements the base methods of an SLC agent. */ +public class DefaultAgent implements SlcAgent { + // private final static Log log = LogFactory.getLog(DefaultAgent.class); + /** UTF-8 charset for encoding. */ + private final static String UTF8 = "UTF-8"; + + private String agentUuid = null; + private ExecutionModulesManager modulesManager; + + private ThreadGroup processesThreadGroup; + private Map runningProcesses = Collections + .synchronizedMap(new HashMap()); + + private String defaultModulePrefix = null; + + /* + * LIFECYCLE + */ + /** Initialization */ + public void init() { + agentUuid = initAgentUuid(); + processesThreadGroup = new ThreadGroup("SLC Processes of Agent #" + + agentUuid); + } + + /** Clean up (needs to be called by overriding method) */ + public void destroy() { + } + + /** + * Called during initialization in order to determines the agent UUID. To be + * overridden. By default creates a new one per instance. + */ + protected String initAgentUuid() { + return UUID.randomUUID().toString(); + } + + /* + * SLC AGENT + */ + public void process(ExecutionProcess process) { + ProcessThread processThread = createProcessThread(processesThreadGroup, + modulesManager, process); + processThread.start(); + runningProcesses.put(process.getUuid(), processThread); + + // clean up old processes + Iterator it = runningProcesses.values().iterator(); + while (it.hasNext()) { + ProcessThread pThread = it.next(); + if (!pThread.isAlive()) + it.remove(); + } + } + + public String process(List uris) { + DefaultProcess process = new DefaultProcess(); + for (URI uri : uris) { + String[] path = uri.getPath().split("/"); + if (path.length < 3) + throw new SlcException("Badly formatted URI: " + uri); + NameVersion nameVersion = new DefaultNameVersion(path[1]); + StringBuilder flow = new StringBuilder(); + for (int i = 2; i < path.length; i++) + flow.append('/').append(path[i]); + + Map values = getQueryMap(uri.getQuery()); + // Get execution module descriptor + ExecutionModuleDescriptor emd = getExecutionModuleDescriptor( + nameVersion.getName(), nameVersion.getVersion()); + process.getRealizedFlows().add( + emd.asRealizedFlow(flow.toString(), values)); + } + process(process); + return process.getUuid(); + } + + public void kill(String processUuid) { + if (runningProcesses.containsKey(processUuid)) { + runningProcesses.get(processUuid).interrupt(); + } else { + // assume is finished + } + } + + public void waitFor(String processUuid, Long millis) { + if (runningProcesses.containsKey(processUuid)) { + try { + if (millis != null) + runningProcesses.get(processUuid).join(millis); + else + runningProcesses.get(processUuid).join(); + } catch (InterruptedException e) { + // silent + } + } else { + // assume is finished + } + } + + /** Creates the thread which will coordinate the execution for this agent. */ + protected ProcessThread createProcessThread( + ThreadGroup processesThreadGroup, + ExecutionModulesManager modulesManager, ExecutionProcess process) { + ProcessThread processThread = new ProcessThread(processesThreadGroup, + modulesManager, process); + return processThread; + } + + public ExecutionModuleDescriptor getExecutionModuleDescriptor( + String moduleName, String moduleVersion) { + // Get execution module descriptor + ExecutionModuleDescriptor emd; + try { + modulesManager + .start(new DefaultNameVersion(moduleName, moduleVersion)); + emd = modulesManager.getExecutionModuleDescriptor(moduleName, + moduleVersion); + } catch (SlcException e) { + if (defaultModulePrefix != null) { + moduleName = defaultModulePrefix + "." + moduleName; + modulesManager.start(new DefaultNameVersion(moduleName, + moduleVersion)); + emd = modulesManager.getExecutionModuleDescriptor(moduleName, + moduleVersion); + } else + throw e; + } + return emd; + } + + public List listExecutionModuleDescriptors() { + return modulesManager.listExecutionModules(); + } + + public boolean ping() { + return true; + } + + /* + * UTILITIES + */ + /** + * @param query + * can be null + */ + static Map getQueryMap(String query) { + Map map = new LinkedHashMap(); + if (query == null) + return map; + String[] params = query.split("&"); + for (String param : params) { + String[] arr = param.split("="); + String name = arr[0]; + Object value = arr.length > 1 ? param.split("=")[1] : Boolean.TRUE; + try { + map.put(URLDecoder.decode(name, UTF8), + URLDecoder.decode(value.toString(), UTF8)); + } catch (UnsupportedEncodingException e) { + throw new SlcException("Cannot decode '" + param + "'", e); + } + } + return map; + } + + /* + * BEAN + */ + public void setModulesManager(ExecutionModulesManager modulesManager) { + this.modulesManager = modulesManager; + } + + public void setDefaultModulePrefix(String defaultModulePrefix) { + this.defaultModulePrefix = defaultModulePrefix; + } + + public String getAgentUuid() { + return agentUuid; + } + + @Override + public String toString() { + return "Agent #" + getAgentUuid(); + } +} diff --git a/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultAgentCli.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultAgentCli.java new file mode 100644 index 000000000..2e6d7f16b --- /dev/null +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultAgentCli.java @@ -0,0 +1,238 @@ +package org.argeo.slc.runtime; + +import java.net.URI; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.DefaultNameVersion; +import org.argeo.slc.NameVersion; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionFlowDescriptor; +import org.argeo.slc.execution.ExecutionModuleDescriptor; +import org.argeo.slc.execution.ExecutionSpec; +import org.argeo.slc.execution.ExecutionSpecAttribute; +import org.argeo.slc.execution.SlcAgent; +import org.argeo.slc.execution.SlcAgentCli; + +/** + * Authenticates thread and executes synchronously a command line execution. + * Reference implementation of args to URIs algorithm. + */ +public class DefaultAgentCli implements SlcAgentCli { + private final static Log log = LogFactory.getLog(DefaultAgentCli.class); + + private final static String UTF8 = "UTF-8"; + private SlcAgent agent; +// private AuthenticationManager authenticationManager; + + private Long timeout = 24 * 60 * 60 * 1000l; + + public String process(String[] args) { +// if (SecurityContextHolder.getContext().getAuthentication() == null) { +// OsAuthenticationToken oat = new OsAuthenticationToken(); +// Authentication authentication = authenticationManager +// .authenticate(oat); +// SecurityContextHolder.getContext() +// .setAuthentication(authentication); +// } + + if (args.length > 0 && args[0].equals("help")) { + StringBuilder buf = new StringBuilder(); + help(args, buf); + log.info("\n" + buf); + return buf.toString(); + } else { + List uris = asURIs(args); + String processUuid = agent.process(uris); + agent.waitFor(processUuid, timeout); + return processUuid; + } + } + + protected void help(String[] rawArgs, StringBuilder buf) { + String[] args = Arrays.copyOfRange(rawArgs, 1, rawArgs.length); + if (args.length == 0) {// modules + for (ExecutionModuleDescriptor emd : agent + .listExecutionModuleDescriptors()) { + appendModule(emd, buf); + } + } else if (args.length == 1 && !args[0].contains("/")) {// single module + NameVersion nameVersion = new DefaultNameVersion(args[0]); + ExecutionModuleDescriptor emd = agent.getExecutionModuleDescriptor( + nameVersion.getName(), nameVersion.getVersion()); + appendModule(emd, buf); + + // flows + for (ExecutionFlowDescriptor efd : emd.getExecutionFlows()) { + buf.append(" ").append(efd.getName()); + if (efd.getDescription() != null + && !efd.getDescription().trim().equals("")) + buf.append(" : ").append(" ").append(efd.getDescription()); + buf.append('\n'); + } + return; + } else { + List uris = asURIs(args); + for (URI uri : uris) { + appendUriHelp(uri, buf); + } + } + } + + protected void appendUriHelp(URI uri, StringBuilder buf) { + String[] path = uri.getPath().split("/"); + NameVersion nameVersion = new DefaultNameVersion(path[1]); + ExecutionModuleDescriptor emd = agent.getExecutionModuleDescriptor( + nameVersion.getName(), nameVersion.getVersion()); + + StringBuilder flow = new StringBuilder(); + for (int i = 2; i < path.length; i++) + flow.append('/').append(path[i]); + String flowPath = flow.toString(); + ExecutionFlowDescriptor efd = findExecutionFlowDescriptor(emd, flowPath); + if (efd == null) + throw new SlcException("Flow " + uri + " not found"); + + appendModule(emd, buf); + + buf.append(" ").append(efd.getName()); + if (efd.getDescription() != null + && !efd.getDescription().trim().equals("")) + buf.append(" : ").append(" ").append(efd.getDescription()); + buf.append('\n'); + Map values = DefaultAgent.getQueryMap(uri.getQuery()); + ExecutionSpec spec = efd.getExecutionSpec(); + for (String attrKey : spec.getAttributes().keySet()) { + ExecutionSpecAttribute esa = spec.getAttributes().get(attrKey); + buf.append(" --").append(attrKey); + if (values.containsKey(attrKey)) + buf.append(" ").append(values.get(attrKey)); + if (esa.getValue() != null) + buf.append(" (").append(esa.getValue()).append(')'); + buf.append('\n'); + } + } + + private void appendModule(ExecutionModuleDescriptor emd, StringBuilder buf) { + buf.append("# ").append(emd.getName()); + if (emd.getDescription() != null + && !emd.getDescription().trim().equals("")) + buf.append(" : ").append(emd.getDescription()); + if (emd.getVersion() != null) + buf.append(" (v").append(emd.getVersion()).append(")"); + buf.append('\n'); + } + + public static List asURIs(String[] args) { + try { + List uris = new ArrayList(); + List leftOvers = new ArrayList(); + + Boolean hasArgs = false; + String currKey = null; + StringBuilder currUri = null; + Iterator argIt = Arrays.asList(args).iterator(); + while (argIt.hasNext()) { + String arg = argIt.next(); + if (!arg.startsWith("-")) { + if (currKey != null) {// value + currUri.append(URLEncoder.encode(arg, UTF8)); + currKey = null; + } else { // module + if (currUri != null) { + uris.add(new URI(currUri.toString())); + } + currUri = new StringBuilder("flow:"); + + String currModule = arg; + currUri.append('/').append(currModule); + if (!arg.contains("/")) { + // flow path not in arg go to next arg + if (!argIt.hasNext()) + throw new SlcException("No flow found"); + String currFlow = argIt.next(); + if (!currFlow.startsWith("/")) + currFlow = "/" + currFlow; + currUri.append(currFlow); + } + } + } else { + if (currUri == null) {// first args + leftOvers.add(arg); + } else { + String key; + if (arg.startsWith("--")) + key = arg.substring(2); + else if (arg.startsWith("-")) + key = arg.substring(1); + else { + throw new SlcException("Cannot intepret key: " + + arg); + } + + if (!hasArgs) { + currUri.append('?'); + hasArgs = true; + } else { + currUri.append('&'); + } + + // deal with boolean keys + if (currKey != null) {// value + currUri.append(URLEncoder.encode("true", UTF8)); + currKey = null; + } + + currKey = key; + currUri.append(URLEncoder.encode(key, UTF8)) + .append('='); + } + } + } + if (currUri != null) + uris.add(new URI(currUri.toString())); + return uris; + } catch (Exception e) { + throw new SlcException("Cannot convert " + Arrays.toString(args) + + " to flow URI", e); + } + } + + private ExecutionFlowDescriptor findExecutionFlowDescriptor( + ExecutionModuleDescriptor emd, String flowPath) { + ExecutionFlowDescriptor flowDescriptor = null; + for (ExecutionFlowDescriptor efd : emd.getExecutionFlows()) { + String name = efd.getName(); + // normalize name as flow path + if (!name.startsWith("/")) + name = "/" + name; + if (name.endsWith("/")) + name = name.substring(0, name.length() - 1); + if (name.equals(flowPath)) { + flowDescriptor = efd; + break; + } + } + return flowDescriptor; + } + + public void setAgent(SlcAgent agent) { + this.agent = agent; + } + +// public void setAuthenticationManager( +// AuthenticationManager authenticationManager) { +// this.authenticationManager = authenticationManager; +// } + + public void setTimeout(Long timeout) { + this.timeout = timeout; + } + +} diff --git a/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultExecutionFlow.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultExecutionFlow.java new file mode 100644 index 000000000..289f660e1 --- /dev/null +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultExecutionFlow.java @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.slc.runtime; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionContext; +import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.execution.ExecutionSpec; +import org.argeo.slc.execution.ExecutionSpecAttribute; + +/** Default implementation of an execution flow. */ +public class DefaultExecutionFlow implements ExecutionFlow { + private final static Log log = LogFactory.getLog(DefaultExecutionFlow.class); + + private final ExecutionSpec executionSpec; + private String name = null; + private Map parameters = new HashMap(); + private List executables = new ArrayList(); + + private String path; + + private Boolean failOnError = true; + + // Only needed if stacked execution flows are used + private ExecutionContext executionContext = null; + + public DefaultExecutionFlow() { + this.executionSpec = new DefaultExecutionSpec(); + } + + public DefaultExecutionFlow(ExecutionSpec executionSpec) { + this.executionSpec = executionSpec; + } + + public DefaultExecutionFlow(ExecutionSpec executionSpec, Map parameters) { + // be sure to have an execution spec + this.executionSpec = (executionSpec == null) ? new DefaultExecutionSpec() : executionSpec; + + // only parameters contained in the executionSpec can be set + for (String parameter : parameters.keySet()) { + if (!executionSpec.getAttributes().containsKey(parameter)) { + throw new SlcException("Parameter " + parameter + " is not defined in the ExecutionSpec"); + } + } + + // set the parameters + this.parameters.putAll(parameters); + + // check that all the required parameters are defined +// MapBindingResult errors = new MapBindingResult(parameters, "execution#" +// + getName()); + Map errors = new HashMap<>(); + for (String key : executionSpec.getAttributes().keySet()) { + ExecutionSpecAttribute attr = executionSpec.getAttributes().get(key); + + if (attr.getIsImmutable() && !isSetAsParameter(key)) { + errors.put(key, "Immutable but not set"); + break; + } + + if (attr.getIsConstant() && !isSetAsParameter(key)) { + errors.put(key, "Constant but not set as parameter"); + break; + } + + if (attr.getIsHidden() && !isSetAsParameter(key)) { + errors.put(key, "Hidden but not set as parameter"); + break; + } + } + + if (!errors.isEmpty()) + throw new SlcException("Could not prepare execution flow: " + errors.toString()); + + } + + public void run() { + try { + for (Runnable executable : executables) { + if (Thread.interrupted()) { + log.error("Flow '" + getName() + "' killed before '" + executable + "'"); + Thread.currentThread().interrupt(); + return; + // throw new ThreadDeath(); + } + this.doExecuteRunnable(executable); + } + } catch (RuntimeException e) { + if (Thread.interrupted()) { + log.error("Flow '" + getName() + "' killed while receiving an unrelated exception", e); + Thread.currentThread().interrupt(); + return; + // throw new ThreadDeath(); + } + if (failOnError) + throw e; + else { + log.error("Execution flow failed," + " but process did not fail" + " because failOnError property" + + " is set to false: " + e); + if (log.isTraceEnabled()) + e.printStackTrace(); + } + } + } + + /** + * List sub-runnables that would be executed if run() method would be called. + */ + public Iterator runnables() { + return executables.iterator(); + } + + /** + * If there is one and only one runnable wrapped return it, throw an exeception + * otherwise. + */ + public Runnable getRunnable() { + if (executables.size() == 1) + return executables.get(0); + else + throw new SlcException("There are " + executables.size() + " runnables in flow " + getName()); + } + + public void doExecuteRunnable(Runnable runnable) { + try { + if (executionContext != null) + if (runnable instanceof ExecutionFlow) + executionContext.beforeFlow((ExecutionFlow) runnable); + runnable.run(); + } finally { + if (executionContext != null) + if (runnable instanceof ExecutionFlow) + executionContext.afterFlow((ExecutionFlow) runnable); + } + } + + public void init() throws Exception { + if (path == null) { + if (name.charAt(0) == '/') { + path = name.substring(0, name.lastIndexOf('/')); + } + } + + if (path != null) { + for (Runnable executable : executables) { + if (executable instanceof DefaultExecutionFlow) { + // so we don't need to have DefaultExecutionFlow + // implementing StructureAware + // FIXME: probably has side effects + DefaultExecutionFlow flow = (DefaultExecutionFlow) executable; + String newPath = path + '/' + flow.getName(); + flow.setPath(newPath); + log.warn(newPath + " was forcibly set on " + flow); + } + } + } + } + + public void setName(String name) { + this.name = name; + } + + public void setExecutables(List executables) { + this.executables = executables; + } + + public void setParameters(Map attributes) { + this.parameters = attributes; + } + + public String getName() { + return name; + } + + public ExecutionSpec getExecutionSpec() { + return executionSpec; + } + + public Object getParameter(String parameterName) { + // Verify that there is a spec attribute + ExecutionSpecAttribute specAttr = null; + if (executionSpec.getAttributes().containsKey(parameterName)) { + specAttr = executionSpec.getAttributes().get(parameterName); + } else { + throw new SlcException("Key " + parameterName + " is not defined in the specifications of " + toString()); + } + + if (parameters.containsKey(parameterName)) { + Object paramValue = parameters.get(parameterName); + return paramValue; + } else { + if (specAttr.getValue() != null) { + return specAttr.getValue(); + } + } + throw new SlcException("Key " + parameterName + " is not set as parameter in " + toString()); + } + + public Boolean isSetAsParameter(String key) { + return parameters.containsKey(key) || (executionSpec.getAttributes().containsKey(key) + && executionSpec.getAttributes().get(key).getValue() != null); + } + + @Override + public String toString() { + return new StringBuffer("Execution flow ").append(name).toString(); + } + + @Override + public boolean equals(Object obj) { + return ((ExecutionFlow) obj).getName().equals(name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public Boolean getFailOnError() { + return failOnError; + } + + public void setFailOnError(Boolean failOnError) { + this.failOnError = failOnError; + } + + public void setExecutionContext(ExecutionContext executionContext) { + this.executionContext = executionContext; + } + +} diff --git a/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultExecutionSpec.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultExecutionSpec.java new file mode 100644 index 000000000..6fc001caa --- /dev/null +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultExecutionSpec.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.slc.runtime; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.argeo.slc.execution.ExecutionSpec; +import org.argeo.slc.execution.ExecutionSpecAttribute; +import org.argeo.slc.execution.RefSpecAttribute; +import org.argeo.slc.execution.RefValueChoice; + +/** Spring based implementation of execution specifications. */ +public class DefaultExecutionSpec implements ExecutionSpec, Serializable { + private static final long serialVersionUID = 7042162759380893595L; + private String description; + private Map attributes = new HashMap(); + + private String name = INTERNAL_NAME; + + public Map getAttributes() { + return attributes; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setAttributes(Map attributes) { + this.attributes = attributes; + } + + public void setName(String name) { + this.name = name; + } + + /** + * The Spring bean name (only relevant for specs declared has high-level beans) + */ + public String getName() { + return name; + } + + public boolean equals(Object obj) { + return ((ExecutionSpec) obj).getName().equals(name); + } + + /** + * The Spring bean description (only relevant for specs declared has high-level + * beans) + */ + public String getDescription() { + return description; + } + + /** + * Generates a list of ref value choices based on the bean available in the + * application ocntext. + */ + protected List buildRefValueChoices(RefSpecAttribute rsa) { + List choices = new ArrayList(); + // FIXME implement something + return choices; + } + +} diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionStack.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultExecutionStack.java similarity index 99% rename from org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionStack.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultExecutionStack.java index d1d06c698..4939e3243 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionStack.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultExecutionStack.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.slc.core.execution; +package org.argeo.slc.runtime; import java.util.HashMap; import java.util.Map; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultProcess.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultProcess.java similarity index 96% rename from org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultProcess.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultProcess.java index 30211800f..9e98685dd 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultProcess.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/DefaultProcess.java @@ -1,4 +1,4 @@ -package org.argeo.slc.core.execution; +package org.argeo.slc.runtime; import java.util.ArrayList; import java.util.List; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ExecutionThread.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/ExecutionThread.java similarity index 96% rename from org.argeo.slc.spring/src/org/argeo/slc/core/execution/ExecutionThread.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/ExecutionThread.java index 31e952d4a..8d95f495b 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ExecutionThread.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/ExecutionThread.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.slc.core.execution; +package org.argeo.slc.runtime; import java.security.AccessControlContext; import java.security.AccessController; @@ -26,10 +26,10 @@ import javax.security.auth.Subject; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; import org.argeo.slc.execution.ExecutionFlowDescriptor; import org.argeo.slc.execution.ExecutionModulesManager; import org.argeo.slc.execution.ExecutionStep; +import org.argeo.slc.execution.FlowConfigurationException; import org.argeo.slc.execution.RealizedFlow; /** Thread of a single execution */ @@ -121,7 +121,7 @@ public class ExecutionThread extends Thread { * Gather object destruction callback to be called in reverse order at the * end of the thread */ - synchronized void registerDestructionCallback(String name, Runnable callback) { + public synchronized void registerDestructionCallback(String name, Runnable callback) { destructionCallbacks.add(callback); } diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/InstantiationManager.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/InstantiationManager.java similarity index 95% rename from org.argeo.slc.spring/src/org/argeo/slc/core/execution/InstantiationManager.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/InstantiationManager.java index 211fc4cf9..0571e8307 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/InstantiationManager.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/InstantiationManager.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.slc.core.execution; +package org.argeo.slc.runtime; import java.util.Stack; @@ -47,7 +47,7 @@ public class InstantiationManager { public void flowInitializationStarted(ExecutionFlow flow, String flowName) { // set the flow name if it is DefaultExecutionFlow if (flow instanceof DefaultExecutionFlow) { - ((DefaultExecutionFlow) flow).setBeanName(flowName); + ((DefaultExecutionFlow) flow).setName(flowName); } if (log.isTraceEnabled()) diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ProcessThread.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/ProcessThread.java similarity index 99% rename from org.argeo.slc.spring/src/org/argeo/slc/core/execution/ProcessThread.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/ProcessThread.java index 926789677..10630687f 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ProcessThread.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/ProcessThread.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.slc.core.execution; +package org.argeo.slc.runtime; import java.security.AccessControlContext; import java.security.AccessController; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ProcessThreadGroup.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/ProcessThreadGroup.java similarity index 98% rename from org.argeo.slc.spring/src/org/argeo/slc/core/execution/ProcessThreadGroup.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/ProcessThreadGroup.java index 17dbff83b..6c25ecfa4 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ProcessThreadGroup.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/ProcessThreadGroup.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.slc.core.execution; +package org.argeo.slc.runtime; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultAgent.java b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultAgent.java index c692820e7..d07643414 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultAgent.java +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultAgent.java @@ -15,207 +15,12 @@ */ package org.argeo.slc.core.execution; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URLDecoder; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.argeo.slc.DefaultNameVersion; -import org.argeo.slc.NameVersion; -import org.argeo.slc.SlcException; -import org.argeo.slc.execution.ExecutionModuleDescriptor; -import org.argeo.slc.execution.ExecutionModulesManager; -import org.argeo.slc.execution.ExecutionProcess; -import org.argeo.slc.execution.SlcAgent; - /** Implements the base methods of an SLC agent. */ -public class DefaultAgent implements SlcAgent { - // private final static Log log = LogFactory.getLog(DefaultAgent.class); - /** UTF-8 charset for encoding. */ - private final static String UTF8 = "UTF-8"; - - private String agentUuid = null; - private ExecutionModulesManager modulesManager; - - private ThreadGroup processesThreadGroup; - private Map runningProcesses = Collections - .synchronizedMap(new HashMap()); - - private String defaultModulePrefix = null; - - /* - * LIFECYCLE - */ - /** Initialization */ - public void init() { - agentUuid = initAgentUuid(); - processesThreadGroup = new ThreadGroup("SLC Processes of Agent #" - + agentUuid); - } - - /** Clean up (needs to be called by overriding method) */ - public void destroy() { - } - - /** - * Called during initialization in order to determines the agent UUID. To be - * overridden. By default creates a new one per instance. - */ - protected String initAgentUuid() { - return UUID.randomUUID().toString(); - } - - /* - * SLC AGENT - */ - public void process(ExecutionProcess process) { - ProcessThread processThread = createProcessThread(processesThreadGroup, - modulesManager, process); - processThread.start(); - runningProcesses.put(process.getUuid(), processThread); - - // clean up old processes - Iterator it = runningProcesses.values().iterator(); - while (it.hasNext()) { - ProcessThread pThread = it.next(); - if (!pThread.isAlive()) - it.remove(); - } - } - - public String process(List uris) { - DefaultProcess process = new DefaultProcess(); - for (URI uri : uris) { - String[] path = uri.getPath().split("/"); - if (path.length < 3) - throw new SlcException("Badly formatted URI: " + uri); - NameVersion nameVersion = new DefaultNameVersion(path[1]); - StringBuilder flow = new StringBuilder(); - for (int i = 2; i < path.length; i++) - flow.append('/').append(path[i]); - - Map values = getQueryMap(uri.getQuery()); - // Get execution module descriptor - ExecutionModuleDescriptor emd = getExecutionModuleDescriptor( - nameVersion.getName(), nameVersion.getVersion()); - process.getRealizedFlows().add( - emd.asRealizedFlow(flow.toString(), values)); - } - process(process); - return process.getUuid(); - } - - public void kill(String processUuid) { - if (runningProcesses.containsKey(processUuid)) { - runningProcesses.get(processUuid).interrupt(); - } else { - // assume is finished - } - } - - public void waitFor(String processUuid, Long millis) { - if (runningProcesses.containsKey(processUuid)) { - try { - if (millis != null) - runningProcesses.get(processUuid).join(millis); - else - runningProcesses.get(processUuid).join(); - } catch (InterruptedException e) { - // silent - } - } else { - // assume is finished - } - } - - /** Creates the thread which will coordinate the execution for this agent. */ - protected ProcessThread createProcessThread( - ThreadGroup processesThreadGroup, - ExecutionModulesManager modulesManager, ExecutionProcess process) { - ProcessThread processThread = new ProcessThread(processesThreadGroup, - modulesManager, process); - return processThread; - } - - public ExecutionModuleDescriptor getExecutionModuleDescriptor( - String moduleName, String moduleVersion) { - // Get execution module descriptor - ExecutionModuleDescriptor emd; - try { - modulesManager - .start(new DefaultNameVersion(moduleName, moduleVersion)); - emd = modulesManager.getExecutionModuleDescriptor(moduleName, - moduleVersion); - } catch (SlcException e) { - if (defaultModulePrefix != null) { - moduleName = defaultModulePrefix + "." + moduleName; - modulesManager.start(new DefaultNameVersion(moduleName, - moduleVersion)); - emd = modulesManager.getExecutionModuleDescriptor(moduleName, - moduleVersion); - } else - throw e; - } - return emd; - } - - public List listExecutionModuleDescriptors() { - return modulesManager.listExecutionModules(); - } +@Deprecated +public class DefaultAgent extends org.argeo.slc.runtime.DefaultAgent { - public boolean ping() { - return true; + public DefaultAgent() { + super(); } - /* - * UTILITIES - */ - /** - * @param query - * can be null - */ - static Map getQueryMap(String query) { - Map map = new LinkedHashMap(); - if (query == null) - return map; - String[] params = query.split("&"); - for (String param : params) { - String[] arr = param.split("="); - String name = arr[0]; - Object value = arr.length > 1 ? param.split("=")[1] : Boolean.TRUE; - try { - map.put(URLDecoder.decode(name, UTF8), - URLDecoder.decode(value.toString(), UTF8)); - } catch (UnsupportedEncodingException e) { - throw new SlcException("Cannot decode '" + param + "'", e); - } - } - return map; - } - - /* - * BEAN - */ - public void setModulesManager(ExecutionModulesManager modulesManager) { - this.modulesManager = modulesManager; - } - - public void setDefaultModulePrefix(String defaultModulePrefix) { - this.defaultModulePrefix = defaultModulePrefix; - } - - public String getAgentUuid() { - return agentUuid; - } - - @Override - public String toString() { - return "Agent #" + getAgentUuid(); - } } diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultAgentCli.java b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultAgentCli.java index e02d50f2f..8e0ccd12d 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultAgentCli.java +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultAgentCli.java @@ -1,238 +1,13 @@ package org.argeo.slc.core.execution; -import java.net.URI; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.DefaultNameVersion; -import org.argeo.slc.NameVersion; -import org.argeo.slc.SlcException; -import org.argeo.slc.execution.ExecutionFlowDescriptor; -import org.argeo.slc.execution.ExecutionModuleDescriptor; -import org.argeo.slc.execution.ExecutionSpec; -import org.argeo.slc.execution.ExecutionSpecAttribute; -import org.argeo.slc.execution.SlcAgent; -import org.argeo.slc.execution.SlcAgentCli; - /** * Authenticates thread and executes synchronously a command line execution. * Reference implementation of args to URIs algorithm. */ -public class DefaultAgentCli implements SlcAgentCli { - private final static Log log = LogFactory.getLog(DefaultAgentCli.class); - - private final static String UTF8 = "UTF-8"; - private SlcAgent agent; -// private AuthenticationManager authenticationManager; - - private Long timeout = 24 * 60 * 60 * 1000l; - - public String process(String[] args) { -// if (SecurityContextHolder.getContext().getAuthentication() == null) { -// OsAuthenticationToken oat = new OsAuthenticationToken(); -// Authentication authentication = authenticationManager -// .authenticate(oat); -// SecurityContextHolder.getContext() -// .setAuthentication(authentication); -// } - - if (args.length > 0 && args[0].equals("help")) { - StringBuilder buf = new StringBuilder(); - help(args, buf); - log.info("\n" + buf); - return buf.toString(); - } else { - List uris = asURIs(args); - String processUuid = agent.process(uris); - agent.waitFor(processUuid, timeout); - return processUuid; - } - } - - protected void help(String[] rawArgs, StringBuilder buf) { - String[] args = Arrays.copyOfRange(rawArgs, 1, rawArgs.length); - if (args.length == 0) {// modules - for (ExecutionModuleDescriptor emd : agent - .listExecutionModuleDescriptors()) { - appendModule(emd, buf); - } - } else if (args.length == 1 && !args[0].contains("/")) {// single module - NameVersion nameVersion = new DefaultNameVersion(args[0]); - ExecutionModuleDescriptor emd = agent.getExecutionModuleDescriptor( - nameVersion.getName(), nameVersion.getVersion()); - appendModule(emd, buf); - - // flows - for (ExecutionFlowDescriptor efd : emd.getExecutionFlows()) { - buf.append(" ").append(efd.getName()); - if (efd.getDescription() != null - && !efd.getDescription().trim().equals("")) - buf.append(" : ").append(" ").append(efd.getDescription()); - buf.append('\n'); - } - return; - } else { - List uris = asURIs(args); - for (URI uri : uris) { - appendUriHelp(uri, buf); - } - } - } - - protected void appendUriHelp(URI uri, StringBuilder buf) { - String[] path = uri.getPath().split("/"); - NameVersion nameVersion = new DefaultNameVersion(path[1]); - ExecutionModuleDescriptor emd = agent.getExecutionModuleDescriptor( - nameVersion.getName(), nameVersion.getVersion()); - - StringBuilder flow = new StringBuilder(); - for (int i = 2; i < path.length; i++) - flow.append('/').append(path[i]); - String flowPath = flow.toString(); - ExecutionFlowDescriptor efd = findExecutionFlowDescriptor(emd, flowPath); - if (efd == null) - throw new SlcException("Flow " + uri + " not found"); - - appendModule(emd, buf); - - buf.append(" ").append(efd.getName()); - if (efd.getDescription() != null - && !efd.getDescription().trim().equals("")) - buf.append(" : ").append(" ").append(efd.getDescription()); - buf.append('\n'); - Map values = DefaultAgent.getQueryMap(uri.getQuery()); - ExecutionSpec spec = efd.getExecutionSpec(); - for (String attrKey : spec.getAttributes().keySet()) { - ExecutionSpecAttribute esa = spec.getAttributes().get(attrKey); - buf.append(" --").append(attrKey); - if (values.containsKey(attrKey)) - buf.append(" ").append(values.get(attrKey)); - if (esa.getValue() != null) - buf.append(" (").append(esa.getValue()).append(')'); - buf.append('\n'); - } - } +@Deprecated +public class DefaultAgentCli extends org.argeo.slc.runtime.DefaultAgentCli { - private void appendModule(ExecutionModuleDescriptor emd, StringBuilder buf) { - buf.append("# ").append(emd.getName()); - if (emd.getDescription() != null - && !emd.getDescription().trim().equals("")) - buf.append(" : ").append(emd.getDescription()); - if (emd.getVersion() != null) - buf.append(" (v").append(emd.getVersion()).append(")"); - buf.append('\n'); + public DefaultAgentCli() { + super(); } - - public static List asURIs(String[] args) { - try { - List uris = new ArrayList(); - List leftOvers = new ArrayList(); - - Boolean hasArgs = false; - String currKey = null; - StringBuilder currUri = null; - Iterator argIt = Arrays.asList(args).iterator(); - while (argIt.hasNext()) { - String arg = argIt.next(); - if (!arg.startsWith("-")) { - if (currKey != null) {// value - currUri.append(URLEncoder.encode(arg, UTF8)); - currKey = null; - } else { // module - if (currUri != null) { - uris.add(new URI(currUri.toString())); - } - currUri = new StringBuilder("flow:"); - - String currModule = arg; - currUri.append('/').append(currModule); - if (!arg.contains("/")) { - // flow path not in arg go to next arg - if (!argIt.hasNext()) - throw new SlcException("No flow found"); - String currFlow = argIt.next(); - if (!currFlow.startsWith("/")) - currFlow = "/" + currFlow; - currUri.append(currFlow); - } - } - } else { - if (currUri == null) {// first args - leftOvers.add(arg); - } else { - String key; - if (arg.startsWith("--")) - key = arg.substring(2); - else if (arg.startsWith("-")) - key = arg.substring(1); - else { - throw new SlcException("Cannot intepret key: " - + arg); - } - - if (!hasArgs) { - currUri.append('?'); - hasArgs = true; - } else { - currUri.append('&'); - } - - // deal with boolean keys - if (currKey != null) {// value - currUri.append(URLEncoder.encode("true", UTF8)); - currKey = null; - } - - currKey = key; - currUri.append(URLEncoder.encode(key, UTF8)) - .append('='); - } - } - } - if (currUri != null) - uris.add(new URI(currUri.toString())); - return uris; - } catch (Exception e) { - throw new SlcException("Cannot convert " + Arrays.toString(args) - + " to flow URI", e); - } - } - - private ExecutionFlowDescriptor findExecutionFlowDescriptor( - ExecutionModuleDescriptor emd, String flowPath) { - ExecutionFlowDescriptor flowDescriptor = null; - for (ExecutionFlowDescriptor efd : emd.getExecutionFlows()) { - String name = efd.getName(); - // normalize name as flow path - if (!name.startsWith("/")) - name = "/" + name; - if (name.endsWith("/")) - name = name.substring(0, name.length() - 1); - if (name.equals(flowPath)) { - flowDescriptor = efd; - break; - } - } - return flowDescriptor; - } - - public void setAgent(SlcAgent agent) { - this.agent = agent; - } - -// public void setAuthenticationManager( -// AuthenticationManager authenticationManager) { -// this.authenticationManager = authenticationManager; -// } - - public void setTimeout(Long timeout) { - this.timeout = timeout; - } - } diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionFlow.java b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionFlow.java index bebde7512..a555906cd 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionFlow.java +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionFlow.java @@ -15,264 +15,33 @@ */ package org.argeo.slc.core.execution; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; import java.util.Map; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.argeo.slc.execution.ExecutionContext; -import org.argeo.slc.execution.ExecutionFlow; import org.argeo.slc.execution.ExecutionSpec; -import org.argeo.slc.execution.ExecutionSpecAttribute; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.InitializingBean; -import org.springframework.validation.MapBindingResult; /** Default implementation of an execution flow. */ -public class DefaultExecutionFlow implements ExecutionFlow, InitializingBean, - BeanNameAware { - private final static Log log = LogFactory - .getLog(DefaultExecutionFlow.class); - - private final ExecutionSpec executionSpec; - private String name = null; - private Map parameters = new HashMap(); - private List executables = new ArrayList(); - - private String path; - - private Boolean failOnError = true; - - // Only needed if stacked execution flows are used - private ExecutionContext executionContext = null; - +@Deprecated +public class DefaultExecutionFlow extends org.argeo.slc.runtime.DefaultExecutionFlow + implements InitializingBean, BeanNameAware { public DefaultExecutionFlow() { - this.executionSpec = new DefaultExecutionSpec(); + super(); } - public DefaultExecutionFlow(ExecutionSpec executionSpec) { - this.executionSpec = executionSpec; + public DefaultExecutionFlow(ExecutionSpec executionSpec, Map parameters) { + super(executionSpec, parameters); } - public DefaultExecutionFlow(ExecutionSpec executionSpec, - Map parameters) { - // be sure to have an execution spec - this.executionSpec = (executionSpec == null) ? new DefaultExecutionSpec() - : executionSpec; - - // only parameters contained in the executionSpec can be set - for (String parameter : parameters.keySet()) { - if (!executionSpec.getAttributes().containsKey(parameter)) { - throw new SlcException("Parameter " + parameter - + " is not defined in the ExecutionSpec"); - } - } - - // set the parameters - this.parameters.putAll(parameters); - - // check that all the required parameters are defined - MapBindingResult errors = new MapBindingResult(parameters, "execution#" - + getName()); - for (String key : executionSpec.getAttributes().keySet()) { - ExecutionSpecAttribute attr = executionSpec.getAttributes() - .get(key); - - if (attr.getIsImmutable() && !isSetAsParameter(key)) { - errors.rejectValue(key, "Immutable but not set"); - break; - } - - if (attr.getIsConstant() && !isSetAsParameter(key)) { - errors.rejectValue(key, "Constant but not set as parameter"); - break; - } - - if (attr.getIsHidden() && !isSetAsParameter(key)) { - errors.rejectValue(key, "Hidden but not set as parameter"); - break; - } - } - - if (errors.hasErrors()) - throw new SlcException("Could not prepare execution flow: " - + errors.toString()); - - } - - public void run() { - try { - for (Runnable executable : executables) { - if (Thread.interrupted()) { - log.error("Flow '" + getName() + "' killed before '" - + executable + "'"); - Thread.currentThread().interrupt(); - return; - // throw new ThreadDeath(); - } - this.doExecuteRunnable(executable); - } - } catch (RuntimeException e) { - if (Thread.interrupted()) { - log.error("Flow '" + getName() - + "' killed while receiving an unrelated exception", e); - Thread.currentThread().interrupt(); - return; - // throw new ThreadDeath(); - } - if (failOnError) - throw e; - else { - log.error("Execution flow failed," - + " but process did not fail" - + " because failOnError property" - + " is set to false: " + e); - if (log.isTraceEnabled()) - e.printStackTrace(); - } - } - } - - /** - * List sub-runnables that would be executed if run() method would be - * called. - */ - public Iterator runnables() { - return executables.iterator(); - } - - /** - * If there is one and only one runnable wrapped return it, throw an - * exeception otherwise. - */ - public Runnable getRunnable() { - if (executables.size() == 1) - return executables.get(0); - else - throw new SlcException("There are " + executables.size() - + " runnables in flow " + getName()); - } - - public void doExecuteRunnable(Runnable runnable) { - try { - if (executionContext != null) - if (runnable instanceof ExecutionFlow) - executionContext.beforeFlow((ExecutionFlow) runnable); - runnable.run(); - } finally { - if (executionContext != null) - if (runnable instanceof ExecutionFlow) - executionContext.afterFlow((ExecutionFlow) runnable); - } + public DefaultExecutionFlow(ExecutionSpec executionSpec) { + super(executionSpec); } public void afterPropertiesSet() throws Exception { - if (path == null) { - if (name.charAt(0) == '/') { - path = name.substring(0, name.lastIndexOf('/')); - } - } - - if (path != null) { - for (Runnable executable : executables) { - if (executable instanceof DefaultExecutionFlow) { - // so we don't need to have DefaultExecutionFlow - // implementing StructureAware - // FIXME: probably has side effects - DefaultExecutionFlow flow = (DefaultExecutionFlow) executable; - String newPath = path + '/' + flow.getName(); - flow.setPath(newPath); - log.warn(newPath + " was forcibly set on " + flow); - } - } - } + init(); } public void setBeanName(String name) { - this.name = name; - } - - public void setExecutables(List executables) { - this.executables = executables; - } - - public void setParameters(Map attributes) { - this.parameters = attributes; - } - - public String getName() { - return name; - } - - public ExecutionSpec getExecutionSpec() { - return executionSpec; - } - - public Object getParameter(String parameterName) { - // Verify that there is a spec attribute - ExecutionSpecAttribute specAttr = null; - if (executionSpec.getAttributes().containsKey(parameterName)) { - specAttr = executionSpec.getAttributes().get(parameterName); - } else { - throw new SlcException("Key " + parameterName - + " is not defined in the specifications of " + toString()); - } - - if (parameters.containsKey(parameterName)) { - Object paramValue = parameters.get(parameterName); - return paramValue; - } else { - if (specAttr.getValue() != null) { - return specAttr.getValue(); - } - } - throw new SlcException("Key " + parameterName - + " is not set as parameter in " + toString()); - } - - public Boolean isSetAsParameter(String key) { - return parameters.containsKey(key) - || (executionSpec.getAttributes().containsKey(key) && executionSpec - .getAttributes().get(key).getValue() != null); - } - - @Override - public String toString() { - return new StringBuffer("Execution flow ").append(name).toString(); - } - - @Override - public boolean equals(Object obj) { - return ((ExecutionFlow) obj).getName().equals(name); + setName(name); } - - @Override - public int hashCode() { - return name.hashCode(); - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public Boolean getFailOnError() { - return failOnError; - } - - public void setFailOnError(Boolean failOnError) { - this.failOnError = failOnError; - } - - public void setExecutionContext(ExecutionContext executionContext) { - this.executionContext = executionContext; - } - } diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java index 41a2f27e9..9fe48f71c 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java @@ -30,6 +30,7 @@ import org.argeo.slc.execution.ExecutionFlowDescriptorConverter; import org.argeo.slc.execution.ExecutionModuleDescriptor; import org.argeo.slc.execution.ExecutionSpec; import org.argeo.slc.execution.ExecutionSpecAttribute; +import org.argeo.slc.execution.FlowConfigurationException; import org.argeo.slc.execution.RefSpecAttribute; import org.argeo.slc.execution.RefValue; import org.argeo.slc.primitive.PrimitiveSpecAttribute; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionSpec.java b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionSpec.java index f36a71f73..fbd031bae 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionSpec.java +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/DefaultExecutionSpec.java @@ -15,15 +15,11 @@ */ package org.argeo.slc.core.execution; -import java.io.Serializable; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.argeo.slc.execution.ExecutionSpec; import org.argeo.slc.execution.ExecutionSpecAttribute; import org.argeo.slc.execution.RefSpecAttribute; import org.argeo.slc.execution.RefValueChoice; @@ -37,53 +33,23 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; /** Spring based implementation of execution specifications. */ -public class DefaultExecutionSpec implements ExecutionSpec, BeanNameAware, - ApplicationContextAware, InitializingBean, Serializable { +@Deprecated +public class DefaultExecutionSpec extends org.argeo.slc.runtime.DefaultExecutionSpec + implements BeanNameAware, ApplicationContextAware, InitializingBean { private static final long serialVersionUID = 5159882223926926539L; - private final static Log log = LogFactory - .getLog(DefaultExecutionSpec.class); + private final static Log log = LogFactory.getLog(DefaultExecutionSpec.class); private transient ApplicationContext applicationContext; - private String description; - private Map attributes = new HashMap(); - - private String name = INTERNAL_NAME; - - public Map getAttributes() { - return attributes; - } - - public void setAttributes(Map attributes) { - this.attributes = attributes; + public DefaultExecutionSpec() { + super(); } public void setBeanName(String name) { - this.name = name; - } - - /** - * The Spring bean name (only relevant for specs declared has high-level - * beans) - */ - public String getName() { - return name; - } - - public boolean equals(Object obj) { - return ((ExecutionSpec) obj).getName().equals(name); - } - - /** - * The Spring bean description (only relevant for specs declared has - * high-level beans) - */ - public String getDescription() { - return description; + setName(name); } private ConfigurableListableBeanFactory getBeanFactory() { - return ((ConfigurableApplicationContext) applicationContext) - .getBeanFactory(); + return ((ConfigurableApplicationContext) applicationContext).getBeanFactory(); } public void setApplicationContext(ApplicationContext applicationContext) { @@ -91,17 +57,16 @@ public class DefaultExecutionSpec implements ExecutionSpec, BeanNameAware, } public void afterPropertiesSet() throws Exception { - if (description == null) { + if (getDescription() == null) { try { - description = getBeanFactory().getBeanDefinition(name) - .getDescription(); + setDescription(getBeanFactory().getBeanDefinition(getName()).getDescription()); } catch (NoSuchBeanDefinitionException e) { // silent } } - for (String key : attributes.keySet()) { - ExecutionSpecAttribute attr = attributes.get(key); + for (String key : getAttributes().keySet()) { + ExecutionSpecAttribute attr = getAttributes().get(key); if (attr instanceof RefSpecAttribute) { RefSpecAttribute rsa = (RefSpecAttribute) attr; if (rsa.getChoices() == null) { @@ -109,26 +74,23 @@ public class DefaultExecutionSpec implements ExecutionSpec, BeanNameAware, rsa.setChoices(choices); } if (log.isTraceEnabled()) - log.debug("Spec attr " + key + " has " - + rsa.getChoices().size() + " choices"); + log.debug("Spec attr " + key + " has " + rsa.getChoices().size() + " choices"); } } } /** * Generates a list of ref value choices based on the bean available in the - * application ocntext. + * application context. */ protected List buildRefValueChoices(RefSpecAttribute rsa) { List choices = new ArrayList(); if (applicationContext == null) { - log.warn("No application context declared," - + " cannot scan ref value choices."); + log.warn("No application context declared," + " cannot scan ref value choices."); return choices; } - beanNames: for (String beanName : getBeanFactory().getBeanNamesForType( - rsa.getTargetClass(), true, false)) { + beanNames: for (String beanName : getBeanFactory().getBeanNamesForType(rsa.getTargetClass(), true, false)) { // Since Spring 3, systemProperties is implicitly defined but has no // bean definition diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ExecutionParameterPostProcessor.java b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ExecutionParameterPostProcessor.java index 84c932ee2..dab4cfb3f 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ExecutionParameterPostProcessor.java +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ExecutionParameterPostProcessor.java @@ -27,6 +27,7 @@ import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; import org.argeo.slc.execution.ExecutionContext; import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.runtime.InstantiationManager; import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.PropertyValue; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ExecutionScope.java b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ExecutionScope.java index 4ac0de200..a931329b6 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ExecutionScope.java +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ExecutionScope.java @@ -23,6 +23,7 @@ import org.argeo.slc.execution.ExecutionContext; import org.argeo.slc.execution.ExecutionFlow; import org.argeo.slc.execution.ExecutionSpec; import org.argeo.slc.execution.ExecutionStack; +import org.argeo.slc.runtime.ExecutionThread; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.config.Scope; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ParameterRef.java b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ParameterRef.java index 45dd0964f..b4eafac41 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ParameterRef.java +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/ParameterRef.java @@ -17,6 +17,7 @@ package org.argeo.slc.core.execution; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.argeo.slc.runtime.InstantiationManager; import org.springframework.beans.factory.FactoryBean; public class ParameterRef implements FactoryBean { diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/runtime.xml b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/runtime.xml index 33542ee20..303d55c3f 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/runtime.xml +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/runtime.xml @@ -37,12 +37,12 @@ - - + diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/specs.xml b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/specs.xml index 7cc960475..b1251d3f4 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/specs.xml +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/specs.xml @@ -21,11 +21,11 @@ xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> - - SLC Third Party Support + + org.argeo.slc + org.argeo.slc.runtime + 2.1.17-SNAPSHOT + org.argeo.slc org.argeo.slc.spring diff --git a/org.argeo.slc.support/src/org/argeo/slc/log4j/SlcExecutionAppender.java b/org.argeo.slc.support/src/org/argeo/slc/log4j/SlcExecutionAppender.java index 190a0b696..6652fa0dc 100644 --- a/org.argeo.slc.support/src/org/argeo/slc/log4j/SlcExecutionAppender.java +++ b/org.argeo.slc.support/src/org/argeo/slc/log4j/SlcExecutionAppender.java @@ -22,9 +22,9 @@ import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.spi.LoggingEvent; -import org.argeo.slc.core.execution.ExecutionThread; -import org.argeo.slc.core.execution.ProcessThreadGroup; import org.argeo.slc.execution.ExecutionStep; +import org.argeo.slc.runtime.ExecutionThread; +import org.argeo.slc.runtime.ProcessThreadGroup; /** Not meant to be used directly in standard log4j config */ public class SlcExecutionAppender extends AppenderSkeleton { @@ -69,15 +69,12 @@ public class SlcExecutionAppender extends AppenderSkeleton { try { log4jLevel = Level.toLevel(level); } catch (Exception e) { - System.err - .println("Log4j level could not be set for level '" - + level + "', resetting it to null."); + System.err.println("Log4j level could not be set for level '" + level + "', resetting it to null."); e.printStackTrace(); level = null; } - if (log4jLevel != null - && !event.getLevel().isGreaterOrEqual(log4jLevel)) { + if (log4jLevel != null && !event.getLevel().isGreaterOrEqual(log4jLevel)) { return; } } @@ -85,13 +82,11 @@ public class SlcExecutionAppender extends AppenderSkeleton { // Check whether we are within an executing process Thread currentThread = Thread.currentThread(); if (currentThread.getThreadGroup() instanceof ProcessThreadGroup) { - if (onlyExecutionThread - && !(currentThread instanceof ExecutionThread)) + if (onlyExecutionThread && !(currentThread instanceof ExecutionThread)) return; final String type; - if (event.getLevel().equals(Level.ERROR) - || event.getLevel().equals(Level.FATAL)) + if (event.getLevel().equals(Level.ERROR) || event.getLevel().equals(Level.FATAL)) type = ExecutionStep.ERROR; else if (event.getLevel().equals(Level.WARN)) type = ExecutionStep.WARNING; @@ -104,17 +99,14 @@ public class SlcExecutionAppender extends AppenderSkeleton { else type = ExecutionStep.INFO; - ExecutionStep step = new ExecutionStep(event.getLoggerName(), - new Date(event.getTimeStamp()), type, event.getMessage() - .toString()); + ExecutionStep step = new ExecutionStep(event.getLoggerName(), new Date(event.getTimeStamp()), type, + event.getMessage().toString()); try { dispatching.set(true); - BlockingQueue steps = ((ProcessThreadGroup) currentThread - .getThreadGroup()).getSteps(); + BlockingQueue steps = ((ProcessThreadGroup) currentThread.getThreadGroup()).getSteps(); if (steps.remainingCapacity() == 0) { - stdOut("WARNING: execution steps queue is full, skipping step: " - + step); + stdOut("WARNING: execution steps queue is full, skipping step: " + step); // FIXME understand why it block indefinitely: the queue // should be emptied by the logging thread } else { diff --git a/pom.xml b/pom.xml index 98a5e915e..070d7b688 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ org.argeo.slc.api + org.argeo.slc.runtime org.argeo.slc.jcr -- 2.30.2