View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   
5   package net.sourceforge.pmd.renderers;
6   
7   import java.io.File;
8   import java.io.FileInputStream;
9   import java.io.FileNotFoundException;
10  import java.io.IOException;
11  import java.io.InputStream;
12  import java.io.StringReader;
13  import java.io.StringWriter;
14  import java.io.Writer;
15  
16  import javax.xml.parsers.DocumentBuilder;
17  import javax.xml.parsers.DocumentBuilderFactory;
18  import javax.xml.parsers.ParserConfigurationException;
19  import javax.xml.transform.Transformer;
20  import javax.xml.transform.TransformerConfigurationException;
21  import javax.xml.transform.TransformerException;
22  import javax.xml.transform.TransformerFactory;
23  import javax.xml.transform.dom.DOMSource;
24  import javax.xml.transform.stream.StreamResult;
25  import javax.xml.transform.stream.StreamSource;
26  
27  import net.sourceforge.pmd.lang.rule.properties.StringProperty;
28  
29  import org.w3c.dom.Document;
30  import org.xml.sax.InputSource;
31  import org.xml.sax.SAXException;
32  
33  /**
34   * Renderer to XML format with a XSL Transformation applied.
35   * 
36   * @author Romain Pelisse, belaran@gmail.com
37   */
38  public class XSLTRenderer extends XMLRenderer {
39  
40      public static final String NAME = "xslt";
41  
42      public static final StringProperty XSLT_FILENAME = new StringProperty("xsltFilename", "The XSLT file name.", null, 0);
43  
44      private Transformer transformer;
45      private String xsltFilename = "/pmd-nicerhtml.xsl";
46      private Writer outputWriter;
47  
48      public XSLTRenderer() {
49  	super();
50  	setName(NAME);
51  	setDescription("XML with a XSL Transformation applied.");
52  	definePropertyDescriptor(XSLT_FILENAME);
53      }
54  
55      public String defaultFileExtension() { return "xsl"; }
56      
57      /**
58       * {@inheritDoc}
59       */
60      @Override
61      public void start() throws IOException {
62  	String xsltFilenameProperty = getProperty(XSLT_FILENAME);
63  	if (xsltFilenameProperty != null) {
64  	    File file = new File(xsltFilenameProperty);
65  	    if (file.exists() && file.canRead()) {
66  		this.xsltFilename = xsltFilenameProperty;
67  	    }
68  	}
69  
70  	// We keep the inital writer to put the final html output
71  	this.outputWriter = getWriter();
72  	// We use a new one to store the XML...
73  	Writer w = new StringWriter();
74  	setWriter(w);
75  	// If don't find the xsl no need to bother doing the all report,
76  	// so we check this here...
77  	InputStream xslt = null;
78  	File file = new File(this.xsltFilename);
79  	if (file.exists() && file.canRead()) {
80  	    xslt = new FileInputStream(file);
81  	} else {
82  	    xslt = this.getClass().getResourceAsStream(this.xsltFilename);
83  	}
84  	if (xslt == null) {
85  	    throw new FileNotFoundException("Can't file XSLT sheet :" + this.xsltFilename);
86  	}
87  	this.prepareTransformer(xslt);
88  	// Now we build the XML file
89  	super.start();
90      }
91  
92      /**
93       * Prepare the transformer, doing the proper "building"...
94       *
95       * @param xslt The stylesheet provided as an InputStream
96       */
97      private void prepareTransformer(InputStream xslt) {
98  	if (xslt != null) {
99  	    try {
100 		//Get a TransformerFactory object
101 		TransformerFactory factory = TransformerFactory.newInstance();
102 		StreamSource src = new StreamSource(xslt);
103 		//Get an XSL Transformer object
104 		this.transformer = factory.newTransformer(src);
105 	    } catch (TransformerConfigurationException e) {
106 		e.printStackTrace();
107 	    }
108 	}
109     }
110 
111     /**
112      * {@inheritDoc}
113      */
114     @Override
115     public void end() throws IOException {
116 	// First we finish the XML report
117 	super.end();
118 	// Now we transform it using XSLT
119 	Writer writer = super.getWriter();
120 	if (writer instanceof StringWriter) {
121 	    StringWriter w = (StringWriter) writer;
122 	    StringBuffer buffer = w.getBuffer();
123 	    Document doc = this.getDocument(buffer.toString());
124 	    this.transform(doc);
125 	} else {
126 	    // Should not happen !
127 	    throw new RuntimeException("Wrong writer");
128 	}
129 
130     }
131 
132     private void transform(Document doc) {
133 	DOMSource source = new DOMSource(doc);
134 	this.setWriter(new StringWriter());
135 	StreamResult result = new StreamResult(this.outputWriter);
136 	try {
137 	    transformer.transform(source, result);
138 	} catch (TransformerException e) {
139 	    e.printStackTrace();
140 	}
141     }
142 
143     private Document getDocument(String xml) {
144 	try {
145 	    DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
146 	    return parser.parse(new InputSource(new StringReader(xml)));
147 	} catch (ParserConfigurationException e) {
148 	    e.printStackTrace();
149 	} catch (SAXException e) {
150 	    e.printStackTrace();
151 	} catch (IOException e) {
152 	    e.printStackTrace();
153 	}
154 	return null;
155     }
156 }