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