]> git.argeo.org Git - gpl/argeo-slc.git/blobdiff - runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionModulesListener.java
Fix //
[gpl/argeo-slc.git] / runtime / org.argeo.slc.support.jcr / src / main / java / org / argeo / slc / jcr / execution / JcrExecutionModulesListener.java
index 1dc79046cdd683f7b2cc7987f79fb17cfdcd7228..4d0c55cb0ed76e4f2915850e7e8945037a3112d5 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;
@@ -13,151 +14,237 @@ 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.core.execution.PrimitiveSpecAttribute;
+import org.argeo.slc.core.execution.RefSpecAttribute;
+import org.argeo.slc.core.execution.RefValueChoice;
 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.execution.ExecutionSpec;
+import org.argeo.slc.execution.ExecutionSpecAttribute;
+import org.argeo.slc.jcr.SlcJcrUtils;
 import org.argeo.slc.jcr.SlcNames;
-import org.argeo.slc.runtime.SlcAgent;
+import org.argeo.slc.jcr.SlcTypes;
 
 /**
  * Synchronizes the local execution runtime with a JCR repository. For the time
  * being the state is completely reset from one start to another.
  */
-public class JcrExecutionModulesListener implements ExecutionModulesListener {
+public class JcrExecutionModulesListener implements ExecutionModulesListener,
+               SlcNames {
        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(NodeType.MIX_TITLE);
-                       moduleVersion.setProperty(Property.JCR_TITLE,
+                       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(SLC_NAME, moduleDescriptor.getName());
+                       moduleNode.setProperty(SLC_VERSION, moduleDescriptor.getVersion());
+                       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,
-                       ExecutionFlowDescriptor executionFlow) {
-               String path = getExecutionFlowPath(module, executionFlow);
+       public synchronized void executionFlowAdded(ModuleDescriptor module,
+                       ExecutionFlowDescriptor efd) {
                try {
-                       Node flowNode;
-                       if (!session.nodeExists(path)) {
-                               Node base = session.getNode(getExecutionModulesPath());
-                               Node moduleNode = base.getNode(module.getName() + '/'
-                                               + module.getVersion());
-                               String relativePath = getExecutionFlowRelativePath(executionFlow);
-                               Iterator<String> names = Arrays.asList(relativePath.split("/"))
-                                               .iterator();
-                               Node currNode = moduleNode;
-                               while (names.hasNext()) {
-                                       String name = names.next();
-                                       if (currNode.hasNode(name))
-                                               currNode = currNode.getNode(name);
-                                       else {
-                                               if (names.hasNext())
-                                                       currNode = currNode.addNode(name);
-                                               else
-                                                       flowNode = currNode.addNode(name);
-                                       }
-                               }
+                       Node agentNode = session.getNode(agent.getNodePath());
+                       Node moduleNode = agentNode.getNode(SlcJcrUtils
+                                       .getModuleNodeName(module));
+                       String relativePath = getExecutionFlowRelativePath(efd);
+                       @SuppressWarnings("unused")
+                       Node flowNode = null;
+                       if (!moduleNode.hasNode(relativePath)) {
+                               flowNode = createExecutionFlowNode(moduleNode, relativePath,
+                                               efd);
                                session.save();
                        } else {
-                               flowNode = session.getNode(path);
+                               flowNode = moduleNode.getNode(relativePath);
                        }
+
+                       if (log.isTraceEnabled())
+                               log.trace("Flow " + efd + " added to JCR");
                } catch (RepositoryException e) {
-                       throw new SlcException("Cannot add flow " + executionFlow
-                                       + " from module " + module, e);
+                       JcrUtils.discardQuietly(session);
+                       throw new SlcException("Cannot add flow " + efd + " from module "
+                                       + module, e);
+               }
+
+       }
+
+       protected Node createExecutionFlowNode(Node moduleNode,
+                       String relativePath, ExecutionFlowDescriptor efd)
+                       throws RepositoryException {
+               Node flowNode = null;
+               Iterator<String> names = Arrays.asList(relativePath.split("/"))
+                               .iterator();
+               // create intermediary paths
+               Node currNode = moduleNode;
+               while (names.hasNext()) {
+                       String name = names.next();
+                       if (currNode.hasNode(name))
+                               currNode = currNode.getNode(name);
+                       else {
+                               if (names.hasNext())
+                                       currNode = currNode.addNode(name);
+                               else
+                                       flowNode = currNode.addNode(name,
+                                                       SlcTypes.SLC_EXECUTION_FLOW);
+                       }
                }
+               flowNode.setProperty(SLC_NAME, efd.getName());
+               String[] tokens = relativePath.split("/");
+               flowNode.setProperty(Property.JCR_TITLE, tokens[tokens.length - 1]);
+               if (efd.getDescription() != null
+                               && efd.getDescription().trim().equals(""))
+                       flowNode.setProperty(Property.JCR_DESCRIPTION, efd.getDescription());
+
+               // execution spec
+               ExecutionSpec executionSpec = efd.getExecutionSpec();
+               String esName = executionSpec.getName();
+               if (!(esName == null || esName.equals(ExecutionSpec.INTERNAL_NAME))) {
+                       Node executionSpecsNode = moduleNode.hasNode(SLC_EXECUTION_SPECS) ? moduleNode
+                                       .getNode(SLC_EXECUTION_SPECS) : moduleNode
+                                       .addNode(SLC_EXECUTION_SPECS);
+                       Node executionSpecNode = executionSpecsNode.addNode(esName,
+                                       SlcTypes.SLC_EXECUTION_SPEC);
+                       executionSpecNode.setProperty(SLC_NAME, esName);
+                       executionSpecNode.setProperty(Property.JCR_TITLE, esName);
+                       if (executionSpec.getDescription() != null
+                                       && !executionSpec.getDescription().trim().equals(""))
+                               executionSpecNode.setProperty(Property.JCR_DESCRIPTION,
+                                               executionSpec.getDescription());
+                       mapExecutionSpec(executionSpecNode, executionSpec);
+                       flowNode.setProperty(SLC_SPEC, executionSpecNode);
+               } else {
+                       mapExecutionSpec(flowNode, executionSpec);
+               }
+               return flowNode;
+       }
 
+       /**
+        * Base can be either an execution spec node, or an execution flow node (in
+        * case the execution spec is internal)
+        */
+       protected void mapExecutionSpec(Node baseNode, ExecutionSpec executionSpec)
+                       throws RepositoryException {
+               for (String attrName : executionSpec.getAttributes().keySet()) {
+                       ExecutionSpecAttribute esa = executionSpec.getAttributes().get(
+                                       attrName);
+                       Node attrNode = baseNode.addNode(attrName);
+                       // booleans
+                       attrNode.addMixin(SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE);
+                       attrNode.setProperty(SLC_IS_IMMUTABLE, esa.getIsImmutable());
+                       attrNode.setProperty(SLC_IS_CONSTANT, esa.getIsConstant());
+                       attrNode.setProperty(SLC_IS_HIDDEN, esa.getIsHidden());
+
+                       if (esa instanceof PrimitiveSpecAttribute) {
+                               attrNode.addMixin(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE);
+                               PrimitiveSpecAttribute psa = (PrimitiveSpecAttribute) esa;
+                               SlcJcrUtils.setPrimitiveAsProperty(attrNode, SLC_VALUE, psa);
+                               attrNode.setProperty(SLC_TYPE, psa.getType());
+                       } else if (esa instanceof RefSpecAttribute) {
+                               attrNode.addMixin(SlcTypes.SLC_REF_SPEC_ATTRIBUTE);
+                               RefSpecAttribute rsa = (RefSpecAttribute) esa;
+                               attrNode.setProperty(SLC_TYPE, rsa.getTargetClassName());
+                               if (rsa.getChoices() != null) {
+                                       for (RefValueChoice choice : rsa.getChoices()) {
+                                               Node choiceNode = attrNode.addNode(choice.getName());
+                                               choiceNode.addMixin(NodeType.MIX_TITLE);
+                                               choiceNode.setProperty(Property.JCR_TITLE,
+                                                               choice.getName());
+                                               if (choice.getDescription() != null
+                                                               && !choice.getDescription().trim().equals(""))
+                                                       choiceNode.setProperty(Property.JCR_DESCRIPTION,
+                                                                       choice.getDescription());
+                                       }
+                               }
+                       }
+               }
        }
 
-       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(
@@ -168,20 +255,21 @@ public class JcrExecutionModulesListener implements ExecutionModulesListener {
                // we assume that it is more than one char long
                if (relativePath.charAt(0) == '/')
                        relativePath = relativePath.substring(1);
+               // FIXME quick hack to avoid duplicate '/'
+               relativePath = relativePath.replaceAll("//", "/");
                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;
-       }
-
 }