From 12419f46844753798cd1b1eab3a7379611f25e47 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Wed, 20 Apr 2011 11:47:53 +0000 Subject: [PATCH] Improve JCR data model Error management ASSIGNED - bug 17: Generalize agent management and registration beyond JMS https://bugzilla.argeo.org/show_bug.cgi?id=17 git-svn-id: https://svn.argeo.org/slc/trunk@4465 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- demo/log4j.properties | 3 +- .../ui/controllers/ProcessController.java | 27 ++-- .../slc/client/ui/editors/ProcessEditor.java | 7 +- .../ui/views/JcrExecutionModulesView.java | 103 +++++------- .../META-INF/spring/jcr.xml | 4 +- .../argeo/slc/execution/ExecutionProcess.java | 3 + .../java/org/argeo/slc/jcr/SlcJcrUtils.java | 38 +++-- .../main/java/org/argeo/slc/jcr/SlcNames.java | 2 +- .../main/java/org/argeo/slc/jcr/SlcTypes.java | 5 +- .../org/argeo/slc/jcr/execution/JcrAgent.java | 52 ++++-- .../JcrExecutionModulesListener.java | 151 +++++++++--------- .../jcr/execution/JcrExecutionProcess.java | 14 +- .../main/resources/org/argeo/slc/jcr/slc.cnd | 17 +- 13 files changed, 237 insertions(+), 189 deletions(-) diff --git a/demo/log4j.properties b/demo/log4j.properties index 7fe0f0cba..b0fbb2be1 100644 --- a/demo/log4j.properties +++ b/demo/log4j.properties @@ -3,7 +3,8 @@ log4j.rootLogger=WARN, development ## Levels log4j.logger.org.argeo=DEBUG -log4j.logger.org.argeo.slc.osgi.OsgiExecutionModulesManager=TRACE +#log4j.logger.org.argeo.slc.osgi.OsgiExecutionModulesManager=TRACE +#log4j.logger.org.argeo.security.core.AbstractSystemExecution=TRACE log4j.logger.org.eclipse.rap=INFO diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/controllers/ProcessController.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/controllers/ProcessController.java index ccb54b5a0..595170389 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/controllers/ProcessController.java +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/controllers/ProcessController.java @@ -11,6 +11,7 @@ import javax.jcr.RepositoryException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.jcr.SlcJcrConstants; import org.argeo.slc.jcr.SlcJcrUtils; import org.argeo.slc.jcr.SlcNames; @@ -34,15 +35,20 @@ public class ProcessController { } public void process(Node processNode) { + JcrExecutionProcess process = new JcrExecutionProcess(processNode); try { // we currently only deal with single agents - Node flowNode = processNode.getNode(SlcNames.SLC_FLOW); - NodeIterator nit = flowNode.getNodes(); + Node realizedFlowNode = processNode.getNode(SlcNames.SLC_FLOW); + NodeIterator nit = realizedFlowNode.getNodes(); if (nit.hasNext()) { - Node firstFlow = nit.nextNode(); + // FIXME find a better way to determine which agent to use + // currently we check the agent of the first registered flow + Node firstRealizedFlow = nit.nextNode(); // we assume there is an nt:address - String firstFlowPath = firstFlow.getNode(SlcNames.SLC_ADDRESS) + String firstFlowPath = firstRealizedFlow + .getNode(SlcNames.SLC_ADDRESS) .getProperty(Property.JCR_PATH).getString(); + Node flowNode = processNode.getSession().getNode(firstFlowPath); String agentFactoryPath = SlcJcrUtils .flowAgentFactoryPath(firstFlowPath); if (!agentFactories.containsKey(agentFactoryPath)) @@ -50,15 +56,18 @@ public class ProcessController { + agentFactoryPath); SlcAgentFactory agentFactory = agentFactories .get(agentFactoryPath); - String agentUuid = ((Node) processNode - .getAncestor(SlcJcrUtils.AGENT_FACTORY_DEPTH + 1)) - .getName(); + Node agentNode = ((Node) flowNode + .getAncestor(SlcJcrUtils.AGENT_FACTORY_DEPTH + 1)); + String agentUuid = agentNode.getProperty(SlcNames.SLC_UUID) + .getString(); // process SlcAgent slcAgent = agentFactory.getAgent(agentUuid); - slcAgent.process(new JcrExecutionProcess(processNode)); + slcAgent.process(process); } - } catch (RepositoryException e) { + } catch (Exception e) { + if (!process.getStatus().equals(ExecutionProcess.ERROR)) + process.setStatus(ExecutionProcess.ERROR); throw new SlcException("Cannot execute " + processNode, e); } } diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditor.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditor.java index e898a64a1..78282df3c 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditor.java +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditor.java @@ -8,6 +8,7 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.nodetype.NodeType; +import org.argeo.eclipse.ui.Error; import org.argeo.jcr.JcrUtils; import org.argeo.slc.SlcException; import org.argeo.slc.client.ui.ClientUiPlugin; @@ -105,7 +106,11 @@ public class ProcessEditor extends FormEditor implements SlcTypes, SlcNames { throw new SlcException("Cannot update status of " + processNode, e); } doSave(null); - processController.process(processNode); + try { + processController.process(processNode); + } catch (Exception e) { + Error.show("Execution of " + processNode + " failed", e); + } } @Override diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/JcrExecutionModulesView.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/JcrExecutionModulesView.java index 025fb55c1..59157a370 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/JcrExecutionModulesView.java +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/JcrExecutionModulesView.java @@ -6,21 +6,16 @@ import java.util.Comparator; import java.util.List; import javax.jcr.Node; -import javax.jcr.NodeIterator; import javax.jcr.Property; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.observation.Event; import javax.jcr.observation.EventIterator; -import javax.jcr.observation.EventListener; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.jcr.AsyncUiEventListener; import org.argeo.eclipse.ui.jcr.DefaultNodeLabelProvider; -import org.argeo.eclipse.ui.jcr.NodesWrapper; import org.argeo.eclipse.ui.jcr.SimpleNodeContentProvider; -import org.argeo.eclipse.ui.jcr.WrappedNode; import org.argeo.slc.SlcException; import org.argeo.slc.client.ui.SlcImages; import org.argeo.slc.client.ui.editors.ProcessEditor; @@ -46,10 +41,11 @@ import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; +/** JCR based view of the execution modules. */ public class JcrExecutionModulesView extends ViewPart implements SlcTypes, SlcNames { - private final static Log log = LogFactory - .getLog(JcrExecutionModulesView.class); + // private final static Log log = LogFactory + // .getLog(JcrExecutionModulesView.class); public static final String ID = "org.argeo.slc.client.ui.jcrExecutionModulesView"; @@ -107,17 +103,17 @@ public class JcrExecutionModulesView extends ViewPart implements SlcTypes, new String[] { SlcJcrConstants.VM_AGENT_FACTORY_PATH }); } - @Override - protected Object[] getChildren(Node node) throws RepositoryException { - if (node.isNodeType(SlcTypes.SLC_AGENT_PROXY)) { - List wrappers = new ArrayList(); - for (NodeIterator nit = node.getNodes(); nit.hasNext();) { - wrappers.add(new AgentNodesWrapper(nit.nextNode())); - } - return wrappers.toArray(); - } - return super.getChildren(node); - } +// @Override +// protected Object[] getChildren(Node node) throws RepositoryException { +// if (node.isNodeType(SlcTypes.SLC_AGENT_FACTORY)) { +// List wrappers = new ArrayList(); +// for (NodeIterator nit = node.getNodes(); nit.hasNext();) { +// wrappers.add(new AgentNodesWrapper(nit.nextNode())); +// } +// return wrappers.toArray(); +// } +// return super.getChildren(node); +// } @Override protected Object[] sort(Object parent, Object[] children) { @@ -158,35 +154,32 @@ public class JcrExecutionModulesView extends ViewPart implements SlcTypes, } - /** Wraps the execution modules of an agent. */ - static class AgentNodesWrapper extends NodesWrapper { - - public AgentNodesWrapper(Node node) { - super(node); - } - - protected List getWrappedNodes() - throws RepositoryException { - List children = new ArrayList(); - Node executionModules = getNode().getNode( - SlcNames.SLC_EXECUTION_MODULES); - for (NodeIterator nit = executionModules.getNodes(); nit.hasNext();) { - for (NodeIterator nitVersions = nit.nextNode().getNodes(); nitVersions - .hasNext();) { - children.add(new WrappedNode(this, nitVersions.nextNode())); - } - } - return children; - } - - } - - class VmAgentObserver implements EventListener { - - public void onEvent(EventIterator events) { +// /** Wraps the execution modules of an agent. */ +// static class AgentNodesWrapper extends NodesWrapper { +// +// public AgentNodesWrapper(Node node) { +// super(node); +// } +// +// protected List getWrappedNodes() +// throws RepositoryException { +// List children = new ArrayList(); +// Node executionModules = getNode(); +// for (NodeIterator nit = executionModules.getNodes(); nit.hasNext();) { +// for (NodeIterator nitVersions = nit.nextNode().getNodes(); nitVersions +// .hasNext();) { +// children.add(new WrappedNode(this, nitVersions.nextNode())); +// } +// } +// return children; +// } +// +// } + + class VmAgentObserver extends AsyncUiEventListener { + protected void onEventInUiThread(EventIterator events) { viewer.refresh(); } - } class ViewLabelProvider extends DefaultNodeLabelProvider implements @@ -200,7 +193,7 @@ public class JcrExecutionModulesView extends ViewPart implements SlcTypes, } public Image getImage(Node node) throws RepositoryException { - if (node.getParent().isNodeType(SlcTypes.SLC_AGENT_PROXY)) + if (node.isNodeType(SlcTypes.SLC_AGENT)) return SlcImages.AGENT; else if (node.isNodeType(SlcTypes.SLC_MODULE)) return SlcImages.MODULE; @@ -243,17 +236,7 @@ public class JcrExecutionModulesView extends ViewPart implements SlcTypes, } class ViewDragListener extends DragSourceAdapter { - - public void dragStart(DragSourceEvent event) { - if (log.isDebugEnabled()) - log.debug("Start Drag " + event); - super.dragStart(event); - } - public void dragSetData(DragSourceEvent event) { - - // System.out.println("dragSetData: " + event); - IStructuredSelection selection = (IStructuredSelection) viewer .getSelection(); if (selection.getFirstElement() instanceof Node) { @@ -286,12 +269,6 @@ public class JcrExecutionModulesView extends ViewPart implements SlcTypes, } } } - - public void dragFinished(DragSourceEvent event) { - if (log.isDebugEnabled()) - log.debug("Finished Drag " + event); - } - } public void setSession(Session session) { diff --git a/modules/agent/org.argeo.slc.agent.jcr/META-INF/spring/jcr.xml b/modules/agent/org.argeo.slc.agent.jcr/META-INF/spring/jcr.xml index 0667606f2..9826c4543 100644 --- a/modules/agent/org.argeo.slc.agent.jcr/META-INF/spring/jcr.xml +++ b/modules/agent/org.argeo.slc.agent.jcr/META-INF/spring/jcr.xml @@ -12,7 +12,9 @@ - + + + diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionProcess.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionProcess.java index 35a84fb7b..7389036ed 100644 --- a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionProcess.java +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionProcess.java @@ -20,6 +20,9 @@ public interface ExecutionProcess { public final static String COMPLETED = "COMPLETED"; /** The process failed because of an unexpected error. */ public final static String ERROR = "ERROR"; + /** The status cannot be retrieved (probably because of unexpected errors). */ + public final static String UNKOWN = "UNKOWN"; + /** * Only a reference to the process has been kept, all monitoring data such * as logs have been purged. diff --git a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrUtils.java b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrUtils.java index ed2294f30..7f0f18a0c 100644 --- a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrUtils.java +++ b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrUtils.java @@ -4,33 +4,42 @@ import java.util.Calendar; import java.util.GregorianCalendar; import org.argeo.jcr.JcrUtils; +import org.argeo.slc.deploy.ModuleDescriptor; -/** Utilities around the SLC JCR model. Note that it relies on fixed base paths. */ +/** + * Utilities around the SLC JCR model. Note that it relies on fixed base paths + * (convention over configuration) for optimization purposes. + */ public class SlcJcrUtils { public final static Integer AGENT_FACTORY_DEPTH = 3; - public final static Integer EXECUTION_MODULES_DEPTH = AGENT_FACTORY_DEPTH + 2; - public final static Integer EXECUTION_FLOWS_DEPTH = EXECUTION_MODULES_DEPTH + 3; /** Extracts the path of a flow relative to its execution module */ public static String flowRelativePath(String fullFlowPath) { String[] tokens = fullFlowPath.split("/"); StringBuffer buf = new StringBuffer(fullFlowPath.length()); - for (int i = EXECUTION_FLOWS_DEPTH; i < tokens.length; i++) { + for (int i = AGENT_FACTORY_DEPTH + 3; i < tokens.length; i++) { buf.append('/').append(tokens[i]); } return buf.toString(); } + /** Module node name based on module name and version */ + public static String getModuleNodeName(ModuleDescriptor moduleDescriptor) { + return moduleDescriptor.getName() + "_" + moduleDescriptor.getVersion(); + } + /** Extracts the execution module name of a flow */ public static String flowExecutionModuleName(String fullFlowPath) { String[] tokens = fullFlowPath.split("/"); - return tokens[EXECUTION_MODULES_DEPTH + 1]; + String moduleNodeName = tokens[AGENT_FACTORY_DEPTH + 2]; + return moduleNodeName.substring(0, moduleNodeName.lastIndexOf('_')); } /** Extracts the execution module version of a flow */ public static String flowExecutionModuleVersion(String fullFlowPath) { String[] tokens = fullFlowPath.split("/"); - return tokens[EXECUTION_MODULES_DEPTH + 2]; + String moduleNodeName = tokens[AGENT_FACTORY_DEPTH + 2]; + return moduleNodeName.substring(moduleNodeName.lastIndexOf('_') + 1); } /** Extracts the agent factory of a flow */ @@ -57,11 +66,14 @@ public class SlcJcrUtils { } - // public static void main(String[] args) { - // String path = - // "/slc/agents/vm/54654654654/executionModules/org.argeo/1.2.3/myFlow"; - // System.out.println(flowRelativePath(path)); - // System.out.println(flowExecutionModuleName(path)); - // System.out.println(flowAgentFactoryPath(path)); - // } + public static void main(String[] args) { + String path = "/slc/agents/vm/default/org.argeo_1.2.3/myPath/myFlow"; + System.out.println("Flow relative path: " + flowRelativePath(path)); + System.out.println("Execution Module Name: " + + flowExecutionModuleName(path)); + System.out.println("Execution Module Version: " + + flowExecutionModuleVersion(path)); + System.out.println("Agent Factory path: " + flowAgentFactoryPath(path)); + } + } diff --git a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcNames.java b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcNames.java index 68579cbae..15d1e4428 100644 --- a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcNames.java +++ b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcNames.java @@ -10,6 +10,6 @@ public interface SlcNames { public final static String SLC_ADDRESS = "slc:address"; public final static String SLC_FLOW = "slc:flow"; - public final static String SLC_EXECUTION_MODULES = "slc:executionModules"; + //public final static String SLC_EXECUTION_MODULES = "slc:executionModules"; } diff --git a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcTypes.java b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcTypes.java index 42a941958..4a3afc933 100644 --- a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcTypes.java +++ b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcTypes.java @@ -3,9 +3,10 @@ package org.argeo.slc.jcr; /** JCR node types used by SLC */ public interface SlcTypes { - public final static String SLC_AGENT_PROXY = "slc:agentProxy"; - //public final static String SLC_AGENT = "slc:agent"; + public final static String SLC_AGENT_FACTORY = "slc:agentFactory"; + public final static String SLC_AGENT = "slc:agent"; public final static String SLC_MODULE = "slc:module"; + public final static String SLC_EXECUTION_MODULE = "slc:executionModule"; public final static String SLC_EXECUTION_FLOW = "slc:executionFlow"; public final static String SLC_PROCESS = "slc:process"; public final static String SLC_REALIZED_FLOW = "slc:realizedFlow"; diff --git a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrAgent.java b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrAgent.java index b75b04a08..69bdba767 100644 --- a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrAgent.java +++ b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrAgent.java @@ -14,36 +14,48 @@ import org.argeo.slc.core.runtime.DefaultAgent; import org.argeo.slc.execution.ExecutionModulesManager; import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.jcr.SlcJcrConstants; +import org.argeo.slc.jcr.SlcNames; import org.argeo.slc.jcr.SlcTypes; import org.argeo.slc.runtime.SlcAgent; import org.argeo.slc.runtime.SlcAgentFactory; -/** SLC agent synchronizing with a JCR repository. */ -public class JcrAgent extends DefaultAgent implements SlcAgentFactory { +/** SLC VM agent synchronizing with a JCR repository. */ +public class JcrAgent extends DefaultAgent implements SlcAgentFactory, SlcNames { private Session session; + /** only one agent per VM is currently supported */ + private final String agentNodeName = "default"; + /* * LIFECYCLE */ protected String initAgentUuid() { try { Node vmAgentFactoryNode = JcrUtils.mkdirs(session, - SlcJcrConstants.VM_AGENT_FACTORY_PATH); - vmAgentFactoryNode.addMixin(SlcTypes.SLC_AGENT_PROXY); - if (!vmAgentFactoryNode.hasNodes()) { + SlcJcrConstants.VM_AGENT_FACTORY_PATH, + SlcTypes.SLC_AGENT_FACTORY); + if (!vmAgentFactoryNode.hasNode(agentNodeName)) { String uuid = UUID.randomUUID().toString(); - vmAgentFactoryNode.addNode(uuid); + Node agentNode = vmAgentFactoryNode.addNode(agentNodeName, + SlcTypes.SLC_AGENT); + agentNode.setProperty(SLC_UUID, uuid); } session.save(); - - return vmAgentFactoryNode.getNodes().nextNode().getName(); + return vmAgentFactoryNode.getNode(agentNodeName) + .getProperty(SLC_UUID).getString(); } catch (RepositoryException e) { - throw new SlcException("Cannot find JCR agent UUID", e); - } finally { JcrUtils.discardQuietly(session); + throw new SlcException("Cannot find JCR agent UUID", e); } } + public void dispose() { + + } + + /* + * SLC AGENT + */ @Override protected ProcessThread createProcessThread( ExecutionModulesManager modulesManager, ExecutionProcess process) { @@ -51,14 +63,13 @@ public class JcrAgent extends DefaultAgent implements SlcAgentFactory { (JcrExecutionProcess) process); } - public void dispose() { - - } - /* * SLC AGENT FACTORY */ public SlcAgent getAgent(String uuid) { + if (!uuid.equals(getAgentUuid())) + throw new SlcException("Internal UUID " + getAgentUuid() + + " is different from argument UUID " + uuid); return this; } @@ -67,10 +78,21 @@ public class JcrAgent extends DefaultAgent implements SlcAgentFactory { } /* - * BEAN METHODS + * UTILITIES + */ + public String getNodePath() { + return SlcJcrConstants.VM_AGENT_FACTORY_PATH + '/' + getAgentNodeName(); + } + + /* + * BEAN */ public void setSession(Session session) { this.session = session; } + public String getAgentNodeName() { + return agentNodeName; + } + } diff --git a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionModulesListener.java b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionModulesListener.java index 7a01e6746..b019ff970 100644 --- a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionModulesListener.java +++ b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionModulesListener.java @@ -4,6 +4,7 @@ import java.util.Arrays; import java.util.Iterator; import javax.jcr.Node; +import javax.jcr.NodeIterator; import javax.jcr.Property; import javax.jcr.RepositoryException; import javax.jcr.Session; @@ -15,10 +16,9 @@ import org.argeo.slc.SlcException; import org.argeo.slc.deploy.ModuleDescriptor; import org.argeo.slc.execution.ExecutionFlowDescriptor; import org.argeo.slc.execution.ExecutionModulesListener; -import org.argeo.slc.jcr.SlcJcrConstants; +import org.argeo.slc.jcr.SlcJcrUtils; import org.argeo.slc.jcr.SlcNames; import org.argeo.slc.jcr.SlcTypes; -import org.argeo.slc.runtime.SlcAgent; /** * Synchronizes the local execution runtime with a JCR repository. For the time @@ -27,96 +27,94 @@ import org.argeo.slc.runtime.SlcAgent; public class JcrExecutionModulesListener implements ExecutionModulesListener { private final static Log log = LogFactory .getLog(JcrExecutionModulesListener.class); + private JcrAgent agent; + /** + * We don't use a thread bound session because many different threads will + * call this critical component and we don't want to login each time. We + * therefore rather protect access to this session via synchronized. + */ private Session session; - private SlcAgent agent; + /* + * LIFECYCLE + */ public void init() { - try { - String modulesPath = getExecutionModulesPath(); - // clean up previous state - if (session.nodeExists(modulesPath)) - session.getNode(modulesPath).remove(); - JcrUtils.mkdirs(session, modulesPath); - session.save(); - } catch (RepositoryException e) { - throw new SlcException( - "Cannot initialize JCR execution module listener", e); - } finally { - JcrUtils.discardQuietly(session); - } + clearAgent(); } public void dispose() { + clearAgent(); + session.logout(); + } + + protected synchronized void clearAgent() { try { - String modulesPath = getExecutionModulesPath(); - // clean up previous state - if (session.nodeExists(modulesPath)) - session.getNode(modulesPath).remove(); + Node agentNode = session.getNode(agent.getNodePath()); + for (NodeIterator nit = agentNode.getNodes(); nit.hasNext();) + nit.nextNode().remove(); session.save(); } catch (RepositoryException e) { - throw new SlcException( - "Cannot dispose JCR execution module listener", e); - } finally { JcrUtils.discardQuietly(session); + throw new SlcException("Cannot clear agent " + agent, e); } } - public void executionModuleAdded(ModuleDescriptor moduleDescriptor) { + /* + * EXECUTION MODULES LISTENER + */ + public synchronized void executionModuleAdded( + ModuleDescriptor moduleDescriptor) { try { - Node base = session.getNode(getExecutionModulesPath()); - Node moduleName = base.hasNode(moduleDescriptor.getName()) ? base - .getNode(moduleDescriptor.getName()) : base - .addNode(moduleDescriptor.getName()); - Node moduleVersion = moduleName.hasNode(moduleDescriptor - .getVersion()) ? moduleName.getNode(moduleDescriptor - .getVersion()) : moduleName.addNode(moduleDescriptor - .getVersion()); - moduleVersion.addMixin(SlcTypes.SLC_MODULE); - moduleVersion.setProperty(SlcNames.SLC_NAME, + Node agentNode = session.getNode(agent.getNodePath()); + String moduleNodeName = SlcJcrUtils + .getModuleNodeName(moduleDescriptor); + Node moduleNode = agentNode.hasNode(moduleNodeName) ? agentNode + .getNode(moduleNodeName) : agentNode + .addNode(moduleNodeName); + moduleNode.addMixin(SlcTypes.SLC_EXECUTION_MODULE); + moduleNode.setProperty(SlcNames.SLC_NAME, moduleDescriptor.getName()); - moduleVersion.setProperty(SlcNames.SLC_VERSION, + moduleNode.setProperty(SlcNames.SLC_VERSION, moduleDescriptor.getVersion()); - moduleVersion.setProperty(Property.JCR_TITLE, + moduleNode.setProperty(Property.JCR_TITLE, moduleDescriptor.getTitle()); - moduleVersion.setProperty(Property.JCR_DESCRIPTION, + moduleNode.setProperty(Property.JCR_DESCRIPTION, moduleDescriptor.getDescription()); session.save(); } catch (RepositoryException e) { + JcrUtils.discardQuietly(session); throw new SlcException("Cannot add module " + moduleDescriptor, e); } } - public void executionModuleRemoved(ModuleDescriptor moduleDescriptor) { + public synchronized void executionModuleRemoved( + ModuleDescriptor moduleDescriptor) { try { - Node base = session.getNode(getExecutionModulesPath()); - if (base.hasNode(moduleDescriptor.getName())) { - Node moduleName = base.getNode(moduleDescriptor.getName()); - if (moduleName.hasNode(moduleDescriptor.getVersion())) - moduleName.getNode(moduleDescriptor.getVersion()).remove(); - if (!moduleName.hasNodes()) - moduleName.remove(); - session.save(); - } + String moduleName = SlcJcrUtils.getModuleNodeName(moduleDescriptor); + Node agentNode = session.getNode(agent.getNodePath()); + if (agentNode.hasNode(moduleName)) + agentNode.getNode(moduleName).remove(); + agentNode.getSession().save(); } catch (RepositoryException e) { throw new SlcException("Cannot remove module " + moduleDescriptor, e); } } - public void executionFlowAdded(ModuleDescriptor module, + public synchronized void executionFlowAdded(ModuleDescriptor module, ExecutionFlowDescriptor executionFlow) { - String path = getExecutionFlowPath(module, executionFlow); try { + Node agentNode = session.getNode(agent.getNodePath()); + Node moduleNode = agentNode.getNode(SlcJcrUtils + .getModuleNodeName(module)); + String relativePath = getExecutionFlowRelativePath(executionFlow); Node flowNode = null; - if (!session.nodeExists(path)) { - Node base = session.getNode(getExecutionModulesPath()); - Node moduleNode = base.getNode(module.getName() + '/' - + module.getVersion()); - String relativePath = getExecutionFlowRelativePath(executionFlow); + if (!moduleNode.hasNode(relativePath)) { Iterator names = Arrays.asList(relativePath.split("/")) .iterator(); + // create intermediary paths Node currNode = moduleNode; while (names.hasNext()) { String name = names.next(); @@ -126,47 +124,45 @@ public class JcrExecutionModulesListener implements ExecutionModulesListener { if (names.hasNext()) currNode = currNode.addNode(name); else - flowNode = currNode.addNode(name); + flowNode = currNode.addNode(name, + SlcTypes.SLC_EXECUTION_FLOW); } } - flowNode.addMixin(SlcTypes.SLC_EXECUTION_FLOW); flowNode.setProperty(SlcNames.SLC_NAME, executionFlow.getName()); session.save(); } else { - flowNode = session.getNode(path); + flowNode = moduleNode.getNode(relativePath); } if (log.isTraceEnabled()) log.trace("Flow " + executionFlow + " added to JCR"); } catch (RepositoryException e) { + JcrUtils.discardQuietly(session); throw new SlcException("Cannot add flow " + executionFlow + " from module " + module, e); } } - public void executionFlowRemoved(ModuleDescriptor module, + public synchronized void executionFlowRemoved(ModuleDescriptor module, ExecutionFlowDescriptor executionFlow) { - String path = getExecutionFlowPath(module, executionFlow); try { - if (session.nodeExists(path)) { - Node flowNode = session.getNode(path); - flowNode.remove(); - session.save(); - } + Node agentNode = session.getNode(agent.getNodePath()); + Node moduleNode = agentNode.getNode(SlcJcrUtils + .getModuleNodeName(module)); + String relativePath = getExecutionFlowRelativePath(executionFlow); + if (!moduleNode.hasNode(relativePath)) + moduleNode.getNode(relativePath).remove(); + agentNode.getSession().save(); } catch (RepositoryException e) { throw new SlcException("Cannot remove flow " + executionFlow + " from module " + module, e); } } - protected String getExecutionFlowPath(ModuleDescriptor module, - ExecutionFlowDescriptor executionFlow) { - String relativePath = getExecutionFlowRelativePath(executionFlow); - return getExecutionModulesPath() + '/' + module.getName() + '/' - + module.getVersion() + '/' + relativePath; - } - + /* + * UTILITIES + */ /** @return the relative path, never starts with '/' */ @SuppressWarnings("deprecation") protected String getExecutionFlowRelativePath( @@ -180,17 +176,16 @@ public class JcrExecutionModulesListener implements ExecutionModulesListener { return relativePath; } - protected String getExecutionModulesPath() { - return SlcJcrConstants.VM_AGENT_FACTORY_PATH + '/' - + agent.getAgentUuid() + '/' + SlcNames.SLC_EXECUTION_MODULES; + /* + * BEAN + */ + public void setAgent(JcrAgent agent) { + this.agent = agent; } + /** Expects a non-shared session with admin authorization */ public void setSession(Session session) { this.session = session; } - public void setAgent(SlcAgent agent) { - this.agent = agent; - } - } diff --git a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionProcess.java b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionProcess.java index ce08b8f38..526b5ebc4 100644 --- a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionProcess.java +++ b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionProcess.java @@ -3,6 +3,8 @@ package org.argeo.slc.jcr.execution; import javax.jcr.Node; import javax.jcr.RepositoryException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.argeo.jcr.JcrUtils; import org.argeo.slc.SlcException; import org.argeo.slc.execution.ExecutionProcess; @@ -10,6 +12,7 @@ import org.argeo.slc.jcr.SlcNames; /** Execution process implementation based on a JCR node. */ public class JcrExecutionProcess implements ExecutionProcess { + private Log log = LogFactory.getLog(JcrExecutionProcess.class); private final Node node; public JcrExecutionProcess(Node node) { @@ -28,7 +31,11 @@ public class JcrExecutionProcess implements ExecutionProcess { try { return node.getProperty(SlcNames.SLC_STATUS).getString(); } catch (RepositoryException e) { - throw new SlcException("Cannot get uuid for " + node, e); + log.error("Cannot get status: " + e); + // we should re-throw exception because this information can + // probably used for monitoring in case there are already unexpected + // exceptions + return UNKOWN; } } @@ -45,7 +52,10 @@ public class JcrExecutionProcess implements ExecutionProcess { } catch (RepositoryException e1) { // silent } - throw new SlcException("Cannot get uuid for " + node, e); + // we should re-throw exception because this information can + // probably used for monitoring in case there are already unexpected + // exceptions + log.error("Cannot set status " + status + ": " + e); } } diff --git a/runtime/org.argeo.slc.support.jcr/src/main/resources/org/argeo/slc/jcr/slc.cnd b/runtime/org.argeo.slc.support.jcr/src/main/resources/org/argeo/slc/jcr/slc.cnd index 62c469bc4..6b79bc9c4 100644 --- a/runtime/org.argeo.slc.support.jcr/src/main/resources/org/argeo/slc/jcr/slc.cnd +++ b/runtime/org.argeo.slc.support.jcr/src/main/resources/org/argeo/slc/jcr/slc.cnd @@ -1,20 +1,31 @@ +// COMMON [slc:nameVersion] > nt:base mixin - slc:name (STRING) m - slc:version (STRING) m -[slc:agentProxy] > mix:title +// AGENT +[slc:agentFactory] > nt:unstructured, mix:title ++ * (slc:agent) + +[slc:agent] > nt:unstructured, mix:title ++ * (slc:module) + +[slc:module] > slc:nameVersion, mix:title mixin -[slc:module] > slc:nameVersion,mix:title +[slc:activableModule] > slc:module mixin -[slc:executionFlow] > mix:title +[slc:executionModule] > slc:activableModule mixin + +[slc:executionFlow] > nt:unstructured, mix:title - slc:name (STRING) m +// PROCESS [slc:process] > nt:unstructured, mix:created, mix:lastModified - slc:uuid (STRING) m - slc:status (STRING) m -- 2.39.2