]> git.argeo.org Git - gpl/argeo-slc.git/commitdiff
Improve JCR data model
authorMathieu Baudier <mbaudier@argeo.org>
Wed, 20 Apr 2011 11:47:53 +0000 (11:47 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Wed, 20 Apr 2011 11:47:53 +0000 (11:47 +0000)
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

13 files changed:
demo/log4j.properties
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/controllers/ProcessController.java
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditor.java
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/JcrExecutionModulesView.java
modules/agent/org.argeo.slc.agent.jcr/META-INF/spring/jcr.xml
runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionProcess.java
runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrUtils.java
runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcNames.java
runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcTypes.java
runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrAgent.java
runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionModulesListener.java
runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionProcess.java
runtime/org.argeo.slc.support.jcr/src/main/resources/org/argeo/slc/jcr/slc.cnd

index 7fe0f0cba09d7f49a22af41c795a711f2c0bbf1d..b0fbb2be1fc42f60f8272f6168fb5d68087bf61a 100644 (file)
@@ -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
 
index ccb54b5a079e008293380742599b93ec2a7be825..595170389b04ab7f686722caef33be979bda1570 100644 (file)
@@ -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);
                }
        }
index e898a64a12d69b04a523ebddcf84d876ca3c62bc..78282df3c3b6213d0ba7e758ba411b9d383f31ca 100644 (file)
@@ -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
index 025fb55c10c757a263ffcae2262779fc68f04ae7..59157a3702bfb5a6d3fab4ebe3364786603a5b5d 100644 (file)
@@ -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<AgentNodesWrapper> wrappers = new ArrayList<AgentNodesWrapper>();
-                               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<AgentNodesWrapper> wrappers = new ArrayList<AgentNodesWrapper>();
+//                             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<WrappedNode> getWrappedNodes()
-                               throws RepositoryException {
-                       List<WrappedNode> children = new ArrayList<WrappedNode>();
-                       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<WrappedNode> getWrappedNodes()
+//                             throws RepositoryException {
+//                     List<WrappedNode> children = new ArrayList<WrappedNode>();
+//                     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) {
index 0667606f203c447637f63cd395f026dc9227620a..9826c454364a9297b439b98e989b66a3ffd34a2f 100644 (file)
@@ -12,7 +12,9 @@
        <bean id="executionModulesListener" class="org.argeo.slc.jcr.execution.JcrExecutionModulesListener"\r
                init-method="init" destroy-method="dispose">\r
                <property name="agent" ref="agent" />\r
-               <property name="session" ref="session" />\r
+               <property name="session">\r
+                       <bean factory-bean="repository" factory-method="login" />\r
+               </property>\r
        </bean>\r
 \r
        <bean id="session" class="org.argeo.security.jcr.SecureThreadBoundSession">\r
index 35a84fb7b7a6af94d266ee0abdc432a4be66470e..7389036ed431c4c1f9df16dcbf1405ae5cb25104 100644 (file)
@@ -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.
index ed2294f30087a45066a3799f706fa5d788312401..7f0f18a0cc2742acfd4ec66536594c36dc99dfd1 100644 (file)
@@ -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));
+       }
+
 }
index 68579cbae70057ed7af89992de453d34e3acc2a4..15d1e44282c876f4426b798965e01ff42de7482a 100644 (file)
@@ -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";
 
 }
index 42a9419582b9b3a53ebc14ec5089fad807ac68ec..4a3afc9331b08e6a1250b13456fd70ebfeb4c4f1 100644 (file)
@@ -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";
index b75b04a08850cb5d9f6d2a0ed319987e1ccfeee3..69bdba76758bd04fc2819fb3047413f774e41bb8 100644 (file)
@@ -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;
+       }
+
 }
index 7a01e6746974d15ceed925990138db0f3d723e2b..b019ff970a072d575263d56447ab70ec567d2c45 100644 (file)
@@ -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<String> 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;
-       }
-
 }
index ce08b8f38136d432617b8b7e8abcb2d145c82143..526b5ebc4e5fb10add998c3b635088423dd59031 100644 (file)
@@ -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);
                }
        }
 
index 62c469bc4963ba9215b60983f1ade79904a0a757..6b79bc9c47e4d14b820c4c9113f84759b9b06c7e 100644 (file)
@@ -1,20 +1,31 @@
 <slc = 'http://www.argeo.org/ns/slc'>
 
+// 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