package org.apache.qetest.xsl;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.types.CommandlineJava;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.types.Path;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.Iterator;
/*
This ant task can, check whether XalanJ's XSLTC processor
can compile XSLT stylesheets correctly.
@author Mukul Gandhi
*/
public class XsltcTestsTask extends Task {
private String inputDir;
private String resultDir;
private static final String XSLT_FILE_EXT = ".xsl";
private static final String expectedTestResultsDoc = "expected_test_results.xml";
private static final String testResultsDoc = "actual_test_results.xml";
private static final String STYLESHEET_COMPILATION_ERR_MESG = "Could not compile stylesheet";
private static final String PASS = "pass";
private static final String FAIL = "fail";
private CommandlineJava commandLineJava = new CommandlineJava();
// method to run this, ant build task
public void execute() throws BuildException {
System.setProperty("javax.xml.transform.TransformerFactory",
"org.apache.xalan.xsltc.trax.TransformerFactoryImpl");
Document expectedTestResultsDocument = getExpectedTestResultsDocument();
Map testResults = new HashMap();
File dirObj = new File(this.inputDir);
File[] fileList = dirObj.listFiles();
boolean isXsltcTestsPassed = true;
try {
for (int idx = 0; idx < fileList.length; idx++) {
String fileName = fileList[idx].getName();
if (fileName.endsWith(XSLT_FILE_EXT)) {
XsltcTestsErrorListener xsltcTestsErrorListener = new XsltcTestsErrorListener();
compileXslDocument(fileName, xsltcTestsErrorListener);
boolean isCompileErrorOccured = STYLESHEET_COMPILATION_ERR_MESG.
equals(xsltcTestsErrorListener.getErrListenerMesg());
boolean hasTestPassed = isTestPassed(expectedTestResultsDocument,
fileName, isCompileErrorOccured);
if (hasTestPassed) {
testResults.put(fileName, Boolean.TRUE);
}
else {
testResults.put(fileName, Boolean.FALSE);
isXsltcTestsPassed = false;
}
}
}
serializeTestResultsToXmlDocument(testResults);
}
catch (Exception ex) {
throw new BuildException(ex.getMessage(), location);
}
if (!isXsltcTestsPassed) {
throw new BuildException("One or more XSLTC tests have failed. Please fix any XSLTC tests problems, " +
"before checking in! XSLTC test results are available at " + resultDir + "/" +
testResultsDoc , location);
}
}
public void setInputDir(String inputDir) {
this.inputDir = inputDir;
}
public void setResultDir(String resultDir) {
this.resultDir = resultDir;
}
/**
* Set the bootclasspathref to be used for this test.
*
* @param bootclasspathref used for running the test
*/
public void setBootclasspathref(Reference ref)
{
String jdkRelease =
System.getProperty("java.version", "0.0").substring(0,3);
if (!jdkRelease.equals("1.1")
&& !jdkRelease.equals("1.2")
&& !jdkRelease.equals("1.3")) {
Path p = (Path)ref.getReferencedObject(this.getProject());
createJvmarg().setValue("-Xbootclasspath/p:" + p);
}
}
/**
* Creates a nested jvmarg element.
*
* @return Argument to send to our JVM if forking
*/
public Commandline.Argument createJvmarg()
{
return commandLineJava.createVmArgument();
}
/*
This method, attempts to compile an XSLT stylesheet. If the stylesheet
cannot be compiled, the registered error listener sets the resulting
error message within a variable.
*/
private void compileXslDocument(String xslName, XsltcTestsErrorListener
xsltcTestsErrorListener) {
try {
TransformerFactory trfFactory = TransformerFactory.newInstance();
trfFactory.setErrorListener(xsltcTestsErrorListener);
Transformer transformer = trfFactory.newTransformer(
new StreamSource(this.inputDir + "/" + xslName));
}
catch (Exception ex) {
// NO OP
}
}
/*
An expected tests results document, is already available before running
this ant task. This method, returns an XML DOM representation of that
XML document.
*/
private Document getExpectedTestResultsDocument() {
Document xmlResultDocument = null;
try {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
xmlResultDocument = docBuilder.parse(this.inputDir + "/" + expectedTestResultsDoc);
}
catch (Exception ex) {
throw new BuildException(ex.getMessage(), location);
}
return xmlResultDocument;
}
/*
This method, checks whether an XSLTC test that has been run,
has passed or not.
*/
private boolean isTestPassed(Document expectedTestResultsDoc,
String xslFileName, boolean isCompileErrorOccured)
throws Exception {
XPath xPath = XPathFactory.newInstance().newXPath();
String isCompileErrorOccuredStr = (new Boolean(isCompileErrorOccured)).toString();
String xpathExprStr = "/expectedResults/file[@name = '" + xslFileName + "' and " +
"compileError = '" + isCompileErrorOccuredStr + "']/expected";
String xpathNodeStrValue = (String)((xPath.compile(xpathExprStr)).
evaluate(expectedTestResultsDoc,
XPathConstants.STRING));
return PASS.equals(xpathNodeStrValue) ? true : false;
}
/*
Given XSLTC overall test results, produced by this class (available as Map object),
this method serializes those results to an XML document.
*/
private void serializeTestResultsToXmlDocument(Map testResultsMap)
throws Exception {
Set> mapEntries = testResultsMap.entrySet();
Iterator> iter = mapEntries.iterator();
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document resultDocument = docBuilder.newDocument();
Element testResultsElem = resultDocument.createElement("testResults");
while (iter.hasNext()) {
Map.Entry mapEntry = iter.next();
String fileName = mapEntry.getKey();
Boolean passStatus = mapEntry.getValue();
Element resultElem = resultDocument.createElement("result");
Element fileNameElem = resultDocument.createElement("fileName");
fileNameElem.appendChild(resultDocument.createTextNode(fileName));
resultElem.appendChild(fileNameElem);
Element statusElem = resultDocument.createElement("status");
statusElem.appendChild(resultDocument.createTextNode(passStatus ==
Boolean.TRUE ? "pass" : "fail"));
resultElem.appendChild(statusElem);
testResultsElem.appendChild(resultElem);
}
resultDocument.appendChild(testResultsElem);
DOMImplementationLS domImplementation = (DOMImplementationLS)
resultDocument.getImplementation();
LSSerializer lsSerializer = domImplementation.createLSSerializer();
(lsSerializer.getDomConfig()).setParameter("format-pretty-print", Boolean.TRUE);
String resultDocumentXmlStr = lsSerializer.writeToString(resultDocument);
Files.write(Paths.get(resultDir + "/" + testResultsDoc),
resultDocumentXmlStr.getBytes());
}
}