001: package csdl.jblanket.report;
002:
003: import csdl.jblanket.JBlanketException;
004: import csdl.jblanket.report.element.ElementContentHandler;
005: import csdl.jblanket.report.element.ElementErrorHandler;
006: import csdl.jblanket.report.element.MethodSetsElement;
007:
008: import java.io.ByteArrayOutputStream;
009: import java.io.File;
010: import java.io.FileInputStream;
011: import java.io.FileOutputStream;
012: import java.io.IOException;
013: import java.io.OutputStream;
014: import java.io.PrintWriter;
015: import java.net.URL;
016: import java.util.Iterator;
017: import java.util.Map;
018:
019: import javax.xml.parsers.DocumentBuilder;
020: import javax.xml.parsers.DocumentBuilderFactory; //import javax.xml.parsers.SAXParser;
021: //import javax.xml.parsers.SAXParserFactory;
022: import javax.xml.transform.Result;
023: import javax.xml.transform.Source;
024: import javax.xml.transform.Transformer;
025: import javax.xml.transform.TransformerFactory;
026: import javax.xml.transform.dom.DOMSource;
027: import javax.xml.transform.stream.StreamResult;
028: import javax.xml.transform.stream.StreamSource;
029:
030: import org.apache.tools.ant.types.EnumeratedAttribute;
031: import org.apache.xerces.parsers.SAXParser;
032: import org.w3c.dom.Document;
033: import org.xml.sax.InputSource;
034: import org.xml.sax.SAXException;
035: import org.xml.sax.XMLReader;
036:
037: /**
038: * Aggregates the output from JBlanket and transforms the aggregate file from XML to HTML.
039: * <p>
040: * First this class combines all methods in the system into one XML file, 'COVER-MethodSets.xml',
041: * according to the following types:
042: * <p>
043: * 'constructor' - constructors.<br>
044: * 'oneline' - methods that contain only one line of code.<br>
045: * 'excludedindividual' - excluded methods chose though ExcludedIndividualMethodsApp.<br>
046: * 'tested' - methods invoked during testing that are not 'oneline' methods.<br>
047: * 'untested' - methods not invoked during testing that are not 'oneline' methods.<br>
048: * <p>
049: * Then the aggregate XML file can be transformed into HTML pages, mimicking the behavior found
050: * in Apache Ant's junitreport task.
051: * <p>
052: * Note that the <code>excluded individual methods</code> take priority over all the other
053: * categories of methods. I.e., if a one-line method was individually excluded by the application,
054: * then it is considered to be an individually excluded methods instead of a one-line method.
055: * <p>
056: * Code is based upon Ant's XMLResultAggregator class.
057: *
058: * @author Joy M. Agustin
059: * @version $Id: AggregateTransformer.java,v 1.1 2004/11/07 00:32:44 timshadel Exp $
060: */
061: public class AggregateTransformer {
062:
063: /** Collection of 'type of method stored' mapped to 'name of file to aggregate' */
064: private Map reportCategories;
065: /** Path of to the JBlanket output directory */
066: private String jblanketDir;
067: /** Path of to the HTML output directory */
068: private File toDir;
069: /** Holds the value from Format class */
070: private String format;
071:
072: /** Use to specify frames in output */
073: public static final String FRAMES = "frames";
074: /** Use to specify no frames in output */
075: public static final String NOFRAMES = "noframes";
076:
077: /** Set of MethodSet's */
078: private MethodSetsElement methodSets = new MethodSetsElement();
079:
080: /**
081: * Provides an attempt at enumeration for HTML formats FRAMES or NOFRAMES
082: *
083: * @author see AggregateTransformer class in Jakarta Ant
084: * @version $Id: AggregateTransformer.java,v 1.1 2004/11/07 00:32:44 timshadel Exp $
085: */
086: public static class Format extends EnumeratedAttribute {
087:
088: /**
089: * Gets an array of possible frame values.
090: *
091: * @return possible frame values.
092: */
093: public String[] getValues() {
094: return new String[] { FRAMES, NOFRAMES };
095: }
096: }
097:
098: /**
099: * Constructs a new instance of this class.
100: *
101: * @param reportCategories the method categories found, i.e., 'tested', 'untested', 'oneline'.
102: * @param reportFormat the format of report, either 'frames' or 'noframes'.
103: * @param jblanketDir the directory for JBlanket output.
104: * @param toDir the directory for HTML output.
105: */
106: public AggregateTransformer(Map reportCategories,
107: String reportFormat, String jblanketDir, File toDir) {
108: super ();
109:
110: this .reportCategories = reportCategories;
111:
112: // check that reportFormat is a legal value
113: Format newFormat = new Format();
114: newFormat.setValue(reportFormat);
115: this .format = newFormat.getValue();
116:
117: // set the JBlanket output directory
118: this .jblanketDir = jblanketDir;
119:
120: // set the HTML output directory
121: this .toDir = toDir;
122: }
123:
124: /**
125: * Creates an aggregate file containing all of the methods that were 'tested', 'untested',
126: * 'oneline', or 'constructor' from the files in 'jblanketDir'. The methods are sorted according
127: * to individual classes.
128: *
129: * @param outFile name of resulting XML aggregate file.
130: * @throws JBlanketException if cannot find <code>outFile</code>, cannot find one of the
131: * files corresponding to a method type, or write to
132: * <code>outFile</code>.
133: */
134: protected void createAggregateFile(File outFile)
135: throws JBlanketException {
136:
137: // combine all tested and untested methods under one root
138: Iterator i = this .reportCategories.keySet().iterator();
139: while (i.hasNext()) {
140: String key = (String) i.next();
141: File nextFile = new File((String) this .reportCategories
142: .get(key));
143: // file for individually excluded files may not exist yet
144: if (!(key.equals("excludedIndividual") && !nextFile
145: .exists())) {
146: parseXmlFile(nextFile, key);
147: }
148: }
149:
150: writeXmlFile();
151: }
152:
153: /**
154: * Parses <code>fileName</code> and aggregates its contained methods into a common repository.
155: *
156: * @param file the XML file to parse.
157: * @param methodCategory the category of methods in <code>fileName</code>.
158: * @throws JBlanketException if unable to open, read, or parse <code>fileName</code>.
159: */
160: private void parseXmlFile(File file, String methodCategory)
161: throws JBlanketException {
162:
163: // create instances needed for parsing
164: XMLReader reader = new SAXParser();
165: /* Attempt at replacing Xerces with Java 1.4 Standard Library
166: XMLReader reader = null;
167: try {
168: // throws SAXException, ParserConfigurationException
169: reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
170: }
171: catch (Exception e) {
172: throw new JBlanketException("Unable to create an XMLReader to read " + fileName, e);
173: }
174: */
175: // register content handler
176: reader.setContentHandler(new ElementContentHandler(
177: this .methodSets, methodCategory));
178: // register error handler
179: reader.setErrorHandler(new ElementErrorHandler());
180: // parse
181:
182: InputSource inputSource = null;
183: try {
184: inputSource = new InputSource(new FileInputStream(file));
185: } catch (IOException e) {
186: throw new JBlanketException("Unable to open file " + file);
187: }
188:
189: inputSource.setSystemId(file.getAbsolutePath());
190: try {
191: reader.parse(inputSource);
192: } catch (SAXException e) {
193: throw new JBlanketException("Unable to parse file " + file,
194: e);
195: } catch (IOException e) {
196: throw new JBlanketException("Unable to read file " + file,
197: e);
198: }
199: }
200:
201: /**
202: * Write all aggregated methods to output XML file 'COVER-MethodSets.xml'.
203: *
204: * @throws JBlanketException if unable to write to output file.
205: */
206: private void writeXmlFile() throws JBlanketException {
207:
208: PrintWriter writer = null;
209: File file = new File(jblanketDir, "COVER-MethodSets.xml");
210: try {
211: writer = new PrintWriter(new FileOutputStream(file));
212: } catch (IOException e) {
213: throw new JBlanketException("Unable to write to file "
214: + file.getAbsoluteFile(), e);
215: }
216:
217: this .methodSets.write(writer);
218:
219: writer.close();
220: }
221:
222: /**
223: * Transforms the XML file <code>xmlFileName</code> to HTML. The default format is with frames.
224: *
225: * @param xmlFileName the name of XML file to transform.
226: * @throws JBlanketException if unable to transform XML file to HTML using XSL.
227: */
228: protected void transformXmlToHtml(String xmlFileName)
229: throws JBlanketException {
230:
231: OutputStream ostream = null;
232:
233: // get the XSL file, default "frames"
234: String xslFileName = "jblanket-frames.xsl";
235: if (NOFRAMES.equals(this .format)) {
236: xslFileName = "jblanket-noframes.xsl";
237: }
238:
239: URL xslUrl = getClass().getResource(xslFileName);
240: if (xslUrl == null) {
241: String message = "Could not find jar resource "
242: + xslFileName + ";\n"
243: + "Add jblanket.jar to classpath";
244: throw new JBlanketException(message);
245: }
246:
247: // transform XML file xmlFileName to HTML
248: try {
249:
250: TransformerFactory tfactory = TransformerFactory
251: .newInstance();
252: Source xslSource = new StreamSource(xslUrl.toExternalForm());
253: // throws javax.xml.transform.TransformerConfigurationExeption
254: Transformer tformer = tfactory.newTransformer(xslSource);
255: DocumentBuilderFactory factory = DocumentBuilderFactory
256: .newInstance();
257: // throws javax.xml.parsers.ParserConfigurationException
258: DocumentBuilder builder = factory.newDocumentBuilder();
259: // throws org.xml.sax.SAXException
260: Document doc = builder.parse(new File(xmlFileName));
261: Source xmlSource = new DOMSource(doc);
262:
263: if (FRAMES.equals(this .format)) {
264: ostream = new ByteArrayOutputStream();
265: } else {
266: ostream = new FileOutputStream(new File(toDir
267: .getAbsolutePath(), "jblanket-noframes.html"));
268: }
269:
270: tformer.setParameter("output.dir", toDir.getAbsolutePath());
271: Result result = new StreamResult(ostream);
272: // following throws javax.xml.transform.TransformerException
273: tformer.transform(xmlSource, result);
274: } catch (Exception e) {
275: throw new JBlanketException(
276: "Unable to transform XML to HTML", e);
277: } finally {
278: try {
279: if (ostream != null) {
280: ostream.close();
281: }
282: } catch (IOException e) {
283: throw new JBlanketException(
284: "Could not close OutputStream for "
285: + xmlFileName, e);
286: }
287: }
288: }
289: }
|