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.html; 024 025 import java.io.*; 026 import java.util.*; 027 028 import org.apache.log4j.Logger; 029 030 import com.jcoverage.coverage.reporting.collation.JavaFilePage; 031 import com.jcoverage.reporting.html.HtmlFormatHelper; 032 import com.jcoverage.reporting.html.Writable; 033 034 /** 035 * 036 */ 037 public class SourceTable implements Writable { 038 039 static Logger logger=Logger.getLogger(SourceTable.class); 040 041 File sourceFile; 042 JavaFilePage page; 043 044 public SourceTable(File sourceFile,JavaFilePage page) { 045 this.sourceFile=sourceFile; 046 this.page=page; 047 } 048 049 public void writeTo(PrintWriter writer) { 050 051 writer.println("<table border=\"0\" cellpadding=\"2\" cellspacing=\"0\" width=\"85%\">"); 052 writer.print("<tr>"); 053 writer.print("<th>Line</th>"); 054 writer.print("<th>Hits</th>"); 055 writer.print("<th class=\"remainder\">Source</th>"); 056 writer.println("</tr>"); 057 058 int lineNo=1; // Java source code lines are 1-based 059 060 try { 061 BufferedReader source=new BufferedReader(new InputStreamReader(new FileInputStream(sourceFile))); 062 063 Iterator coverage=page.getSourceFileLineCoverageSet().iterator(); 064 065 while(coverage.hasNext()) { 066 Map.Entry entry=(Map.Entry)coverage.next(); 067 int nextLineNo=((Integer)entry.getKey()).intValue(); 068 069 while (lineNo<nextLineNo) { 070 String line=source.readLine(); 071 if (line==null) { 072 break; 073 } 074 writeRow(writer,page,lineNo,0,indentSource(line)); 075 lineNo++; 076 } 077 078 if (lineNo==nextLineNo) { 079 String line=source.readLine(); 080 if (line==null) { 081 // As above 082 break; 083 } 084 writeRow(writer,page,nextLineNo,((Long)entry.getValue()).longValue(),indentSource(line)); 085 lineNo++; 086 } 087 088 } 089 090 while (true) { 091 String remainder=source.readLine(); 092 if (remainder==null) { 093 // We have come to the end of the file. 094 break; 095 } 096 writeRow(writer,page,lineNo,0,indentSource(remainder)); 097 lineNo++; 098 } 099 100 } catch (Exception ex) { 101 writer.println("<p>Failed to read java source file: "); 102 writer.println("<pre>"); 103 writer.println(ex.toString()); 104 writer.println("</pre>"); 105 } 106 107 writer.println("</table>"); 108 } 109 110 private void writeRow(PrintWriter writer,JavaFilePage page,int lineNo,long hits,String line) { 111 String cssClass=(lineNo%2==0?"yin":"yang"); 112 boolean validLine=page.getValidSourceLines().contains(new Integer(lineNo)); 113 if (validLine && hits==0) { 114 cssClass="highlight"; 115 } 116 117 writer.print("<tr class=\""+cssClass+"\">"); 118 119 writeCell(writer,String.valueOf(lineNo),"lineno"); 120 121 if (validLine) { 122 writeCell(writer,String.valueOf(hits),"hits"); 123 } else { 124 writeCell(writer," ","hits"); 125 } 126 127 writeCell(writer,"<tt>"+line+"</tt>","code"); 128 writer.println("</tr>"); 129 } 130 131 void writeCell(PrintWriter writer,String content,String cssClass) { 132 writer.print("<td class=\""+cssClass+"\">"+content+"</td>"); 133 } 134 135 /** 136 * @return a String that has leading spaces converted into non-breaking spaces. 137 */ 138 static String indentSource(String line) { 139 StringBuffer sb=new StringBuffer(HtmlFormatHelper.replaceCharacterEntities(HtmlFormatHelper.untabify(line,HtmlFormatHelper.TAB_WIDTH))); 140 StringBuffer newsb=new StringBuffer(); 141 int i=0; 142 while(i<sb.length() && sb.charAt(i)==' ') { 143 i++; 144 newsb.append(" "); 145 } 146 newsb.append(sb.substring(i)); 147 148 // For CSS rendering reasons, we always like to have something in the table cell, even if it's just a space. 149 if (newsb.length()==0) { 150 newsb.append(" "); 151 } 152 153 return newsb.toString(); 154 } 155 156 }