2 * Copyright (C) 2007-2012 Argeo GmbH
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org
.argeo
.slc
.jcr
;
18 import java
.util
.Date
;
19 import java
.util
.GregorianCalendar
;
20 import java
.util
.HashMap
;
22 import java
.util
.UUID
;
24 import javax
.jcr
.Credentials
;
25 import javax
.jcr
.Node
;
26 import javax
.jcr
.Property
;
27 import javax
.jcr
.PropertyIterator
;
28 import javax
.jcr
.Repository
;
29 import javax
.jcr
.Session
;
30 import javax
.jcr
.query
.Query
;
31 import javax
.jcr
.query
.QueryManager
;
33 import org
.apache
.commons
.logging
.Log
;
34 import org
.apache
.commons
.logging
.LogFactory
;
35 import org
.argeo
.jcr
.JcrUtils
;
36 import org
.argeo
.slc
.SlcException
;
37 import org
.argeo
.slc
.SlcNames
;
38 import org
.argeo
.slc
.SlcTypes
;
39 import org
.argeo
.slc
.core
.attachment
.Attachment
;
40 import org
.argeo
.slc
.core
.attachment
.AttachmentsEnabled
;
41 import org
.argeo
.slc
.test
.TestResult
;
42 import org
.argeo
.slc
.test
.TestResultPart
;
43 import org
.argeo
.slc
.test
.TestRun
;
44 import org
.argeo
.slc
.test
.TestStatus
;
47 * {@link TestResult} wrapping a JCR node of type
48 * {@link SlcTypes#SLC_TEST_RESULT}.
50 public class JcrTestResult
implements TestResult
, SlcNames
, AttachmentsEnabled
{
51 private final static Log log
= LogFactory
.getLog(JcrTestResult
.class);
53 /** Should only be set for an already existing result. */
55 private Repository repository
;
56 private Session session
;
58 * For testing purposes, best practice is to not set them explicitely but
59 * via other mechanisms such as JAAS or SPring Security.
61 private Credentials credentials
= null;
62 private String resultType
= SlcTypes
.SLC_TEST_RESULT
;
64 /** cached for performance purposes */
65 private String nodeIdentifier
= null;
67 private Map
<String
, String
> attributes
= new HashMap
<String
, String
>();
71 session
= repository
.login(credentials
);
74 uuid
= UUID
.randomUUID().toString();
75 String path
= SlcJcrUtils
.createResultPath(session
, uuid
);
76 Node resultNode
= JcrUtils
.mkdirs(session
, path
, resultType
);
77 resultNode
.setProperty(SLC_UUID
, uuid
);
78 for (String attr
: attributes
.keySet()) {
79 String property
= attr
;
80 // compatibility with legacy applications
81 if ("testCase".equals(attr
))
82 property
= SLC_TEST_CASE
;
83 else if ("testCaseType".equals(attr
))
84 property
= SLC_TEST_CASE_TYPE
;
85 resultNode
.setProperty(property
, attributes
.get(attr
));
88 if (log
.isDebugEnabled())
89 log
.debug("Created test result " + uuid
);
91 } catch (Exception e
) {
92 JcrUtils
.discardQuietly(session
);
93 throw new SlcException("Cannot initialize JCR result", e
);
97 public void destroy() {
98 JcrUtils
.logoutQuietly(session
);
99 if (log
.isTraceEnabled())
100 log
.trace("Logged out session for result " + uuid
);
103 public Node
getNode() {
106 if (nodeIdentifier
!= null) {
107 return session
.getNodeByIdentifier(nodeIdentifier
);
109 QueryManager qm
= session
.getWorkspace().getQueryManager();
110 Query q
= qm
.createQuery("select * from ["
111 + SlcTypes
.SLC_TEST_RESULT
+ "] where [slc:uuid]='"
112 + uuid
+ "'", Query
.JCR_SQL2
);
113 resultNode
= JcrUtils
.querySingleNode(q
);
114 if (resultNode
!= null)
115 nodeIdentifier
= resultNode
.getIdentifier();
118 } catch (Exception e
) {
119 throw new SlcException("Cannot get result node", e
);
123 public void notifyTestRun(TestRun testRun
) {
124 // TODO store meta data about the test running
125 // if (log.isDebugEnabled())
126 // log.debug("Running test "
127 // + testRun.getTestDefinition().getClass().getName() + "...");
130 public void addResultPart(TestResultPart testResultPart
) {
131 Node node
= getNode();
134 // error : revert all unsaved changes on the resultNode to be sure
135 // it is in a consistant state
136 if (testResultPart
.getExceptionMessage() != null)
137 JcrUtils
.discardQuietly(node
.getSession());
138 node
.getSession().save();
140 // add the new result part, retrieving status information
141 Node resultPartNode
= node
.addNode(SlcNames
.SLC_RESULT_PART
,
143 resultPartNode
.setProperty(SLC_SUCCESS
, testResultPart
.getStatus()
144 .equals(TestStatus
.PASSED
));
145 if (testResultPart
.getMessage() != null)
146 resultPartNode
.setProperty(SLC_MESSAGE
,
147 testResultPart
.getMessage());
148 if (testResultPart
.getStatus().equals(TestStatus
.ERROR
)) {
149 resultPartNode
.setProperty(SLC_ERROR_MESSAGE
,
150 (testResultPart
.getExceptionMessage() == null) ?
""
151 : testResultPart
.getExceptionMessage());
154 // helper update aggregate status node
156 if (!node
.hasNode(SLC_AGGREGATED_STATUS
)) {
158 mainStatus
= node
.addNode(SLC_AGGREGATED_STATUS
,
160 mainStatus
.setProperty(SLC_SUCCESS
,
161 resultPartNode
.getProperty(SLC_SUCCESS
).getBoolean());
162 if (resultPartNode
.hasProperty(SLC_MESSAGE
))
163 mainStatus
.setProperty(SLC_MESSAGE
, resultPartNode
164 .getProperty(SLC_MESSAGE
).getString());
165 if (resultPartNode
.hasProperty(SLC_ERROR_MESSAGE
))
166 mainStatus
.setProperty(SLC_ERROR_MESSAGE
, resultPartNode
167 .getProperty(SLC_ERROR_MESSAGE
).getString());
169 mainStatus
= node
.getNode(SLC_AGGREGATED_STATUS
);
170 if (mainStatus
.hasProperty(SLC_ERROR_MESSAGE
)) {
171 // main status already in error we do nothing
172 } else if (resultPartNode
.hasProperty(SLC_ERROR_MESSAGE
)) {
173 // main status was not in error and new result part is in
174 // error; we update main status
175 mainStatus
.setProperty(SLC_SUCCESS
, false);
176 mainStatus
.setProperty(SLC_ERROR_MESSAGE
, resultPartNode
177 .getProperty(SLC_ERROR_MESSAGE
).getString());
178 if (resultPartNode
.hasProperty(SLC_MESSAGE
))
179 mainStatus
.setProperty(SLC_MESSAGE
, resultPartNode
180 .getProperty(SLC_MESSAGE
).getString());
182 // remove old message to remain consistent
183 mainStatus
.setProperty(SLC_MESSAGE
, "");
184 } else if (!mainStatus
.getProperty(SLC_SUCCESS
).getBoolean()) {
185 // main status was already failed and new result part is not
186 // in error, we do nothing
187 } else if (!resultPartNode
.getProperty(SLC_SUCCESS
)
189 // new resultPart that is failed
190 mainStatus
.setProperty(SLC_SUCCESS
, false);
191 if (resultPartNode
.hasProperty(SLC_MESSAGE
))
192 mainStatus
.setProperty(SLC_MESSAGE
, resultPartNode
193 .getProperty(SLC_MESSAGE
).getString());
195 // remove old message to remain consistent
196 mainStatus
.setProperty(SLC_MESSAGE
, "");
197 } else if (resultPartNode
.hasProperty(SLC_MESSAGE
)
198 && (!mainStatus
.hasProperty(SLC_MESSAGE
) || (""
199 .equals(mainStatus
.getProperty(SLC_MESSAGE
)
200 .getString().trim())))) {
201 mainStatus
.setProperty(SLC_MESSAGE
, resultPartNode
202 .getProperty(SLC_MESSAGE
).getString());
205 JcrUtils
.updateLastModified(node
);
206 node
.getSession().save();
207 } catch (Exception e
) {
208 JcrUtils
.discardUnderlyingSessionQuietly(node
);
209 throw new SlcException("Cannot add ResultPart to node " + node
, e
);
213 public String
getUuid() {
214 Node node
= getNode();
216 return node
.getProperty(SLC_UUID
).getString();
217 } catch (Exception e
) {
218 throw new SlcException("Cannot get UUID from " + node
, e
);
222 /** JCR session is NOT logged out */
223 public void close() {
224 Node node
= getNode();
226 if (node
.hasNode(SLC_COMPLETED
))
228 node
.setProperty(SLC_COMPLETED
, new GregorianCalendar());
229 JcrUtils
.updateLastModified(node
);
230 node
.getSession().save();
231 } catch (Exception e
) {
232 JcrUtils
.discardUnderlyingSessionQuietly(node
);
233 throw new SlcException("Cannot get close date from " + node
, e
);
237 public Date
getCloseDate() {
238 Node node
= getNode();
240 if (!node
.hasNode(SLC_COMPLETED
))
242 return node
.getProperty(SLC_COMPLETED
).getDate().getTime();
243 } catch (Exception e
) {
244 throw new SlcException("Cannot get close date from " + node
, e
);
248 public Map
<String
, String
> getAttributes() {
249 Node node
= getNode();
251 Map
<String
, String
> map
= new HashMap
<String
, String
>();
252 PropertyIterator pit
= node
.getProperties();
253 while (pit
.hasNext()) {
254 Property p
= pit
.nextProperty();
256 map
.put(p
.getName(), p
.getValue().getString());
259 } catch (Exception e
) {
260 throw new SlcException("Cannot get close date from " + node
, e
);
264 public void addAttachment(Attachment attachment
) {
268 public void setUuid(String uuid
) {
272 public void setRepository(Repository repository
) {
273 this.repository
= repository
;
276 public void setResultType(String resultType
) {
277 this.resultType
= resultType
;
280 public void setAttributes(Map
<String
, String
> attributes
) {
282 throw new SlcException(
283 "Attributes cannot be set on an already initialized test result."
284 + " Update the related JCR node directly instead.");
285 this.attributes
= attributes
;
288 public void setCredentials(Credentials credentials
) {
289 this.credentials
= credentials
;