1 9 package com.vladium.emma.report.xml; 10 11 import java.io.BufferedWriter ; 12 import java.io.File ; 13 import java.io.FileOutputStream ; 14 import java.io.IOException ; 15 import java.io.OutputStreamWriter ; 16 import java.io.UnsupportedEncodingException ; 17 import java.io.Writer ; 18 import java.util.Date ; 19 import java.util.Iterator ; 20 21 import com.vladium.util.Files; 22 import com.vladium.util.IConstants; 23 import com.vladium.util.IProperties; 24 import com.vladium.util.Strings; 25 import com.vladium.emma.IAppConstants; 26 import com.vladium.emma.IAppErrorCodes; 27 import com.vladium.emma.EMMAProperties; 28 import com.vladium.emma.EMMARuntimeException; 29 import com.vladium.emma.data.ICoverageData; 30 import com.vladium.emma.data.IMetaData; 31 import com.vladium.emma.report.AbstractReportGenerator; 32 import com.vladium.emma.report.AllItem; 33 import com.vladium.emma.report.ClassItem; 34 import com.vladium.emma.report.IItem; 35 import com.vladium.emma.report.IItemAttribute; 36 import com.vladium.emma.report.IItemMetadata; 37 import com.vladium.emma.report.ItemComparator; 38 import com.vladium.emma.report.MethodItem; 39 import com.vladium.emma.report.PackageItem; 40 import com.vladium.emma.report.SourcePathCache; 41 import com.vladium.emma.report.SrcFileItem; 42 43 47 public 48 final class ReportGenerator extends AbstractReportGenerator 49 implements IAppErrorCodes 50 { 51 53 55 public String getType () 56 { 57 return TYPE; 58 } 59 60 public void process (final IMetaData mdata, final ICoverageData cdata, 61 final SourcePathCache cache, final IProperties properties) 62 throws EMMARuntimeException 63 { 64 initialize (mdata, cdata, cache, properties); 65 66 long start = 0, end; 67 final boolean trace1 = m_log.atTRACE1 (); 68 69 if (trace1) start = System.currentTimeMillis (); 70 71 { 72 m_view.getRoot ().accept (this, null); 73 close (); 74 } 75 76 if (trace1) 77 { 78 end = System.currentTimeMillis (); 79 80 m_log.trace1 ("process", "[" + getType () + "] report generated in " + (end - start) + " ms"); 81 } 82 } 83 84 public void cleanup () 85 { 86 close (); 87 88 super.cleanup (); 89 } 90 91 92 94 public Object visit (final AllItem item, final Object ctx) 95 { 96 try 97 { 98 File outFile = m_settings.getOutFile (); 99 if (outFile == null) 100 { 101 outFile = new File ("coverage.xml"); 102 m_settings.setOutFile (outFile); 103 } 104 105 final File fullOutFile = Files.newFile (m_settings.getOutDir (), outFile); 106 107 m_log.info ("writing [" + getType () + "] report to [" + fullOutFile.getAbsolutePath () + "] ..."); 108 109 openOutFile (fullOutFile, m_settings.getOutEncoding (), true); 110 111 m_out.write ("<?xml version=\"1.0\" encoding=\"" + m_settings.getOutEncoding () + "\"?>"); 113 114 try 116 { 117 final StringBuffer label = new StringBuffer (101); 118 119 label.append ("<!-- "); 120 label.append (IAppConstants.APP_NAME); 121 label.append (" v"); label.append (IAppConstants.APP_VERSION_WITH_BUILD_ID_AND_TAG); 122 label.append (" report, generated "); 123 label.append (new Date (EMMAProperties.getTimeStamp ())); 124 label.append (" -->"); 125 126 m_out.write (label.toString ()); 127 m_out.newLine (); 128 129 m_out.flush (); 130 } 131 catch (IOException ioe) 132 { 133 throw new EMMARuntimeException (IAppErrorCodes.REPORT_IO_FAILURE, ioe); 134 } 135 136 eol (); 137 openElementTag ("report"); 138 closeElementTag (false); 139 m_out.incIndent (); 140 141 eol (); 143 openElementTag ("stats"); 144 closeElementTag (false); 145 m_out.incIndent (); 146 { 147 emitStatsCount ("packages", item.getChildCount ()); 148 emitStatsCount ("classes", item.getAggregate (IItem.TOTAL_CLASS_COUNT)); 149 emitStatsCount ("methods", item.getAggregate (IItem.TOTAL_METHOD_COUNT)); 150 151 if (m_srcView && m_hasSrcFileInfo) 152 { 153 emitStatsCount ("srcfiles", item.getAggregate (IItem.TOTAL_SRCFILE_COUNT)); 154 155 if (m_hasLineNumberInfo) 156 emitStatsCount ("srclines", item.getAggregate (IItem.TOTAL_LINE_COUNT)); 157 } 158 } 159 m_out.decIndent (); 160 eol (); 161 endElement ("stats"); 162 163 eol (); 165 openElementTag ("data"); 166 closeElementTag (false); 167 m_out.incIndent (); 168 { 169 final ItemComparator childrenOrder = m_typeSortComparators [PackageItem.getTypeMetadata ().getTypeID ()]; 170 emitItem (item, childrenOrder); 171 } 172 m_out.decIndent (); 173 eol (); 174 endElement ("data"); 175 176 m_out.decIndent (); 177 eol (); 178 endElement ("report"); 179 } 180 catch (IOException ioe) 181 { 182 throw new EMMARuntimeException (IAppErrorCodes.REPORT_IO_FAILURE, ioe); 183 } 184 185 return ctx; 186 } 187 188 189 public Object visit (final PackageItem item, final Object ctx) 190 { 191 if (m_verbose) m_log.verbose (" report: processing package [" + item.getName () + "] ..."); 192 193 try 194 { 195 final ItemComparator childrenOrder = m_typeSortComparators [m_srcView ? SrcFileItem.getTypeMetadata ().getTypeID () : ClassItem.getTypeMetadata ().getTypeID ()]; 196 emitItem (item, childrenOrder); 197 } 198 catch (IOException ioe) 199 { 200 throw new EMMARuntimeException (IAppErrorCodes.REPORT_IO_FAILURE, ioe); 201 } 202 203 return ctx; 204 } 205 206 207 public Object visit (final SrcFileItem item, final Object ctx) 208 { 209 try 210 { 211 final ItemComparator childrenOrder = m_typeSortComparators [ClassItem.getTypeMetadata ().getTypeID ()]; 212 emitItem (item, childrenOrder); 213 } 214 catch (IOException ioe) 215 { 216 throw new EMMARuntimeException (IAppErrorCodes.REPORT_IO_FAILURE, ioe); 217 } 218 219 return ctx; 220 } 221 222 public Object visit (final ClassItem item, final Object ctx) 223 { 224 try 225 { 226 final ItemComparator childrenOrder = m_typeSortComparators [MethodItem.getTypeMetadata ().getTypeID ()]; 227 emitItem (item, childrenOrder); 228 } 229 catch (IOException ioe) 230 { 231 throw new EMMARuntimeException (IAppErrorCodes.REPORT_IO_FAILURE, ioe); 232 } 233 234 return ctx; 235 } 236 237 public Object visit (final MethodItem item, final Object ctx) 238 { 239 try 240 { 241 emitItem (item, null); 242 } 243 catch (IOException ioe) 244 { 245 throw new EMMARuntimeException (IAppErrorCodes.REPORT_IO_FAILURE, ioe); 246 } 247 248 return ctx; 249 } 250 251 253 255 257 258 private static final class IndentingWriter extends BufferedWriter 259 { 260 public void newLine () throws IOException 261 { 262 m_state = 0; 263 super.write (IConstants.EOL, 0, IConstants.EOL.length ()); 264 } 265 266 public void write (final char [] cbuf, final int off, final int len) throws IOException 267 { 268 indent (); 269 super.write (cbuf, off, len); 270 } 271 272 public void write (int c) throws IOException 273 { 274 indent (); 275 super.write (c); 276 } 277 278 public void write (final String s, final int off, final int len) throws IOException 279 { 280 indent (); 281 super.write (s, off, len); 282 } 283 284 285 IndentingWriter (final Writer out, final int buffer, final int indent) 286 { 287 super (out, buffer); 288 m_indent = indent; 289 } 290 291 292 void incIndent (final int delta) 293 { 294 if (delta < 0) throw new IllegalArgumentException ("delta be non-negative: " + delta); 295 296 m_indent += delta; 297 } 298 299 void incIndent () 300 { 301 incIndent (INDENT_INCREMENT); 302 } 303 304 void decIndent (final int delta) 305 { 306 if (delta < 0) throw new IllegalArgumentException ("delta be non-negative: " + delta); 307 if (delta > m_indent) throw new IllegalArgumentException ("delta = " + delta + ", current indent = " + m_indent); 308 309 m_indent -= delta; 310 } 311 312 void decIndent () 313 { 314 decIndent (INDENT_INCREMENT); 315 } 316 317 String getIndent () 318 { 319 if (m_indent <= 0) 320 return ""; 321 else 322 { 323 if ((m_sindent == null) || (m_sindent.length () < m_indent)) 324 { 325 final char [] ca = new char [m_indent]; 326 327 for (int i = 0; i < m_indent; ++ i) ca [i] = ' '; 328 m_sindent = new String (ca); 329 330 return m_sindent; 331 } 332 else 333 { 334 return m_sindent.substring (0, m_indent); 335 } 336 } 337 } 338 339 340 private void indent () 341 throws IOException 342 { 343 if (m_state == 0) 344 { 345 final String indent = getIndent (); 346 super.write (indent, 0, indent.length ()); 347 348 m_state = 1; 349 } 350 } 351 352 353 private int m_indent; 354 private int m_state; 355 private transient String m_sindent; 356 357 private static final int INDENT_INCREMENT = 2; 358 359 } 361 362 private void emitStatsCount (final String name, final int value) 363 throws IOException 364 { 365 eol (); 366 openElementTag (name); 367 m_out.write (" value=\"" + value); 368 m_out.write ('"'); 369 closeElementTag (true); 370 } 371 372 private void emitItem (final IItem item, final ItemComparator childrenOrder) 373 throws IOException 374 { 375 final IItemMetadata metadata = item.getMetadata (); 376 final int [] columns = m_settings.getColumnOrder (); 377 final String tag = metadata.getTypeName (); 378 379 eol (); 380 381 { 383 openElementTag (tag); 384 385 m_out.write (" name=\""); 386 m_out.write (Strings.HTMLEscape (item.getName ())); 387 m_out.write ('"'); 388 389 closeElementTag (false); 390 } 391 392 eol (); 393 394 m_out.incIndent (); 395 396 emitItemCoverage (item, columns); 397 398 final boolean deeper = (childrenOrder != null) && (m_settings.getDepth () > metadata.getTypeID ()) && (item.getChildCount () > 0); 399 400 if (deeper) 401 { 402 for (Iterator packages = item.getChildren (childrenOrder); packages.hasNext (); ) 403 { 404 ((IItem) packages.next ()).accept (this, null); 405 } 406 407 eol (); 408 } 409 410 m_out.decIndent (); 411 412 { 414 endElement (tag); 415 } 416 } 417 418 421 private void emitItemCoverage (final IItem item, final int [] columns) 422 throws IOException 423 { 424 final StringBuffer buf = new StringBuffer (64); 425 426 for (int c = 0, cLimit = columns.length; c < cLimit; ++ c) 427 { 428 final int attrID = columns [c]; 429 430 if (attrID != IItemAttribute.ATTRIBUTE_NAME_ID) 431 { 432 final IItemAttribute attr = item.getAttribute (attrID, m_settings.getUnitsType ()); 433 434 if (attr != null) 435 { 436 openElementTag ("coverage"); 437 438 m_out.write (" type=\""); 439 m_out.write (Strings.HTMLEscape (attr.getName ())); 440 m_out.write ("\" value=\""); 441 attr.format (item, buf); 442 m_out.write (Strings.HTMLEscape (buf.toString ())); 443 m_out.write ('"'); 444 buf.setLength (0); 445 446 closeElementTag (true); 447 448 eol (); 449 } 450 } 451 } 452 453 } 454 455 private void openElementTag (final String tag) 456 throws IOException 457 { 458 m_out.write ('<'); 459 m_out.write (tag); 460 } 461 462 private void closeElementTag (final boolean simple) 463 throws IOException 464 { 465 if (simple) 466 m_out.write ("/>"); 467 else 468 m_out.write ('>'); 469 } 470 471 private void endElement (final String tag) 472 throws IOException 473 { 474 m_out.write ("</"); 475 m_out.write (tag); 476 m_out.write ('>'); 477 } 478 479 private void eol () 480 throws IOException 481 { 482 m_out.newLine (); 483 } 484 485 private void close () 486 { 487 if (m_out != null) 488 { 489 try 490 { 491 m_out.flush (); 492 m_out.close (); 493 } 494 catch (IOException ioe) 495 { 496 throw new EMMARuntimeException (IAppErrorCodes.REPORT_IO_FAILURE, ioe); 497 } 498 finally 499 { 500 m_out = null; 501 } 502 } 503 } 504 505 private void openOutFile (final File file, final String encoding, final boolean mkdirs) 506 { 507 try 508 { 509 if (mkdirs) 510 { 511 final File parent = file.getParentFile (); 512 if (parent != null) parent.mkdirs (); 513 } 514 515 m_out = new IndentingWriter (new OutputStreamWriter (new FileOutputStream (file), encoding), IO_BUF_SIZE, 0); 516 } 517 catch (UnsupportedEncodingException uee) 518 { 519 throw new EMMARuntimeException (uee); 521 } 522 catch (IOException fnfe) { 526 throw new EMMARuntimeException (fnfe); 528 } 529 } 530 531 532 private IndentingWriter m_out; 533 534 private static final String TYPE = "xml"; 535 private static final int IO_BUF_SIZE = 64 * 1024; 536 537 } | Popular Tags |