19439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/*
28949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta * Copyright (c) 2014 The Android Open Source Project
39439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Copyright (c) 2008-2009, Motorola, Inc.
49439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
59439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * All rights reserved.
69439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
79439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Redistribution and use in source and binary forms, with or without
89439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * modification, are permitted provided that the following conditions are met:
99439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Redistributions of source code must retain the above copyright notice,
119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * this list of conditions and the following disclaimer.
129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Redistributions in binary form must reproduce the above copyright notice,
149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * this list of conditions and the following disclaimer in the documentation
159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * and/or other materials provided with the distribution.
169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Neither the name of the Motorola, Inc. nor the names of its contributors
189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * may be used to endorse or promote products derived from this software
199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * without specific prior written permission.
209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * POSSIBILITY OF SUCH DAMAGE.
329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */
339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellypackage javax.obex;
359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.IOException;
379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.InputStream;
389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.OutputStream;
399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.DataInputStream;
409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.DataOutputStream;
419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.ByteArrayOutputStream;
429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/**
4405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * This class implements the <code>Operation</code> interface. It will read and
4505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * write data via puts and gets.
462e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly * @hide
479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */
482e0da96e757a977154063f980d3f4e1abd41cf09Nick Pellypublic final class ClientOperation implements Operation, BaseStream {
499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
503998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private ClientSession mParent;
519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
523998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mInputOpen;
539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
543998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private PrivateInputStream mPrivateInput;
559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
563998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mPrivateInputOpen;
579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
583998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private PrivateOutputStream mPrivateOutput;
599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
603998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mPrivateOutputOpen;
619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
623998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private String mExceptionMessage;
639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
643998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private int mMaxPacketSize;
659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
663998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mOperationDone;
679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
683998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mGetOperation;
699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
708949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta    private boolean mGetFinalFlag;
718949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta
723998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private HeaderSet mRequestHeader;
739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
743998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private HeaderSet mReplyHeader;
759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
763998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mEndOfBodySent;
779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun    /**
799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Creates new OperationImpl to read and write data to a server
809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param maxSize the maximum packet size
819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param p the parent to this object
829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param type <code>true</code> if this is a get request;
8305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        <code>false</code. if this is a put request
8405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @param header the header to set in the initial request
8505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @throws IOException if the an IO error occurred
869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
873998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public ClientOperation(int maxSize, ClientSession p, HeaderSet header, boolean type)
883998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            throws IOException {
899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
903998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mParent = p;
913998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mEndOfBodySent = false;
923998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mInputOpen = true;
933998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mOperationDone = false;
943998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mMaxPacketSize = maxSize;
953998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mGetOperation = type;
968949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta        mGetFinalFlag = false;
979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
983998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateInputOpen = false;
993998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateOutputOpen = false;
1003998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateInput = null;
1013998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateOutput = null;
1029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1033998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mReplyHeader = new HeaderSet();
1049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1053998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mRequestHeader = new HeaderSet();
1069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int[] headerList = header.getHeaderList();
1089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (headerList != null) {
1109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            for (int i = 0; i < headerList.length; i++) {
1123998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mRequestHeader.setHeader(headerList[i], header.getHeader(headerList[i]));
1139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
1149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1163998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((header).mAuthChall != null) {
1173998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            mRequestHeader.mAuthChall = new byte[(header).mAuthChall.length];
1183998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            System.arraycopy((header).mAuthChall, 0, mRequestHeader.mAuthChall, 0,
1193998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    (header).mAuthChall.length);
1209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1223998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((header).mAuthResp != null) {
1233998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            mRequestHeader.mAuthResp = new byte[(header).mAuthResp.length];
1243998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            System.arraycopy((header).mAuthResp, 0, mRequestHeader.mAuthResp, 0,
1253998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    (header).mAuthResp.length);
1269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1280d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz
1290d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz        if ((header).mConnectionID != null) {
1300d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz            mRequestHeader.mConnectionID = new byte[4];
1310d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz            System.arraycopy((header).mConnectionID, 0, mRequestHeader.mConnectionID, 0,
1320d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz                    4);
1330d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz
1340d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz        }
1359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
1369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
1388949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta     * Allows to set flag which will force GET to be always sent as single packet request with
1398949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta     * final flag set. This is to improve compatibility with some profiles, i.e. PBAP which
1408949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta     * require requests to be sent this way.
1418949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta     */
1428949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta    public void setGetFinalFlag(boolean flag) {
1438949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta        mGetFinalFlag = flag;
1448949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta    }
1458949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta
1468949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta    /**
14705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Sends an ABORT message to the server. By calling this method, the
1489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * corresponding input and output streams will be closed along with this
1499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * object.
15005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @throws IOException if the transaction has already ended or if an OBEX
15105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         server called this method
1529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
1539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public synchronized void abort() throws IOException {
1549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
1559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        //no compatible with sun-ri
1563998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((mOperationDone) && (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE)) {
1579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Operation has already ended");
1589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1603998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mExceptionMessage = "Operation aborted";
1613998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((!mOperationDone) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
1623998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            mOperationDone = true;
1639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            /*
1649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * Since we are not sending any headers or returning any headers then
1659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * we just need to write and read the same bytes
1669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             */
1673998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            mParent.sendRequest(ObexHelper.OBEX_OPCODE_ABORT, null, mReplyHeader, null);
1689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1693998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_OK) {
1709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                throw new IOException("Invalid response code from server");
1719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
1729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1733998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            mExceptionMessage = null;
1749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        close();
1779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
1789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
18005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Retrieves the response code retrieved from the server. Response codes are
18105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * defined in the <code>ResponseCodes</code> interface.
1829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the response code retrieved from the server
1832e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an error occurred in the transport layer during
18405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         the transaction; if this method is called on a
18505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         <code>HeaderSet</code> object created by calling
18605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         <code>createHeaderSet</code> in a <code>ClientSession</code>
18705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         object
1889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
1899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public synchronized int getResponseCode() throws IOException {
1909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        //avoid dup validateConnection
1913998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((mReplyHeader.responseCode == -1)
1923998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                || (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
1939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            validateConnection();
1949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1963998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        return mReplyHeader.responseCode;
1979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
1989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
2009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * This method will always return <code>null</code>
2019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return <code>null</code>
2029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
2039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public String getEncoding() {
2049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return null;
2059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
2089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Returns the type of content that the resource connected to is providing.
2099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * E.g. if the connection is via HTTP, then the value of the content-type
2109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * header field is returned.
2119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the content type of the resource that the URL references, or
21205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         <code>null</code> if not known
2139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
2149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public String getType() {
2159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        try {
2163998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            return (String)mReplyHeader.getHeader(HeaderSet.TYPE);
2179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } catch (IOException e) {
2189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return null;
2199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
2239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Returns the length of the content which is being provided. E.g. if the
22405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * connection is via HTTP, then the value of the content-length header field
22505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * is returned.
2269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the content length of the resource that this connection's URL
22705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         references, or -1 if the content length is not known
2289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
2299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public long getLength() {
2309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        try {
2313998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            Long temp = (Long)mReplyHeader.getHeader(HeaderSet.LENGTH);
2329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (temp == null) {
2349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return -1;
2359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
2369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return temp.longValue();
2379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
2389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } catch (IOException e) {
2399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return -1;
2409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
2449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Open and return an input stream for a connection.
2459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return an input stream
2462e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an I/O error occurs
2479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
2489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public InputStream openInputStream() throws IOException {
2499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
2519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2523998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateInputOpen)
2539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("no more input streams available");
2543998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mGetOperation) {
2559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // send the GET request here
2569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            validateConnection();
2579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
2583998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (mPrivateInput == null) {
2593998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mPrivateInput = new PrivateInputStream(this);
2609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
2619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2633998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateInputOpen = true;
2649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2653998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        return mPrivateInput;
2669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
26805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun    /**
2699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Open and return a data input stream for a connection.
2709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return an input stream
2712e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an I/O error occurs
2729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
2739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public DataInputStream openDataInputStream() throws IOException {
2749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return new DataInputStream(openInputStream());
2759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
2789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Open and return an output stream for a connection.
2799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return an output stream
2802e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an I/O error occurs
2819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
2829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public OutputStream openOutputStream() throws IOException {
2833998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
2849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
2859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureNotDone();
2869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2873998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateOutputOpen)
2889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("no more output streams available");
2899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2903998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateOutput == null) {
2919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // there are 3 bytes operation headers and 3 bytes body headers //
29265208317ba9d16486b47ebcaa868c596d424c87fLixin Yue            mPrivateOutput = new PrivateOutputStream(this, getMaxPacketSize());
2939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2953998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateOutputOpen = true;
2969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2973998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        return mPrivateOutput;
2989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public int getMaxPacketSize() {
30165208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        return mMaxPacketSize - 6 - getHeaderLength();
30265208317ba9d16486b47ebcaa868c596d424c87fLixin Yue    }
30365208317ba9d16486b47ebcaa868c596d424c87fLixin Yue
30465208317ba9d16486b47ebcaa868c596d424c87fLixin Yue    public int getHeaderLength() {
30565208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        // OPP may need it
30665208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        byte[] headerArray = ObexHelper.createHeader(mRequestHeader, false);
30765208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        return headerArray.length;
3089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
3119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Open and return a data output stream for a connection.
3129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return an output stream
3132e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an I/O error occurs
3149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public DataOutputStream openDataOutputStream() throws IOException {
3169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return new DataOutputStream(openOutputStream());
3179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
3209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Closes the connection and ends the transaction
3212e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if the operation has already ended or is closed
3229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void close() throws IOException {
3243998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mInputOpen = false;
3253998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateInputOpen = false;
3263998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateOutputOpen = false;
3273998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mParent.setRequestInactive();
3289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
3319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Returns the headers that have been received during the operation.
33205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Modifying the object returned has no effect on the headers that are sent
33305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * or retrieved.
3349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the headers received during this <code>Operation</code>
3352e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if this <code>Operation</code> has been closed
3369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3373998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public HeaderSet getReceivedHeader() throws IOException {
3389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
3399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3403998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        return mReplyHeader;
3419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
3449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Specifies the headers that should be sent in the next OBEX message that
3459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * is sent.
3469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param headers the headers to send in the next message
34705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @throws IOException if this <code>Operation</code> has been closed or the
34805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         transaction has ended and no further messages will be exchanged
3492e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IllegalArgumentException if <code>headers</code> was not created
35005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         by a call to <code>ServerRequestHandler.createHeaderSet()</code>
3512e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws NullPointerException if <code>headers</code> is <code>null</code>
3529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void sendHeaders(HeaderSet headers) throws IOException {
3549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
3553998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mOperationDone) {
3569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Operation has already exchanged all data");
3579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (headers == null) {
3603998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            throw new IOException("Headers may not be null");
3619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int[] headerList = headers.getHeaderList();
3649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (headerList != null) {
3659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            for (int i = 0; i < headerList.length; i++) {
3663998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mRequestHeader.setHeader(headerList[i], headers.getHeader(headerList[i]));
3679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
3689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
37205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Verifies that additional information may be sent. In other words, the
3739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * operation is not done.
3742e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if the operation is completed
3759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void ensureNotDone() throws IOException {
3773998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mOperationDone) {
3789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Operation has completed");
3799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
3839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Verifies that the connection is open and no exceptions should be thrown.
3842e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an exception needs to be thrown
3859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void ensureOpen() throws IOException {
3873998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mParent.ensureOpen();
3889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3893998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mExceptionMessage != null) {
3903998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            throw new IOException(mExceptionMessage);
3919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3923998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (!mInputOpen) {
3939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Operation has already ended");
3949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
3989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Verifies that the connection is open and the proper data has been read.
3992e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an IO error occurs
4009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
4019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    private void validateConnection() throws IOException {
4029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
4039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // to sure only one privateInput object exist.
4053998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateInput == null) {
4069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            startProcessing();
4079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
4089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
4099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
4119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Sends a request to the client of the specified type
41205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @param opCode the request code to send to the client
4139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return <code>true</code> if there is more data to send;
41405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         <code>false</code> if there is no more data to send
4152e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an IO error occurs
4169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
41705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun    private boolean sendRequest(int opCode) throws IOException {
4189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        boolean returnValue = false;
4199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ByteArrayOutputStream out = new ByteArrayOutputStream();
4209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int bodyLength = -1;
4213998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        byte[] headerArray = ObexHelper.createHeader(mRequestHeader, true);
4223998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateOutput != null) {
4233998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            bodyLength = mPrivateOutput.size();
4249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
4259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /*
4279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * Determine if there is space to add a body request.  At present
4289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * this method checks to see if there is room for at least a 17
4299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * byte body header.  This number needs to be at least 6 so that
4309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * there is room for the header ID and length and the reply ID and
4319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * length, but it is a waste of resources if we can't send much of
4329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * the body.
4339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         */
4343998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((ObexHelper.BASE_PACKET_LENGTH + headerArray.length) > mMaxPacketSize) {
4359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            int end = 0;
4369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            int start = 0;
4379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // split & send the headerArray in multiple packets.
4389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            while (end != headerArray.length) {
4409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                //split the headerArray
4413998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                end = ObexHelper.findHeaderEnd(headerArray, start, mMaxPacketSize
4423998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        - ObexHelper.BASE_PACKET_LENGTH);
4430d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz                // can not split
4449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (end == -1) {
4453998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mOperationDone = true;
4469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    abort();
4473998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mExceptionMessage = "Header larger then can be sent in a packet";
4483998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mInputOpen = false;
4499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4503998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    if (mPrivateInput != null) {
4513998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        mPrivateInput.close();
4529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
4539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4543998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    if (mPrivateOutput != null) {
4553998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        mPrivateOutput.close();
4569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
4579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    throw new IOException("OBEX Packet exceeds max packet size");
4589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                byte[] sendHeader = new byte[end - start];
4619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                System.arraycopy(headerArray, start, sendHeader, 0, sendHeader.length);
46205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun                if (!mParent.sendRequest(opCode, sendHeader, mReplyHeader, mPrivateInput)) {
4639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    return false;
4649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4663998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
4679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    return false;
4689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                start = end;
4719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
4729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (bodyLength > 0) {
4749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return true;
4759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
4769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return false;
4779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
4789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
4799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write(headerArray);
4809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
4819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (bodyLength > 0) {
4839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            /*
4843998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun             * Determine if we can send the whole body or just part of
4859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * the body.  Remember that there is the 3 bytes for the
4869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * response message and 3 bytes for the header ID and length
4879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             */
4883998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (bodyLength > (mMaxPacketSize - headerArray.length - 6)) {
4899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                returnValue = true;
4909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4913998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                bodyLength = mMaxPacketSize - headerArray.length - 6;
4929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
4939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4943998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            byte[] body = mPrivateOutput.readBytes(bodyLength);
4959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            /*
4979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * Since this is a put request if the final bit is set or
4989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * the output stream is closed we need to send the 0x49
4999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * (End of Body) otherwise, we need to send 0x48 (Body)
5009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             */
5013998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if ((mPrivateOutput.isClosed()) && (!returnValue) && (!mEndOfBodySent)
50205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun                    && ((opCode & 0x80) != 0)) {
5039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(0x49);
5043998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mEndOfBodySent = true;
5059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
5069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(0x48);
5079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            bodyLength += 3;
5109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write((byte)(bodyLength >> 8));
5119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write((byte)bodyLength);
5129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (body != null) {
5149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(body);
5159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
5179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5183998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateOutputOpen && bodyLength <= 0 && !mEndOfBodySent) {
5199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // only 0x82 or 0x83 can send 0x49
52005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun            if ((opCode & 0x80) == 0) {
5219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(0x48);
5229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
5239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(0x49);
5243998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mEndOfBodySent = true;
5259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            bodyLength = 3;
5299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write((byte)(bodyLength >> 8));
5309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write((byte)bodyLength);
5319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
5329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (out.size() == 0) {
53405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun            if (!mParent.sendRequest(opCode, null, mReplyHeader, mPrivateInput)) {
5359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return false;
5369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return returnValue;
5389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
5399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if ((out.size() > 0)
54005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun                && (!mParent.sendRequest(opCode, out.toByteArray(), mReplyHeader, mPrivateInput))) {
5419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return false;
5429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
5439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5440d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz        // send all of the output data in 0x48,
5459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // send 0x49 with empty body
5463998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((mPrivateOutput != null) && (mPrivateOutput.size() > 0))
5479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            returnValue = true;
5489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return returnValue;
5509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
5519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
55305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * This method starts the processing thread results. It will send the
55405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * initial request. If the response takes more then one packet, a thread
5559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * will be started to handle additional requests
5562e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an IO error occurs
5579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
5589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    private synchronized void startProcessing() throws IOException {
5599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5603998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateInput == null) {
5613998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            mPrivateInput = new PrivateInputStream(this);
5629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
5639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        boolean more = true;
5649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5653998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mGetOperation) {
5663998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (!mOperationDone) {
5678949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                if (!mGetFinalFlag) {
5688949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                    mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
5698949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                    while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
5708949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                        more = sendRequest(0x03);
5718949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                    }
5728949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta
5738949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                    if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
5748949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                        mParent.sendRequest(0x83, null, mReplyHeader, mPrivateInput);
5758949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                    }
5768949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                    if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
5778949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                        mOperationDone = true;
5788949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                    }
5798949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                } else {
5808949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                    more = sendRequest(0x83);
5818949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta
5828949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                    if (more) {
5838949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                        throw new IOException("FINAL_GET forced but data did not fit into single packet!");
5848949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                    }
5859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5863998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mOperationDone = true;
5879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
5889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
5909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5913998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (!mOperationDone) {
5923998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
5933998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
5949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    more = sendRequest(0x02);
5959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
5979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5993998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
6003998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mParent.sendRequest(0x82, null, mReplyHeader, mPrivateInput);
6019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
6029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6033998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
6043998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mOperationDone = true;
6059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
6069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
6079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
6089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
6109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Continues the operation since there is no data to read.
61105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @param sendEmpty <code>true</code> if the operation should send an empty
61205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        packet or not send anything if there is no data to send
61305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @param inStream <code>true</code> if the stream is input stream or is
61405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        output stream
6152e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an IO error occurs
6169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
6179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public synchronized boolean continueOperation(boolean sendEmpty, boolean inStream)
6189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throws IOException {
6199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6203998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mGetOperation) {
6213998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if ((inStream) && (!mOperationDone)) {
6229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // to deal with inputstream in get operation
6233998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mParent.sendRequest(0x83, null, mReplyHeader, mPrivateInput);
6249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                /*
6259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                  * Determine if that was not the last packet in the operation
6269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                  */
6273998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
6283998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mOperationDone = true;
6299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
6309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return true;
6329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6333998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            } else if ((!inStream) && (!mOperationDone)) {
6349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // to deal with outputstream in get operation
6359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6363998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mPrivateInput == null) {
6373998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mPrivateInput = new PrivateInputStream(this);
6389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
6398949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta
6408949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                if (!mGetFinalFlag) {
6418949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                    sendRequest(0x03);
6428949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                } else {
6438949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                    sendRequest(0x83);
6448949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta
6458949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                    if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
6468949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                        mOperationDone = true;
6478949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                    }
6488949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                }
6499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return true;
6509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6513998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            } else if (mOperationDone) {
6529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return false;
6539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
6549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
6563998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if ((!inStream) && (!mOperationDone)) {
6579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // to deal with outputstream in put operation
6583998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mReplyHeader.responseCode == -1) {
6593998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
6609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
6619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                sendRequest(0x02);
6629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return true;
6633998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            } else if ((inStream) && (!mOperationDone)) {
6649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // How to deal with inputstream  in put operation ?
6659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return false;
6669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6673998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            } else if (mOperationDone) {
6689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return false;
6699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
6709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
6729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return false;
6739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
6749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
6769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Called when the output or input stream is closed.
6779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param inStream <code>true</code> if the input stream is closed;
67805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        <code>false</code> if the output stream is closed
6792e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an IO error occurs
6809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
6819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void streamClosed(boolean inStream) throws IOException {
6823998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (!mGetOperation) {
6833998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if ((!inStream) && (!mOperationDone)) {
6849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // to deal with outputstream in put operation
6859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                boolean more = true;
6879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6883998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0)) {
6893998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    byte[] headerArray = ObexHelper.createHeader(mRequestHeader, false);
6909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    if (headerArray.length <= 0)
6919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        more = false;
6929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
6939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // If have not sent any data so send  all now
6943998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mReplyHeader.responseCode == -1) {
6953998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
6969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
6979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6983998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
6999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    more = sendRequest(0x02);
7009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
7019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                /*
7039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * According to the IrOBEX specification, after the final put, you
7049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * only have a single reply to send.  so we don't need the while
7059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * loop.
7069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 */
7073998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
7089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    sendRequest(0x82);
7109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
7113998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mOperationDone = true;
7123998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            } else if ((inStream) && (mOperationDone)) {
7139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // how to deal with input stream in put stream ?
7143998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mOperationDone = true;
7159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
7169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
7173998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if ((inStream) && (!mOperationDone)) {
7189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // to deal with inputstream in get operation
7209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // Have not sent any data so send it all now
7219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7223998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mReplyHeader.responseCode == -1) {
7233998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
7249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
7259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7263998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
7279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    if (!sendRequest(0x83)) {
7289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        break;
7299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
7309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
7313998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
7323998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mParent.sendRequest(0x83, null, mReplyHeader, mPrivateInput);
7339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
7343998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mOperationDone = true;
7353998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            } else if ((!inStream) && (!mOperationDone)) {
7369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // to deal with outputstream in get operation
7379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // part of the data may have been sent in continueOperation.
7389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                boolean more = true;
7409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7413998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0)) {
7423998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    byte[] headerArray = ObexHelper.createHeader(mRequestHeader, false);
7439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    if (headerArray.length <= 0)
7449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        more = false;
7459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
7469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7473998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mPrivateInput == null) {
7483998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mPrivateInput = new PrivateInputStream(this);
7499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
7503998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0))
7519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    more = false;
7529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7533998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
7543998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
7559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    more = sendRequest(0x03);
7569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
7579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                sendRequest(0x83);
7589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                //                parent.sendRequest(0x83, null, replyHeaders, privateInput);
7593998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
7603998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mOperationDone = true;
7619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
7629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
7639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
7649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
765fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie
766fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie    public void noBodyHeader(){
767fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie    }
7689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly}
769