]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionModulesListener.java
Primitive arguments working
[gpl/argeo-slc.git] / runtime / org.argeo.slc.support.jcr / src / main / java / org / argeo / slc / jcr / execution / JcrExecutionModulesListener.java
1 package org.argeo.slc.jcr.execution;
2
3 import java.util.Arrays;
4 import java.util.Iterator;
5
6 import javax.jcr.Node;
7 import javax.jcr.NodeIterator;
8 import javax.jcr.Property;
9 import javax.jcr.RepositoryException;
10 import javax.jcr.Session;
11 import javax.jcr.nodetype.NodeType;
12
13 import org.apache.commons.logging.Log;
14 import org.apache.commons.logging.LogFactory;
15 import org.argeo.jcr.JcrUtils;
16 import org.argeo.slc.SlcException;
17 import org.argeo.slc.core.execution.PrimitiveSpecAttribute;
18 import org.argeo.slc.core.execution.RefSpecAttribute;
19 import org.argeo.slc.core.execution.RefValueChoice;
20 import org.argeo.slc.deploy.ModuleDescriptor;
21 import org.argeo.slc.execution.ExecutionFlowDescriptor;
22 import org.argeo.slc.execution.ExecutionModulesListener;
23 import org.argeo.slc.execution.ExecutionSpec;
24 import org.argeo.slc.execution.ExecutionSpecAttribute;
25 import org.argeo.slc.jcr.SlcJcrUtils;
26 import org.argeo.slc.jcr.SlcNames;
27 import org.argeo.slc.jcr.SlcTypes;
28
29 /**
30 * Synchronizes the local execution runtime with a JCR repository. For the time
31 * being the state is completely reset from one start to another.
32 */
33 public class JcrExecutionModulesListener implements ExecutionModulesListener,
34 SlcNames {
35 private final static Log log = LogFactory
36 .getLog(JcrExecutionModulesListener.class);
37 private JcrAgent agent;
38
39 /**
40 * We don't use a thread bound session because many different threads will
41 * call this critical component and we don't want to login each time. We
42 * therefore rather protect access to this session via synchronized.
43 */
44 private Session session;
45
46 /*
47 * LIFECYCLE
48 */
49 public void init() {
50 clearAgent();
51 }
52
53 public void dispose() {
54 clearAgent();
55 session.logout();
56 }
57
58 protected synchronized void clearAgent() {
59 try {
60 Node agentNode = session.getNode(agent.getNodePath());
61 for (NodeIterator nit = agentNode.getNodes(); nit.hasNext();)
62 nit.nextNode().remove();
63 session.save();
64 } catch (RepositoryException e) {
65 JcrUtils.discardQuietly(session);
66 throw new SlcException("Cannot clear agent " + agent, e);
67 }
68 }
69
70 /*
71 * EXECUTION MODULES LISTENER
72 */
73 public synchronized void executionModuleAdded(
74 ModuleDescriptor moduleDescriptor) {
75 try {
76 Node agentNode = session.getNode(agent.getNodePath());
77 String moduleNodeName = SlcJcrUtils
78 .getModuleNodeName(moduleDescriptor);
79 Node moduleNode = agentNode.hasNode(moduleNodeName) ? agentNode
80 .getNode(moduleNodeName) : agentNode
81 .addNode(moduleNodeName);
82 moduleNode.addMixin(SlcTypes.SLC_EXECUTION_MODULE);
83 moduleNode.setProperty(SLC_NAME, moduleDescriptor.getName());
84 moduleNode.setProperty(SLC_VERSION, moduleDescriptor.getVersion());
85 moduleNode.setProperty(Property.JCR_TITLE,
86 moduleDescriptor.getTitle());
87 moduleNode.setProperty(Property.JCR_DESCRIPTION,
88 moduleDescriptor.getDescription());
89 session.save();
90 } catch (RepositoryException e) {
91 JcrUtils.discardQuietly(session);
92 throw new SlcException("Cannot add module " + moduleDescriptor, e);
93 }
94
95 }
96
97 public synchronized void executionModuleRemoved(
98 ModuleDescriptor moduleDescriptor) {
99 try {
100 String moduleName = SlcJcrUtils.getModuleNodeName(moduleDescriptor);
101 Node agentNode = session.getNode(agent.getNodePath());
102 if (agentNode.hasNode(moduleName))
103 agentNode.getNode(moduleName).remove();
104 agentNode.getSession().save();
105 } catch (RepositoryException e) {
106 throw new SlcException("Cannot remove module " + moduleDescriptor,
107 e);
108 }
109 }
110
111 public synchronized void executionFlowAdded(ModuleDescriptor module,
112 ExecutionFlowDescriptor efd) {
113 try {
114 Node agentNode = session.getNode(agent.getNodePath());
115 Node moduleNode = agentNode.getNode(SlcJcrUtils
116 .getModuleNodeName(module));
117 String relativePath = getExecutionFlowRelativePath(efd);
118 @SuppressWarnings("unused")
119 Node flowNode = null;
120 if (!moduleNode.hasNode(relativePath)) {
121 flowNode = createExecutionFlowNode(moduleNode, relativePath,
122 efd);
123 session.save();
124 } else {
125 flowNode = moduleNode.getNode(relativePath);
126 }
127
128 if (log.isTraceEnabled())
129 log.trace("Flow " + efd + " added to JCR");
130 } catch (RepositoryException e) {
131 JcrUtils.discardQuietly(session);
132 throw new SlcException("Cannot add flow " + efd + " from module "
133 + module, e);
134 }
135
136 }
137
138 protected Node createExecutionFlowNode(Node moduleNode,
139 String relativePath, ExecutionFlowDescriptor efd)
140 throws RepositoryException {
141 Node flowNode = null;
142 Iterator<String> names = Arrays.asList(relativePath.split("/"))
143 .iterator();
144 // create intermediary paths
145 Node currNode = moduleNode;
146 while (names.hasNext()) {
147 String name = names.next();
148 if (currNode.hasNode(name))
149 currNode = currNode.getNode(name);
150 else {
151 if (names.hasNext())
152 currNode = currNode.addNode(name);
153 else
154 flowNode = currNode.addNode(name,
155 SlcTypes.SLC_EXECUTION_FLOW);
156 }
157 }
158 flowNode.setProperty(SLC_NAME, efd.getName());
159 String[] tokens = relativePath.split("/");
160 flowNode.setProperty(Property.JCR_TITLE, tokens[tokens.length - 1]);
161 if (efd.getDescription() != null
162 && efd.getDescription().trim().equals(""))
163 flowNode.setProperty(Property.JCR_DESCRIPTION, efd.getDescription());
164
165 // execution spec
166 ExecutionSpec executionSpec = efd.getExecutionSpec();
167 String esName = executionSpec.getName();
168 if (!(esName == null || esName.equals(ExecutionSpec.INTERNAL_NAME))) {
169 Node executionSpecsNode = moduleNode.hasNode(SLC_EXECUTION_SPECS) ? moduleNode
170 .getNode(SLC_EXECUTION_SPECS) : moduleNode
171 .addNode(SLC_EXECUTION_SPECS);
172 Node executionSpecNode = executionSpecsNode.addNode(esName,
173 SlcTypes.SLC_EXECUTION_SPEC);
174 executionSpecNode.setProperty(SLC_NAME, esName);
175 executionSpecNode.setProperty(Property.JCR_TITLE, esName);
176 if (executionSpec.getDescription() != null
177 && !executionSpec.getDescription().trim().equals(""))
178 executionSpecNode.setProperty(Property.JCR_DESCRIPTION,
179 executionSpec.getDescription());
180 mapExecutionSpec(executionSpecNode, executionSpec);
181 flowNode.setProperty(SLC_SPEC, executionSpecNode);
182 } else {
183 mapExecutionSpec(flowNode, executionSpec);
184 }
185 return flowNode;
186 }
187
188 /**
189 * Base can be either an execution spec node, or an execution flow node (in
190 * case the execution spec is internal)
191 */
192 protected void mapExecutionSpec(Node baseNode, ExecutionSpec executionSpec)
193 throws RepositoryException {
194 for (String attrName : executionSpec.getAttributes().keySet()) {
195 ExecutionSpecAttribute esa = executionSpec.getAttributes().get(
196 attrName);
197 Node attrNode = baseNode.addNode(attrName);
198 // booleans
199 attrNode.addMixin(SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE);
200 attrNode.setProperty(SLC_IS_IMMUTABLE, esa.getIsImmutable());
201 attrNode.setProperty(SLC_IS_CONSTANT, esa.getIsConstant());
202 attrNode.setProperty(SLC_IS_HIDDEN, esa.getIsHidden());
203
204 if (esa instanceof PrimitiveSpecAttribute) {
205 attrNode.addMixin(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE);
206 PrimitiveSpecAttribute psa = (PrimitiveSpecAttribute) esa;
207 SlcJcrUtils.setPrimitiveAsProperty(attrNode, SLC_VALUE, psa);
208 attrNode.setProperty(SLC_TYPE, psa.getType());
209 } else if (esa instanceof RefSpecAttribute) {
210 attrNode.addMixin(SlcTypes.SLC_REF_SPEC_ATTRIBUTE);
211 RefSpecAttribute rsa = (RefSpecAttribute) esa;
212 attrNode.setProperty(SLC_TYPE, rsa.getTargetClassName());
213 if (rsa.getChoices() != null) {
214 for (RefValueChoice choice : rsa.getChoices()) {
215 Node choiceNode = attrNode.addNode(choice.getName());
216 choiceNode.addMixin(NodeType.MIX_TITLE);
217 choiceNode.setProperty(Property.JCR_TITLE,
218 choice.getName());
219 if (choice.getDescription() != null
220 && !choice.getDescription().trim().equals(""))
221 choiceNode.setProperty(Property.JCR_DESCRIPTION,
222 choice.getDescription());
223 }
224 }
225 }
226 }
227 }
228
229 public synchronized void executionFlowRemoved(ModuleDescriptor module,
230 ExecutionFlowDescriptor executionFlow) {
231 try {
232 Node agentNode = session.getNode(agent.getNodePath());
233 Node moduleNode = agentNode.getNode(SlcJcrUtils
234 .getModuleNodeName(module));
235 String relativePath = getExecutionFlowRelativePath(executionFlow);
236 if (!moduleNode.hasNode(relativePath))
237 moduleNode.getNode(relativePath).remove();
238 agentNode.getSession().save();
239 } catch (RepositoryException e) {
240 throw new SlcException("Cannot remove flow " + executionFlow
241 + " from module " + module, e);
242 }
243 }
244
245 /*
246 * UTILITIES
247 */
248 /** @return the relative path, never starts with '/' */
249 @SuppressWarnings("deprecation")
250 protected String getExecutionFlowRelativePath(
251 ExecutionFlowDescriptor executionFlow) {
252 String relativePath = executionFlow.getPath() == null ? executionFlow
253 .getName() : executionFlow.getPath() + '/'
254 + executionFlow.getName();
255 // we assume that it is more than one char long
256 if (relativePath.charAt(0) == '/')
257 relativePath = relativePath.substring(1);
258 return relativePath;
259 }
260
261 /*
262 * BEAN
263 */
264 public void setAgent(JcrAgent agent) {
265 this.agent = agent;
266 }
267
268 /** Expects a non-shared session with admin authorization */
269 public void setSession(Session session) {
270 this.session = session;
271 }
272
273 }