• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
PrivateInputStream(BaseStream p)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
available()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
read()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
read(byte[] b)101     public int read(byte[] b) throws IOException {
102         return read(b, 0, b.length);
103     }
104 
105     @Override
read(byte[] b, int offset, int length)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      */
writeBytes(byte[] body, int start)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      */
ensureOpen()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
close()177     public void close() throws IOException {
178         mOpen = false;
179         mParent.streamClosed(true);
180     }
181 }
182