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