• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2  *
3  * This program and the accompanying materials are made available under
4  * the terms of the Common Public License v1.0 which accompanies this distribution,
5  * and is available at http://www.eclipse.org/legal/cpl-v10.html
6  *
7  * $Id: AbstractReportGenerator.java,v 1.1.1.1.2.4 2005/04/24 23:51:37 vlad_r Exp $
8  */
9 package com.vladium.emma.report;
10 
11 import java.util.Iterator;
12 import java.util.Set;
13 import java.util.TreeSet;
14 
15 import com.vladium.logging.Logger;
16 import com.vladium.util.Descriptors;
17 import com.vladium.util.IProperties;
18 import com.vladium.util.IntIntMap;
19 import com.vladium.util.IntVector;
20 import com.vladium.util.ObjectIntMap;
21 import com.vladium.emma.EMMARuntimeException;
22 import com.vladium.emma.data.ClassDescriptor;
23 import com.vladium.emma.data.ICoverageData;
24 import com.vladium.emma.data.IMetaData;
25 
26 // ----------------------------------------------------------------------------
27 /**
28  * @author Vlad Roubtsov, (C) 2003
29  */
30 public
31 abstract class AbstractReportGenerator extends AbstractItemVisitor
32                                        implements IReportGenerator
33 {
34     // public: ................................................................
35 
36 
create(final String type)37     public static IReportGenerator create (final String type)
38     {
39         if ((type == null) || (type.length () == 0))
40             throw new IllegalArgumentException ("null/empty input: type");
41 
42         // TODO: proper pluggability pattern here
43 
44         if ("html".equals (type))
45             return new com.vladium.emma.report.html.ReportGenerator ();
46         else if ("lcov".equals (type))
47             return new com.vladium.emma.report.lcov.ReportGenerator ();
48         else if ("txt".equals (type))
49             return new com.vladium.emma.report.txt.ReportGenerator ();
50         else if ("xml".equals (type))
51             return new com.vladium.emma.report.xml.ReportGenerator ();
52         else // TODO: error code
53             throw new EMMARuntimeException ("no report generator class found for type [" + type + "]");
54     }
55 
56 
initialize(final IMetaData mdata, final ICoverageData cdata, final SourcePathCache cache, final IProperties properties)57     public void initialize (final IMetaData mdata, final ICoverageData cdata,
58                             final SourcePathCache cache, final IProperties properties)
59         throws EMMARuntimeException
60     {
61         m_log = Logger.getLogger ();
62         m_verbose = m_log.atVERBOSE ();
63 
64         m_settings = ReportProperties.parseProperties (properties, getType ());
65 
66         m_cache = cache;
67 
68         m_hasSrcFileInfo = mdata.hasSrcFileData ();
69         m_hasLineNumberInfo = mdata.hasLineNumberData ();
70 
71         boolean debugInfoWarning = false;
72         boolean bailOut = false;
73 
74         // src view is not possible if 'm_hasSrcFileInfo' is false:
75         if (! mdata.hasSrcFileData () && (m_settings.getViewType () == IReportDataView.HIER_SRC_VIEW))
76         {
77             debugInfoWarning = true;
78 
79             m_log.warning ("not all instrumented classes were compiled with source file");
80             m_log.warning ("debug data: no sources will be embedded in the report.");
81 
82             m_settings.setViewType (IReportDataView.HIER_CLS_VIEW);
83         }
84 
85         // line coverage column must be removed if 'm_hasLineNumberInfo' is false:
86         if (! m_hasLineNumberInfo)
87         {
88             final int [] userColumnIDs = m_settings.getColumnOrder ();
89             final IntVector columnIDs = new IntVector ();
90 
91             boolean removed = false;
92             for (int c = 0; c < userColumnIDs.length; ++ c)
93             {
94                 if (userColumnIDs [c] == IItemAttribute.ATTRIBUTE_LINE_COVERAGE_ID)
95                     removed = true;
96                 else
97                     columnIDs.add (userColumnIDs [c]);
98             }
99 
100             // at this point it is possible that there are no columns left: bail out
101             if (removed)
102             {
103                 debugInfoWarning = true;
104 
105                 if (columnIDs.size () == 0)
106                 {
107                     m_log.warning ("line coverage requested in a report of type [" + getType () + "] but");
108                     m_log.warning ("not all instrumented classes were compiled with line number");
109                     m_log.warning ("debug data: since this was the only requested column, no report will be generated.");
110 
111                     bailOut = true;
112                 }
113                 else
114                 {
115                     m_log.warning ("line coverage requested in a report of type [" + getType () + "] but");
116                     m_log.warning ("not all instrumented classes were compiled with line number");
117                     m_log.warning ("debug data: this column will be removed from the report.");
118 
119                     m_settings.setColumnOrder (columnIDs.values ());
120 
121                     final int [] userSort = m_settings.getSortOrder ();
122                     final IntVector sort = new IntVector ();
123 
124                     for (int c = 0; c < userSort.length; c += 2)
125                     {
126                         if (Math.abs (userSort [c]) != IItemAttribute.ATTRIBUTE_LINE_COVERAGE_ID)
127                         {
128                             sort.add (userSort [c]);
129                             sort.add (userSort [c + 1]);
130                         }
131                     }
132 
133                     m_settings.setSortOrder (sort.values ());
134                 }
135             }
136         }
137         // note: no need to adjust m_metrics due to possible column removal above
138 
139         // SF FR 971176: provide user with sample classes that caused the above warnings
140         if (debugInfoWarning && m_log.atINFO ())
141         {
142             final Set /* String */ sampleClassNames = new TreeSet ();
143             final ObjectIntMap /* packageVMName:String -> count:int */ countMap = new ObjectIntMap ();
144             final int [] _count = new int [1];
145 
146             for (Iterator /* ClassDescriptor */ descriptors = mdata.iterator (); descriptors.hasNext (); )
147             {
148                 final ClassDescriptor cls = (ClassDescriptor) descriptors.next ();
149 
150                 // SF BUG 979717: this check was incorrectly absent in the initial FR impl:
151                 if (! cls.hasCompleteLineNumberInfo () || ! cls.hasSrcFileInfo ())
152                 {
153                     final String packageVMName = cls.getPackageVMName ();
154                     final int count = countMap.get (packageVMName, _count)
155                         ? _count [0]
156                         : 0;
157 
158                     if (count < MAX_DEBUG_INFO_WARNING_COUNT)
159                     {
160                         sampleClassNames.add (Descriptors.vmNameToJavaName (cls.getClassVMName ()));
161                         countMap.put (packageVMName, count + 1);
162                     }
163                 }
164             }
165 
166             m_log.info ("showing up to " + MAX_DEBUG_INFO_WARNING_COUNT + " classes without full debug info per package:");
167             for (Iterator /* String */ names = sampleClassNames.iterator (); names.hasNext (); )
168             {
169                 m_log.info ("  " + names.next ());
170             }
171         }
172 
173         if (bailOut)
174         {
175             // TODO: error code
176             throw new EMMARuntimeException ("BAILED OUT");
177         }
178 
179         final IItemMetadata [] allTypes = IItemMetadata.Factory.getAllTypes ();
180         m_typeSortComparators = new ItemComparator [allTypes.length];
181 
182         for (int t = 0; t < allTypes.length; ++ t)
183         {
184             final IntVector orderedAttrIDsWithDir = new IntVector ();
185             final long typeAttrIDSet = allTypes [t].getAttributeIDs ();
186 
187             for (int s = 0; s < m_settings.getSortOrder ().length; s += 2)
188             {
189                 final int attrID = m_settings.getSortOrder () [s];
190 
191                 if ((typeAttrIDSet & (1 << attrID)) != 0)
192                 {
193                     orderedAttrIDsWithDir.add (attrID);
194 
195                     final int dir = m_settings.getSortOrder () [s + 1];
196                     orderedAttrIDsWithDir.add (dir);
197                 }
198             }
199 
200             m_typeSortComparators [t] = ItemComparator.Factory.create (orderedAttrIDsWithDir.values (), m_settings.getUnitsType ());
201         }
202 
203         m_metrics = new int [allTypes.length];
204         final IntIntMap metrics = m_settings.getMetrics ();
205         for (int t = 0; t < m_metrics.length; ++ t)
206         {
207             m_metrics [t] = -1;
208             metrics.get (t, m_metrics, t);
209         }
210 
211         final IReportDataModel model = IReportDataModel.Factory.create (mdata, cdata);
212         m_view = model.getView (m_settings.getViewType ());
213 
214         m_srcView = (m_settings.getViewType () == IReportDataView.HIER_SRC_VIEW);
215     }
216 
cleanup()217     public void cleanup ()
218     {
219         reset ();
220     }
221 
222     // protected: .............................................................
223 
224 
reset()225     protected void reset ()
226     {
227         m_settings = null;
228         m_cache = null;
229         m_view = null;
230         m_srcView = false;
231 
232         //m_typeSortIDs = null;
233         m_typeSortComparators = null;
234         m_metrics = null;
235 
236         m_log = null;
237     }
238 
239 
240     protected ReportProperties.ParsedProperties m_settings;
241     protected SourcePathCache m_cache;
242     protected IReportDataView m_view;
243     protected boolean m_srcView;
244 
245     protected boolean m_hasSrcFileInfo, m_hasLineNumberInfo;
246     protected ItemComparator [] m_typeSortComparators; // m_typeSortComparators [t] is a comparator representing the sort order for item type t
247     protected int [] m_metrics; // -1 means no pass/fail check for this attribute
248 
249     protected Logger m_log; // every report generator is used on a single thread but the logger needs to be run()-scoped
250     protected boolean m_verbose;
251 
252     // package: ...............................................................
253 
254     // private: ...............................................................
255 
256 
257     private static final int MAX_DEBUG_INFO_WARNING_COUNT = 3; // per package
258 
259 } // end of class
260 // ----------------------------------------------------------------------------
261