]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrUtils.java
Improve launcher
[gpl/argeo-slc.git] / runtime / org.argeo.slc.support.jcr / src / main / java / org / argeo / slc / jcr / SlcJcrUtils.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
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;
17
18 import java.util.Calendar;
19 import java.util.GregorianCalendar;
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.RepositoryException;
26 import javax.jcr.Session;
27 import javax.jcr.nodetype.NodeType;
28
29 import org.argeo.jcr.JcrUtils;
30 import org.argeo.jcr.UserJcrUtils;
31 import org.argeo.slc.SlcException;
32 import org.argeo.slc.core.execution.PrimitiveAccessor;
33 import org.argeo.slc.core.execution.PrimitiveUtils;
34 import org.argeo.slc.deploy.ModuleDescriptor;
35 import org.argeo.slc.test.TestStatus;
36
37 /**
38 * Utilities around the SLC JCR model. Note that it relies on fixed base paths
39 * (convention over configuration) for optimization purposes.
40 */
41 public class SlcJcrUtils implements SlcNames {
42 public final static Integer AGENT_FACTORY_DEPTH = 3;
43
44 /** Extracts the path of a flow relative to its execution module */
45 public static String flowRelativePath(String fullFlowPath) {
46 String[] tokens = fullFlowPath.split("/");
47 StringBuffer buf = new StringBuffer(fullFlowPath.length());
48 for (int i = AGENT_FACTORY_DEPTH + 3; i < tokens.length; i++) {
49 buf.append('/').append(tokens[i]);
50 }
51 return buf.toString();
52 }
53
54 /** Extracts the path to the related execution module */
55 public static String modulePath(String fullFlowPath) {
56 String[] tokens = fullFlowPath.split("/");
57 StringBuffer buf = new StringBuffer(fullFlowPath.length());
58 for (int i = 0; i < AGENT_FACTORY_DEPTH + 3; i++) {
59 if (!tokens[i].equals(""))
60 buf.append('/').append(tokens[i]);
61 }
62 return buf.toString();
63 }
64
65 /** Extracts the module name from a flow path */
66 public static String moduleName(String fullFlowPath) {
67 String[] tokens = fullFlowPath.split("/");
68 String moduleName = tokens[AGENT_FACTORY_DEPTH + 2];
69 moduleName = moduleName.substring(0, moduleName.indexOf('_'));
70 return moduleName;
71 }
72
73 /** Module node name based on module name and version */
74 public static String getModuleNodeName(ModuleDescriptor moduleDescriptor) {
75 return moduleDescriptor.getName() + "_" + moduleDescriptor.getVersion();
76 }
77
78 /** Extracts the agent factory of a flow */
79 public static String flowAgentFactoryPath(String fullFlowPath) {
80 String[] tokens = fullFlowPath.split("/");
81 StringBuffer buf = new StringBuffer(fullFlowPath.length());
82 // first token is always empty
83 for (int i = 1; i < AGENT_FACTORY_DEPTH + 1; i++) {
84 buf.append('/').append(tokens[i]);
85 }
86 return buf.toString();
87 }
88
89 /** Create a new execution process path based on the current time */
90 public static String createExecutionProcessPath(Session session, String uuid) {
91 Calendar now = new GregorianCalendar();
92 return getSlcProcessesBasePath(session) + '/'
93 + JcrUtils.dateAsPath(now, true) + uuid;
94 }
95
96 /** Get the base for the user processi. */
97 public static String getSlcProcessesBasePath(Session session) {
98 try {
99 Node userHome = UserJcrUtils.getUserHome(session);
100 if (userHome == null)
101 throw new SlcException("No user home available for "
102 + session.getUserID());
103 return userHome.getPath() + '/' + SlcNames.SLC_SYSTEM + '/'
104 + SlcNames.SLC_PROCESSES;
105 } catch (RepositoryException re) {
106 throw new SlcException(
107 "Unexpected error while getting Slc Results Base Path.", re);
108 }
109 }
110
111 /**
112 * Create a new execution result path in the user home based on the current
113 * time
114 */
115 public static String createResultPath(Session session, String uuid)
116 throws RepositoryException {
117 Calendar now = new GregorianCalendar();
118 StringBuffer absPath = new StringBuffer(
119 SlcJcrResultUtils.getSlcResultsBasePath(session) + '/');
120 // Remove hours and add title property to the result process path on
121 // request of O. Capillon
122 // return getSlcProcessesBasePath(session) + '/'
123 // + JcrUtils.dateAsPath(now, true) + uuid;
124 String relPath = JcrUtils.dateAsPath(now, false);
125 List<String> names = JcrUtils.tokenize(relPath);
126 for (String name : names) {
127 absPath.append(name + "/");
128 Node node = JcrUtils.mkdirs(session, absPath.toString());
129 try {
130 node.addMixin(NodeType.MIX_TITLE);
131 node.setProperty(Property.JCR_TITLE, name.substring(1));
132 } catch (RepositoryException e) {
133 throw new SlcException(
134 "unable to create execution process path", e);
135 }
136 }
137 return absPath.toString() + uuid;
138 }
139
140 /**
141 * Set the value of the primitive accessor as a JCR property. Does nothing
142 * if the value is null.
143 */
144 public static void setPrimitiveAsProperty(Node node, String propertyName,
145 PrimitiveAccessor primitiveAccessor) {
146 String type = primitiveAccessor.getType();
147 Object value = primitiveAccessor.getValue();
148 setPrimitiveAsProperty(node, propertyName, type, value);
149 }
150
151 /** Map a primitive value to JCR property value. */
152 public static void setPrimitiveAsProperty(Node node, String propertyName,
153 String type, Object value) {
154 if (value == null)
155 return;
156 if (value instanceof CharSequence)
157 value = PrimitiveUtils.convert(type,
158 ((CharSequence) value).toString());
159 if (value instanceof char[])
160 value = new String((char[]) value);
161
162 try {
163 if (type.equals(PrimitiveAccessor.TYPE_STRING))
164 node.setProperty(propertyName, value.toString());
165 else if (type.equals(PrimitiveAccessor.TYPE_PASSWORD))
166 node.setProperty(propertyName, value.toString());
167 else if (type.equals(PrimitiveAccessor.TYPE_INTEGER))
168 node.setProperty(propertyName, (long) ((Integer) value));
169 else if (type.equals(PrimitiveAccessor.TYPE_LONG))
170 node.setProperty(propertyName, ((Long) value));
171 else if (type.equals(PrimitiveAccessor.TYPE_FLOAT))
172 node.setProperty(propertyName, (double) ((Float) value));
173 else if (type.equals(PrimitiveAccessor.TYPE_DOUBLE))
174 node.setProperty(propertyName, ((Double) value));
175 else if (type.equals(PrimitiveAccessor.TYPE_BOOLEAN))
176 node.setProperty(propertyName, ((Boolean) value));
177 else
178 throw new SlcException("Unsupported type " + type);
179 } catch (RepositoryException e) {
180 throw new SlcException("Cannot set primitive of " + type
181 + " as property " + propertyName + " on " + node, e);
182 }
183 }
184
185 /** Aggregates the {@link TestStatus} of this sub-tree. */
186 public static Integer aggregateTestStatus(Node node) {
187 try {
188 Integer status = TestStatus.PASSED;
189 if (node.isNodeType(SlcTypes.SLC_CHECK))
190 if (node.getProperty(SLC_SUCCESS).getBoolean())
191 status = TestStatus.PASSED;
192 else if (node.hasProperty(SLC_ERROR_MESSAGE))
193 status = TestStatus.ERROR;
194 else
195 status = TestStatus.FAILED;
196
197 NodeIterator it = node.getNodes();
198 while (it.hasNext()) {
199 Node curr = it.nextNode();
200
201 // Manually skip aggregated status
202 if (!SlcNames.SLC_AGGREGATED_STATUS.equals(curr.getName())) {
203 Integer childStatus = aggregateTestStatus(curr);
204 if (childStatus > status)
205 status = childStatus;
206 }
207 }
208 return status;
209 } catch (Exception e) {
210 throw new SlcException("Could not aggregate test status from "
211 + node, e);
212 }
213 }
214
215 /**
216 * Aggregates the {@link TestStatus} of this sub-tree.
217 *
218 * @return the same {@link StringBuffer}, for convenience (typically calling
219 * toString() on it)
220 */
221 public static StringBuffer aggregateTestMessages(Node node,
222 StringBuffer messages) {
223 try {
224 if (node.isNodeType(SlcTypes.SLC_CHECK)) {
225 if (node.hasProperty(SLC_MESSAGE)) {
226 if (messages.length() > 0)
227 messages.append('\n');
228 messages.append(node.getProperty(SLC_MESSAGE).getString());
229 }
230 if (node.hasProperty(SLC_ERROR_MESSAGE)) {
231 if (messages.length() > 0)
232 messages.append('\n');
233 messages.append(node.getProperty(SLC_ERROR_MESSAGE)
234 .getString());
235 }
236 }
237 NodeIterator it = node.getNodes();
238 while (it.hasNext()) {
239 Node child = it.nextNode();
240 // Manually skip aggregated status
241 if (!SlcNames.SLC_AGGREGATED_STATUS.equals(child.getName())) {
242 aggregateTestMessages(child, messages);
243 }
244 }
245 return messages;
246 } catch (Exception e) {
247 throw new SlcException("Could not aggregate test messages from "
248 + node, e);
249 }
250 }
251
252 /** Prevents instantiation */
253 private SlcJcrUtils() {
254 }
255 }