blob: 96026495dbd560fbd6a2fb8456ac33885c950b39 [file] [log] [blame]
/*
* Copyright (c) 2008-2009, Motorola, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the Motorola, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package javax.obex;
import java.io.InputStream;
import java.io.IOException;
/**
* This object provides an input stream to the Operation objects used in this
* package.
*
* TODO: Include the other read() methods defined in InputStream.
*
* @hide
*/
public class PrivateInputStream extends InputStream {
private BaseStream parent;
private byte[] data;
private int index;
private boolean isOpen;
public PrivateInputStream() {
}
/**
* Creates an input stream for the <code>Operation</code> to read from
*
* @param p the connection this input stream is for
*/
public PrivateInputStream(BaseStream p) {
parent = p;
data = new byte[0];
index = 0;
isOpen = true;
}
/**
* Returns the number of bytes that can be read (or skipped over) from this
* input stream without blocking by the next caller of a method for this
* input stream. The next caller might be the same thread or or another
* thread.
*
* @return the number of bytes that can be read from this input stream
* without blocking
*
* @throws IOException if an I/O error occurs
*/
@Override
public synchronized int available() throws IOException {
ensureOpen();
return data.length - index;
}
/**
* Reads the next byte of data from the input stream. The value byte is
* returned as an int in the range 0 to 255. If no byte is available
* because the end of the stream has been reached, the value -1 is
* returned. This method blocks until input data is available, the end of
* the stream is detected, or an exception is thrown.
*
* @return the byte read from the input stream or -1 if it reaches the end
* of stream
*
* @throws IOException if an I/O error occurs
*/
@Override
public synchronized int read() throws IOException {
ensureOpen();
while (data.length == index) {
if (!parent.continueOperation(true, true)) {
return -1;
}
}
return (data[index++] & 0xFF);
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public synchronized int read(byte[] b, int offset, int length) throws IOException {
if (b == null) {
throw new NullPointerException("buffer is null");
}
if ((offset | length) < 0 || length > b.length - offset) {
throw new ArrayIndexOutOfBoundsException("index outof bound");
}
ensureOpen();
int currentDataLength = data.length - index;
int remainReadLength = length;
int offset1 = offset;
int result = 0;
while (currentDataLength <= remainReadLength) {
System.arraycopy(data, index, b, offset1, currentDataLength);
index += currentDataLength;
offset1 += currentDataLength;
result += currentDataLength;
remainReadLength -= currentDataLength;
if (!parent.continueOperation(true, true)) {
return result == 0 ? -1 : result;
}
currentDataLength = data.length - index;
}
if (remainReadLength > 0) {
System.arraycopy(data, index, b, offset1, remainReadLength);
index += remainReadLength;
result += remainReadLength;
}
return result;
}
/**
* Allows the <code>OperationImpl</code> thread to add body data to the
* input stream.
*
* @param body the data to add to the stream
*
* @param start the start of the body to array to copy
*/
public synchronized void writeBytes(byte[] body, int start) {
int length = (body.length - start) + (data.length - index);
byte[] temp = new byte[length];
System.arraycopy(data, index, temp, 0, data.length - index);
System.arraycopy(body, start, temp, data.length - index, body.length - start);
data = temp;
index = 0;
notifyAll();
}
/**
* Verifies that this stream is open
*
* @throws IOException if the stream is not open
*/
private void ensureOpen() throws IOException {
parent.ensureOpen();
if (!isOpen) {
throw new IOException("Input stream is closed");
}
}
/**
* Closes the input stream. If the input stream is already closed, do
* nothing.
*
* @throws IOException this will never happen
*/
@Override
public void close() throws IOException {
isOpen = false;
parent.streamClosed(true);
}
}