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