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