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 */
023package com.jcoverage.coverage.reporting.xml;
024
025import com.jcoverage.coverage.Instrumentation;
026import com.jcoverage.util.ClassHelper;
027
028import gnu.getopt.Getopt;
029import gnu.getopt.LongOpt;
030
031import java.io.File;
032import java.io.FileInputStream;
033import java.io.FileWriter;
034import java.io.InputStream;
035import java.io.IOException;
036import java.io.ObjectInputStream;
037import java.io.PrintWriter;
038
039import java.util.Iterator;
040import java.util.Map;
041
042import org.apache.log4j.Logger;
043
044
045public 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}