]> 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
Remove deprecated APIs
[gpl/argeo-slc.git] / runtime / org.argeo.slc.support.jcr / src / main / java / org / argeo / slc / jcr / execution / JcrExecutionModulesListener.java
1 /*
2 * Copyright (C) 2007-2012 Mathieu Baudier
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.slc.jcr.execution;
17
18 import java.util.Arrays;
19 import java.util.Iterator;
20 import java.util.List;
21
22 import javax.jcr.Node;
23 import javax.jcr.NodeIterator;
24 import javax.jcr.Property;
25 import javax.jcr.Repository;
26 import javax.jcr.RepositoryException;
27 import javax.jcr.Session;
28 import javax.jcr.nodetype.NodeType;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.argeo.jcr.JcrUtils;
33 import org.argeo.slc.SlcException;
34 import org.argeo.slc.core.execution.PrimitiveSpecAttribute;
35 import org.argeo.slc.core.execution.PrimitiveValue;
36 import org.argeo.slc.core.execution.RefSpecAttribute;
37 import org.argeo.slc.core.execution.RefValueChoice;
38 import org.argeo.slc.deploy.ModuleDescriptor;
39 import org.argeo.slc.execution.ExecutionFlowDescriptor;
40 import org.argeo.slc.execution.ExecutionModuleDescriptor;
41 import org.argeo.slc.execution.ExecutionModulesListener;
42 import org.argeo.slc.execution.ExecutionModulesManager;
43 import org.argeo.slc.execution.ExecutionSpec;
44 import org.argeo.slc.execution.ExecutionSpecAttribute;
45 import org.argeo.slc.jcr.SlcJcrUtils;
46 import org.argeo.slc.jcr.SlcNames;
47 import org.argeo.slc.jcr.SlcTypes;
48
49 /**
50 * Synchronizes the local execution runtime with a JCR repository. For the time
51 * being the state is completely reset from one start to another.
52 */
53 public class JcrExecutionModulesListener implements ExecutionModulesListener,
54 SlcNames {
55 private final static String SLC_EXECUTION_MODULES_PROPERTY = "slc.executionModules";
56
57 private final static Log log = LogFactory
58 .getLog(JcrExecutionModulesListener.class);
59 private JcrAgent agent;
60
61 private ExecutionModulesManager modulesManager;
62
63 private Repository repository;
64 /**
65 * We don't use a thread bound session because many different threads will
66 * call this critical component and we don't want to login each time. We
67 * therefore rather protect access to this session via synchronized.
68 */
69 private Session session;
70
71 /*
72 * LIFECYCLE
73 */
74 public void init() {
75 try {
76 session = repository.login();
77 clearAgent();
78 if (modulesManager != null) {
79 Node agentNode = session.getNode(agent.getNodePath());
80
81 List<ModuleDescriptor> moduleDescriptors = modulesManager
82 .listModules();
83
84 // scan SLC-ExecutionModule metadata
85 for (ModuleDescriptor md : moduleDescriptors) {
86 if (md.getMetadata().containsKey(
87 ExecutionModuleDescriptor.SLC_EXECUTION_MODULE)) {
88 String moduleNodeName = SlcJcrUtils
89 .getModuleNodeName(md);
90 Node moduleNode = agentNode.hasNode(moduleNodeName) ? agentNode
91 .getNode(moduleNodeName) : agentNode
92 .addNode(moduleNodeName);
93 moduleNode.addMixin(SlcTypes.SLC_EXECUTION_MODULE);
94 moduleNode.setProperty(SLC_NAME, md.getName());
95 moduleNode.setProperty(SLC_VERSION, md.getVersion());
96 moduleNode.setProperty(Property.JCR_TITLE,
97 md.getTitle());
98 moduleNode.setProperty(Property.JCR_DESCRIPTION,
99 md.getDescription());
100 moduleNode.setProperty(SLC_STARTED, md.getStarted());
101 }
102 }
103
104 // scan execution modules property
105 String executionModules = System
106 .getProperty(SLC_EXECUTION_MODULES_PROPERTY);
107 if (executionModules != null) {
108 for (String executionModule : executionModules.split(",")) {
109 allModules: for (ModuleDescriptor md : moduleDescriptors) {
110 String moduleNodeName = SlcJcrUtils
111 .getModuleNodeName(md);
112 if (md.getName().equals(executionModule)) {
113 Node moduleNode = agentNode
114 .hasNode(moduleNodeName) ? agentNode
115 .getNode(moduleNodeName) : agentNode
116 .addNode(moduleNodeName);
117 moduleNode
118 .addMixin(SlcTypes.SLC_EXECUTION_MODULE);
119 moduleNode.setProperty(SLC_NAME, md.getName());
120 moduleNode.setProperty(SLC_VERSION,
121 md.getVersion());
122 moduleNode.setProperty(Property.JCR_TITLE,
123 md.getTitle());
124 moduleNode.setProperty(
125 Property.JCR_DESCRIPTION,
126 md.getDescription());
127 moduleNode.setProperty(SLC_STARTED,
128 md.getStarted());
129 break allModules;
130 }
131 }
132 }
133
134 // save if needed
135 if (session.hasPendingChanges())
136 session.save();
137 }
138 }
139 } catch (RepositoryException e) {
140 JcrUtils.discardQuietly(session);
141 JcrUtils.logoutQuietly(session);
142 throw new SlcException("Cannot initialize modules", e);
143 }
144 }
145
146 public void destroy() {
147 clearAgent();
148 JcrUtils.logoutQuietly(session);
149 }
150
151 protected synchronized void clearAgent() {
152 try {
153 Node agentNode = session.getNode(agent.getNodePath());
154 for (NodeIterator nit = agentNode.getNodes(); nit.hasNext();)
155 nit.nextNode().remove();
156 session.save();
157 } catch (RepositoryException e) {
158 JcrUtils.discardQuietly(session);
159 throw new SlcException("Cannot clear agent " + agent, e);
160 }
161 }
162
163 /*
164 * EXECUTION MODULES LISTENER
165 */
166
167 public synchronized void executionModuleAdded(
168 ModuleDescriptor moduleDescriptor) {
169 syncExecutionModule(moduleDescriptor);
170 }
171
172 protected void syncExecutionModule(ModuleDescriptor moduleDescriptor) {
173 try {
174 Node agentNode = session.getNode(agent.getNodePath());
175 String moduleNodeName = SlcJcrUtils
176 .getModuleNodeName(moduleDescriptor);
177 Node moduleNode = agentNode.hasNode(moduleNodeName) ? agentNode
178 .getNode(moduleNodeName) : agentNode
179 .addNode(moduleNodeName);
180 moduleNode.addMixin(SlcTypes.SLC_EXECUTION_MODULE);
181 moduleNode.setProperty(SLC_NAME, moduleDescriptor.getName());
182 moduleNode.setProperty(SLC_VERSION, moduleDescriptor.getVersion());
183 moduleNode.setProperty(Property.JCR_TITLE,
184 moduleDescriptor.getTitle());
185 moduleNode.setProperty(Property.JCR_DESCRIPTION,
186 moduleDescriptor.getDescription());
187 moduleNode.setProperty(SLC_STARTED, moduleDescriptor.getStarted());
188 session.save();
189 } catch (RepositoryException e) {
190 JcrUtils.discardQuietly(session);
191 throw new SlcException("Cannot sync module " + moduleDescriptor, e);
192 }
193 }
194
195 public synchronized void executionModuleRemoved(
196 ModuleDescriptor moduleDescriptor) {
197 try {
198 String moduleName = SlcJcrUtils.getModuleNodeName(moduleDescriptor);
199 Node agentNode = session.getNode(agent.getNodePath());
200 if (agentNode.hasNode(moduleName)) {
201 Node moduleNode = agentNode.getNode(moduleName);
202 for (NodeIterator nit = moduleNode.getNodes(); nit.hasNext();) {
203 nit.nextNode().remove();
204 }
205 moduleNode.setProperty(SLC_STARTED, false);
206 }
207 session.save();
208 } catch (RepositoryException e) {
209 JcrUtils.discardQuietly(session);
210 throw new SlcException("Cannot remove module " + moduleDescriptor,
211 e);
212 }
213 }
214
215 public synchronized void executionFlowAdded(ModuleDescriptor module,
216 ExecutionFlowDescriptor efd) {
217 try {
218 Node agentNode = session.getNode(agent.getNodePath());
219 Node moduleNode = agentNode.getNode(SlcJcrUtils
220 .getModuleNodeName(module));
221 String relativePath = getExecutionFlowRelativePath(efd);
222 @SuppressWarnings("unused")
223 Node flowNode = null;
224 if (!moduleNode.hasNode(relativePath)) {
225 flowNode = createExecutionFlowNode(moduleNode, relativePath,
226 efd);
227 session.save();
228 } else {
229 flowNode = moduleNode.getNode(relativePath);
230 }
231
232 if (log.isTraceEnabled())
233 log.trace("Flow " + efd + " added to JCR");
234 } catch (RepositoryException e) {
235 JcrUtils.discardQuietly(session);
236 throw new SlcException("Cannot add flow " + efd + " from module "
237 + module, e);
238 }
239
240 }
241
242 protected Node createExecutionFlowNode(Node moduleNode,
243 String relativePath, ExecutionFlowDescriptor efd)
244 throws RepositoryException {
245 Node flowNode = null;
246 Iterator<String> names = Arrays.asList(relativePath.split("/"))
247 .iterator();
248 // create intermediary paths
249 Node currNode = moduleNode;
250 while (names.hasNext()) {
251 String name = names.next();
252 if (currNode.hasNode(name))
253 currNode = currNode.getNode(name);
254 else {
255 if (names.hasNext())
256 currNode = currNode.addNode(name);
257 else
258 flowNode = currNode.addNode(name,
259 SlcTypes.SLC_EXECUTION_FLOW);
260 }
261 }
262
263 // name, description
264 flowNode.setProperty(SLC_NAME, efd.getName());
265 String[] tokens = relativePath.split("/");
266 String endName = tokens[tokens.length - 1];
267 flowNode.setProperty(Property.JCR_TITLE, endName);
268 if (efd.getDescription() != null
269 && !efd.getDescription().trim().equals("")) {
270 flowNode.setProperty(Property.JCR_DESCRIPTION, efd.getDescription());
271 } else {
272 flowNode.setProperty(Property.JCR_DESCRIPTION, endName);
273 }
274
275 // execution spec
276 ExecutionSpec executionSpec = efd.getExecutionSpec();
277 String esName = executionSpec.getName();
278 if (!(esName == null || esName.equals(ExecutionSpec.INTERNAL_NAME))) {
279 // reference spec node
280 Node executionSpecsNode = moduleNode.hasNode(SLC_EXECUTION_SPECS) ? moduleNode
281 .getNode(SLC_EXECUTION_SPECS) : moduleNode
282 .addNode(SLC_EXECUTION_SPECS);
283 Node executionSpecNode = executionSpecsNode.addNode(esName,
284 SlcTypes.SLC_EXECUTION_SPEC);
285 executionSpecNode.setProperty(SLC_NAME, esName);
286 executionSpecNode.setProperty(Property.JCR_TITLE, esName);
287 if (executionSpec.getDescription() != null
288 && !executionSpec.getDescription().trim().equals(""))
289 executionSpecNode.setProperty(Property.JCR_DESCRIPTION,
290 executionSpec.getDescription());
291 mapExecutionSpec(executionSpecNode, executionSpec);
292 flowNode.setProperty(SLC_SPEC, executionSpecNode);
293 } else {
294 // internal spec node
295 mapExecutionSpec(flowNode, executionSpec);
296 }
297
298 // values
299 for (String attr : efd.getValues().keySet()) {
300 ExecutionSpecAttribute esa = executionSpec.getAttributes()
301 .get(attr);
302 if (esa instanceof PrimitiveSpecAttribute) {
303 PrimitiveSpecAttribute psa = (PrimitiveSpecAttribute) esa;
304 Node valueNode = flowNode.addNode(attr);
305 valueNode.setProperty(SLC_TYPE, psa.getType());
306 SlcJcrUtils.setPrimitiveAsProperty(valueNode, SLC_VALUE,
307 (PrimitiveValue) efd.getValues().get(attr));
308 }
309 }
310
311 return flowNode;
312 }
313
314 /**
315 * Base can be either an execution spec node, or an execution flow node (in
316 * case the execution spec is internal)
317 */
318 protected void mapExecutionSpec(Node baseNode, ExecutionSpec executionSpec)
319 throws RepositoryException {
320 for (String attrName : executionSpec.getAttributes().keySet()) {
321 ExecutionSpecAttribute esa = executionSpec.getAttributes().get(
322 attrName);
323 Node attrNode = baseNode.addNode(attrName);
324 // booleans
325 attrNode.addMixin(SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE);
326 attrNode.setProperty(SLC_IS_IMMUTABLE, esa.getIsImmutable());
327 attrNode.setProperty(SLC_IS_CONSTANT, esa.getIsConstant());
328 attrNode.setProperty(SLC_IS_HIDDEN, esa.getIsHidden());
329
330 if (esa instanceof PrimitiveSpecAttribute) {
331 attrNode.addMixin(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE);
332 PrimitiveSpecAttribute psa = (PrimitiveSpecAttribute) esa;
333 SlcJcrUtils.setPrimitiveAsProperty(attrNode, SLC_VALUE, psa);
334 attrNode.setProperty(SLC_TYPE, psa.getType());
335 } else if (esa instanceof RefSpecAttribute) {
336 attrNode.addMixin(SlcTypes.SLC_REF_SPEC_ATTRIBUTE);
337 RefSpecAttribute rsa = (RefSpecAttribute) esa;
338 attrNode.setProperty(SLC_TYPE, rsa.getTargetClassName());
339 Object value = rsa.getValue();
340 if (rsa.getChoices() != null) {
341 Integer index = null;
342 int count = 0;
343 for (RefValueChoice choice : rsa.getChoices()) {
344 String name = choice.getName();
345 if (value != null && name.equals(value.toString()))
346 index = count;
347 Node choiceNode = attrNode.addNode(choice.getName());
348 choiceNode.addMixin(NodeType.MIX_TITLE);
349 choiceNode.setProperty(Property.JCR_TITLE,
350 choice.getName());
351 if (choice.getDescription() != null
352 && !choice.getDescription().trim().equals(""))
353 choiceNode.setProperty(Property.JCR_DESCRIPTION,
354 choice.getDescription());
355 count++;
356 }
357
358 if (index != null)
359 attrNode.setProperty(SLC_VALUE, index);
360 }
361 }
362 }
363 }
364
365 public synchronized void executionFlowRemoved(ModuleDescriptor module,
366 ExecutionFlowDescriptor executionFlow) {
367 try {
368 Node agentNode = session.getNode(agent.getNodePath());
369 Node moduleNode = agentNode.getNode(SlcJcrUtils
370 .getModuleNodeName(module));
371 String relativePath = getExecutionFlowRelativePath(executionFlow);
372 if (moduleNode.hasNode(relativePath))
373 moduleNode.getNode(relativePath).remove();
374 agentNode.getSession().save();
375 } catch (RepositoryException e) {
376 throw new SlcException("Cannot remove flow " + executionFlow
377 + " from module " + module, e);
378 }
379 }
380
381 /*
382 * UTILITIES
383 */
384 /** @return the relative path, never starts with '/' */
385 @SuppressWarnings("deprecation")
386 protected String getExecutionFlowRelativePath(
387 ExecutionFlowDescriptor executionFlow) {
388 String relativePath = executionFlow.getPath() == null ? executionFlow
389 .getName() : executionFlow.getPath() + '/'
390 + executionFlow.getName();
391 // we assume that it is more than one char long
392 if (relativePath.charAt(0) == '/')
393 relativePath = relativePath.substring(1);
394 // FIXME quick hack to avoid duplicate '/'
395 relativePath = relativePath.replaceAll("//", "/");
396 return relativePath;
397 }
398
399 /*
400 * BEAN
401 */
402 public void setAgent(JcrAgent agent) {
403 this.agent = agent;
404 }
405
406 public void setRepository(Repository repository) {
407 this.repository = repository;
408 }
409
410 public void setModulesManager(ExecutionModulesManager modulesManager) {
411 this.modulesManager = modulesManager;
412 }
413
414 }