Clover coverage report - gsbase - 2.0.1
Coverage timestamp: Sat Jan 1 2005 12:30:02 EST
file stats: LOC: 375   Methods: 19
NCLOC: 144   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
Trace.java 12.5% 18.1% 31.6% 19.1%
coverage coverage
 1    /*
 2    * Copyright (c) 1998, 2005 Gargoyle Software Inc. All rights reserved.
 3    *
 4    * Redistribution and use in source and binary forms, with or without
 5    * modification, are permitted provided that the following conditions are met:
 6    *
 7    * 1. Redistributions of source code must retain the above copyright notice,
 8    * this list of conditions and the following disclaimer.
 9    * 2. Redistributions in binary form must reproduce the above copyright notice,
 10    * this list of conditions and the following disclaimer in the documentation
 11    * and/or other materials provided with the distribution.
 12    * 3. The end-user documentation included with the redistribution, if any, must
 13    * include the following acknowledgment:
 14    *
 15    * "This product includes software developed by Gargoyle Software Inc.
 16    * (http://www.GargoyleSoftware.com/)."
 17    *
 18    * Alternately, this acknowledgment may appear in the software itself, if
 19    * and wherever such third-party acknowledgments normally appear.
 20    * 4. The name "Gargoyle Software" must not be used to endorse or promote
 21    * products derived from this software without prior written permission.
 22    * For written permission, please contact info@GargoyleSoftware.com.
 23    * 5. Products derived from this software may not be called "GSBase", nor may
 24    * "GSBase" appear in their name, without prior written permission of
 25    * Gargoyle Software Inc.
 26    *
 27    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 28    * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 29    * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
 30    * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 31    * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 32    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 33    * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 34    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 35    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 36    * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 37    */
 38    package com.gargoylesoftware.base.trace;
 39   
 40   
 41    //TODO: If a trace string contains newlines then prefix each line with the
 42    // required number of spaces
 43    //TODO: Default channels should be thread specific.
 44    // - setDefaultChannel(Thread, Channel);
 45    // - setDefaultChannel(ThreadGroup, Channel);
 46    // - setDefaultChannel(Channel);
 47   
 48    import com.gargoylesoftware.base.util.DetailedNullPointerException;
 49    import java.io.PrintWriter;
 50    import java.io.StringWriter;
 51    import java.util.ArrayList;
 52    import java.util.List;
 53    import java.util.StringTokenizer;
 54   
 55    /**
 56    * A class that provides a mechanism for logging diagnostic messages. This
 57    * mechanism is significantly faster then calling System.out.println directly
 58    * as the printing is done on a background thread which does not impact the
 59    * performance of the application threads.
 60    * <p>
 61    * The methods for tracing are print(String), println(String) and
 62    * printStackTrace(Throwable). The basic idea is that we want the trace
 63    * methods to return to the working threads as quickly as possible so we
 64    * put the thing to be traced on a queue. The queue is then processed by
 65    * a second thread which performs all the formatting and actual output.<p>
 66    *
 67    * Trace can be configured using the {@link TraceController} class - see
 68    * {@link #getController()}. It is possible to redirect System.out and
 69    * System.err so that calling System.out.println("foo") will be the same
 70    * as calling Trace.println("foo")
 71    * <pre>
 72    * Trace.getController().setOutRedirected(true);
 73    * Trace.getController().setErrRedirected(true);
 74    * </pre>
 75    *
 76    * Calls to any of the print methods will print to a {@link TraceChannel}
 77    * which in turn will print using whatever {@link TraceWriter}s have been
 78    * added to it. Print methods that do not take a {@link TraceChannel}
 79    * will use the default channel - see
 80    * {@link TraceController#setDefaultChannel(TraceChannel)}<p>
 81    *
 82    * <b>If you are using this code in a JVM prior to 1.3 then you need to read this:</b>
 83    * <br />Because trace lines are being processed on a second thread, there
 84    * might still be trace messages in the queue when the VM exits. To solve
 85    * this problem we introduce the method {@link #exit(int)} which will shut
 86    * down the second thread and then call System.exit(). If you are running on
 87    * a java 1.3 VM or higher then it is not neccessary to call {@link #exit(int)}
 88    * as Trace will automatically install a shutdown hook which will do the
 89    * neccessary cleanup.<p>
 90    *
 91    * @version $Revision: 1.7 $
 92    * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
 93    */
 94    public class Trace {
 95    /** An exception used to determine where the code is at any point in time. */
 96    public static class WhereAmIException extends Exception {
 97    private static final long serialVersionUID = 6876505080685244104L;
 98   
 99    /** Instantiate one */
 100  0 public WhereAmIException() {
 101  0 super("?? Where am I ??");
 102    }
 103    }
 104   
 105    /**
 106    * The equivilent of "standard out"
 107    */
 108    public static final TraceChannel out = new TraceChannel("STDOUT");
 109    /**
 110    * The equivilent of "standard error"
 111    */
 112    public static final TraceChannel err = new TraceChannel("STDERR");
 113   
 114    // line separator used for println
 115    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
 116   
 117    private static final TraceItemDispatcher TRACE_ITEM_DISPATCHER = new TraceItemDispatcher();
 118    private static final TraceController TRACE_CONTROLLER = new TraceController();
 119   
 120   
 121    /**
 122    * Private constructor to prevent instantiation of this class.
 123    */
 124  0 private Trace() {
 125    }
 126   
 127    /**
 128    * Print a line to the specified channel.
 129    * If the channel is null then nothing will be printed.
 130    * @param channel The trace channel to use
 131    * @param string The text string to write.
 132    */
 133  3 public static void print( final TraceChannel channel, String string ) {
 134  3 assertNotNull("channel", channel);
 135  3 if( string == null ) {
 136  0 string = "<null>";
 137    }
 138   
 139  3 final TraceItemDispatcher dispatcher = getDispatcher();
 140  3 final TraceItem item = dispatcher.getNewTraceItem();
 141   
 142  3 item.setMessage(string);
 143  3 item.setChannel(channel);
 144  3 dispatcher.dispatch(item);
 145    }
 146   
 147    /**
 148    * Print a line to the default channel
 149    * If the channel is null then nothing will be printed.
 150    * @param string The text string to write.
 151    */
 152  0 public static void print( final String string ) {
 153  0 print( getController().getDefaultChannel(), string );
 154    }
 155   
 156    /**
 157    * Print the line to the specified channel with a new line at the end.
 158    * If the channel is null then nothing will be printed.
 159    * @param channel The trace channel to use
 160    * @param string the string to write.
 161    */
 162  52 public static void println( final TraceChannel channel, final String string ) {
 163  52 if( channel == null ) {
 164  52 return;
 165    }
 166  0 print( channel, string + LINE_SEPARATOR );
 167    }
 168   
 169    /**
 170    * Print the line to the default channel with a new line at the end.
 171    *
 172    * @param string the string to write.
 173    */
 174  0 public static void println( final String string ) {
 175  0 print( getController().getDefaultChannel(), string + LINE_SEPARATOR );
 176    }
 177   
 178    /**
 179    * Print the stack trace to the specified channel.
 180    * If the channel is null then nothing will be printed.
 181    *
 182    * @param channel The trace channel to use
 183    * @param throwable The exception to print
 184    */
 185  0 public static void printStackTrace( final TraceChannel channel,
 186    final Throwable throwable ) {
 187   
 188  0 if( channel == null ) {
 189  0 return;
 190    }
 191  0 if( throwable == null ) {
 192  0 println( channel, "<null exception>" );
 193  0 return;
 194    }
 195   
 196  0 final TraceItemDispatcher dispatcher = getDispatcher();
 197  0 final TraceItem item = dispatcher.getNewTraceItem();
 198   
 199  0 item.setThrowable(throwable);
 200  0 item.setChannel(channel);
 201  0 dispatcher.dispatch(item);
 202    }
 203   
 204    /**
 205    * Print the stack trace to the default channel.
 206    * @param throwable The exception to print.
 207    */
 208  0 public static void printStackTrace( final Throwable throwable ) {
 209  0 printStackTrace( getController().getDefaultChannel(), throwable );
 210    }
 211   
 212    /**
 213    * Print the specified lines to the default trace channel.
 214    * @param lines The lines to print.
 215    */
 216  0 public static void printLines( final String lines[] ) {
 217  0 printLines( getController().getDefaultChannel(), lines );
 218    }
 219   
 220    /**
 221    * Print the specified lines to the trace channel.
 222    * If the channel is null then nothing will be printed.
 223    *
 224    * @param channel The trace channel to use
 225    * @param lines the lines to print.
 226    */
 227  0 public static void printLines( final TraceChannel channel, final String lines[] ) {
 228  0 if( channel == null ) {
 229  0 return;
 230    }
 231  0 if( lines == null ) {
 232  0 println( channel, "<null lines>" );
 233  0 return;
 234    }
 235   
 236    //TODO: Send the array as one request to the dispatcher so that the prefix
 237    // string is only printed once for the array
 238  0 int i;
 239  0 for( i=0; i<lines.length; i++ ) {
 240  0 println( channel, lines[i] );
 241    }
 242    }
 243   
 244    /**
 245    * Print a stack trace to show where we came from. It will be printed to the default
 246    * channel.
 247    */
 248  0 public static void whereAmI() {
 249  0 whereAmI( getController().getDefaultChannel() );
 250    }
 251   
 252    /**
 253    * Print a stack trace to show where we came from. If the channel is null then
 254    * nothing will be printed.
 255    * @param channel The trace channel to use.
 256    */
 257  0 public static void whereAmI( final TraceChannel channel ) {
 258  0 if( channel == null ) {
 259  0 return;
 260    }
 261   
 262  0 printStackTrace( channel, new WhereAmIException() );
 263    }
 264   
 265    /**
 266    * Dump the stack trace from the specified throwable into an array
 267    * of strings where each line in the trace is a separate string.
 268    * Additionally, expand all tabs to spaces.
 269    *
 270    * @param t The exception.
 271    * @return The resulting string.
 272    */
 273  0 public static String[] throwableToStringArray( final Throwable t ) {
 274  0 assertNotNull("t", t);
 275   
 276  0 String token;
 277  0 char c;
 278  0 StringBuffer buffer;
 279  0 int length;
 280  0 int i;
 281   
 282  0 final List vector = new ArrayList();
 283  0 final StringTokenizer tokenizer
 284    = new StringTokenizer( throwableToString(t), "\n");
 285   
 286  0 while( tokenizer.hasMoreTokens() ) {
 287  0 token = tokenizer.nextToken();
 288   
 289    // Now expand the tabs
 290  0 length = token.length();
 291  0 buffer = new StringBuffer(length*2);
 292  0 for( i=0; i<length; i++ ) {
 293  0 c = token.charAt(i);
 294  0 if( c == '\t' ) {
 295  0 buffer.append(" ");
 296    }
 297    else {
 298  0 buffer.append(c);
 299    }
 300    }
 301  0 vector.add(buffer.toString());
 302    }
 303   
 304  0 final String array[] = new String[vector.size()];
 305  0 vector.toArray(array);
 306  0 return array;
 307    }
 308   
 309    /**
 310    * Dump the stack trace from the specified throwable into a String.
 311    *
 312    * @param t The exception.
 313    * @return The resulting string.
 314    */
 315  0 public static String throwableToString( final Throwable t ) {
 316  0 assertNotNull("t", t);
 317   
 318  0 final StringWriter writer = new StringWriter();
 319  0 final PrintWriter printWriter = new PrintWriter(writer);
 320  0 t.printStackTrace(printWriter);
 321  0 printWriter.close();
 322  0 return writer.toString();
 323    }
 324   
 325    /**
 326    * Return the controller object for the debugging stuff
 327    *
 328    * @return The controller in use.
 329    */
 330  5 public static TraceController getController() {
 331  5 return TRACE_CONTROLLER;
 332    }
 333   
 334    /** @return The dispatcher */
 335  9 static TraceItemDispatcher getDispatcher() {
 336  9 return TRACE_ITEM_DISPATCHER;
 337    }
 338   
 339    /**
 340    * Flush the trace queue.
 341    */
 342  1 public static void flush() {
 343  1 getDispatcher().flush();
 344    }
 345   
 346    /**
 347    * Shutdown all buffering and exit the VM with the specified
 348    * status code.
 349    * <p>
 350    * <b>Note</b> This is no longer needed if you are running JDK1.3 or higher as
 351    * we now register a shutdown hook to disable buffering before the VM exits.
 352    * @param statusCode The status code returned when the application exits.
 353    */
 354  0 public static void exit( final int statusCode ) {
 355  0 getController().setBufferingEnabled(false);
 356  0 System.exit(statusCode);
 357    }
 358   
 359   
 360    /**
 361    * Verify that the specified value is not null. If it is then throw an exception
 362    *
 363    * @param fieldName The name of the field to check
 364    * @param fieldValue The value of the field to check
 365    * @exception DetailedNullPointerException If fieldValue is null
 366    */
 367  3 protected static final void assertNotNull( final String fieldName, final Object fieldValue )
 368    throws DetailedNullPointerException {
 369   
 370  3 if( fieldValue == null ) {
 371  0 throw new DetailedNullPointerException(fieldName);
 372    }
 373    }
 374    }
 375