com.gc.iotools.stream.reader.inspection
Class DiagnosticReader<T extends Reader>

java.lang.Object
  extended by java.io.Reader
      extended by java.io.FilterReader
          extended by com.gc.iotools.stream.reader.inspection.DiagnosticReader<T>
Type Parameters:
T - Type of the wrapped (contained) Reader to use in getWrappedReader().
All Implemented Interfaces:
Closeable, Readable

public class DiagnosticReader<T extends Reader>
extends FilterReader

A decorating Reader that detects and log useful debug informations about the stream passed in the constructor, and detects wrong usage patterns.

It normally acts as a FilterReader simply forwarding all the calls to the Reader passed in the constructor, but also keeping track of the usage of the methods.

Errors are both logged at WARN level and available through the standard class interface. Future version will allow the customization of this behavior disable the logging.

It is designed to detect also errors that happens during object finalization, but to detect these errors in tests you must be very careful on your test design (see example). Errors in finalizers are available trough the getFinalizationErrors() method.

It's an useful tool in unit tests to detect wrong handling of the streams, but it can be used in main applications too since it adds a very little overhead in standard situations.

Sample Usage (in Junit 4):

 @org.junit.Test
 public void testWarnDoubleClose() throws Exception {
  Reader myTestData = ....
  DiagnosticReader<Reader> diagIs =
            new DiagnosticReader<Reader>(myTestData);
  //The class and the method under test
  MyClassUnderTest.myMethodUnderTest(diagIs);
  final String[] instanceWarnings = diagIs.getInstanceWarnings();
  assertTrue("No problems" + diagIs.getStatusMessage(),
                        instanceWarnings.length == 0);
 }
 

If your code free resources in finalize() methods, or the libraries you use do so you must use a more complex testing strategy because the references to to the active DiagnosticReader instance in your Junit prevents the class from being garbage collected. See the wiki for details and getFinalizationErrors().

Since:
1.2.14
Version:
$Id: DiagnosticReader.java 523 2013-01-02 15:46:17Z gabriele.contini@gmail.com $
Author:
Gabriele Contini

Field Summary
 
Fields inherited from class java.io.FilterReader
in
 
Fields inherited from class java.io.Reader
lock
 
Constructor Summary
DiagnosticReader(T in)
           Constructor for DiagnosticReader.
DiagnosticReader(T reader, int logDepth)
           Constructor for DiagnosticReader.
 
Method Summary
 void clearInstanceWarnings()
           clearInstanceWarnings
 void close()
          
 void finalize()
          
 int getCloseCount()
          Returns the number of times that close was called on this stream.
 byte[] getContent()
           Return the current captured bytes, if capture was enabled.
static String[] getFinalizationErrors()
           Returns an array of descriptions of finalization errors.
 String[] getInstanceWarnings()
           getInstanceWarnings
 String getStatusMessage()
           Returns a string representation of the usage errors of the stream until now.
 T getWrappedReader()
           Returns the wrapped (original) Reader passed in the constructor.
 boolean isMethodCalledAfterClose()
           isMethodCalledAfterClose check if some operation on the current reader was attempted after the method close() was invoked.
 void mark(int readlimit)
          
 boolean markSupported()
          
 int read()
          
 int read(char[] b)
          
 int read(char[] b, int off, int len)
          
 void reset()
          
static void resetFinalizationErrors()
           resetFinalizationErrors
static void setDefaultLogDepth(int defaultFrameDepth)
           Setter for the field defaultLogDepth.
 long skip(long n)
          
 
Methods inherited from class java.io.FilterReader
ready
 
Methods inherited from class java.io.Reader
read
 
Methods inherited from class java.lang.Object
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

DiagnosticReader

public DiagnosticReader(T in)

Constructor for DiagnosticReader.

Parameters:
in - the source Reader.

DiagnosticReader

public DiagnosticReader(T reader,
                        int logDepth)

Constructor for DiagnosticReader.

Parameters:
Reader - the source Reader
logDepth - Number of stack frames to log. It overrides the default static value.
Method Detail

getFinalizationErrors

public static String[] getFinalizationErrors()

Returns an array of descriptions of finalization errors. For instance when the stream is finalized but it was not closed.

Returns:
Description of finalization erros as an array of String objects.

resetFinalizationErrors

public static void resetFinalizationErrors()

resetFinalizationErrors


setDefaultLogDepth

public static void setDefaultLogDepth(int defaultFrameDepth)

Setter for the field defaultLogDepth.

Parameters:
defaultFrameDepth - a int.

clearInstanceWarnings

public void clearInstanceWarnings()

clearInstanceWarnings


close

public void close()
           throws IOException

Specified by:
close in interface Closeable
Overrides:
close in class FilterReader
Throws:
IOException

finalize

public void finalize()
              throws Throwable

Overrides:
finalize in class Object
Throws:
Throwable

getCloseCount

public int getCloseCount()
Returns the number of times that close was called on this stream.

Returns:
number of times that close was called on this stream.

getContent

public byte[] getContent()

Return the current captured bytes, if capture was enabled.

The capture buffer might be truncated if maxCapture is set.

Returns:
the current captured bytes.

getInstanceWarnings

public String[] getInstanceWarnings()

getInstanceWarnings

Returns:
an array of String objects.

getStatusMessage

public String getStatusMessage()

Returns a string representation of the usage errors of the stream until now. Null if no error happened yet.

Returns:
String message that represents the errors, null if no error.

getWrappedReader

public T getWrappedReader()

Returns the wrapped (original) Reader passed in the constructor. Any calls made to the returned stream will not be tracked by DiagnosticReader, so this method should be used with care, and close() and read() methods should'nt be called on the returned Reader. Instead these methods should be called on DiagnosticReader that simply forwards them to the underlying stream.

Returns:
The original Reader passed in the constructor

isMethodCalledAfterClose

public boolean isMethodCalledAfterClose()

isMethodCalledAfterClose check if some operation on the current reader was attempted after the method close() was invoked.

Returns:
a boolean: true if some operation was invoked after close().

mark

public void mark(int readlimit)
          throws IOException

Overrides:
mark in class FilterReader
Throws:
IOException

markSupported

public boolean markSupported()

Overrides:
markSupported in class FilterReader

read

public int read()
         throws IOException

Overrides:
read in class FilterReader
Throws:
IOException

read

public int read(char[] b)
         throws IOException

Overrides:
read in class Reader
Throws:
IOException

read

public int read(char[] b,
                int off,
                int len)
         throws IOException

Overrides:
read in class FilterReader
Throws:
IOException

reset

public void reset()
           throws IOException

Overrides:
reset in class FilterReader
Throws:
IOException

skip

public long skip(long n)
          throws IOException

Overrides:
skip in class FilterReader
Throws:
IOException


Copyright © 2008–2014. All rights reserved.