Home | History | Annotate | Download | only in obex
      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.IOException;
     36 import java.io.OutputStream;
     37 import java.io.ByteArrayOutputStream;
     38 
     39 /**
     40  * This object provides an output stream to the Operation objects used in this
     41  * package.
     42  * @hide
     43  */
     44 public final class PrivateOutputStream extends OutputStream {
     45 
     46     private BaseStream mParent;
     47 
     48     private ByteArrayOutputStream mArray;
     49 
     50     private boolean mOpen;
     51 
     52     private int mMaxPacketSize;
     53 
     54     /**
     55      * Creates an empty <code>PrivateOutputStream</code> to write to.
     56      * @param p the connection that this stream runs over
     57      */
     58     public PrivateOutputStream(BaseStream p, int maxSize) {
     59         mParent = p;
     60         mArray = new ByteArrayOutputStream();
     61         mMaxPacketSize = maxSize;
     62         mOpen = true;
     63     }
     64 
     65     /**
     66      * Determines how many bytes have been written to the output stream.
     67      * @return the number of bytes written to the output stream
     68      */
     69     public int size() {
     70         return mArray.size();
     71     }
     72 
     73     /**
     74      * Writes the specified byte to this output stream. The general contract for
     75      * write is that one byte is written to the output stream. The byte to be
     76      * written is the eight low-order bits of the argument b. The 24 high-order
     77      * bits of b are ignored.
     78      * @param b the byte to write
     79      * @throws IOException if an I/O error occurs
     80      */
     81     @Override
     82     public synchronized void write(int b) throws IOException {
     83         ensureOpen();
     84         mParent.ensureNotDone();
     85         mArray.write(b);
     86         if (mArray.size() == mMaxPacketSize) {
     87             mParent.continueOperation(true, false);
     88         }
     89     }
     90 
     91     @Override
     92     public void write(byte[] buffer) throws IOException {
     93         write(buffer, 0, buffer.length);
     94     }
     95 
     96     @Override
     97     public synchronized void write(byte[] buffer, int offset, int count) throws IOException {
     98         int offset1 = offset;
     99         int remainLength = count;
    100 
    101         if (buffer == null) {
    102             throw new IOException("buffer is null");
    103         }
    104         if ((offset | count) < 0 || count > buffer.length - offset) {
    105             throw new IndexOutOfBoundsException("index outof bound");
    106         }
    107 
    108         ensureOpen();
    109         mParent.ensureNotDone();
    110         while ((mArray.size() + remainLength) >= mMaxPacketSize) {
    111             int bufferLeft = mMaxPacketSize - mArray.size();
    112             mArray.write(buffer, offset1, bufferLeft);
    113             offset1 += bufferLeft;
    114             remainLength -= bufferLeft;
    115             mParent.continueOperation(true, false);
    116         }
    117         if (remainLength > 0) {
    118             mArray.write(buffer, offset1, remainLength);
    119         }
    120     }
    121 
    122     /**
    123      * Reads the bytes that have been written to this stream.
    124      * @param size the size of the array to return
    125      * @return the byte array that is written
    126      */
    127     public synchronized byte[] readBytes(int size) {
    128         if (mArray.size() > 0) {
    129             byte[] temp = mArray.toByteArray();
    130             mArray.reset();
    131             byte[] result = new byte[size];
    132             System.arraycopy(temp, 0, result, 0, size);
    133             if (temp.length != size) {
    134                 mArray.write(temp, size, temp.length - size);
    135             }
    136             return result;
    137         } else {
    138             return null;
    139         }
    140     }
    141 
    142     /**
    143      * Verifies that this stream is open
    144      * @throws IOException if the stream is not open
    145      */
    146     private void ensureOpen() throws IOException {
    147         mParent.ensureOpen();
    148         if (!mOpen) {
    149             throw new IOException("Output stream is closed");
    150         }
    151     }
    152 
    153     /**
    154      * Closes the output stream. If the input stream is already closed, do
    155      * nothing.
    156      * @throws IOException this will never happen
    157      */
    158     @Override
    159     public void close() throws IOException {
    160         mOpen = false;
    161         mParent.streamClosed(false);
    162     }
    163 
    164     /**
    165      * Determines if the connection is closed
    166      * @return <code>true</code> if the connection is closed; <code>false</code>
    167      *         if the connection is open
    168      */
    169     public boolean isClosed() {
    170         return !mOpen;
    171     }
    172 }
    173