1 /*******************************************************************************
2  * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *    Brock Janiczak -initial API and implementation
10  *
11  *******************************************************************************/
12 package org.jacoco.report.xml;
13 
14 import java.io.IOException;
15 import java.io.OutputStream;
16 import java.util.Collection;
17 import java.util.List;
18 
19 import org.jacoco.core.analysis.IBundleCoverage;
20 import org.jacoco.core.data.ExecutionData;
21 import org.jacoco.core.data.SessionInfo;
22 import org.jacoco.report.IReportVisitor;
23 import org.jacoco.report.ISourceFileLocator;
24 import org.jacoco.report.internal.AbstractGroupVisitor;
25 import org.jacoco.report.internal.xml.XMLCoverageWriter;
26 import org.jacoco.report.internal.xml.XMLDocument;
27 import org.jacoco.report.internal.xml.XMLElement;
28 import org.jacoco.report.internal.xml.XMLGroupVisitor;
29 
30 /**
31  * Report formatter that creates a single XML file for a coverage session
32  */
33 public class XMLFormatter {
34 
35 	private static final String PUBID = "-//JACOCO//DTD Report 1.0//EN";
36 
37 	private static final String SYSTEM = "report.dtd";
38 
39 	private String outputEncoding = "UTF-8";
40 
41 	/**
42 	 * Sets the encoding used for generated XML document. Default is UTF-8.
43 	 *
44 	 * @param outputEncoding
45 	 *            XML output encoding
46 	 */
setOutputEncoding(final String outputEncoding)47 	public void setOutputEncoding(final String outputEncoding) {
48 		this.outputEncoding = outputEncoding;
49 	}
50 
51 	/**
52 	 * Creates a new visitor to write a report to the given stream.
53 	 *
54 	 * @param output
55 	 *            output stream to write the report to
56 	 * @return visitor to emit the report data to
57 	 * @throws IOException
58 	 *             in case of problems with the output stream
59 	 */
createVisitor(final OutputStream output)60 	public IReportVisitor createVisitor(final OutputStream output)
61 			throws IOException {
62 		final XMLElement root = new XMLDocument("report", PUBID, SYSTEM,
63 				outputEncoding, true, output);
64 		class RootVisitor extends XMLGroupVisitor implements IReportVisitor {
65 
66 			RootVisitor(final XMLElement element) throws IOException {
67 				super(element, null);
68 			}
69 
70 			private List<SessionInfo> sessionInfos;
71 
72 			public void visitInfo(final List<SessionInfo> sessionInfos,
73 					final Collection<ExecutionData> executionData)
74 					throws IOException {
75 				this.sessionInfos = sessionInfos;
76 			}
77 
78 			@Override
79 			protected void handleBundle(final IBundleCoverage bundle,
80 					final ISourceFileLocator locator) throws IOException {
81 				writeHeader(bundle.getName());
82 				XMLCoverageWriter.writeBundle(bundle, element);
83 			}
84 
85 			@Override
86 			protected AbstractGroupVisitor handleGroup(final String name)
87 					throws IOException {
88 				writeHeader(name);
89 				return new XMLGroupVisitor(element, name);
90 			}
91 
92 			private void writeHeader(final String name) throws IOException {
93 				element.attr("name", name);
94 				for (final SessionInfo i : sessionInfos) {
95 					final XMLElement sessioninfo = root.element("sessioninfo");
96 					sessioninfo.attr("id", i.getId());
97 					sessioninfo.attr("start", i.getStartTimeStamp());
98 					sessioninfo.attr("dump", i.getDumpTimeStamp());
99 				}
100 			}
101 
102 			@Override
103 			protected void handleEnd() throws IOException {
104 				element.close();
105 			}
106 		}
107 		return new RootVisitor(root);
108 	}
109 
110 }
111