2 * Copyright (C) 2007-2012 Mathieu Baudier
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
.execution
;
18 import java
.util
.Collections
;
19 import java
.util
.GregorianCalendar
;
20 import java
.util
.HashMap
;
23 import javax
.jcr
.Node
;
24 import javax
.jcr
.NodeIterator
;
25 import javax
.jcr
.Property
;
26 import javax
.jcr
.PropertyIterator
;
27 import javax
.jcr
.RepositoryException
;
28 import javax
.jcr
.Session
;
29 import javax
.jcr
.query
.Query
;
30 import javax
.jcr
.query
.QueryManager
;
32 import org
.apache
.commons
.logging
.Log
;
33 import org
.apache
.commons
.logging
.LogFactory
;
34 import org
.argeo
.jcr
.JcrUtils
;
35 import org
.argeo
.slc
.SlcException
;
36 import org
.argeo
.slc
.core
.attachment
.Attachment
;
37 import org
.argeo
.slc
.core
.structure
.SimpleSElement
;
38 import org
.argeo
.slc
.core
.structure
.tree
.TreeSPath
;
39 import org
.argeo
.slc
.core
.test
.SimpleResultPart
;
40 import org
.argeo
.slc
.core
.test
.tree
.PartSubList
;
41 import org
.argeo
.slc
.core
.test
.tree
.TreeTestResult
;
42 import org
.argeo
.slc
.core
.test
.tree
.TreeTestResultListener
;
43 import org
.argeo
.slc
.jcr
.SlcJcrUtils
;
44 import org
.argeo
.slc
.jcr
.SlcNames
;
45 import org
.argeo
.slc
.jcr
.SlcTypes
;
46 import org
.argeo
.slc
.test
.TestResultPart
;
47 import org
.argeo
.slc
.test
.TestStatus
;
50 * Persists results in JCR by listening to {@link TreeTestResult}. This is to
51 * facilitate transition from legacy approaches and should not be used in new
54 public class JcrResultListener
implements TreeTestResultListener
, SlcNames
{
55 private final static Log log
= LogFactory
.getLog(JcrResultListener
.class);
57 private Session session
;
59 /** Caches the mapping between SLC uuids and internal JCR identifiers */
60 private Map
<String
, String
> uuidToIdentifier
= Collections
61 .synchronizedMap(new HashMap
<String
, String
>());
63 public void resultPartAdded(TreeTestResult testResult
,
64 TestResultPart testResultPart
) {
66 String uuid
= testResult
.getUuid();
67 Node resultNode
= getResultNode(uuid
);
68 if (resultNode
== null) {
69 resultNode
= createResultNode(testResult
);
72 String partParentPath
;
73 TreeSPath currentPath
= testResult
.getCurrentPath();
74 if (currentPath
!= null) {
75 String subPath
= currentPath
.getAsUniqueString();
76 partParentPath
= resultNode
.getPath() + subPath
;
78 partParentPath
= resultNode
.getPath();
79 // TODO create some depth?
83 if (session
.itemExists(partParentPath
)) {
84 partParentNode
= session
.getNode(partParentPath
);
86 partParentNode
= JcrUtils
.mkdirs(session
, partParentPath
);
90 SimpleSElement element
= null;
91 if (testResult
.getElements().containsKey(currentPath
)) {
92 element
= (SimpleSElement
) testResult
.getElements().get(
96 String elementLabel
= element
!= null && element
.getLabel() != null
97 && !element
.getLabel().trim().equals("") ? element
99 String partNodeName
= elementLabel
!= null ? JcrUtils
100 .replaceInvalidChars(elementLabel
, '_') : Long
101 .toString(System
.currentTimeMillis());
103 Node resultPartNode
= partParentNode
.addNode(partNodeName
,
105 resultPartNode
.setProperty(SLC_SUCCESS
,
106 testResultPart
.getStatus() == TestStatus
.PASSED
);
107 if (elementLabel
!= null)
108 resultPartNode
.setProperty(Property
.JCR_TITLE
, elementLabel
);
109 if (testResultPart
.getMessage() != null)
110 resultPartNode
.setProperty(SLC_MESSAGE
,
111 testResultPart
.getMessage());
112 if (testResultPart
.getExceptionMessage() != null)
113 resultPartNode
.setProperty(SLC_ERROR_MESSAGE
,
114 testResultPart
.getExceptionMessage());
115 // JcrUtils.debug(resultPartNode);
117 JcrUtils
.updateLastModified(resultNode
);
119 if (element
!= null) {
120 element
= (SimpleSElement
) testResult
.getElements().get(
122 if (log
.isTraceEnabled())
123 log
.trace(" Path= " + currentPath
+ ", part="
124 + testResultPart
.getMessage());
125 for (Map
.Entry
<String
, String
> tag
: element
.getTags()
127 String tagNodeName
= JcrUtils
.replaceInvalidChars(
129 // log.debug("key=" + tag.getKey() + ", tagNodeName="
131 Node tagNode
= resultPartNode
.addNode(tagNodeName
,
132 SlcTypes
.SLC_PROPERTY
);
133 tagNode
.setProperty(SLC_NAME
, tag
.getKey());
134 tagNode
.setProperty(SLC_VALUE
, tag
.getValue());
139 } catch (RepositoryException e
) {
140 JcrUtils
.discardQuietly(session
);
141 log
.error("Cannot add result part " + testResultPart
+ " to "
143 // throw new SlcException("Cannot add result part " + testResultPart
144 // + " to " + testResult, e);
149 /** @return null if does not exist */
150 protected Node
getResultNode(String uuid
) throws RepositoryException
{
152 if (uuidToIdentifier
.containsKey(uuid
)) {
153 return session
.getNodeByIdentifier(uuidToIdentifier
.get(uuid
));
159 "select * from [slc:result] where [slc:uuid]='"
160 + uuid
+ "'", Query
.JCR_SQL2
);
161 resultNode
= JcrUtils
.querySingleNode(q
);
162 if (resultNode
!= null)
163 uuidToIdentifier
.put(uuid
, resultNode
.getIdentifier());
168 protected Node
createResultNode(TreeTestResult testResult
)
169 throws RepositoryException
{
170 String uuid
= testResult
.getUuid();
171 String path
= SlcJcrUtils
.createResultPath(session
.getUserID(), uuid
);
172 Node resultNode
= JcrUtils
.mkdirs(session
, path
, SlcTypes
.SLC_TEST_RESULT
);
173 resultNode
.setProperty(SLC_UUID
, uuid
);
174 for (Map
.Entry
<String
, String
> entry
: testResult
.getAttributes()
176 resultNode
.setProperty(entry
.getKey(), entry
.getValue());
179 uuidToIdentifier
.put(uuid
, resultNode
.getIdentifier());
183 public void close(TreeTestResult testResult
) {
185 String uuid
= testResult
.getUuid();
186 Node resultNode
= getResultNode(uuid
);
187 if (resultNode
== null)
188 resultNode
= createResultNode(testResult
);
189 JcrUtils
.updateLastModified(resultNode
);
190 GregorianCalendar closeDate
= new GregorianCalendar();
191 closeDate
.setTime(testResult
.getCloseDate());
192 resultNode
.setProperty(SLC_COMPLETED
, closeDate
);
194 uuidToIdentifier
.remove(uuid
);
197 if (log
.isDebugEnabled())
198 log
.debug("Closed test result " + uuid
);
199 } catch (RepositoryException e
) {
200 JcrUtils
.discardQuietly(session
);
201 log
.error("Cannot close result " + testResult
, e
);
202 // throw new SlcException("Cannot close result " + testResult, e);
207 public void addAttachment(TreeTestResult testResult
, Attachment attachment
) {
211 public void setSession(Session session
) {
212 this.session
= session
;
216 * Creates and populates a {@link TreeTestResult} from the related result
217 * node. Meant to simplify migration of legacy applications. This is no
220 public static TreeTestResult
nodeToTreeTestResult(Node resultNode
) {
222 String resultPath
= resultNode
.getPath();
223 TreeTestResult ttr
= new TreeTestResult();
225 ttr
.setUuid(resultNode
.getProperty(SLC_UUID
).getString());
226 if (resultNode
.hasProperty(SLC_COMPLETED
))
227 ttr
.setCloseDate(resultNode
.getProperty(SLC_COMPLETED
)
228 .getDate().getTime());
230 for (PropertyIterator pit
= resultNode
.getProperties(); pit
232 Property p
= pit
.nextProperty();
233 if (p
.getName().indexOf(':') < 0) {
234 ttr
.getAttributes().put(p
.getName(), p
.getString());
238 QueryManager qm
= resultNode
.getSession().getWorkspace()
240 String statement
= "SELECT * FROM [" + SlcTypes
.SLC_CHECK
241 + "] WHERE ISDESCENDANTNODE(['" + resultPath
+ "'])";
242 NodeIterator nit
= qm
.createQuery(statement
, Query
.JCR_SQL2
)
243 .execute().getNodes();
244 while (nit
.hasNext()) {
245 Node checkNode
= nit
.nextNode();
246 String relPath
= checkNode
.getPath().substring(
247 resultPath
.length());
248 TreeSPath tsp
= new TreeSPath(relPath
);
251 SimpleResultPart srp
= new SimpleResultPart();
252 if (checkNode
.getProperty(SLC_SUCCESS
).getBoolean())
253 srp
.setStatus(TestStatus
.PASSED
);
254 else if (checkNode
.hasProperty(SLC_ERROR_MESSAGE
))
255 srp
.setStatus(TestStatus
.ERROR
);
257 srp
.setStatus(TestStatus
.FAILED
);
258 if (checkNode
.hasProperty(SLC_MESSAGE
))
259 srp
.setMessage(checkNode
.getProperty(SLC_MESSAGE
)
261 if (!ttr
.getResultParts().containsKey(tsp
))
262 ttr
.getResultParts().put(tsp
, new PartSubList());
263 ttr
.getResultParts().get(tsp
).getParts().add(srp
);
266 SimpleSElement elem
= new SimpleSElement();
267 if (checkNode
.hasProperty(Property
.JCR_TITLE
))
268 elem
.setLabel(checkNode
.getProperty(Property
.JCR_TITLE
)
271 elem
.setLabel("");// some legacy code expect it to be set
272 for (NodeIterator tagIt
= checkNode
.getNodes(); tagIt
.hasNext();) {
273 Node tagNode
= tagIt
.nextNode();
275 tagNode
.getProperty(SLC_NAME
).getString(),
276 tagNode
.getProperty(SLC_VALUE
).getString());
278 ttr
.getElements().put(tsp
, elem
);
281 } catch (RepositoryException e
) {
282 throw new SlcException("Cannot generate tree test result from "