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    }