001 /*
002 * Cobertura - http://cobertura.sourceforge.net/
003 *
004 * Copyright (C) 2003 jcoverage ltd.
005 * Copyright (C) 2005 Mark Doliner <thekingant@users.sourceforge.net>
006 * Copyright (C) 2005 Jeremy Thomerson <jthomerson@users.sourceforge.net>
007 *
008 * Cobertura is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License as published
010 * by the Free Software Foundation; either version 2 of the License,
011 * or (at your option) any later version.
012 *
013 * Cobertura is distributed in the hope that it will be useful, but
014 * WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016 * General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with Cobertura; if not, write to the Free Software
020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
021 * USA
022 */
023
024 package net.sourceforge.cobertura.reporting.xml;
025
026 import java.io.File;
027 import java.io.FileWriter;
028 import java.io.IOException;
029 import java.io.PrintWriter;
030 import java.util.Iterator;
031
032 import net.sourceforge.cobertura.coverage.CoverageData;
033 import net.sourceforge.cobertura.reporting.Clazz;
034 import net.sourceforge.cobertura.reporting.CoverageReport;
035 import net.sourceforge.cobertura.reporting.Package;
036
037 import org.apache.log4j.Logger;
038
039 public class XMLReport
040 {
041
042 private static final Logger logger = Logger.getLogger(XMLReport.class);
043
044 private final int indentRate = 2;
045 private final PrintWriter pw;
046
047 private int indent = 0;
048
049 public XMLReport(CoverageReport coverage, File outputDir, File sourceDirectory)
050 throws IOException
051 {
052 pw = new PrintWriter(new FileWriter(new File(outputDir,
053 "coverage.xml")));
054
055 try
056 {
057 println("<?xml version=\"1.0\"?>");
058 if (sourceDirectory == null)
059 {
060 println("<coverage>");
061 }
062 else
063 {
064 println("<coverage src=\"" + sourceDirectory + "\">");
065 }
066 increaseIndentation();
067 dumpPackages(coverage);
068 decreaseIndentation();
069 println("</coverage>");
070 }
071 finally
072 {
073 pw.close();
074 }
075 }
076
077 void increaseIndentation()
078 {
079 indent += indentRate;
080 }
081
082 void decreaseIndentation()
083 {
084 indent -= indentRate;
085 }
086
087 void indent()
088 {
089 for (int i = 0; i < indent; i++)
090 {
091 pw.print(' ');
092 }
093 }
094
095 void println(String ln)
096 {
097 indent();
098 pw.println(ln);
099 }
100
101 private void dumpPackages(CoverageReport coverage)
102 {
103 Iterator it = coverage.getPackages().iterator();
104 while (it.hasNext())
105 {
106 dumpPackage((Package)it.next());
107 }
108 }
109
110 private void dumpPackage(Package pack)
111 {
112 println("<package name=\"" + pack.getName() + "\"" + " line-rate=\""
113 + pack.getLineCoverageRate() + "\"" + " branch-rate=\""
114 + pack.getBranchCoverageRate() + "\"" + ">");
115 increaseIndentation();
116 dumpClasses((Clazz[])pack.getClasses().toArray(new Clazz[pack.getClasses().size()]));
117 decreaseIndentation();
118 println("</package>");
119 }
120
121 private void dumpClasses(Clazz[] clazzes)
122 {
123 for (int i = 0; i < clazzes.length; i++)
124 {
125 dumpClass(clazzes[i]);
126 }
127 }
128
129 void dumpClass(Clazz clazz)
130 {
131 println("<class name=\"" + clazz.getLongName() + "\">");
132 increaseIndentation();
133 dumpClassDetails(clazz);
134 decreaseIndentation();
135 println("</class>");
136 }
137
138 private void dumpClassDetails(Clazz clazz)
139 {
140 println("<file name=\"" + clazz.getLongFileName() + "\"/>");
141 println("<line rate=\"" + clazz.getLineCoverageRate() + "\"/>");
142 println("<branch rate=\"" + clazz.getBranchCoverageRate() + "\"/>");
143
144 println("<methods>");
145 increaseIndentation();
146 dumpMethods(clazz.getRawCoverageData());
147 decreaseIndentation();
148 println("</methods>");
149
150 StringBuffer sb = new StringBuffer();
151 CoverageData instrumentation = clazz.getRawCoverageData();
152 Iterator iter = instrumentation.getValidLineNumbers().iterator();
153 while (iter.hasNext())
154 {
155 sb.append(iter.next());
156 if (iter.hasNext())
157 {
158 sb.append(", ");
159 }
160 }
161 println("<valid lines=\"" + sb.toString() + "\"/>");
162
163 iter = instrumentation.getValidLineNumbers().iterator();
164 while (iter.hasNext())
165 {
166 int lineNumber = ((Integer)iter.next()).intValue();
167 long hitCount = instrumentation.getHitCount(lineNumber);
168 println("<line number=\"" + lineNumber + "\" hits=\"" + hitCount
169 + "\"/>");
170 }
171 }
172
173 private String xmlEscape(String str)
174 {
175 str = str.replaceAll("<", "<");
176 str = str.replaceAll(">", ">");
177 return str;
178 }
179
180 private void dumpMethods(CoverageData instrumentation)
181 {
182 Iterator iter = instrumentation.getMethodNamesAndDescriptors()
183 .iterator();
184 while (iter.hasNext())
185 {
186
187 String methodNameAndSignature = (String)iter.next();
188
189 println("<method nameAndSignature=\""
190 + xmlEscape(methodNameAndSignature) + "\">");
191 increaseIndentation();
192
193 try
194 {
195 println("<line rate=\""
196 + instrumentation
197 .getLineCoverageRate(methodNameAndSignature)
198 + "\"/>");
199 println("<branch rate=\""
200 + instrumentation
201 .getBranchCoverageRate(methodNameAndSignature)
202 + "\"/>");
203 }
204 catch (IllegalArgumentException ex)
205 {
206 logger.warn(ex);
207 }
208
209 decreaseIndentation();
210 println("</method>");
211 }
212 }
213
214 }