1 package org
.argeo
.slc
.jcr
.execution
;
3 import java
.util
.Arrays
;
4 import java
.util
.Iterator
;
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
;
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
;
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.
36 public class JcrExecutionModulesListener
implements ExecutionModulesListener
,
38 private final static String SLC_EXECUTION_MODULES_PROPERTY
= "slc.executionModules";
40 private final static Log log
= LogFactory
41 .getLog(JcrExecutionModulesListener
.class);
42 private JcrAgent agent
;
44 private ExecutionModulesManager modulesManager
;
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.
51 private Session session
;
58 if (modulesManager
!= null) {
59 List
<ModuleDescriptor
> moduleDescriptors
= modulesManager
61 String executionModules
= System
62 .getProperty(SLC_EXECUTION_MODULES_PROPERTY
);
63 if (executionModules
!= null)
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(
72 Node moduleNode
= agentNode
73 .hasNode(moduleNodeName
) ? agentNode
74 .getNode(moduleNodeName
) : agentNode
75 .addNode(moduleNodeName
);
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);
92 } catch (RepositoryException e
) {
93 JcrUtils
.discardQuietly(session
);
94 throw new SlcException("Cannot initialize modules", e
);
99 public void dispose() {
104 protected synchronized void clearAgent() {
106 Node agentNode
= session
.getNode(agent
.getNodePath());
107 for (NodeIterator nit
= agentNode
.getNodes(); nit
.hasNext();)
108 nit
.nextNode().remove();
110 } catch (RepositoryException e
) {
111 JcrUtils
.discardQuietly(session
);
112 throw new SlcException("Cannot clear agent " + agent
, e
);
117 * EXECUTION MODULES LISTENER
119 public synchronized void executionModuleAdded(
120 ModuleDescriptor moduleDescriptor
) {
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);
137 } catch (RepositoryException e
) {
138 JcrUtils
.discardQuietly(session
);
139 throw new SlcException("Cannot add module " + moduleDescriptor
, e
);
144 public synchronized void executionModuleRemoved(
145 ModuleDescriptor moduleDescriptor
) {
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();
154 moduleNode
.setProperty(SLC_STARTED
, false);
157 } catch (RepositoryException e
) {
158 JcrUtils
.discardQuietly(session
);
159 throw new SlcException("Cannot remove module " + moduleDescriptor
,
164 public synchronized void executionFlowAdded(ModuleDescriptor module
,
165 ExecutionFlowDescriptor efd
) {
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
,
178 flowNode
= moduleNode
.getNode(relativePath
);
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 "
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("/"))
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
);
205 currNode
= currNode
.addNode(name
);
207 flowNode
= currNode
.addNode(name
,
208 SlcTypes
.SLC_EXECUTION_FLOW
);
213 flowNode
.setProperty(SLC_NAME
, efd
.getName());
214 String
[] tokens
= relativePath
.split("/");
215 String endName
= tokens
[tokens
.length
- 1];
216 if (efd
.getDescription() != null
217 && !efd
.getDescription().trim().equals("")) {
218 flowNode
.setProperty(Property
.JCR_TITLE
, efd
.getDescription());
220 flowNode
.setProperty(Property
.JCR_TITLE
, endName
);
222 flowNode
.setProperty(Property
.JCR_DESCRIPTION
, endName
);
225 ExecutionSpec executionSpec
= efd
.getExecutionSpec();
226 String esName
= executionSpec
.getName();
227 if (!(esName
== null || esName
.equals(ExecutionSpec
.INTERNAL_NAME
))) {
228 // reference spec node
229 Node executionSpecsNode
= moduleNode
.hasNode(SLC_EXECUTION_SPECS
) ? moduleNode
230 .getNode(SLC_EXECUTION_SPECS
) : moduleNode
231 .addNode(SLC_EXECUTION_SPECS
);
232 Node executionSpecNode
= executionSpecsNode
.addNode(esName
,
233 SlcTypes
.SLC_EXECUTION_SPEC
);
234 executionSpecNode
.setProperty(SLC_NAME
, esName
);
235 executionSpecNode
.setProperty(Property
.JCR_TITLE
, esName
);
236 if (executionSpec
.getDescription() != null
237 && !executionSpec
.getDescription().trim().equals(""))
238 executionSpecNode
.setProperty(Property
.JCR_DESCRIPTION
,
239 executionSpec
.getDescription());
240 mapExecutionSpec(executionSpecNode
, executionSpec
);
241 flowNode
.setProperty(SLC_SPEC
, executionSpecNode
);
243 // internal spec node
244 mapExecutionSpec(flowNode
, executionSpec
);
248 for (String attr
: efd
.getValues().keySet()) {
249 ExecutionSpecAttribute esa
= executionSpec
.getAttributes()
251 if (esa
instanceof PrimitiveSpecAttribute
) {
252 PrimitiveSpecAttribute psa
= (PrimitiveSpecAttribute
) esa
;
253 Node valueNode
= flowNode
.addNode(attr
);
254 valueNode
.setProperty(SLC_TYPE
, psa
.getType());
255 SlcJcrUtils
.setPrimitiveAsProperty(valueNode
, SLC_VALUE
,
256 (PrimitiveValue
) efd
.getValues().get(attr
));
264 * Base can be either an execution spec node, or an execution flow node (in
265 * case the execution spec is internal)
267 protected void mapExecutionSpec(Node baseNode
, ExecutionSpec executionSpec
)
268 throws RepositoryException
{
269 for (String attrName
: executionSpec
.getAttributes().keySet()) {
270 ExecutionSpecAttribute esa
= executionSpec
.getAttributes().get(
272 Node attrNode
= baseNode
.addNode(attrName
);
274 attrNode
.addMixin(SlcTypes
.SLC_EXECUTION_SPEC_ATTRIBUTE
);
275 attrNode
.setProperty(SLC_IS_IMMUTABLE
, esa
.getIsImmutable());
276 attrNode
.setProperty(SLC_IS_CONSTANT
, esa
.getIsConstant());
277 attrNode
.setProperty(SLC_IS_HIDDEN
, esa
.getIsHidden());
279 if (esa
instanceof PrimitiveSpecAttribute
) {
280 attrNode
.addMixin(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
);
281 PrimitiveSpecAttribute psa
= (PrimitiveSpecAttribute
) esa
;
282 SlcJcrUtils
.setPrimitiveAsProperty(attrNode
, SLC_VALUE
, psa
);
283 attrNode
.setProperty(SLC_TYPE
, psa
.getType());
284 } else if (esa
instanceof RefSpecAttribute
) {
285 attrNode
.addMixin(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
);
286 RefSpecAttribute rsa
= (RefSpecAttribute
) esa
;
287 attrNode
.setProperty(SLC_TYPE
, rsa
.getTargetClassName());
288 if (rsa
.getChoices() != null) {
289 for (RefValueChoice choice
: rsa
.getChoices()) {
290 Node choiceNode
= attrNode
.addNode(choice
.getName());
291 choiceNode
.addMixin(NodeType
.MIX_TITLE
);
292 choiceNode
.setProperty(Property
.JCR_TITLE
,
294 if (choice
.getDescription() != null
295 && !choice
.getDescription().trim().equals(""))
296 choiceNode
.setProperty(Property
.JCR_DESCRIPTION
,
297 choice
.getDescription());
304 public synchronized void executionFlowRemoved(ModuleDescriptor module
,
305 ExecutionFlowDescriptor executionFlow
) {
307 Node agentNode
= session
.getNode(agent
.getNodePath());
308 Node moduleNode
= agentNode
.getNode(SlcJcrUtils
309 .getModuleNodeName(module
));
310 String relativePath
= getExecutionFlowRelativePath(executionFlow
);
311 if (!moduleNode
.hasNode(relativePath
))
312 moduleNode
.getNode(relativePath
).remove();
313 agentNode
.getSession().save();
314 } catch (RepositoryException e
) {
315 throw new SlcException("Cannot remove flow " + executionFlow
316 + " from module " + module
, e
);
323 /** @return the relative path, never starts with '/' */
324 @SuppressWarnings("deprecation")
325 protected String
getExecutionFlowRelativePath(
326 ExecutionFlowDescriptor executionFlow
) {
327 String relativePath
= executionFlow
.getPath() == null ? executionFlow
328 .getName() : executionFlow
.getPath() + '/'
329 + executionFlow
.getName();
330 // we assume that it is more than one char long
331 if (relativePath
.charAt(0) == '/')
332 relativePath
= relativePath
.substring(1);
333 // FIXME quick hack to avoid duplicate '/'
334 relativePath
= relativePath
.replaceAll("//", "/");
341 public void setAgent(JcrAgent agent
) {
345 /** Expects a non-shared session with admin authorization */
346 public void setSession(Session session
) {
347 this.session
= session
;
350 public void setModulesManager(ExecutionModulesManager modulesManager
) {
351 this.modulesManager
= modulesManager
;