Project Report: fawkez

Packagesummary org.jcoderz.phoenix.report

org.jcoderz.phoenix.report.EmmaReportReader

LineHitsNoteSource
1  /*
2   * $Id: EmmaReportReader.java 1464 2009-05-10 17:54:09Z amandel $
3   *
4   * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5   *
6   * Redistribution and use in source and binary forms, with or without
7   * modification, are permitted provided that the following conditions are
8   * met:
9   *
10   *    * Redistributions of source code must retain the above copyright
11   *      notice, this list of conditions and the following disclaimer.
12   *    * Redistributions in binary form must reproduce the above
13   *      copyright notice, this list of conditions and the following
14   *      disclaimer in the documentation and/or other materials
15   *      provided with the distribution.
16   *    * Neither the name of the jCoderZ.org Project nor the names of
17   *      its contributors may be used to endorse or promote products
18   *      derived from this software without specific prior written
19   *      permission.
20   *
21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32   */
33  package org.jcoderz.phoenix.report;
34  
35  import java.io.File;
36  import java.io.IOException;
37  import java.util.ArrayList;
38  import java.util.HashMap;
39  import java.util.Iterator;
40  import java.util.List;
41  import java.util.Map;
42  import java.util.Map.Entry;
43  import java.util.logging.Level;
44  import java.util.logging.Logger;
45  
46  import javax.xml.bind.JAXBException;
47  
48  import org.jcoderz.phoenix.report.jaxb.Item;
49  import org.jcoderz.phoenix.report.jaxb.ObjectFactory;
50  
51  import com.vladium.emma.data.ClassDescriptor;
52  import com.vladium.emma.data.DataFactory;
53  import com.vladium.emma.data.ICoverageData;
54  import com.vladium.emma.data.IMergeable;
55  import com.vladium.emma.data.IMetaData;
56  import com.vladium.emma.data.MethodDescriptor;
57  import com.vladium.emma.data.ICoverageData.DataHolder;
58  
59  /**
60   * Reads the coverage report generated by emma (http://emma.sourceforge.net/).
61   *
62   * @author Andreas Mandel
63   */
64  public class EmmaReportReader
65          extends AbstractReportReader
66  {
67      /** JAXB context path. */
68      public static final String JCOVERAGE_JAXB_CONTEXT_PATH
69              = "org.jcoderz.phoenix.coverage.jaxb";
70  
710     private static final String CLASSNAME
72              = EmmaReportReader.class.getName();
73  
740     private static final Logger logger = Logger.getLogger(CLASSNAME);
75  
76      /**
77       * Used if all branches of a line are covered. If there are 2
78       * branches in a line 1/2 of this value is assigned as hit
79       * counter.
80       */
81      private static final int EMMA_FULL_PERCENTAGE = 100;
82  
83      private IMetaData mEmmaMetaData;
84      private ICoverageData mEmmaCoverageData;
85  
86      EmmaReportReader ()
87              throws JAXBException
88      {
890         super(JCOVERAGE_JAXB_CONTEXT_PATH);
900     }
91  
92      /** {@inheritDoc} */
93      public final void parse (File f)
94              throws JAXBException
95      {
96          try
97          {
980             final IMergeable[] emmaReport = DataFactory.load(f);
990             mEmmaMetaData = (IMetaData) emmaReport[DataFactory.TYPE_METADATA];
1000(1)            mEmmaCoverageData = (ICoverageData)
101                  emmaReport[DataFactory.TYPE_COVERAGEDATA];
1020             if (mEmmaMetaData == null)
103              {
1040                 logger.warning(
105                      "Read no meta data from emma in file '" + f + "'.");
106              }
1070             if (mEmmaCoverageData == null)
108              {
1090                 logger.warning(
110                      "Read no coverage info from emma in file '" + f + "'.");
111              }
112          }
1130         catch (IOException e)
114          {
1150             throw new JAXBException("Cannot read Emma report at '"
116                  + f + "'.", e);
1170         }
1180     }
119  
120      /** {@inheritDoc} */
121      public final Map<ResourceInfo, List<Item>> getItems ()
122          throws JAXBException
123      {
1240         final Map<ResourceInfo, List<Item>> itemMap
125              = new HashMap<ResourceInfo, List<Item>>();
126  
1270(2)        final Iterator<ClassDescriptor> i = mEmmaMetaData.iterator();
1280         while (i.hasNext())
129          {
1300             final ClassDescriptor clazz = i.next();
1310             final String srcFileName = clazz.getSrcFileName();
132              final String fileName;
1330             if (srcFileName != null)
134              {
1350                 fileName = srcFileName.substring(
136                      0, srcFileName.lastIndexOf('.'));
137              }
138              else
139              { // fall back if data is not available.
1400                 fileName = clazz.getClassVMName().substring(
141                      clazz.getClassVMName().lastIndexOf('/') + 1);
142              }
1430             final String classname
144                  = clazz.getClassVMName().substring(
145                      clazz.getClassVMName().lastIndexOf('/') + 1);
1460             final ResourceInfo source
147                  = ResourceInfo.lookup(
148                      clazz.getPackageVMName().replaceAll("/", "."), fileName);
1490             if (source != null)
150              {
1510                 if (logger.isLoggable(Level.FINER))
152                  {
1530                     logger.finer(
154                          "Processing coverage info for resource " + source);
155                  }
1560                 processClazz(itemMap, source, clazz,
157                     mEmmaCoverageData == null
158                         ? null : mEmmaCoverageData.getCoverage(clazz));
159              }
160              else
161              {
1620                 if (logger.isLoggable(Level.FINER))
163                  {
1640                     logger.finer(
165                          "Ignoring coverage info for class "
166                          + clazz.getPackageVMName().replaceAll("/", ".") + "."
167                          + classname + "@" + clazz.getSrcFileName());
168                  }
169              }
1700         }
1710         return itemMap;
172      }
173  
174      private void processClazz (Map<ResourceInfo, List<Item>> itemMap,
175          ResourceInfo source, ClassDescriptor clazz, DataHolder coverage)
176              throws JAXBException
177      {
1780         logger.fine("Processing class '" + clazz.getName() + "'");
179  
1800         final Map<Integer, CoverageDetail> lineCoverage
181              = collectLineCoverage(clazz, coverage);
182  
1830         final List<Item> itemList
184              = createItemEntries(lineCoverage);
185  
1860         if (!itemList.isEmpty())
187          {
1880             if (itemMap.containsKey(source))
189              {
1900                final List<Item> l = itemMap.get(source);
1910                l.addAll(itemList);
1920             }
193              else
194              {
1950                itemMap.put(source, itemList);
196              }
197          }
1980     }
199  
200      /**
201       * Collect all counters per line number mapping.
202       * Emma has a block view on the source but we need a line
203       * by line info.
204       * @param clazz the static info from emma
205       * @param coverage the dynamic coverage data
206       * @return a map mapping from line number to coverage data.
207       */
208      private Map<Integer, CoverageDetail> collectLineCoverage (
209          final ClassDescriptor clazz, DataHolder coverage)
210      {
2110         final MethodDescriptor[] methods = clazz.getMethods();
2120         final Map<Integer, CoverageDetail> lineCoverage
213              = new HashMap<Integer, CoverageDetail>();
2140         for (int methodNr = 0; methodNr < methods.length; methodNr++)
215          {
2160             final MethodDescriptor method = methods[methodNr];
2170             if (method.getBlockSizes() != null
218                  && method.getBlockMap() != null)
219              {
2200                 boolean[] methodCoverage = null;
2210                 if (coverage != null && coverage.m_coverage.length > methodNr)
222                  {
2230                     methodCoverage = coverage.m_coverage[methodNr];
224                  }
2250                 final int[][] map = method.getBlockMap();
2260                 for (int blockNr = 0;
2270                     blockNr < map.length; blockNr++)
228                  {
2290                     final int[] blockLines = map[blockNr];
2300                     if (methodCoverage != null
231                          && methodCoverage.length > blockNr
232                          && methodCoverage[blockNr])
233                      {
2340                         markCovered(lineCoverage, blockLines);
235                      }
236                      else
237                      {
2380                         markNotCovered(lineCoverage, blockLines);
239                      }
240                  }
241              }
242          }
2430         return lineCoverage;
244      }
245  
246      /**
247       * Creates finding report entries out of the line info.
248       * @param lineCoverage map from line number to its coverage info.
249       * @return a list of finding items.
250       * @throws JAXBException the the object creation for the jaxb
251       *  objects fails.
252       */
253      private List<Item> createItemEntries (
254          final Map<Integer, CoverageDetail> lineCoverage)
255          throws JAXBException
256      {
2570         final List<Item> itemList = new ArrayList<Item>();
2580         for (Entry<Integer, CoverageDetail> entry : lineCoverage.entrySet())
259          {
2600            final CoverageDetail c = entry.getValue();
2610            final Item item = new ObjectFactory().createItem();
2620            item.setOrigin(Origin.COVERAGE);
2630            if (c.mNotVisitedBranches > 0)
264             {
2650                final int branches
266                     = c.mVisitedBranches + c.mNotVisitedBranches;
2670                item.setCounter(
268                     (EMMA_FULL_PERCENTAGE * c.mVisitedBranches)
269                         / branches);
2700            }
271             else
272             {
2730                item.setCounter(EMMA_FULL_PERCENTAGE);
274             }
2750            item.setLine(entry.getKey());
2760            item.setSeverity(Severity.COVERAGE);
2770(3)           item.setFindingType("coverage"); // FIXME: use type
2780            itemList.add(item);
2790        }
2800        return itemList;
281      }
282  
283      private void markCovered (Map<Integer, CoverageDetail> lineCoverage,
284          int[] lines)
285      {
2860         for (int line : lines)
287          {
2880             getLine(lineCoverage, line).mVisitedBranches++;
289          }
2900     }
291  
292      private void markNotCovered (Map<Integer, CoverageDetail> lineCoverage,
293          int[] lines)
294      {
2950         for (int line : lines)
296          {
2970             getLine(lineCoverage, line).mNotVisitedBranches++;
298          }
2990     }
300  
301      private CoverageDetail getLine (
302          Map<Integer, CoverageDetail> lineCoverage, int line)
303      {
3040         CoverageDetail result = lineCoverage.get(line);
3050         if (result == null)
306          {
3070             result = new CoverageDetail();
3080             lineCoverage.put(line, result);
309          }
3100         return result;
311      }
312  
313  
3140(4)    private static class CoverageDetail
315      {
316          private int mNotVisitedBranches;
317          private int mVisitedBranches;
318      }
319  }

Findings in this File

w (1) 100 : 0 method org.jcoderz.phoenix.report.EmmaReportReader.parse(File) accesses list or array with constant index
d (2) 127 : 67 [unchecked] unchecked conversion found : java.util.Iterator required: java.util.Iterator<com.vladium.emma.data.ClassDescriptor>
i (3) 277 : 0 Comment matches to-do format '(TODO|FIXME|CHECKME)'.
c (4) 314 : 5 Utility classes should not have a public or default constructor.