19439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/* 29439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Copyright (c) 2008-2009, Motorola, Inc. 39439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 49439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * All rights reserved. 59439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 69439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Redistribution and use in source and binary forms, with or without 79439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * modification, are permitted provided that the following conditions are met: 89439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 99439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Redistributions of source code must retain the above copyright notice, 109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * this list of conditions and the following disclaimer. 119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Redistributions in binary form must reproduce the above copyright notice, 139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * this list of conditions and the following disclaimer in the documentation 149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * and/or other materials provided with the distribution. 159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Neither the name of the Motorola, Inc. nor the names of its contributors 179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * may be used to endorse or promote products derived from this software 189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * without specific prior written permission. 199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * POSSIBILITY OF SUCH DAMAGE. 319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellypackage javax.obex; 349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 352e0da96e757a977154063f980d3f4e1abd41cf09Nick Pellyimport java.io.IOException; 362e0da96e757a977154063f980d3f4e1abd41cf09Nick Pellyimport java.io.OutputStream; 372e0da96e757a977154063f980d3f4e1abd41cf09Nick Pellyimport java.io.ByteArrayOutputStream; 389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/** 409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * This object provides an output stream to the Operation objects used in this 419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * package. 422e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly * @hide 439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 443998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejunpublic final class PrivateOutputStream extends OutputStream { 459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 463998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun private BaseStream mParent; 479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 483998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun private ByteArrayOutputStream mArray; 499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 503998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun private boolean mOpen; 519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 523998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun private int mMaxPacketSize; 539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Creates an empty <code>PrivateOutputStream</code> to write to. 569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @param p the connection that this stream runs over 579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public PrivateOutputStream(BaseStream p, int maxSize) { 593998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun mParent = p; 603998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun mArray = new ByteArrayOutputStream(); 613998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun mMaxPacketSize = maxSize; 6205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun mOpen = true; 639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Determines how many bytes have been written to the output stream. 679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @return the number of bytes written to the output stream 689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 693998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun public int size() { 703998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun return mArray.size(); 719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 7405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * Writes the specified byte to this output stream. The general contract for 7505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * write is that one byte is written to the output stream. The byte to be 7605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * written is the eight low-order bits of the argument b. The 24 high-order 7705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * bits of b are ignored. 789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @param b the byte to write 792e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly * @throws IOException if an I/O error occurs 809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly @Override 829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public synchronized void write(int b) throws IOException { 839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly ensureOpen(); 843998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun mParent.ensureNotDone(); 853998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun mArray.write(b); 863998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun if (mArray.size() == mMaxPacketSize) { 873998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun mParent.continueOperation(true, false); 889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly @Override 929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public void write(byte[] buffer) throws IOException { 939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly write(buffer, 0, buffer.length); 949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly @Override 979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public synchronized void write(byte[] buffer, int offset, int count) throws IOException { 989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly int offset1 = offset; 999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly int remainLength = count; 1009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 1019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly if (buffer == null) { 1023998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun throw new IOException("buffer is null"); 1039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly if ((offset | count) < 0 || count > buffer.length - offset) { 1059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly throw new IndexOutOfBoundsException("index outof bound"); 1069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 1089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly ensureOpen(); 1093998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun mParent.ensureNotDone(); 110a9c4c594ef29e097be8be0537657fa8d9529502eErik Ljungberg while ((mArray.size() + remainLength) >= mMaxPacketSize) { 111a9c4c594ef29e097be8be0537657fa8d9529502eErik Ljungberg int bufferLeft = mMaxPacketSize - mArray.size(); 112a9c4c594ef29e097be8be0537657fa8d9529502eErik Ljungberg mArray.write(buffer, offset1, bufferLeft); 113a9c4c594ef29e097be8be0537657fa8d9529502eErik Ljungberg offset1 += bufferLeft; 114a9c4c594ef29e097be8be0537657fa8d9529502eErik Ljungberg remainLength -= bufferLeft; 115a9c4c594ef29e097be8be0537657fa8d9529502eErik Ljungberg mParent.continueOperation(true, false); 116a9c4c594ef29e097be8be0537657fa8d9529502eErik Ljungberg } 117a9c4c594ef29e097be8be0537657fa8d9529502eErik Ljungberg if (remainLength > 0) { 118a9c4c594ef29e097be8be0537657fa8d9529502eErik Ljungberg mArray.write(buffer, offset1, remainLength); 1199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 1229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 1239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Reads the bytes that have been written to this stream. 1249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @param size the size of the array to return 1259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @return the byte array that is written 1269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 1273998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun public synchronized byte[] readBytes(int size) { 1283998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun if (mArray.size() > 0) { 1293998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun byte[] temp = mArray.toByteArray(); 1303998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun mArray.reset(); 1319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly byte[] result = new byte[size]; 1329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly System.arraycopy(temp, 0, result, 0, size); 1339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly if (temp.length != size) { 1343998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun mArray.write(temp, size, temp.length - size); 1359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly return result; 1379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } else { 1389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly return null; 1399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 1429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 1439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Verifies that this stream is open 1442e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly * @throws IOException if the stream is not open 1459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 1469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private void ensureOpen() throws IOException { 1473998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun mParent.ensureOpen(); 1483998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun if (!mOpen) { 1499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly throw new IOException("Output stream is closed"); 1509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 1539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 15405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * Closes the output stream. If the input stream is already closed, do 1559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * nothing. 1562e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly * @throws IOException this will never happen 1579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 1589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly @Override 1599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public void close() throws IOException { 1603998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun mOpen = false; 1613998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun mParent.streamClosed(false); 1629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 1649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 1659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Determines if the connection is closed 16605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * @return <code>true</code> if the connection is closed; <code>false</code> 16705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * if the connection is open 1689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 1693998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun public boolean isClosed() { 1703998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun return !mOpen; 1719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly} 173