[jboss-cvs] JBoss Profiler SVN: r522 - in branches/JBossProfiler2: src/etc and 1 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Sun Apr 19 17:15:37 EDT 2009


Author: jesper.pedersen
Date: 2009-04-19 17:15:37 -0400 (Sun, 19 Apr 2009)
New Revision: 522

Added:
   branches/JBossProfiler2/src/etc/style.css
   branches/JBossProfiler2/src/main/org/jboss/profiler/client/HTMLUtil.java
Modified:
   branches/JBossProfiler2/build.xml
   branches/JBossProfiler2/src/main/org/jboss/profiler/client/SnapshotUtil.java
Log:
[JBPROFILER-72] Convert command line client reports to HTML

Modified: branches/JBossProfiler2/build.xml
===================================================================
--- branches/JBossProfiler2/build.xml	2009-04-19 15:17:56 UTC (rev 521)
+++ branches/JBossProfiler2/build.xml	2009-04-19 21:15:37 UTC (rev 522)
@@ -165,13 +165,14 @@
         <copy todir="${build.dir}">
             <fileset dir="${etc.dir}">
                <include name="**/jboss-profiler-client.properties"/>
+               <include name="**/style.css"/>
             </fileset>
         </copy>
 
         <jar destfile="${dist.dir}/${jboss-profiler-client.jar}"
              basedir="${build.dir}"
              manifest="${etc.dir}/client-manifest.mf"
-             includes="org/jboss/profiler/client/*,org/jboss/profiler/client/cmd/**,org/jboss/profiler/shared/**,**/*.xml,**/*.properties"
+             includes="org/jboss/profiler/client/*,org/jboss/profiler/client/cmd/**,org/jboss/profiler/shared/**,**/*.xml,**/*.properties,**/*.css"
              excludes="**/*.java"/>
     </target>
 

Added: branches/JBossProfiler2/src/etc/style.css
===================================================================
--- branches/JBossProfiler2/src/etc/style.css	                        (rev 0)
+++ branches/JBossProfiler2/src/etc/style.css	2009-04-19 21:15:37 UTC (rev 522)
@@ -0,0 +1,147 @@
+/*
+ * JBoss Tattletale
+ * Copyright (C) 2009 Red Hat Middleware LLC.
+ * All rights reserved.
+ * 
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+html {
+    height: 100%;
+    min-height: 100%;
+    background-color : #ffffff;
+    color : #454545;
+    border-collapse : collapse; 
+    border-style: none;
+    margin : 0px auto; 
+    padding: 0px;
+}
+
+body {
+    background-color : #ffffff;
+    color : #454545;
+    margin : 0px auto; 
+    text-align : left;
+    font-family : "Lucida Grand", Verdana, Arial, Helvetica, sans-serif;
+    font-size: 10pt;
+    border-collapse : collapse; 
+    border-style: none;
+    padding: 5px;
+}
+
+p {
+    margin: 5px;
+}
+
+a {
+    color: #527fa8;
+}
+
+hr {
+    border-top: 1px solid #a4b2b9;
+    border-right: 0px solid #a4b2b9;
+    border-left: 0px solid #a4b2b9;
+    border-bottom: 0px solid #a4b2b9;
+    margin-bottom: 3px;
+}
+
+img {
+    border: 0px;
+}
+
+h1 {
+    font-family : "Lucida Grand", Verdana, Arial, Helvetica, sans-serif;
+    font-size : 14pt; 
+    font-weight : bold; 
+    background-color: white;
+    color: #50667c;
+}
+
+h2 {
+    font-family : "Lucida Grand", Verdana, Arial, Helvetica, sans-serif;
+    font-size : 11pt; 
+    font-weight : bold; 
+    background-color: white;
+    color: #50667c;
+}
+
+h3 {
+    font-family : "Lucida Grand", Verdana, Arial, Helvetica, sans-serif;
+    font-size : 11pt; 
+    font-weight : bold; 
+    background-color: white;
+    color: #50667c;
+}
+
+h4 {
+    font-family : "Lucida Grand", Verdana, Arial, Helvetica, sans-serif;
+    font-size : 10pt; 
+    font-weight : bold; 
+    background-color: white;
+    color: #50667c;
+}
+
+h5 {
+    font-family : "Lucida Grand", Verdana, Arial, Helvetica, sans-serif;
+    font-size : 10pt; 
+    font-weight : bold; 
+    background-color: white;
+    color: #50667c;
+}
+
+h6 {
+    font-family : "Lucida Grand", Verdana, Arial, Helvetica, sans-serif;
+    font-size : 10pt; 
+    font-weight : bold; 
+    background-color: white;
+    color: #50667c;
+}
+
+table {
+    width: 100%;
+    border-collapse : collapse; 
+    border-style: none;
+}
+
+tr th {
+    background-color: #d9e0e3;
+    font-size: 10pt;
+    font-weight: bold;
+    color: #5f6a6f;
+    text-align: left;
+    padding: 3px;
+}
+
+tr td {
+    font-size: 10pt;
+    font-weight: bold;
+    vertical-align: top;
+    text-align: left;
+    padding: 3px;
+}
+
+.roweven {
+    background-color: white;
+}
+
+.rowodd {
+    background-color: #eff4f7;
+}

Added: branches/JBossProfiler2/src/main/org/jboss/profiler/client/HTMLUtil.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/client/HTMLUtil.java	                        (rev 0)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/client/HTMLUtil.java	2009-04-19 21:15:37 UTC (rev 522)
@@ -0,0 +1,84 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.profiler.client;
+
+import org.jboss.profiler.shared.Version;
+
+import java.io.BufferedWriter;
+
+import org.jboss.logging.Logger;
+
+/**
+ * The HTML utility class
+ * @author Jesper Pedersen <jesper.pedersen at jboss.org>
+ */
+public class HTMLUtil {
+  /** The logger */
+  private static Logger log = Logger.getLogger(HTMLUtil.class);
+
+  /** New line character */
+  protected static final String NEW_LINE = System.getProperty("line.separator");
+
+  /**
+   * Constructor
+   */
+  private HTMLUtil() {
+  }
+
+  /**
+   * Write HTML header
+   * @param bw The buffered writer
+   * @param title The title for the page
+   * @param toplevel Is the file in top-level directory
+   * @exception Exception Thrown if an error occurs
+   */
+  public static void header(BufferedWriter bw, String title, boolean toplevel) throws Exception {
+    bw.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">" + NEW_LINE);
+    bw.write("<html>" + NEW_LINE);
+    bw.write("<head>" + NEW_LINE);
+    bw.write("  <title>" + Version.FULL_VERSION + ": " + title + "</title>" + NEW_LINE);
+    bw.write("  <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">" + NEW_LINE);
+    if (toplevel) {
+      bw.write("  <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">" + NEW_LINE);
+    } else {
+      bw.write("  <link rel=\"stylesheet\" type=\"text/css\" href=\"../style.css\">" + NEW_LINE);
+    }
+    bw.write("</head>" + NEW_LINE);
+    bw.write("<body>" + NEW_LINE);
+    bw.write(NEW_LINE);
+  }
+
+  /**
+   * Write HTML footer
+   * @param bw The buffered writer
+   * @exception Exception Thrown if an error occurs
+   */
+  public static void footer(BufferedWriter bw) throws Exception {
+    bw.write(NEW_LINE);
+    bw.write("<p>" + NEW_LINE);
+    bw.write("<hr>" + NEW_LINE);
+    bw.write("Generated by: <a href=\"http://www.jboss.org/jbossprofiler\">" + Version.FULL_VERSION + "</a>" + NEW_LINE);
+    bw.write(NEW_LINE);
+    bw.write("</body>" + NEW_LINE);
+    bw.write("</html>" + NEW_LINE);
+  }
+}

Modified: branches/JBossProfiler2/src/main/org/jboss/profiler/client/SnapshotUtil.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/client/SnapshotUtil.java	2009-04-19 15:17:56 UTC (rev 521)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/client/SnapshotUtil.java	2009-04-19 21:15:37 UTC (rev 522)
@@ -35,10 +35,15 @@
 import org.jboss.profiler.shared.ThreadComparator;
 import org.jboss.profiler.shared.ThreadInfo;
 import org.jboss.profiler.shared.ThreadInfoProxy;
+import org.jboss.profiler.shared.Version;
 
 import java.io.BufferedWriter;
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.Writer;
 import java.text.DecimalFormat;
 import java.text.SimpleDateFormat;
@@ -47,10 +52,10 @@
 import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Locale;
-import java.util.List;
 import java.util.Map;
-import java.util.Iterator;
 
 import org.jboss.logging.Logger;
 
@@ -223,6 +228,9 @@
       dumpClasses(classes, info, snapshot.getAllocations(), directory);
       dumpCaller(snapshot.getMethodRepository(), snapshot.getThreads(), directory);
       dumpWaitTime(classes, directory);
+
+      dumpIndex(directory);
+      dumpCSS(directory);
     }
   }
 
@@ -242,28 +250,55 @@
     SimpleDateFormat dateFormat = new SimpleDateFormat("dd MMMMM yyyy HH:mm:ss:SSS");
     DecimalFormat df = new DecimalFormat("#0.00");
 
-    FileWriter fw = new FileWriter(directory + "overview.txt");
+    boolean odd = true;
+
+    FileWriter fw = new FileWriter(directory + "overview.html");
     BufferedWriter bw = new BufferedWriter(fw, 8192);
-    bw.write("From : " + dateFormat.format(snapshot.getFrom()) + NEW_LINE);
-    bw.write("To   : " + dateFormat.format(snapshot.getTo()) + NEW_LINE);
+    HTMLUtil.header(bw, "Overview", true);
+
+    bw.write("<h1>Overview</h1>" + NEW_LINE);
     bw.write(NEW_LINE);
-    bw.write("Total: " + df.format(new Date(snapshot.getTo().getTime() - snapshot.getFrom().getTime()).getTime()) + " ms" + NEW_LINE);
-    bw.write(NEW_LINE);
 
+    bw.write("<table>" + NEW_LINE);
+    bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+    bw.write("    <td>From</td><td>" + dateFormat.format(snapshot.getFrom()) + "</td>" + NEW_LINE);
+    bw.write("  </tr>" + NEW_LINE);
+    bw.write("  <tr class=\"roweven\">" + NEW_LINE);
+    bw.write("    <td>To</td><td>" + dateFormat.format(snapshot.getTo()) + "</td>" + NEW_LINE);
+    bw.write("  </tr>" + NEW_LINE);
+    bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+    bw.write("    <td>Total</td><td>" + df.format(new Date(snapshot.getTo().getTime() - snapshot.getFrom().getTime()).getTime()) + " ms</td>" + NEW_LINE);
+    bw.write("  </tr>" + NEW_LINE);
+    bw.write("</table>" + NEW_LINE);
+
     Collections.sort(snapshot.getThreads(), new ThreadComparator());
 
-    bw.write("Threads:" + NEW_LINE);
-    bw.write("========" + NEW_LINE);
+    bw.write("<h2>Threads</h2>" + NEW_LINE);
 
+    bw.write("<table>" + NEW_LINE);
+    bw.write("  <tr>" + NEW_LINE);
+    bw.write("     <th>Name</th>" + NEW_LINE);
+    bw.write("     <th>Time</th>" + NEW_LINE);
+    bw.write("  </tr>" + NEW_LINE);
+    odd = true;
     for (ThreadInfo ti: snapshot.getThreads()) {
-      bw.write("Thread-" + ti.getId() + "\t" + df.format(Math.nanoToMilli(ti.getTotalTime())) + " ms");
-      bw.write(NEW_LINE);
+      if (odd) {
+        bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+      } else {
+        bw.write("  <tr class=\"roweven\">" + NEW_LINE);
+      }
+      bw.write("    <td><a href=\"threads/thread-" + ti.getId() + ".html\">Thread-" + ti.getId() + "</a></td>" + NEW_LINE);
+      bw.write("    <td>" + df.format(Math.nanoToMilli(ti.getTotalTime())) + " ms</td>" + NEW_LINE);
+      bw.write("  </tr>" + NEW_LINE);
 
       if (ti instanceof ThreadInfoProxy) {
         ThreadInfoProxy tip = (ThreadInfoProxy)ti;
         tip.resetFrames();
       }
+
+      odd = !odd;
     }
+    bw.write("</table>" + NEW_LINE);
 
     bw.write(NEW_LINE);
     dumpMostTime(info, bw);
@@ -273,16 +308,30 @@
 
     Collections.sort(classes, new TimedClassComparator(TimedClassComparator.NAME));
 
-    bw.write("Classes:" + NEW_LINE);
-    bw.write("========" + NEW_LINE);
+    bw.write("<h2>Classes</h2>" + NEW_LINE);
 
+    bw.write("<table>" + NEW_LINE);
+    bw.write("  <tr>" + NEW_LINE);
+    bw.write("     <th>Name</th>" + NEW_LINE);
+    bw.write("     <th>Type</th>" + NEW_LINE);
+    bw.write("     <th>Time</th>" + NEW_LINE);
+    bw.write("  </tr>" + NEW_LINE);
+    odd = true;
     for (TimedClassInfo tci: classes) {
-      bw.write(Util.getPrettyName(tci) + "\t");
-      bw.write(Util.getDescription(tci) + "\t");
-      bw.write(df.format(tci.getTotalTime()) + " ms");
-      bw.write(NEW_LINE);
+      if (odd) {
+        bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+      } else {
+        bw.write("  <tr class=\"roweven\">" + NEW_LINE);
+      }
+      bw.write("    <td><a href=\"classes/" + tci.getClassName().replace('/', '.') + ".html\">" + Util.getPrettyName(tci) + "</a></td>" + NEW_LINE);
+      bw.write("    <td>" + Util.getDescription(tci) + "</td>" + NEW_LINE);
+      bw.write("    <td>" + df.format(tci.getTotalTime()) + " ms</td>" + NEW_LINE);
+      bw.write("  </tr>" + NEW_LINE);
+      odd = !odd;
     }
+    bw.write("</table>" + NEW_LINE);
     
+    HTMLUtil.footer(bw);
     bw.flush();
     bw.close();
   }
@@ -299,16 +348,31 @@
 
     for (ThreadInfo ti: threads) {
       FileWriter ftw = new FileWriter(directory + "threads" + File.separator + 
-                                      "thread-" + ti.getId() + ".txt");
+                                      "thread-" + ti.getId() + ".html");
       BufferedWriter bw = new BufferedWriter(ftw, 8192);
 
-      bw.write("Thread: " + ti.getId() + NEW_LINE);
-      bw.write("Name: " + ti.getName() + NEW_LINE);
-      bw.write("Priority: " + ti.getPriority() + NEW_LINE);
-      bw.write("Daemon: " + ti.isDaemon() + NEW_LINE);
+      HTMLUtil.header(bw, "Thread: " + ti.getId(), false);
 
+      bw.write("<h1>Thread: " + ti.getId() + "</h1>" + NEW_LINE);
+      bw.write(NEW_LINE);
+
+      bw.write("<table>" + NEW_LINE);
+      bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+      bw.write("    <td>Thread</td><td>" + ti.getId() + "</td>" + NEW_LINE);
+      bw.write("  </tr>" + NEW_LINE);
+      bw.write("  <tr class=\"roweven\">" + NEW_LINE);
+      bw.write("    <td>Name</td><td>" + ti.getName() + "</td>" + NEW_LINE);
+      bw.write("  </tr>" + NEW_LINE);
+      bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+      bw.write("    <td>Priority</td><td>" + ti.getPriority() + "</td>" + NEW_LINE);
+      bw.write("  </tr>" + NEW_LINE);
+      bw.write("  <tr class=\"roweven\">" + NEW_LINE);
+      bw.write("    <td>Daemon</td><td>" + ti.isDaemon() + "</td>" + NEW_LINE);
+      bw.write("  </tr>" + NEW_LINE);
+
       if (ti.getGroups() != null) {
-        bw.write("Groups: ");
+        bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+        bw.write("    <td>Groups</td><td>");
 
         Iterator it = ti.getGroups().iterator();
         while (it.hasNext()) {
@@ -319,9 +383,11 @@
           }
         }
 
-        bw.write(NEW_LINE);
+        bw.write("</td>" + NEW_LINE);
       }
       
+      bw.write("</table>" + NEW_LINE);
+
       bw.write(NEW_LINE);
 
       int frameNumber = 1;
@@ -331,6 +397,9 @@
         frameNumber++;
         bw.write(NEW_LINE);
       }
+
+      HTMLUtil.footer(bw);
+
       bw.flush();
       bw.close();
 
@@ -350,11 +419,22 @@
    * @exception Exception If an error occurs
    */
   protected void dumpFrame(MethodRepository mr, FrameInfo fi, int fn, Writer w) throws Exception {
-    w.write("Frame: " + fn + NEW_LINE);
-    w.write("Count\tMs (T)\tMs (N)\t% (T)\t% (N)\tMethod" + NEW_LINE);
+    w.write("<h2>Frame: " + fn + "</h2>" + NEW_LINE);
 
+    w.write("<table>" + NEW_LINE);
+    w.write("  <tr>" + NEW_LINE);
+    w.write("     <th>Count</th>" + NEW_LINE);
+    w.write("     <th>Ms (T)</th>" + NEW_LINE);
+    w.write("     <th>Ms (N)</th>" + NEW_LINE);
+    w.write("     <th>% (T)</th>" + NEW_LINE);
+    w.write("     <th>% (N)</th>" + NEW_LINE);
+    w.write("     <th>Method</th>" + NEW_LINE);
+    w.write("  </tr>" + NEW_LINE);
+
     long totalTime = fi.getTotalTime();
     dumpFrame(mr, fi, 0, (double)totalTime, w);
+
+    w.write("</table>" + NEW_LINE);
   }
 
   /**
@@ -372,12 +452,14 @@
     long total = fi.getTotalTime();
     long net = fi.getNetTime();
 
-    w.write(fi.getCount() + "\t");
-    w.write(df.format(Math.nanoToMilli(total)) + "\t");
-    w.write(df.format(Math.nanoToMilli(net)) + "\t");
-    w.write(df.format(Math.toPercent(total, tt)) + "\t");
-    w.write(df.format(Math.toPercent(net, tt)) + "\t");
+    w.write("  <tr  class=\"roweven\">" + NEW_LINE);
+    w.write("    <td>" + fi.getCount() + "</td>" + NEW_LINE);
+    w.write("    <td>" + df.format(Math.nanoToMilli(total)) + "</td>" + NEW_LINE);
+    w.write("    <td>" + df.format(Math.nanoToMilli(net)) + "</td>" + NEW_LINE);
+    w.write("    <td>" + df.format(Math.toPercent(total, tt)) + "</td>" + NEW_LINE);
+    w.write("    <td>" + df.format(Math.toPercent(net, tt)) + "</td>" + NEW_LINE);
     
+    w.write("    <td>");
     for (int i = 0; i < level; i++) {
       w.write("+");
     }
@@ -387,7 +469,8 @@
     
     MethodInfo mi = mr.getInfo(fi.getMethod());
     w.write(Util.getPrettyName(mi));
-    w.write(NEW_LINE);
+    w.write("    </td>" + NEW_LINE);
+    w.write("  </tr>" + NEW_LINE);
 
     List<FrameInfo> l = fi.getChildren();
     if (l != null) {
@@ -404,10 +487,17 @@
    * @exception Exception If an error occurs
    */
   protected void dumpMostTime(Map<String, List<CombinedFrameInfo>> info, Writer w) throws Exception {
-    w.write("Most time:" + NEW_LINE);
-    w.write("==========" + NEW_LINE);
-    w.write("Count\tMs\tAvg\t%\tMethod" + NEW_LINE);
+    w.write("<h2>Most time</h2>" + NEW_LINE);
 
+    w.write("<table>" + NEW_LINE);
+    w.write("  <tr>" + NEW_LINE);
+    w.write("     <th>Count</th>" + NEW_LINE);
+    w.write("     <th>Ms</th>" + NEW_LINE);
+    w.write("     <th>Avg</th>" + NEW_LINE);
+    w.write("     <th>%</th>" + NEW_LINE);
+    w.write("     <th>Method</th>" + NEW_LINE);
+    w.write("  </tr>" + NEW_LINE);
+
     List<CombinedFrameInfo> allMethods = new ArrayList<CombinedFrameInfo>();
 
     Iterator it = info.values().iterator();
@@ -420,18 +510,29 @@
 
     DecimalFormat df = new DecimalFormat("#0.00");
     
+    boolean odd = true;
     for (int i = 0; i < 10 && i < allMethods.size(); i++) {
       CombinedFrameInfo cfi = allMethods.get(i);
+
+      if (odd) {
+        w.write("  <tr class=\"rowodd\">" + NEW_LINE);
+      } else {
+        w.write("  <tr class=\"roweven\">" + NEW_LINE);
+      }
       
-      w.write(cfi.getCount() + "\t");
-      w.write(df.format(cfi.getTotalTime()) + "\t");
-      w.write(df.format(cfi.getTotalTime() / cfi.getCount()) + "\t");
-      w.write(df.format(cfi.getPercent()) + "\t");
-      w.write(cfi.getPrettyName() + NEW_LINE);
+      w.write("    <td>" + cfi.getCount() + "</td>" + NEW_LINE);
+      w.write("    <td>" + df.format(cfi.getTotalTime()) + "</td>" + NEW_LINE);
+      w.write("    <td>" + df.format(cfi.getTotalTime() / cfi.getCount()) + "</td>" + NEW_LINE);
+      w.write("    <td>" + df.format(cfi.getPercent()) + "</td>" + NEW_LINE);
+      w.write("    <td><a href=\"classes/" + cfi.getClassName().replace('/', '.') + ".html\">" + cfi.getPrettyName() + "</a></td>" + NEW_LINE);
+      w.write("  </tr>" + NEW_LINE);
+      odd = !odd;
     }
 
+    w.write("</table>" + NEW_LINE);
+
     w.write(NEW_LINE);
-    dumpHotspot(allMethods, 10, w);
+    dumpHotspot(allMethods, 10, true, w);
   }
 
   /**
@@ -451,40 +552,61 @@
       methods.addAll(l);
     }
 
-    FileWriter fw = new FileWriter(directory + "methods.txt");
+    FileWriter fw = new FileWriter(directory + "methods.html");
     BufferedWriter bw = new BufferedWriter(fw, 8192);
 
-    bw.write("Methods:" + NEW_LINE);
-    bw.write("--------" + NEW_LINE);
-    bw.write("Count\tMs\tAvg\t%\tMethod" + NEW_LINE);
+    HTMLUtil.header(bw, "Methods", true);
 
+    bw.write("<h1>Methods</h1>" + NEW_LINE);
+
+    bw.write("<table>" + NEW_LINE);
+    bw.write("  <tr>" + NEW_LINE);
+    bw.write("     <th>Count</th>" + NEW_LINE);
+    bw.write("     <th>Ms</th>" + NEW_LINE);
+    bw.write("     <th>Avg</th>" + NEW_LINE);
+    bw.write("     <th>%</th>" + NEW_LINE);
+    bw.write("     <th>Method</th>" + NEW_LINE);
+    bw.write("  </tr>" + NEW_LINE);
+
     Collections.sort(methods, new CombinedFrameComparator(CombinedFrameComparator.TOTAL_TIME));
 
     DecimalFormat df = new DecimalFormat("#0.00");
 
+    boolean odd = true;
     int count = 0;
 
     for (int i = 0; i < methods.size(); i++) {
       CombinedFrameInfo h = methods.get(i);
 
       if (h.getTotalTime() >= threshold) {
+        if (odd) {
+          bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+        } else {
+          bw.write("  <tr class=\"roweven\">" + NEW_LINE);
+        }
         double avg = h.getTotalTime() / h.getCount();
 
-        bw.write(h.getCount() + "\t");
-        bw.write(df.format(h.getTotalTime()) + "\t");
-        bw.write(df.format(avg) + "\t");
-        bw.write(df.format(h.getPercent()) + "\t");
-        bw.write(h.getPrettyName() + NEW_LINE);
+        bw.write("    <td>" + h.getCount() + "</td>" + NEW_LINE);
+        bw.write("    <td>" + df.format(h.getTotalTime()) + "</td>" + NEW_LINE);
+        bw.write("    <td>" + df.format(avg) + "</td>" + NEW_LINE);
+        bw.write("    <td>" + df.format(h.getPercent()) + "</td>" + NEW_LINE);
+        bw.write("    <td><a href=\"classes/" + h.getClassName().replace('/', '.') + ".html\">" + h.getPrettyName() + "</a></td>" + NEW_LINE);
+        bw.write("  </tr>" + NEW_LINE);
+        odd = !odd;
       } else {
         count++;
       }
     }
 
+    bw.write("</table>" + NEW_LINE);
+
     if (count > 0) {
       bw.write(NEW_LINE);
       bw.write(count + " methods below threshold." + NEW_LINE);
     }
 
+    HTMLUtil.footer(bw);
+
     bw.flush();
     bw.close();
   }
@@ -506,17 +628,27 @@
       hotspots.addAll(l);
     }
 
-    FileWriter fw = new FileWriter(directory + "hotspots.txt");
+    FileWriter fw = new FileWriter(directory + "hotspots.html");
     BufferedWriter bw = new BufferedWriter(fw, 8192);
 
-    bw.write("Hotspots:" + NEW_LINE);
-    bw.write("---------" + NEW_LINE);
-    bw.write("Count\tMs\tAvg\t%\tMethod" + NEW_LINE);
+    HTMLUtil.header(bw, "Hotspots", true);
 
+    bw.write("<h1>Hotspots</h1>" + NEW_LINE);
+
+    bw.write("<table>" + NEW_LINE);
+    bw.write("  <tr>" + NEW_LINE);
+    bw.write("     <th>Count</th>" + NEW_LINE);
+    bw.write("     <th>Ms</th>" + NEW_LINE);
+    bw.write("     <th>Avg</th>" + NEW_LINE);
+    bw.write("     <th>%</th>" + NEW_LINE);
+    bw.write("     <th>Method</th>" + NEW_LINE);
+    bw.write("  </tr>" + NEW_LINE);
+
     Collections.sort(hotspots, new CombinedFrameComparator(CombinedFrameComparator.TOTAL_TIME_AVG));
 
     DecimalFormat df = new DecimalFormat("#0.00");
 
+    boolean odd = true;
     int count = 0;
 
     for (int i = 0; i < hotspots.size(); i++) {
@@ -525,21 +657,32 @@
       double avg = h.getTotalTime() / h.getCount();
 
       if (avg >= threshold) {
-        bw.write(h.getCount() + "\t");
-        bw.write(df.format(h.getTotalTime()) + "\t");
-        bw.write(df.format(avg) + "\t");
-        bw.write(df.format(h.getPercent()) + "\t");
-        bw.write(h.getPrettyName() + NEW_LINE);
+        if (odd) {
+          bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+        } else {
+          bw.write("  <tr class=\"roweven\">" + NEW_LINE);
+        }
+        bw.write("    <td>" + h.getCount() + "</td>" + NEW_LINE);
+        bw.write("    <td>" + df.format(h.getTotalTime()) + "</td>" + NEW_LINE);
+        bw.write("    <td>" + df.format(avg) + "</td>" + NEW_LINE);
+        bw.write("    <td>" + df.format(h.getPercent()) + "</td>" + NEW_LINE);
+        bw.write("    <td><a href=\"classes/" + h.getClassName().replace('/', '.') + ".html\">" + h.getPrettyName() + "</a></td>" + NEW_LINE);
+        bw.write("  </tr>" + NEW_LINE);
+        odd = !odd;
       } else {
         count++;
       }
     }
 
+    bw.write("</table>" + NEW_LINE);
+
     if (count > 0) {
       bw.write(NEW_LINE);
       bw.write(count + " methods below threshold." + NEW_LINE);
     }
 
+    HTMLUtil.footer(bw);
+
     bw.flush();
     bw.close();
   }
@@ -548,37 +691,59 @@
    * Dump the hotspots to a file writer
    * @param hotspots The hotspots
    * @param max The maximum hotspots
+   * @param include Include links
    * @param w The writer
    * @exception Exception If an error occurs
    */
-  protected void dumpHotspot(List<CombinedFrameInfo> hotspots, int max, Writer w) throws Exception {
-    w.write("Hotspots:" + NEW_LINE);
-    w.write("=========" + NEW_LINE);
-    w.write("Count\tMs\tAvg\t%\tMethod" + NEW_LINE);
+  protected void dumpHotspot(List<CombinedFrameInfo> hotspots, int max, boolean include, Writer w) throws Exception {
+    w.write("<h2>Hotspots</h2>" + NEW_LINE);
 
     if (hotspots != null) {
+      w.write("<table>" + NEW_LINE);
+      w.write("  <tr>" + NEW_LINE);
+      w.write("     <th>Count</th>" + NEW_LINE);
+      w.write("     <th>Ms</th>" + NEW_LINE);
+      w.write("     <th>Avg</th>" + NEW_LINE);
+      w.write("     <th>%</th>" + NEW_LINE);
+      w.write("     <th>Method</th>" + NEW_LINE);
+      w.write("  </tr>" + NEW_LINE);
+      
       Collections.sort(hotspots, new CombinedFrameComparator(CombinedFrameComparator.TOTAL_TIME_AVG));
 
       DecimalFormat df = new DecimalFormat("#0.00");
 
       int count = 0;
-
+      boolean odd = true;
       for (int i = 0; i < max && i < hotspots.size(); i++) {
         CombinedFrameInfo h = hotspots.get(i);
         
         double avg = h.getTotalTime() / h.getCount();
 
         if (avg >= threshold) {
-          w.write(h.getCount() + "\t");
-          w.write(df.format(h.getTotalTime()) + "\t");
-          w.write(df.format(avg) + "\t");
-          w.write(df.format(h.getPercent()) + "\t");
-          w.write(h.getPrettyName() + NEW_LINE);
+          if (odd) {
+            w.write("  <tr class=\"rowodd\">" + NEW_LINE);
+          } else {
+            w.write("  <tr class=\"roweven\">" + NEW_LINE);
+          }
+      
+          w.write("    <td>" + h.getCount() + "</td>" + NEW_LINE);
+          w.write("    <td>" + df.format(h.getTotalTime()) + "</td>" + NEW_LINE);
+          w.write("    <td>" + df.format(avg) + "</td>" + NEW_LINE);
+          w.write("    <td>" + df.format(h.getPercent()) + "</td>" + NEW_LINE);
+          if (include) {
+            w.write("    <td><a href=\"classes/" + h.getClassName().replace('/', '.') + ".html\">" + h.getPrettyName() + "</a></td>" + NEW_LINE);
+          } else {
+            w.write("    <td>" + h.getPrettyName() + "</td>" + NEW_LINE);
+          }
+          w.write("  </tr>" + NEW_LINE);
+          odd = !odd;
         } else {
           count++;
         }
       }
 
+      w.write("</table>" + NEW_LINE);
+
       if (count > 0) {
         w.write(NEW_LINE);
         w.write(count + " methods below threshold." + NEW_LINE);
@@ -596,12 +761,28 @@
     if (snapshot.getAllocations() != null && snapshot.getAllocations().size() > 0) {
       Collections.sort(snapshot.getAllocations(), new AllocationComparator());
 
-      w.write("Allocations:" + NEW_LINE);
-      w.write("============" + NEW_LINE);
+      w.write("<h2>Allocations</h2>" + NEW_LINE);
+
+      w.write("<table>" + NEW_LINE);
+      w.write("  <tr>" + NEW_LINE);
+      w.write("     <th>Class</th>" + NEW_LINE);
+      w.write("     <th>Allocations</th>" + NEW_LINE);
+      w.write("  </tr>" + NEW_LINE);
       
+      boolean odd = true;
       for (AllocationInfo ai: snapshot.getAllocations()) {
-        w.write(ai.getClassName() + "\t" + ai.getCount() + NEW_LINE);
+        if (odd) {
+          w.write("  <tr class=\"rowodd\">" + NEW_LINE);
+        } else {
+          w.write("  <tr class=\"roweven\">" + NEW_LINE);
+        }
+        w.write("    <td><a href=\"classes/" + ai.getClassName().replace('/', '.') + ".html\">" + ai.getClassName() + "</a></td>" + NEW_LINE);
+        w.write("    <td>" + ai.getCount() + "</td>" + NEW_LINE);
+        w.write("  </tr>" + NEW_LINE);
+        odd = !odd;
       }
+
+      w.write("</table>" + NEW_LINE);
     }
   }
 
@@ -623,21 +804,43 @@
 
     DecimalFormat df = new DecimalFormat("#0.00");
     
-    FileWriter fw = new FileWriter(directory + "classes.txt");
+    FileWriter fw = new FileWriter(directory + "classes.html");
     BufferedWriter bw = new BufferedWriter(fw, 8192);
 
-    bw.write("Classes:" + NEW_LINE);
-    bw.write("--------" + NEW_LINE);
+    HTMLUtil.header(bw, "Classes", true);
 
+    bw.write("<h1>Classes</h1>" + NEW_LINE);
+    
+    bw.write("<table>" + NEW_LINE);
+    bw.write("  <tr>" + NEW_LINE);
+    bw.write("     <th>Class</th>" + NEW_LINE);
+    bw.write("     <th>Type</th>" + NEW_LINE);
+    bw.write("     <th>Time</th>" + NEW_LINE);
+    bw.write("  </tr>" + NEW_LINE);
+
+    boolean odd = true;
     for (TimedClassInfo tci: classes) {
-      bw.write(Util.getPrettyName(tci) + "\t");
-      bw.write(Util.getDescription(tci) + "\t");
-      bw.write(df.format(tci.getTotalTime()) + " ms" + NEW_LINE);
+      if (odd) {
+        bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+      } else {
+        bw.write("  <tr class=\"roweven\">" + NEW_LINE);
+      }
 
+      bw.write("    <td><a href=\"classes/" + tci.getClassName().replace('/', '.') + ".html\">" + Util.getPrettyName(tci) + "</a></td>" + NEW_LINE);
+      bw.write("    <td>" + Util.getDescription(tci) + "</td>" + NEW_LINE);
+      bw.write("    <td>" + df.format(tci.getTotalTime()) + " ms</td>" + NEW_LINE);
+
+      bw.write("  </tr>" + NEW_LINE);
+      odd = !odd;
+
       List<CombinedFrameInfo> l = info.get(tci.getClassName());
       dumpClass(tci, l, allocs, directory);
     }
 
+    bw.write("</table>" + NEW_LINE);
+
+    HTMLUtil.footer(bw);
+
     bw.flush();
     bw.close();
   }
@@ -657,17 +860,25 @@
 
     String prettyClassName = Util.getPrettyName(tci);
     FileWriter fcw = new FileWriter(directory + "classes" + File.separator + 
-                                    prettyClassName + ".txt");
+                                    prettyClassName + ".html");
     BufferedWriter bw = new BufferedWriter(fcw, 8192);
+
+    HTMLUtil.header(bw, "Class: " + prettyClassName, false);
     
-    bw.write(Util.getPrettyName(tci) + "\t" + Util.getDescription(tci) + NEW_LINE);
+    bw.write("<h1>" + Util.getPrettyName(tci) + " (" + Util.getDescription(tci) + ")</h1>" + NEW_LINE);
     
     DecimalFormat df = new DecimalFormat("#0.00");
     
-    bw.write("Total time: " + df.format(tci.getTotalTime()) + " ms" + NEW_LINE);
-    bw.write(" Wait time: " + df.format(tci.getWaitTime()) + " ms" + NEW_LINE);
+    bw.write("<table>" + NEW_LINE);
+    bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+    bw.write("    <td>Total time</td><td>" + df.format(tci.getTotalTime()) + " ms</td>" + NEW_LINE);
+    bw.write("  </tr>" + NEW_LINE);
+    bw.write("  <tr class=\"roweven\">" + NEW_LINE);
+    bw.write("    <td>Wait time</td><td>" + df.format(tci.getWaitTime()) + " ms</td>" + NEW_LINE);
+    bw.write("  </tr>" + NEW_LINE);
 
     if (allocs != null && allocs.size() > 0) {
+      bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
       long alloc = 0;
       boolean found = false;
 
@@ -680,33 +891,59 @@
       }
 
       if (alloc < 2) {
-        bw.write(alloc + " allocation" + NEW_LINE);
+        bw.write("    <td>Allocation</td><td>" + alloc + "</td>" + NEW_LINE);
       } else {
-        bw.write(alloc + " allocations" + NEW_LINE);
+        bw.write("    <td>Allocations</td><td>" + alloc + "</td>" + NEW_LINE);
       }
+      bw.write("  </tr>" + NEW_LINE);
     }
+
+    bw.write("</table>" + NEW_LINE);
+
+    bw.write("<h2>Callers</h2>" + NEW_LINE);
+
+    bw.write("<a href=\"../caller/" + prettyClassName + ".html\">Report</a></td>" + NEW_LINE);
     
     bw.write(NEW_LINE);
     
-    bw.write("Methods:" + NEW_LINE);
-    bw.write("========" + NEW_LINE);
-    bw.write("Count\tMs\t% (C)\t% (T)\tMethod" + NEW_LINE);
+    bw.write("<h2>Methods</h2>" + NEW_LINE);
 
+    bw.write("<table>" + NEW_LINE);
+    bw.write("  <tr>" + NEW_LINE);
+    bw.write("     <th>Count</th>" + NEW_LINE);
+    bw.write("     <th>Ms</th>" + NEW_LINE);
+    bw.write("     <th>% (C)</th>" + NEW_LINE);
+    bw.write("     <th>% (T)</th>" + NEW_LINE);
+    bw.write("     <th>Method</th>" + NEW_LINE);
+    bw.write("  </tr>" + NEW_LINE);
+
     if (cfs != null) {
       Collections.sort(cfs, new CombinedFrameComparator(CombinedFrameComparator.TOTAL_TIME));
 
+      boolean odd = true;
       for (CombinedFrameInfo cfi : cfs) {
-        bw.write(cfi.getCount() + "\t");
-        bw.write(df.format(cfi.getTotalTime()) + "\t");
-        bw.write(df.format(Math.toPercent(cfi.getTotalTime(), tci.getTotalTime())) + "\t");
-        bw.write(df.format(cfi.getPercent()) + "\t");
-        bw.write(cfi.getPrettyName() + NEW_LINE);
+        if (odd) {
+          bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+        } else {
+          bw.write("  <tr class=\"roweven\">" + NEW_LINE);
+        }
+        bw.write("    <td>" + cfi.getCount() + "</td>" + NEW_LINE);
+        bw.write("    <td>" + df.format(cfi.getTotalTime()) + "</td>" + NEW_LINE);
+        bw.write("    <td>" + df.format(Math.toPercent(cfi.getTotalTime(), tci.getTotalTime())) + "</td>" + NEW_LINE);
+        bw.write("    <td>" + df.format(cfi.getPercent()) + "</td>" + NEW_LINE);
+        bw.write("    <td>" + cfi.getPrettyName() + "</td>" + NEW_LINE);
+        bw.write("  </tr>" + NEW_LINE);
+        odd = !odd;
       }
     }
+
+    bw.write("</table>" + NEW_LINE);
     
     bw.write(NEW_LINE);
-    dumpHotspot(cfs, Integer.MAX_VALUE, bw);
+    dumpHotspot(cfs, Integer.MAX_VALUE, false, bw);
     
+    HTMLUtil.footer(bw);
+
     bw.flush();
     bw.close();
   }
@@ -719,15 +956,15 @@
    */
   protected void dumpPackages(Map<String, List<CombinedFrameInfo>> info,
                               String directory) throws Exception {
-    FileWriter fw = new FileWriter(directory + "packages.txt");
+    FileWriter fw = new FileWriter(directory + "packages.html");
     BufferedWriter bw = new BufferedWriter(fw, 8192);
 
     DecimalFormat df = new DecimalFormat("#0.00");
     
-    bw.write("Packages:" + NEW_LINE);
-    bw.write("=========" + NEW_LINE);
-    bw.write("%\tMs\tPackage" + NEW_LINE);
+    HTMLUtil.header(bw, "Packages", true);
 
+    bw.write("<h1>Packages</h1>" + NEW_LINE);
+    
     Map<String, CombinedFrameInfo> packages = new HashMap<String, CombinedFrameInfo>();
 
     Iterator it = info.entrySet().iterator();
@@ -756,24 +993,43 @@
     List<CombinedFrameInfo> result = new ArrayList<CombinedFrameInfo>(packages.values());
     Collections.sort(result, new CombinedFrameComparator(CombinedFrameComparator.TOTAL_TIME));
 
+    bw.write("<table>" + NEW_LINE);
+    bw.write("  <tr>" + NEW_LINE);
+    bw.write("     <th>%</th>" + NEW_LINE);
+    bw.write("     <th>Ms</th>" + NEW_LINE);
+    bw.write("     <th>Package</th>" + NEW_LINE);
+    bw.write("  </tr>" + NEW_LINE);
+
+    boolean odd = true;
+
     int count = 0;
 
     for (CombinedFrameInfo cfi: result) { 
       if (cfi.getTotalTime() > threshold) {
-        bw.write(df.format(cfi.getPercent()) + "\t");
-        bw.write(df.format(cfi.getTotalTime()) + "\t");
-        bw.write(cfi.getClassName());
-        bw.write(NEW_LINE);
+        if (odd) {
+          bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+        } else {
+          bw.write("  <tr class=\"roweven\">" + NEW_LINE);
+        }
+        bw.write("    <td>" + df.format(cfi.getPercent()) + "</td>" + NEW_LINE);
+        bw.write("    <td>" + df.format(cfi.getTotalTime()) + "</td>" + NEW_LINE);
+        bw.write("    <td>" + cfi.getClassName() + "</td>" + NEW_LINE);
+        bw.write("   </tr>" + NEW_LINE);
+        odd = !odd;
       } else {
         count++;
       }
     }
 
+    bw.write("</table>" + NEW_LINE);
+
     if (count > 0) {
       bw.write(NEW_LINE);
       bw.write(count + " packages below threshold." + NEW_LINE);
     }
 
+    HTMLUtil.footer(bw);
+
     bw.flush();
     bw.close();
   }
@@ -812,9 +1068,14 @@
       Map<String, CombinedFrameInfo> value = (Map<String, CombinedFrameInfo>)entry.getValue();
 
       FileWriter ftw = new FileWriter(directory + "caller" + File.separator + 
-                                      key.replace('/', '.') + ".txt");
+                                      key.replace('/', '.') + ".html");
       BufferedWriter bw = new BufferedWriter(ftw, 8192);
 
+      HTMLUtil.header(bw, "Caller: " + key.replace('/', '.'), false);
+
+      bw.write("<h1>Callers of " + key.replace('/', '.') + "</h1>" + NEW_LINE);
+      bw.write(NEW_LINE);
+
       Map<String, List<CombinedFrameInfo>> m = new HashMap<String, List<CombinedFrameInfo>>();
 
       Iterator vit = value.values().iterator();
@@ -838,26 +1099,38 @@
 
         Collections.sort(callers, new CombinedFrameComparator(CombinedFrameComparator.TOTAL_TIME));
 
-        bw.write(methodName + ":" + NEW_LINE);
-        for (int i = 1; i < methodName.length() + 2; i++) {
-          bw.write("-");
-        }
-        bw.write(NEW_LINE);
+        bw.write("<h2>" + methodName + "</h2>" + NEW_LINE);
 
-        bw.write("Count\tAvg\tMs\tMethod");
-        bw.write(NEW_LINE);
+        bw.write("<table>" + NEW_LINE);
+        bw.write("  <tr>" + NEW_LINE);
+        bw.write("     <th>Count</th>" + NEW_LINE);
+        bw.write("     <th>Avg</th>" + NEW_LINE);
+        bw.write("     <th>Ms</th>" + NEW_LINE);
+        bw.write("     <th>Method</th>" + NEW_LINE);
+        bw.write("  </tr>" + NEW_LINE);
+        
+        boolean odd = true;
 
         for (CombinedFrameInfo cfi : callers) {
-          bw.write(cfi.getCount() + "\t");
-          bw.write(df.format(cfi.getTotalTime() / (double)cfi.getCount()) + "\t");
-          bw.write(df.format(cfi.getTotalTime()) + "\t");
-          bw.write(cfi.getPrettyName());
-          bw.write(NEW_LINE);
+          if (odd) {
+            bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+          } else {
+            bw.write("  <tr class=\"roweven\">" + NEW_LINE);
+          }
+          bw.write("    <td>" + cfi.getCount() + "</td>" + NEW_LINE);
+          bw.write("    <td>" + df.format(cfi.getTotalTime() / (double)cfi.getCount()) + "</td>" + NEW_LINE);
+          bw.write("    <td>" + df.format(cfi.getTotalTime()) + "</td>" + NEW_LINE);
+          bw.write("    <td>" + cfi.getPrettyName() + "</td>" + NEW_LINE);
+          bw.write("   </tr>" + NEW_LINE);
+          odd = !odd;
         }
 
+        bw.write("</table>" + NEW_LINE);
         bw.write(NEW_LINE);
       }
 
+      HTMLUtil.footer(bw);
+
       bw.flush();
       bw.close();
     }
@@ -875,29 +1148,52 @@
 
     DecimalFormat df = new DecimalFormat("#0.00");
     
-    FileWriter fw = new FileWriter(directory + "waittime.txt");
+    FileWriter fw = new FileWriter(directory + "waittime.html");
     BufferedWriter bw = new BufferedWriter(fw, 8192);
 
-    bw.write("Classes:" + NEW_LINE);
-    bw.write("--------" + NEW_LINE);
+    HTMLUtil.header(bw, "Wait time", true);
 
+    bw.write("<h1>Wait time</h1>" + NEW_LINE);
+    bw.write(NEW_LINE);
+
+    bw.write("<h2>Classes</h2>" + NEW_LINE);
+
+    bw.write("<table>" + NEW_LINE);
+    bw.write("  <tr>" + NEW_LINE);
+    bw.write("     <th>Class</th>" + NEW_LINE);
+    bw.write("     <th>Type</th>" + NEW_LINE);
+    bw.write("     <th>Time</th>" + NEW_LINE);
+    bw.write("  </tr>" + NEW_LINE);
+
+    boolean odd = true;
     int count = 0;
 
     for (TimedClassInfo tci: classes) {
       if (tci.getWaitTime() >= threshold) {
-        bw.write(Util.getPrettyName(tci) + "\t");
-        bw.write(Util.getDescription(tci) + "\t");
-        bw.write(df.format(tci.getWaitTime()) + " ms" + NEW_LINE);
+        if (odd) {
+          bw.write("  <tr class=\"rowodd\">" + NEW_LINE);
+        } else {
+          bw.write("  <tr class=\"roweven\">" + NEW_LINE);
+        }
+        bw.write("    <td><a href=\"classes/" + tci.getClassName().replace('/', '.') + ".html\">" + Util.getPrettyName(tci) + "</a></td>" + NEW_LINE);
+        bw.write("    <td>" + Util.getDescription(tci) + "</td>" + NEW_LINE);
+        bw.write("    <td>" + df.format(tci.getWaitTime()) + " ms</td>" + NEW_LINE);
+        bw.write("   </tr>" + NEW_LINE);
+        odd = !odd;
       } else {
         count++;
       }
     }
 
+    bw.write("</table>" + NEW_LINE);
+
     if (count > 0) {
       bw.write(NEW_LINE);
       bw.write(count + " classes below threshold." + NEW_LINE);
     }
 
+    HTMLUtil.footer(bw);
+
     bw.flush();
     bw.close();
   }
@@ -934,4 +1230,75 @@
       }
     }
   }
+
+  /**
+   * Dump index.html
+   * @param outputDir where the reports go
+   * @exception Exception Thrown if an error occurs
+   */
+  private void dumpIndex(String outputDir) throws Exception {
+    FileWriter fw = new FileWriter(outputDir + "index.html");
+    BufferedWriter bw = new BufferedWriter(fw, 8192);
+
+    HTMLUtil.header(bw, "Main", true);
+
+    bw.write("<h1>" + Version.FULL_VERSION + "</h1>" + NEW_LINE);
+    bw.write(NEW_LINE);
+
+    bw.write("<h2>Reports</h2>" + NEW_LINE);
+    bw.write(NEW_LINE);
+
+    bw.write("<ul>" + NEW_LINE);
+
+    bw.write("<li><a href=\"overview.html\">Overview</a></li>");
+    bw.write("<li><a href=\"hotspots.html\">Hotspots</a></li>");
+    bw.write("<li><a href=\"packages.html\">Packages</a></li>");
+    bw.write("<li><a href=\"classes.html\">Classes</a></li>");
+    bw.write("<li><a href=\"methods.html\">Methods</a></li>");
+    bw.write("<li><a href=\"waittime.html\">Wait time</a></li>");
+
+    bw.write("</ul>" + NEW_LINE);
+
+    HTMLUtil.footer(bw);
+
+    bw.flush();
+    bw.close();
+  }
+
+  /**
+   * Dump CSS files
+   * @param outputDir where the reports go
+   * @exception Exception Thrown if an error occurs
+   */
+  private void dumpCSS(String outputDir) throws Exception {
+    byte buffer[] = new byte[8192];
+    int bytesRead;
+    
+    InputStream is = null;
+    OutputStream os = null;
+    try {
+      is = Thread.currentThread().getContextClassLoader().getResourceAsStream("style.css");
+      os = new FileOutputStream(outputDir + "style.css");
+      
+      while ((bytesRead = is.read(buffer)) != -1) {
+        os.write(buffer, 0, bytesRead);
+      }
+
+      os.flush();
+    } finally {
+      try {
+        if (is != null) {
+          is.close();
+        }
+      } catch (IOException ioe) {
+      }
+
+      try {
+        if (os != null) {
+          os.close();
+        }
+      } catch (IOException ioe) {
+      }
+    }
+  }
 }




More information about the jboss-cvs-commits mailing list