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