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 }