PrivateInputStream.java revision 3998bf009acaf8cde4d7f837f8b8e41ae0a65141
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 33package javax.obex; 34 35import java.io.InputStream; 36import java.io.IOException; 37 38/** 39 * This object provides an input stream to the Operation objects used in this 40 * package. 41 * 42 * @hide 43 */ 44public final class PrivateInputStream extends InputStream { 45 46 private BaseStream mParent; 47 48 private byte[] mData; 49 50 private int mIndex; 51 52 private boolean mOpen; 53 54 /** 55 * Creates an input stream for the <code>Operation</code> to read from 56 * 57 * @param p the connection this input stream is for 58 */ 59 public PrivateInputStream(BaseStream p) { 60 mParent = p; 61 mData = new byte[0]; 62 mIndex = 0; 63 mOpen = true; 64 } 65 66 /** 67 * Returns the number of bytes that can be read (or skipped over) from this 68 * input stream without blocking by the next caller of a method for this 69 * input stream. The next caller might be the same thread or or another 70 * thread. 71 * 72 * @return the number of bytes that can be read from this input stream 73 * without blocking 74 * 75 * @throws IOException if an I/O error occurs 76 */ 77 @Override 78 public synchronized int available() throws IOException { 79 ensureOpen(); 80 return mData.length - mIndex; 81 } 82 83 /** 84 * Reads the next byte of data from the input stream. The value byte is 85 * returned as an int in the range 0 to 255. If no byte is available 86 * because the end of the stream has been reached, the value -1 is 87 * returned. This method blocks until input data is available, the end of 88 * the stream is detected, or an exception is thrown. 89 * 90 * @return the byte read from the input stream or -1 if it reaches the end 91 * of stream 92 * 93 * @throws IOException if an I/O error occurs 94 */ 95 @Override 96 public synchronized int read() throws IOException { 97 ensureOpen(); 98 while (mData.length == mIndex) { 99 if (!mParent.continueOperation(true, true)) { 100 return -1; 101 } 102 } 103 return (mData[mIndex++] & 0xFF); 104 } 105 106 @Override 107 public int read(byte[] b) throws IOException { 108 return read(b, 0, b.length); 109 } 110 111 @Override 112 public synchronized int read(byte[] b, int offset, int length) throws IOException { 113 114 if (b == null) { 115 throw new IOException("buffer is null"); 116 } 117 if ((offset | length) < 0 || length > b.length - offset) { 118 throw new ArrayIndexOutOfBoundsException("index outof bound"); 119 } 120 ensureOpen(); 121 122 int currentDataLength = mData.length - mIndex; 123 int remainReadLength = length; 124 int offset1 = offset; 125 int result = 0; 126 127 while (currentDataLength <= remainReadLength) { 128 System.arraycopy(mData, mIndex, b, offset1, currentDataLength); 129 mIndex += currentDataLength; 130 offset1 += currentDataLength; 131 result += currentDataLength; 132 remainReadLength -= currentDataLength; 133 134 if (!mParent.continueOperation(true, true)) { 135 return result == 0 ? -1 : result; 136 } 137 currentDataLength = mData.length - mIndex; 138 } 139 if (remainReadLength > 0) { 140 System.arraycopy(mData, mIndex, b, offset1, remainReadLength); 141 mIndex += remainReadLength; 142 result += remainReadLength; 143 } 144 return result; 145 } 146 147 /** 148 * Allows the <code>OperationImpl</code> thread to add body data to the 149 * input stream. 150 * 151 * @param body the data to add to the stream 152 * 153 * @param start the start of the body to array to copy 154 */ 155 public synchronized void writeBytes(byte[] body, int start) { 156 157 int length = (body.length - start) + (mData.length - mIndex); 158 byte[] temp = new byte[length]; 159 160 System.arraycopy(mData, mIndex, temp, 0, mData.length - mIndex); 161 System.arraycopy(body, start, temp, mData.length - mIndex, body.length - start); 162 163 mData = temp; 164 mIndex = 0; 165 notifyAll(); 166 } 167 168 /** 169 * Verifies that this stream is open 170 * 171 * @throws IOException if the stream is not open 172 */ 173 private void ensureOpen() throws IOException { 174 mParent.ensureOpen(); 175 if (!mOpen) { 176 throw new IOException("Input stream is closed"); 177 } 178 } 179 180 /** 181 * Closes the input stream. If the input stream is already closed, do 182 * nothing. 183 * 184 * @throws IOException this will never happen 185 */ 186 @Override 187 public void close() throws IOException { 188 mOpen = false; 189 mParent.streamClosed(true); 190 } 191} 192