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 }