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    }