Home | History | Annotate | Download | only in obex
      1 /*
      2  * Copyright (c) 2008-2009, Motorola, Inc.
      3  *
      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  *
      9  * - Redistributions of source code must retain the above copyright notice,
     10  * this list of conditions and the following disclaimer.
     11  *
     12  * - Redistributions in binary form must reproduce the above copyright notice,
     13  * this list of conditions and the following disclaimer in the documentation
     14  * and/or other materials provided with the distribution.
     15  *
     16  * - Neither the name of the Motorola, Inc. nor the names of its contributors
     17  * may be used to endorse or promote products derived from this software
     18  * without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
     24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30  * POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 package javax.obex;
     34 
     35 import java.io.InputStream;
     36 import java.io.IOException;
     37 
     38 /**
     39  * This object provides an input stream to the Operation objects used in this
     40  * package.
     41  * @hide
     42  */
     43 public final class PrivateInputStream extends InputStream {
     44 
     45     private BaseStream mParent;
     46 
     47     private byte[] mData;
     48 
     49     private int mIndex;
     50 
     51     private boolean mOpen;
     52 
     53     /**
     54      * Creates an input stream for the <code>Operation</code> to read from
     55      * @param p the connection this input stream is for
     56      */
     57     public PrivateInputStream(BaseStream p) {
     58         mParent = p;
     59         mData = new byte[0];
     60         mIndex = 0;
     61         mOpen = true;
     62     }
     63 
     64     /**
     65      * Returns the number of bytes that can be read (or skipped over) from this
     66      * input stream without blocking by the next caller of a method for this
     67      * input stream. The next caller might be the same thread or or another
     68      * thread.
     69      * @return the number of bytes that can be read from this input stream
     70      *         without blocking
     71      * @throws IOException if an I/O error occurs
     72      */
     73     @Override
     74     public synchronized int available() throws IOException {
     75         ensureOpen();
     76         return mData.length - mIndex;
     77     }
     78 
     79     /**
     80      * Reads the next byte of data from the input stream. The value byte is
     81      * returned as an int in the range 0 to 255. If no byte is available because
     82      * the end of the stream has been reached, the value -1 is returned. This
     83      * method blocks until input data is available, the end of the stream is
     84      * detected, or an exception is thrown.
     85      * @return the byte read from the input stream or -1 if it reaches the end of
     86      *         stream
     87      * @throws IOException if an I/O error occurs
     88      */
     89     @Override
     90     public synchronized int read() throws IOException {
     91         ensureOpen();
     92         while (mData.length == mIndex) {
     93             if (!mParent.continueOperation(true, true)) {
     94                 return -1;
     95             }
     96         }
     97         return (mData[mIndex++] & 0xFF);
     98     }
     99 
    100     @Override
    101     public int read(byte[] b) throws IOException {
    102         return read(b, 0, b.length);
    103     }
    104 
    105     @Override
    106     public synchronized int read(byte[] b, int offset, int length) throws IOException {
    107 
    108         if (b == null) {
    109             throw new IOException("buffer is null");
    110         }
    111         if ((offset | length) < 0 || length > b.length - offset) {
    112             throw new ArrayIndexOutOfBoundsException("index outof bound");
    113         }
    114         ensureOpen();
    115 
    116         int currentDataLength = mData.length - mIndex;
    117         int remainReadLength = length;
    118         int offset1 = offset;
    119         int result = 0;
    120 
    121         while (currentDataLength <= remainReadLength) {
    122             System.arraycopy(mData, mIndex, b, offset1, currentDataLength);
    123             mIndex += currentDataLength;
    124             offset1 += currentDataLength;
    125             result += currentDataLength;
    126             remainReadLength -= currentDataLength;
    127 
    128             if (!mParent.continueOperation(true, true)) {
    129                 return result == 0 ? -1 : result;
    130             }
    131             currentDataLength = mData.length - mIndex;
    132         }
    133         if (remainReadLength > 0) {
    134             System.arraycopy(mData, mIndex, b, offset1, remainReadLength);
    135             mIndex += remainReadLength;
    136             result += remainReadLength;
    137         }
    138         return result;
    139     }
    140 
    141     /**
    142      * Allows the <code>OperationImpl</code> thread to add body data to the
    143      * input stream.
    144      * @param body the data to add to the stream
    145      * @param start the start of the body to array to copy
    146      */
    147     public synchronized void writeBytes(byte[] body, int start) {
    148 
    149         int length = (body.length - start) + (mData.length - mIndex);
    150         byte[] temp = new byte[length];
    151 
    152         System.arraycopy(mData, mIndex, temp, 0, mData.length - mIndex);
    153         System.arraycopy(body, start, temp, mData.length - mIndex, body.length - start);
    154 
    155         mData = temp;
    156         mIndex = 0;
    157         notifyAll();
    158     }
    159 
    160     /**
    161      * Verifies that this stream is open
    162      * @throws IOException if the stream is not open
    163      */
    164     private void ensureOpen() throws IOException {
    165         mParent.ensureOpen();
    166         if (!mOpen) {
    167             throw new IOException("Input stream is closed");
    168         }
    169     }
    170 
    171     /**
    172      * Closes the input stream. If the input stream is already closed, do
    173      * nothing.
    174      * @throws IOException this will never happen
    175      */
    176     @Override
    177     public void close() throws IOException {
    178         mOpen = false;
    179         mParent.streamClosed(true);
    180     }
    181 }
    182