Clover coverage report - DrJava Test Coverage (drjava-20120422-r5456)
Coverage timestamp: Sun Apr 22 2012 03:13:25 CDT
file stats: LOC: 268   Methods: 12
NCLOC: 148   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
JoinInputStream.java 0% 0% 0% 0%
coverage
 1    /*BEGIN_COPYRIGHT_BLOCK
 2    *
 3    * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu)
 4    * All rights reserved.
 5    *
 6    * Redistribution and use in source and binary forms, with or without
 7    * modification, are permitted provided that the following conditions are met:
 8    * * Redistributions of source code must retain the above copyright
 9    * notice, this list of conditions and the following disclaimer.
 10    * * Redistributions in binary form must reproduce the above copyright
 11    * notice, this list of conditions and the following disclaimer in the
 12    * documentation and/or other materials provided with the distribution.
 13    * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
 14    * names of its contributors may be used to endorse or promote products
 15    * derived from this software without specific prior written permission.
 16    *
 17    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18    * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20    * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 21    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 22    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 23    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 24    * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 25    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 26    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 27    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28    *
 29    * This software is Open Source Initiative approved Open Source Software.
 30    * Open Source Initative Approved is a trademark of the Open Source Initiative.
 31    *
 32    * This file is part of DrJava. Download the current version of this project
 33    * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
 34    *
 35    * END_COPYRIGHT_BLOCK*/
 36   
 37    // based on:
 38    //-< JoinInputStream.java >------------------------------------------*--------*
 39    // JSYNC Version 1.04 (c) 1998 GARRET * ? *
 40    // (Java synchronization classes) * /\| *
 41    // * / \ *
 42    // Created: 20-Jun-98 K.A. Knizhnik * / [] \ *
 43    // Last update: 10-Jul-98 K.A. Knizhnik * GARRET *
 44    //-------------------------------------------------------------------*--------*
 45    // Mutiplexing input from several threads.
 46    //-------------------------------------------------------------------*--------*
 47   
 48    package edu.rice.cs.util;
 49   
 50    import java.io.*;
 51   
 52    public class JoinInputStream extends InputStream {
 53    /** Create stream joining streams specified in the array.
 54    *
 55    * @param streams array with input streams which should be joined
 56    * @param bufferSize specifies size of read buffer
 57    */
 58  0 public JoinInputStream(InputStream[] streams, int bufferSize) {
 59  0 openedStreams = nReaders = streams.length;
 60  0 reader = new ReaderThread[nReaders];
 61  0 for (int i = 0; i < nReaders; i++) {
 62  0 reader[i] = new ReaderThread(this, streams[i], bufferSize);
 63  0 reader[i].start();
 64    }
 65  0 currentReader = 0;
 66    }
 67   
 68    /** Create stream joining two specified streams.
 69    *
 70    * @param one first input stream to be merged
 71    * @param two second input stream to be merged
 72    * @param bufferSize specifies size of read buffer
 73    */
 74  0 public JoinInputStream(InputStream one, InputStream two, int bufferSize) {
 75  0 this(new InputStream[] { one, two}, bufferSize);
 76    }
 77   
 78    /** Create stream joining two specified streams.
 79    *
 80    * @param one first input stream to be merged
 81    * @param two second input stream to be merged
 82    */
 83  0 public JoinInputStream(InputStream one, InputStream two) {
 84  0 this(one, two, defaultBufferSize);
 85    }
 86   
 87    /** Reads the next byte of data from one of input streams. The value
 88    * byte is returned as an <code>int</code> in the range
 89    * <code > 0</code> to <code>255</code>. If no byte is available
 90    * because the end of the stream has been reached, the value
 91    * <code>-1</code> is returned. This method blocks until input data
 92    * is available, the end of the stream is detected or an exception
 93    * is catched.<p>
 94    *
 95    * @return the next byte of data, or <code>-1</code> if the end of the
 96    * stream is reached.
 97    * @exception IOException if an I/O error occurs.
 98    */
 99  0 public synchronized int read() throws IOException {
 100  0 while (openedStreams != 0) {
 101  0 for (int i = 0; i < nReaders; i++) {
 102  0 ReaderThread rd = reader[currentReader];
 103  0 if (rd.available > 0) {
 104  0 return rd.read();
 105    }
 106  0 currentReader += 1;
 107  0 if (currentReader == nReaders) {
 108  0 currentReader = 0;
 109    }
 110    }
 111  0 try {
 112  0 wait();
 113    } catch(InterruptedException ex) {
 114  0 break;
 115    }
 116    }
 117  0 return -1;
 118    }
 119   
 120    /**
 121    * Reads up to <code>len</code> bytes of data from one of input streams
 122    * into an array of bytes. This method blocks until some input is
 123    * available. If the first argument is <code>null,</code> up to
 124    * <code>len</code> bytes are read and discarded.
 125    * <p>
 126    * The <code>read</code> method of <code>InputStream</code> reads a
 127    * single byte at a time using the read method of zero arguments to
 128    * fill in the array. Subclasses are encouraged to provide a more
 129    * efficient implementation of this method.
 130    *
 131    * @param b the buffer into which the data is read.
 132    * @param off the start offset of the data.
 133    * @param len the maximum number of bytes read.
 134    * @return the total number of bytes read into the buffer, or
 135    * <code>-1</code> if there is no more data because the end of
 136    * the stream has been reached.
 137    * @exception IOException if an I/O error occurs.
 138    */
 139  0 public synchronized int read(byte b[], int off, int len) throws IOException {
 140  0 while (openedStreams != 0) {
 141  0 for (int i = 0; i < nReaders; i++) {
 142  0 ReaderThread rd = reader[currentReader];
 143  0 if (rd.available > 0) {
 144  0 return rd.read(b, off, len);
 145    }
 146  0 currentReader += 1;
 147  0 if (currentReader == nReaders) {
 148  0 currentReader = 0;
 149    }
 150    }
 151  0 try {
 152  0 wait();
 153    } catch(InterruptedException ex) {
 154  0 break;
 155    }
 156    }
 157  0 return -1;
 158    }
 159   
 160    /** Close all attached input streams and stop their listener threads. */
 161  0 public void close() throws IOException {
 162  0 for (int i = 0; i < nReaders; i++) {
 163  0 if (reader[i].available >= 0) {
 164  0 reader[i].close();
 165    }
 166    }
 167    }
 168   
 169    /** Get index of thread from which data was retrieved in last
 170    * <code>read</code> operation. Indices are started from 0.
 171    *
 172    * @return index of thread from which data was taken in last
 173    * <code>read</code> operation.
 174    */
 175  0 public final int getStreamIndex() {
 176  0 return currentReader;
 177    }
 178   
 179    /** Default size of read buffer.
 180    */
 181    static public int defaultBufferSize = 4096;
 182   
 183    protected int nReaders;
 184    protected ReaderThread[] reader;
 185    protected int currentReader;
 186    protected int openedStreams;
 187    }
 188   
 189    class ReaderThread extends Thread {
 190    volatile int available;
 191    volatile int pos;
 192    volatile byte[] buffer;
 193    volatile InputStream stream;
 194    volatile IOException exception;
 195    volatile JoinInputStream monitor;
 196   
 197  0 ReaderThread(JoinInputStream monitor, InputStream stream, int bufferSize) {
 198  0 this.stream = stream;
 199  0 this.monitor = monitor;
 200  0 buffer = new byte[bufferSize];
 201  0 available = 0;
 202  0 pos = 0;
 203  0 exception = null;
 204    }
 205   
 206  0 public synchronized void run() {
 207  0 while (true) {
 208  0 int len;
 209  0 try {
 210  0 len = stream.read(buffer);
 211    } catch(IOException ex) {
 212  0 exception = ex;
 213  0 len = -1;
 214    }
 215  0 synchronized(monitor) {
 216  0 available = len;
 217  0 pos = 0;
 218  0 monitor.notify();
 219  0 if (len < 0) {
 220  0 try {
 221  0 stream.close();
 222    } catch(IOException ex) {}
 223  0 monitor.openedStreams -= 1;
 224  0 return;
 225    }
 226    }
 227  0 do {
 228  0 try {
 229  0 wait();
 230    } catch(InterruptedException ex) {
 231  0 return;
 232    }
 233  0 } while(available != 0); // preclude spurious wakeups
 234    }
 235    }
 236   
 237  0 synchronized int read() throws IOException {
 238  0 if (exception != null) {
 239  0 throw exception;
 240    }
 241  0 int ch = buffer[pos] & 0xFF;
 242  0 if (++pos == available) {
 243  0 available = 0;
 244  0 notify();
 245    }
 246  0 return ch;
 247    }
 248   
 249  0 synchronized int read(byte[] b, int off, int len) throws IOException {
 250  0 if (exception != null) {
 251  0 throw exception;
 252    }
 253  0 if (available - pos <= len) {
 254  0 len = available - pos;
 255  0 available = 0;
 256  0 notify();
 257    }
 258  0 System.arraycopy(buffer, pos, b, off, len);
 259  0 pos += len;
 260  0 return len;
 261    }
 262   
 263  0 void close() throws IOException {
 264    //stop();
 265  0 interrupt();
 266  0 stream.close();
 267    }
 268    }