/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.renderers;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import net.sourceforge.pmd.lang.rule.properties.StringProperty;
/**
* Renderer to XML format with a XSL Transformation applied.
*
* @author Romain Pelisse, belaran@gmail.com
*/
public class XSLTRenderer extends XMLRenderer {
public static final String NAME = "xslt";
public static final StringProperty XSLT_FILENAME = new StringProperty("xsltFilename", "The XSLT file name.", null,
0);
private Transformer transformer;
private String xsltFilename = "/pmd-nicerhtml.xsl";
private Writer outputWriter;
public XSLTRenderer() {
super();
setName(NAME);
setDescription("XML with a XSL Transformation applied.");
definePropertyDescriptor(XSLT_FILENAME);
}
@Override
public String defaultFileExtension() {
return "xsl";
}
/**
* {@inheritDoc}
*/
@Override
public void start() throws IOException {
String xsltFilenameProperty = getProperty(XSLT_FILENAME);
if (xsltFilenameProperty != null) {
File file = new File(xsltFilenameProperty);
if (file.exists() && file.canRead()) {
this.xsltFilename = xsltFilenameProperty;
}
}
// We keep the inital writer to put the final html output
this.outputWriter = getWriter();
// We use a new one to store the XML...
Writer w = new StringWriter();
setWriter(w);
// If don't find the xsl no need to bother doing the all report,
// so we check this here...
InputStream xslt = null;
File file = new File(this.xsltFilename);
if (file.exists() && file.canRead()) {
xslt = new FileInputStream(file);
} else {
xslt = this.getClass().getResourceAsStream(this.xsltFilename);
}
if (xslt == null) {
throw new FileNotFoundException("Can't file XSLT sheet :" + this.xsltFilename);
}
this.prepareTransformer(xslt);
// Now we build the XML file
super.start();
}
/**
* Prepare the transformer, doing the proper "building"...
*
* @param xslt
* The stylesheet provided as an InputStream
*/
private void prepareTransformer(InputStream xslt) {
if (xslt != null) {
try {
// Get a TransformerFactory object
TransformerFactory factory = TransformerFactory.newInstance();
StreamSource src = new StreamSource(xslt);
// Get an XSL Transformer object
this.transformer = factory.newTransformer(src);
} catch (TransformerConfigurationException e) {
e.printStackTrace();
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void end() throws IOException {
// First we finish the XML report
super.end();
// Now we transform it using XSLT
Writer writer = super.getWriter();
if (writer instanceof StringWriter) {
StringWriter w = (StringWriter) writer;
StringBuffer buffer = w.getBuffer();
Document doc = this.getDocument(buffer.toString());
this.transform(doc);
} else {
// Should not happen !
throw new RuntimeException("Wrong writer");
}
}
private void transform(Document doc) {
DOMSource source = new DOMSource(doc);
this.setWriter(new StringWriter());
StreamResult result = new StreamResult(this.outputWriter);
try {
transformer.transform(source, result);
} catch (TransformerException e) {
e.printStackTrace();
}
}
private Document getDocument(String xml) {
try {
DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
return parser.parse(new InputSource(new StringReader(xml)));
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}