001 /** 002 * www.jcoverage.com 003 * Copyright (C)2003 jcoverage ltd. 004 * 005 * This file is part of jcoverage. 006 * 007 * jcoverage is free software; you can redistribute it and/or modify 008 * it under the terms of the GNU General Public License as published 009 * by the Free Software Foundation; either version 2 of the License, 010 * or (at your option) any later version. 011 * 012 * jcoverage is distributed in the hope that it will be useful, but 013 * WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with jcoverage; if not, write to the Free Software 019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 020 * USA 021 * 022 */ 023 package com.jcoverage.coverage.reporting.xml; 024 025 import com.jcoverage.coverage.Instrumentation; 026 import com.jcoverage.util.ClassHelper; 027 028 import gnu.getopt.Getopt; 029 import gnu.getopt.LongOpt; 030 031 import java.io.File; 032 import java.io.FileInputStream; 033 import java.io.FileWriter; 034 import java.io.InputStream; 035 import java.io.IOException; 036 import java.io.ObjectInputStream; 037 import java.io.PrintWriter; 038 039 import java.util.Iterator; 040 import java.util.Map; 041 042 import org.apache.log4j.Logger; 043 044 045 public class Main { 046 static final Logger logger=Logger.getLogger(Main.class); 047 048 final int indentRate=2; 049 final PrintWriter pw; 050 051 int indent=0; 052 053 void increaseIndentation() { 054 indent+=indentRate; 055 } 056 057 void decreaseIndentation() { 058 indent-=indentRate; 059 } 060 061 void indent() { 062 for(int i=0;i<indent;i++) { 063 pw.print(' '); 064 } 065 } 066 067 void println(String ln) { 068 indent(); 069 pw.println(ln); 070 } 071 072 public static void main(String[] args) throws Exception { 073 if(logger.isDebugEnabled()) { 074 for(int i=0;i<args.length;i++) { 075 logger.debug("args["+i+"]: "+args[i]); 076 } 077 } 078 079 LongOpt[] longOpts=new LongOpt[3]; 080 longOpts[0]=new LongOpt("instrumentation",LongOpt.REQUIRED_ARGUMENT,null,'i'); 081 longOpts[1]=new LongOpt("output",LongOpt.REQUIRED_ARGUMENT,null,'o'); 082 longOpts[2]=new LongOpt("source",LongOpt.REQUIRED_ARGUMENT,null,'s'); 083 084 Getopt g=new Getopt(Main.class.getName(),args,":i:o:s:",longOpts); 085 086 int c; 087 088 File serializedInstrumentation=null; 089 File outputDirectory=null; 090 File sourceDirectory=null; 091 092 while((c=g.getopt())!=-1) { 093 switch(c) { 094 case 'i': 095 serializedInstrumentation=new File(g.getOptarg()); 096 break; 097 case 'o': 098 outputDirectory=new File(g.getOptarg()); 099 break; 100 case 's': 101 sourceDirectory=new File(g.getOptarg()); 102 break; 103 } 104 } 105 106 new Main(new FileInputStream(serializedInstrumentation),new PrintWriter(new FileWriter(new File(outputDirectory,"coverage.xml"))),sourceDirectory); 107 } 108 109 110 Main(InputStream serializedInstrumentation,PrintWriter pw,File sourceDirectory) throws IOException,ClassNotFoundException { 111 this.pw=pw; 112 113 try { 114 ObjectInputStream objects=new ObjectInputStream(serializedInstrumentation); 115 116 println("<?xml version=\"1.0\"?>"); 117 if(sourceDirectory==null) { 118 println("<coverage>"); 119 } else { 120 println("<coverage src=\""+sourceDirectory+"\">"); 121 } 122 increaseIndentation(); 123 dump(((Map)objects.readObject()).entrySet().iterator()); 124 decreaseIndentation(); 125 println("</coverage>"); 126 } finally { 127 try { 128 serializedInstrumentation.close(); 129 } catch(IOException ex) { 130 logger.warn(ex); 131 } 132 133 pw.close(); 134 } 135 } 136 137 void dump(Iterator entySetIterator) { 138 while(entySetIterator.hasNext()) { 139 dump((Map.Entry)entySetIterator.next()); 140 } 141 } 142 143 void dump(Map.Entry entry) { 144 println("<class name=\""+entry.getKey()+"\">"); 145 increaseIndentation(); 146 dump((String)entry.getKey(),(Instrumentation)entry.getValue()); 147 decreaseIndentation(); 148 println("</class>"); 149 } 150 151 String getFileName(String className,Instrumentation instrumentation) { 152 return ClassHelper.getPackageName(className).replace('.','/')+'/'+instrumentation.getSourceFileName(); 153 } 154 155 void dumpMethods(Instrumentation instrumentation) { 156 Iterator i=instrumentation.getMethodNamesAndSignatures().iterator(); 157 while(i.hasNext()) { 158 159 String methodNameAndSignature=(String)i.next(); 160 161 println("<method nameAndSignature=\""+methodNameAndSignature+"\">"); 162 increaseIndentation(); 163 164 try { 165 println("<line rate=\""+instrumentation.getLineCoverageRate(methodNameAndSignature)+"\"/>"); 166 println("<branch rate=\""+instrumentation.getBranchCoverageRate(methodNameAndSignature)+"\"/>"); 167 } catch(IllegalArgumentException ex) { 168 logger.warn(ex); 169 } 170 171 decreaseIndentation(); 172 println("</method>"); 173 } 174 } 175 176 void dump(String className,Instrumentation instrumentation) { 177 println("<file name=\""+getFileName(className,instrumentation)+"\"/>"); 178 println("<line rate=\""+instrumentation.getLineCoverageRate()+"\"/>"); 179 println("<branch rate=\""+instrumentation.getBranchCoverageRate()+"\"/>"); 180 181 182 println("<methods>"); 183 increaseIndentation(); 184 dumpMethods(instrumentation); 185 decreaseIndentation(); 186 println("</methods>"); 187 188 StringBuffer sb=new StringBuffer(); 189 Iterator i=instrumentation.getSourceLineNumbers().iterator(); 190 while(i.hasNext()) { 191 sb.append(i.next()); 192 if(i.hasNext()) { 193 sb.append(", "); 194 } 195 } 196 println("<valid lines=\""+sb.toString()+"\"/>"); 197 198 i=instrumentation.getCoverage().entrySet().iterator(); 199 while(i.hasNext()) { 200 Map.Entry entry=(Map.Entry)i.next(); 201 println("<line number=\""+entry.getKey()+"\" hits=\""+entry.getValue()+"\"/>"); 202 } 203 } 204 }