1 package org
.argeo
.slc
.jcr
;
4 import java
.util
.GregorianCalendar
;
5 import java
.util
.HashMap
;
9 import javax
.jcr
.Credentials
;
10 import javax
.jcr
.Node
;
11 import javax
.jcr
.Property
;
12 import javax
.jcr
.PropertyIterator
;
13 import javax
.jcr
.Repository
;
14 import javax
.jcr
.Session
;
15 import javax
.jcr
.query
.Query
;
16 import javax
.jcr
.query
.QueryManager
;
18 import org
.apache
.commons
.logging
.Log
;
19 import org
.apache
.commons
.logging
.LogFactory
;
20 import org
.argeo
.jcr
.JcrUtils
;
21 import org
.argeo
.slc
.SlcException
;
22 import org
.argeo
.slc
.SlcNames
;
23 import org
.argeo
.slc
.SlcTypes
;
24 import org
.argeo
.slc
.attachment
.Attachment
;
25 import org
.argeo
.slc
.attachment
.AttachmentsEnabled
;
26 import org
.argeo
.slc
.test
.TestResult
;
27 import org
.argeo
.slc
.test
.TestResultPart
;
28 import org
.argeo
.slc
.test
.TestRun
;
29 import org
.argeo
.slc
.test
.TestStatus
;
32 * {@link TestResult} wrapping a JCR node of type
33 * {@link SlcTypes#SLC_TEST_RESULT}.
35 public class JcrTestResult
implements TestResult
, SlcNames
, AttachmentsEnabled
{
36 private final static Log log
= LogFactory
.getLog(JcrTestResult
.class);
38 /** Should only be set for an already existing result. */
40 private Repository repository
;
41 private Session session
;
43 * For testing purposes, best practice is to not set them explicitely but
44 * via other mechanisms such as JAAS or SPring Security.
46 private Credentials credentials
= null;
47 private String resultType
= SlcTypes
.SLC_TEST_RESULT
;
49 /** cached for performance purposes */
50 private String nodeIdentifier
= null;
52 private Map
<String
, String
> attributes
= new HashMap
<String
, String
>();
56 session
= repository
.login(credentials
);
59 uuid
= UUID
.randomUUID().toString();
60 String path
= SlcJcrUtils
.createResultPath(session
, uuid
);
61 Node resultNode
= JcrUtils
.mkdirs(session
, path
, resultType
);
62 resultNode
.setProperty(SLC_UUID
, uuid
);
63 for (String attr
: attributes
.keySet()) {
64 String property
= attr
;
65 // compatibility with legacy applications
66 if ("testCase".equals(attr
))
67 property
= SLC_TEST_CASE
;
68 else if ("testCaseType".equals(attr
))
69 property
= SLC_TEST_CASE_TYPE
;
70 resultNode
.setProperty(property
, attributes
.get(attr
));
73 if (log
.isDebugEnabled())
74 log
.debug("Created test result " + uuid
);
76 } catch (Exception e
) {
77 JcrUtils
.discardQuietly(session
);
78 throw new SlcException("Cannot initialize JCR result", e
);
82 public void destroy() {
83 JcrUtils
.logoutQuietly(session
);
84 if (log
.isTraceEnabled())
85 log
.trace("Logged out session for result " + uuid
);
88 public Node
getNode() {
91 if (nodeIdentifier
!= null) {
92 return session
.getNodeByIdentifier(nodeIdentifier
);
94 QueryManager qm
= session
.getWorkspace().getQueryManager();
95 Query q
= qm
.createQuery("select * from ["
96 + SlcTypes
.SLC_TEST_RESULT
+ "] where [slc:uuid]='"
97 + uuid
+ "'", Query
.JCR_SQL2
);
98 resultNode
= JcrUtils
.querySingleNode(q
);
99 if (resultNode
!= null)
100 nodeIdentifier
= resultNode
.getIdentifier();
103 } catch (Exception e
) {
104 throw new SlcException("Cannot get result node", e
);
108 public void notifyTestRun(TestRun testRun
) {
109 // TODO store meta data about the test running
110 // if (log.isDebugEnabled())
111 // log.debug("Running test "
112 // + testRun.getTestDefinition().getClass().getName() + "...");
115 public void addResultPart(TestResultPart testResultPart
) {
116 Node node
= getNode();
119 // error : revert all unsaved changes on the resultNode to be sure
120 // it is in a consistant state
121 if (testResultPart
.getExceptionMessage() != null)
122 JcrUtils
.discardQuietly(node
.getSession());
123 node
.getSession().save();
125 // add the new result part, retrieving status information
126 Node resultPartNode
= node
.addNode(SlcNames
.SLC_RESULT_PART
,
128 resultPartNode
.setProperty(SLC_SUCCESS
, testResultPart
.getStatus()
129 .equals(TestStatus
.PASSED
));
130 if (testResultPart
.getMessage() != null)
131 resultPartNode
.setProperty(SLC_MESSAGE
,
132 testResultPart
.getMessage());
133 if (testResultPart
.getStatus().equals(TestStatus
.ERROR
)) {
134 resultPartNode
.setProperty(SLC_ERROR_MESSAGE
,
135 (testResultPart
.getExceptionMessage() == null) ?
""
136 : testResultPart
.getExceptionMessage());
139 // helper update aggregate status node
141 if (!node
.hasNode(SLC_AGGREGATED_STATUS
)) {
143 mainStatus
= node
.addNode(SLC_AGGREGATED_STATUS
,
145 mainStatus
.setProperty(SLC_SUCCESS
,
146 resultPartNode
.getProperty(SLC_SUCCESS
).getBoolean());
147 if (resultPartNode
.hasProperty(SLC_MESSAGE
))
148 mainStatus
.setProperty(SLC_MESSAGE
, resultPartNode
149 .getProperty(SLC_MESSAGE
).getString());
150 if (resultPartNode
.hasProperty(SLC_ERROR_MESSAGE
))
151 mainStatus
.setProperty(SLC_ERROR_MESSAGE
, resultPartNode
152 .getProperty(SLC_ERROR_MESSAGE
).getString());
154 mainStatus
= node
.getNode(SLC_AGGREGATED_STATUS
);
155 if (mainStatus
.hasProperty(SLC_ERROR_MESSAGE
)) {
156 // main status already in error we do nothing
157 } else if (resultPartNode
.hasProperty(SLC_ERROR_MESSAGE
)) {
158 // main status was not in error and new result part is in
159 // error; we update main status
160 mainStatus
.setProperty(SLC_SUCCESS
, false);
161 mainStatus
.setProperty(SLC_ERROR_MESSAGE
, resultPartNode
162 .getProperty(SLC_ERROR_MESSAGE
).getString());
163 if (resultPartNode
.hasProperty(SLC_MESSAGE
))
164 mainStatus
.setProperty(SLC_MESSAGE
, resultPartNode
165 .getProperty(SLC_MESSAGE
).getString());
167 // remove old message to remain consistent
168 mainStatus
.setProperty(SLC_MESSAGE
, "");
169 } else if (!mainStatus
.getProperty(SLC_SUCCESS
).getBoolean()) {
170 // main status was already failed and new result part is not
171 // in error, we do nothing
172 } else if (!resultPartNode
.getProperty(SLC_SUCCESS
)
174 // new resultPart that is failed
175 mainStatus
.setProperty(SLC_SUCCESS
, false);
176 if (resultPartNode
.hasProperty(SLC_MESSAGE
))
177 mainStatus
.setProperty(SLC_MESSAGE
, resultPartNode
178 .getProperty(SLC_MESSAGE
).getString());
180 // remove old message to remain consistent
181 mainStatus
.setProperty(SLC_MESSAGE
, "");
182 } else if (resultPartNode
.hasProperty(SLC_MESSAGE
)
183 && (!mainStatus
.hasProperty(SLC_MESSAGE
) || (""
184 .equals(mainStatus
.getProperty(SLC_MESSAGE
)
185 .getString().trim())))) {
186 mainStatus
.setProperty(SLC_MESSAGE
, resultPartNode
187 .getProperty(SLC_MESSAGE
).getString());
190 JcrUtils
.updateLastModified(node
);
191 node
.getSession().save();
192 } catch (Exception e
) {
193 JcrUtils
.discardUnderlyingSessionQuietly(node
);
194 throw new SlcException("Cannot add ResultPart to node " + node
, e
);
198 public String
getUuid() {
199 Node node
= getNode();
201 return node
.getProperty(SLC_UUID
).getString();
202 } catch (Exception e
) {
203 throw new SlcException("Cannot get UUID from " + node
, e
);
207 /** JCR session is NOT logged out */
208 public void close() {
209 Node node
= getNode();
211 if (node
.hasNode(SLC_COMPLETED
))
213 node
.setProperty(SLC_COMPLETED
, new GregorianCalendar());
214 JcrUtils
.updateLastModified(node
);
215 node
.getSession().save();
216 } catch (Exception e
) {
217 JcrUtils
.discardUnderlyingSessionQuietly(node
);
218 throw new SlcException("Cannot get close date from " + node
, e
);
222 public Date
getCloseDate() {
223 Node node
= getNode();
225 if (!node
.hasNode(SLC_COMPLETED
))
227 return node
.getProperty(SLC_COMPLETED
).getDate().getTime();
228 } catch (Exception e
) {
229 throw new SlcException("Cannot get close date from " + node
, e
);
233 public Map
<String
, String
> getAttributes() {
234 Node node
= getNode();
236 Map
<String
, String
> map
= new HashMap
<String
, String
>();
237 PropertyIterator pit
= node
.getProperties();
238 while (pit
.hasNext()) {
239 Property p
= pit
.nextProperty();
241 map
.put(p
.getName(), p
.getValue().getString());
244 } catch (Exception e
) {
245 throw new SlcException("Cannot get close date from " + node
, e
);
249 public void addAttachment(Attachment attachment
) {
253 public void setUuid(String uuid
) {
257 public void setRepository(Repository repository
) {
258 this.repository
= repository
;
261 public void setResultType(String resultType
) {
262 this.resultType
= resultType
;
265 public void setAttributes(Map
<String
, String
> attributes
) {
267 throw new SlcException(
268 "Attributes cannot be set on an already initialized test result."
269 + " Update the related JCR node directly instead.");
270 this.attributes
= attributes
;
273 public void setCredentials(Credentials credentials
) {
274 this.credentials
= credentials
;