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
.Repository
;
11 import javax
.jcr
.RepositoryException
;
12 import javax
.jcr
.Session
;
13 import javax
.jcr
.nodetype
.NodeType
;
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
;
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.
37 public class JcrExecutionModulesListener
implements ExecutionModulesListener
,
39 private final static String SLC_EXECUTION_MODULES_PROPERTY
= "slc.executionModules";
41 private final static Log log
= LogFactory
42 .getLog(JcrExecutionModulesListener
.class);
43 private JcrAgent agent
;
45 private ExecutionModulesManager modulesManager
;
47 private Repository repository
;
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.
53 private Session session
;
60 session
= repository
.login();
62 if (modulesManager
!= null) {
63 List
<ModuleDescriptor
> moduleDescriptors
= modulesManager
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(
75 Node moduleNode
= agentNode
76 .hasNode(moduleNodeName
) ? agentNode
77 .getNode(moduleNodeName
) : agentNode
78 .addNode(moduleNodeName
);
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);
97 } catch (RepositoryException e
) {
98 JcrUtils
.discardQuietly(session
);
99 JcrUtils
.logoutQuietly(session
);
100 throw new SlcException("Cannot initialize modules", e
);
104 public void destroy() {
106 JcrUtils
.logoutQuietly(session
);
109 protected synchronized void clearAgent() {
111 Node agentNode
= session
.getNode(agent
.getNodePath());
112 for (NodeIterator nit
= agentNode
.getNodes(); nit
.hasNext();)
113 nit
.nextNode().remove();
115 } catch (RepositoryException e
) {
116 JcrUtils
.discardQuietly(session
);
117 throw new SlcException("Cannot clear agent " + agent
, e
);
122 * EXECUTION MODULES LISTENER
124 public synchronized void executionModuleAdded(
125 ModuleDescriptor moduleDescriptor
) {
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);
142 } catch (RepositoryException e
) {
143 JcrUtils
.discardQuietly(session
);
144 throw new SlcException("Cannot add module " + moduleDescriptor
, e
);
149 public synchronized void executionModuleRemoved(
150 ModuleDescriptor moduleDescriptor
) {
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();
159 moduleNode
.setProperty(SLC_STARTED
, false);
162 } catch (RepositoryException e
) {
163 JcrUtils
.discardQuietly(session
);
164 throw new SlcException("Cannot remove module " + moduleDescriptor
,
169 public synchronized void executionFlowAdded(ModuleDescriptor module
,
170 ExecutionFlowDescriptor efd
) {
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
,
183 flowNode
= moduleNode
.getNode(relativePath
);
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 "
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("/"))
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
);
210 currNode
= currNode
.addNode(name
);
212 flowNode
= currNode
.addNode(name
,
213 SlcTypes
.SLC_EXECUTION_FLOW
);
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());
226 flowNode
.setProperty(Property
.JCR_DESCRIPTION
, endName
);
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
);
248 // internal spec node
249 mapExecutionSpec(flowNode
, executionSpec
);
253 for (String attr
: efd
.getValues().keySet()) {
254 ExecutionSpecAttribute esa
= executionSpec
.getAttributes()
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
));
269 * Base can be either an execution spec node, or an execution flow node (in
270 * case the execution spec is internal)
272 protected void mapExecutionSpec(Node baseNode
, ExecutionSpec executionSpec
)
273 throws RepositoryException
{
274 for (String attrName
: executionSpec
.getAttributes().keySet()) {
275 ExecutionSpecAttribute esa
= executionSpec
.getAttributes().get(
277 Node attrNode
= baseNode
.addNode(attrName
);
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());
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
,
299 if (choice
.getDescription() != null
300 && !choice
.getDescription().trim().equals(""))
301 choiceNode
.setProperty(Property
.JCR_DESCRIPTION
,
302 choice
.getDescription());
309 public synchronized void executionFlowRemoved(ModuleDescriptor module
,
310 ExecutionFlowDescriptor executionFlow
) {
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
);
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("//", "/");
346 public void setAgent(JcrAgent agent
) {
350 public void setRepository(Repository repository
) {
351 this.repository
= repository
;
354 public void setModulesManager(ExecutionModulesManager modulesManager
) {
355 this.modulesManager
= modulesManager
;