/* * 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.*; /** * This object provides an input stream to the Operation objects used in this * package. * * OPTIMIZATION: Include the other read() methods defined in InputStream. * * @version 0.3 November 28, 2008 */ 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 Operation 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 * * @exception 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 * * @exception 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 OperationImpl 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 * * @exception 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. * * @exception IOException this will never happen */ @Override public void close() throws IOException { isOpen = false; parent.streamClosed(true); } }