<groupId>hsqldb</groupId>\r
<artifactId>hsqldb</artifactId>\r
</dependency>\r
+ <dependency>\r
+ <groupId>xalan</groupId>\r
+ <artifactId>xalan</artifactId>\r
+ </dependency>\r
</dependencies>\r
</project>
\ No newline at end of file
+++ /dev/null
-package org.argeo.slc.core.test.tree;\r
-\r
-import java.util.Vector;\r
-\r
-import org.argeo.slc.core.structure.tree.TreeSPath;\r
-import org.argeo.slc.core.test.TestResult;\r
-import org.argeo.slc.core.test.TestResultListener;\r
-import org.argeo.slc.core.test.TestResultPart;\r
-\r
-/**\r
- * Abstract asynchronous implementation of a listener listening to a\r
- * <code>TreeTestResult</code>.\r
- * \r
- * @deprecated listeners should be called synchronously\r
- * @see TreeTestResult\r
- */\r
-public abstract class AsynchronousTreeTestResultListener implements\r
- TestResultListener, Runnable {\r
- private Vector<PartStruct> partStructs = new Vector<PartStruct>();\r
- private Thread thread;\r
-\r
- private Boolean synchronous = true;\r
-\r
- protected AsynchronousTreeTestResultListener() {\r
- this(true);\r
- }\r
-\r
- protected AsynchronousTreeTestResultListener(Boolean synchronousByDefault) {\r
- synchronous = synchronousByDefault;\r
- }\r
-\r
- /** Starts the underlying thread. */\r
- public void init() {\r
- if (!synchronous) {\r
- thread = new Thread(this);\r
- thread.start();\r
- }\r
- }\r
-\r
- /** Finish the remaining and destroy */\r
- public void close(TestResult testResult) {\r
- // FIXME: make behavior more robust when multiple results are\r
- // registering this listener.\r
- synchronized (partStructs) {\r
- // TODO: put a timeout\r
- while (partStructs.size() != 0) {\r
- try {\r
- partStructs.wait(500);\r
- } catch (InterruptedException e) {\r
- // silent\r
- }\r
- }\r
- thread = null;\r
- partStructs.notifyAll();\r
- }\r
- postClose((TreeTestResult) testResult);\r
- }\r
-\r
- public final void resultPartAdded(TestResult testResult,\r
- TestResultPart testResultPart) {\r
- TreeTestResult result = (TreeTestResult) testResult;\r
- PartStruct partStruct = new PartStruct(result.getCurrentPath(), result\r
- .getUuid(), testResultPart, result);\r
-\r
- if (!synchronous) {\r
- synchronized (partStructs) {\r
- partStructs.add(partStruct);\r
- partStructs.notifyAll();\r
- }\r
- } else {\r
- resultPartAdded(partStruct);\r
- }\r
- }\r
-\r
- /** Called when a result part has been added. */\r
- protected abstract void resultPartAdded(PartStruct partStruct);\r
-\r
- /**\r
- * Called at the end of close. Default implementation is empty. To be\r
- * overridden.\r
- */\r
- protected void postClose(TreeTestResult testResult) {\r
-\r
- }\r
-\r
- public void run() {\r
- while (thread != null) {\r
- synchronized (partStructs) {\r
- for (PartStruct partStruct : partStructs) {\r
- resultPartAdded(partStruct);\r
- }\r
-\r
- partStructs.clear();\r
- partStructs.notifyAll();\r
- while (partStructs.size() == 0) {\r
- try {\r
- partStructs.wait();\r
- } catch (InterruptedException e) {\r
- // silent\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- /** Structure used to pass tree specific information to subclasses. */\r
- protected static class PartStruct {\r
- /** The tree path of this part. */\r
- public final TreeSPath path;\r
- /** The test result id of the related test result */\r
- public final String uuid;\r
- /** The part itself */\r
- public final TestResultPart part;\r
- /** The tree test result itself. */\r
- public final TreeTestResult result;\r
-\r
- /** Constructor */\r
- public PartStruct(TreeSPath path, String uuid, TestResultPart part,\r
- TreeTestResult result) {\r
- super();\r
- this.path = path;\r
- this.uuid = uuid;\r
- this.part = part;\r
- this.result = result;\r
- }\r
-\r
- }\r
-\r
- public Boolean getSynchronous() {\r
- return synchronous;\r
- }\r
-\r
- public void setSynchronous(Boolean synchronous) {\r
- this.synchronous = synchronous;\r
- }\r
-\r
-}\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
\r
-import org.argeo.slc.core.test.SimpleResultPart;\r
-import org.argeo.slc.core.test.TestResult;\r
import org.argeo.slc.core.test.TestResultListener;\r
import org.argeo.slc.core.test.TestResultPart;\r
import org.argeo.slc.core.test.TestStatus;\r
-import org.argeo.slc.core.test.tree.AsynchronousTreeTestResultListener.PartStruct;\r
\r
/**\r
* Listener logging tree-based test results to the underlying logging system.\r
--- /dev/null
+package org.argeo.slc.core.test.tree;\r
+\r
+import java.io.File;\r
+import java.io.FileOutputStream;\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+import javax.xml.transform.Templates;\r
+import javax.xml.transform.Transformer;\r
+import javax.xml.transform.TransformerFactory;\r
+import javax.xml.transform.dom.DOMResult;\r
+import javax.xml.transform.dom.DOMSource;\r
+import javax.xml.transform.stream.StreamResult;\r
+import javax.xml.transform.stream.StreamSource;\r
+\r
+import org.springframework.core.io.Resource;\r
+import org.springframework.oxm.Marshaller;\r
+import org.springframework.xml.transform.StringResult;\r
+import org.w3c.dom.Document;\r
+\r
+import org.apache.commons.io.IOUtils;\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+\r
+import org.argeo.slc.core.SlcException;\r
+import org.argeo.slc.core.test.TestResultListener;\r
+import org.argeo.slc.core.test.TestResultPart;\r
+\r
+public class XsltReportGenerator implements TestResultListener<TreeTestResult> {\r
+ private Log log = LogFactory.getLog(getClass());\r
+\r
+ private DocumentBuilder documentBuilder = null;\r
+\r
+ private Resource xsltStyleSheet;\r
+\r
+ private Templates templates;\r
+\r
+ private Marshaller marshaller;\r
+\r
+ private String outputDir;\r
+ private String outputFileExtension = "html";\r
+\r
+ private Boolean logXml = false;\r
+\r
+ public void init() {\r
+ if (templates != null)\r
+ return;\r
+\r
+ if (xsltStyleSheet == null)\r
+ throw new SlcException("XSLT style sheet not specified.");\r
+\r
+ InputStream in = null;\r
+ try {\r
+ TransformerFactory transformerFactory = TransformerFactory\r
+ .newInstance();\r
+ in = xsltStyleSheet.getInputStream();\r
+ StreamSource xsltSource = new StreamSource(in);\r
+ templates = transformerFactory.newTemplates(xsltSource);\r
+ } catch (Exception e) {\r
+ throw new SlcException("Could not initialize templates", e);\r
+ } finally {\r
+ IOUtils.closeQuietly(in);\r
+ }\r
+ }\r
+\r
+ public void resultPartAdded(TreeTestResult testResult,\r
+ TestResultPart testResultPart) {\r
+\r
+ }\r
+\r
+ public void close(TreeTestResult testResult) {\r
+ if (templates == null)\r
+ throw new SlcException("XSLT template not initialized");\r
+\r
+ File file = getFile(testResult);\r
+ OutputStream out = null;\r
+\r
+ try {\r
+ Transformer transformer = templates.newTransformer();\r
+\r
+ if (documentBuilder == null)\r
+ documentBuilder = DocumentBuilderFactory.newInstance()\r
+ .newDocumentBuilder();\r
+\r
+ Document document = documentBuilder.newDocument();\r
+ DOMResult marshallResult = new DOMResult(document);\r
+ marshaller.marshal(testResult, marshallResult);\r
+\r
+ if (logXml) {\r
+ Transformer identityTransformer = TransformerFactory\r
+ .newInstance().newTransformer();\r
+ StringResult xmlResult = new StringResult();\r
+ identityTransformer.transform(new DOMSource(marshallResult\r
+ .getNode()), xmlResult);\r
+ log.info("Marshalled XML:\n" + xmlResult);\r
+ }\r
+\r
+ DOMSource transfoSource = new DOMSource(marshallResult.getNode());\r
+\r
+ if (outputDir != null) {\r
+ File dir = new File(outputDir);\r
+ dir.mkdirs();\r
+ out = new FileOutputStream(file);\r
+ StreamResult outputResult = new StreamResult(out);\r
+ transformer.transform(transfoSource, outputResult);\r
+ } else {\r
+ // print on console if no output dir\r
+ StringResult result = new StringResult();\r
+ transformer.transform(transfoSource, result);\r
+ log.info("Generated report:\n" + result);\r
+ }\r
+ } catch (Exception e) {\r
+ throw new SlcException(\r
+ "Could not transform test result to " + file, e);\r
+ } finally {\r
+ IOUtils.closeQuietly(out);\r
+ }\r
+ }\r
+\r
+ public Resource getXsltStyleSheet() {\r
+ return xsltStyleSheet;\r
+ }\r
+\r
+ public void setXsltStyleSheet(Resource xsltStyleSheet) {\r
+ this.xsltStyleSheet = xsltStyleSheet;\r
+ }\r
+\r
+ public void setTemplates(Templates templates) {\r
+ this.templates = templates;\r
+ }\r
+\r
+ public void setMarshaller(Marshaller marshaller) {\r
+ this.marshaller = marshaller;\r
+ }\r
+\r
+ public void setOutputDir(String outputDir) {\r
+ this.outputDir = outputDir;\r
+ }\r
+\r
+ public void setOutputFileExtension(String outputFileExtension) {\r
+ this.outputFileExtension = outputFileExtension;\r
+ }\r
+\r
+ protected File getFile(TreeTestResult result) {\r
+ Long time = System.currentTimeMillis();\r
+ return new File(outputDir + File.separator + time + "-"\r
+ + result.getUuid() + "." + outputFileExtension);\r
+ }\r
+\r
+ public void setLogXml(Boolean logXml) {\r
+ this.logXml = logXml;\r
+ }\r
+\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<xsl:stylesheet version="1.0"\r
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"\r
+ xmlns:slc="http://argeo.org/projects/slc/schemas"\r
+ exclude-result-prefixes="slc">\r
+\r
+ <xsl:output method="html" omit-xml-declaration="yes" />\r
+\r
+ <xsl:template match="/">\r
+ <html>\r
+ <head>\r
+ <title>Result</title>\r
+ </head>\r
+ <body style="font-family: sans-serif">\r
+ <h1>\r
+ Result\r
+ <xsl:value-of select="slc:tree-test-result/@uuid" />\r
+ </h1>\r
+ <xsl:for-each\r
+ select="slc:tree-test-result/slc:result-parts/slc:result-part">\r
+ <h2>\r
+ <xsl:value-of select="@path" />\r
+ </h2>\r
+ <table>\r
+ <xsl:for-each\r
+ select="slc:part-sub-list/slc:parts/slc:simple-result-part">\r
+ <tr>\r
+ <xsl:choose>\r
+ <xsl:when\r
+ test="slc:status = 'PASSED' ">\r
+ <td style="color:green">\r
+ <xsl:value-of\r
+ select="slc:message" />\r
+ </td>\r
+ </xsl:when>\r
+ <xsl:otherwise>\r
+ <td style="color:red">\r
+ <xsl:value-of\r
+ select="slc:message" />\r
+ </td>\r
+ </xsl:otherwise>\r
+ </xsl:choose>\r
+ </tr>\r
+ </xsl:for-each>\r
+ </table>\r
+ </xsl:for-each>\r
+ </body>\r
+ </html>\r
+ </xsl:template>\r
+</xsl:stylesheet>
\ No newline at end of file
parent="slcDefault.test.basicTreeTestResult">\r
<property name="listeners">\r
<list merge="true">\r
- <ref bean="slcDefault.ws.client.treeTestResultWsNotfier" />\r
+ <ref\r
+ bean="slcDefault.ws.client.treeTestResultWsNotfier" />\r
+ <ref bean="xsltReportGenerator" />\r
</list>\r
</property>\r
</bean>\r
+\r
+ <bean id="xsltReportGenerator"\r
+ class="org.argeo.slc.core.test.tree.XsltReportGenerator"\r
+ init-method="init">\r
+ <property name="xsltStyleSheet"\r
+ value="classpath:/org/argeo/slc/core/test/tree/basicReport.xslt" />\r
+ <property name="marshaller" ref="slcDefault.castor.marshaller" />\r
+ <property name="logXml" value="false" />\r
+ <!-- \r
+ <property name="outputDir" value="D:\dev\test\SLC\SlcReports" />\r
+ -->\r
+ </bean>\r
</beans>
\ No newline at end of file