summaryrefslogtreecommitdiffstats
path: root/obex/javax/obex/ClientOperation.java
diff options
context:
space:
mode:
Diffstat (limited to 'obex/javax/obex/ClientOperation.java')
-rw-r--r--obex/javax/obex/ClientOperation.java840
1 files changed, 840 insertions, 0 deletions
diff --git a/obex/javax/obex/ClientOperation.java b/obex/javax/obex/ClientOperation.java
new file mode 100644
index 0000000..dc4e944
--- /dev/null
+++ b/obex/javax/obex/ClientOperation.java
@@ -0,0 +1,840 @@
+/*
+ * Copyright (c) 2008-2009, Motorola, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the Motorola, Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package javax.obex;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.ByteArrayOutputStream;
+
+/**
+ * This class implements the <code>Operation</code> interface. It will read
+ * and write data via puts and gets.
+ *
+ * @version 0.3 November 28, 2008
+ */
+public class ClientOperation implements Operation, BaseStream {
+
+ /**
+ * Defines the basic packet length used by OBEX. Event OBEX packet has the
+ * same basic format:<BR>
+ * Byte 0: Request or Response Code
+ * Byte 1&2: Length of the packet.
+ */
+ private static final int BASE_PACKET_LENGTH = 3;
+
+ private ClientSession parent;
+
+ private InputStream socketInput;
+
+ private PrivateInputStream privateInput;
+
+ private PrivateOutputStream privateOutput;
+
+ private boolean isClosed;
+
+ private String exceptionMessage;
+
+ private int maxPacketSize;
+
+ private boolean isDone;
+
+ private boolean isGet;
+
+ private HeaderSet requestHeaders;
+
+ private HeaderSet replyHeaders;
+
+ private boolean isEndOfBodySent;
+
+ private boolean inputStreamOpened;
+
+ private boolean outputStreamOpened;
+
+ private boolean isValidateConnected;
+
+ /**
+ * Creates new OperationImpl to read and write data to a server
+ *
+ * @param in the input stream to read from
+ *
+ * @param maxSize the maximum packet size
+ *
+ * @param p the parent to this object
+ *
+ * @param headers the headers to set in the initial request
+ *
+ * @param type <code>true</code> if this is a get request;
+ * <code>false</code. if this is a put request
+ *
+ * @exception IOExcpetion if the an IO error occured
+ */
+ public ClientOperation(InputStream in, int maxSize, ClientSession p, HeaderSet header,
+ boolean type) throws IOException {
+
+ parent = p;
+ isEndOfBodySent = false;
+ socketInput = in;
+ isClosed = false;
+ isDone = false;
+ maxPacketSize = maxSize;
+ isGet = type;
+
+ inputStreamOpened = false;
+ outputStreamOpened = false;
+ isValidateConnected = false;
+
+ privateInput = null;
+ privateOutput = null;
+
+ replyHeaders = new HeaderSet();
+
+ requestHeaders = new HeaderSet();
+
+ int[] headerList = header.getHeaderList();
+
+ if (headerList != null) {
+
+ for (int i = 0; i < headerList.length; i++) {
+ requestHeaders.setHeader(headerList[i], header.getHeader(headerList[i]));
+ }
+ }
+
+ if ((header).authChall != null) {
+ requestHeaders.authChall = new byte[(header).authChall.length];
+ System.arraycopy((header).authChall, 0, requestHeaders.authChall, 0,
+ (header).authChall.length);
+ }
+
+ if ((header).authResp != null) {
+ requestHeaders.authResp = new byte[(header).authResp.length];
+ System.arraycopy((header).authResp, 0, requestHeaders.authResp, 0,
+ (header).authResp.length);
+
+ }
+ // requestHeaders = (HeaderSet)header;
+ }
+
+ /**
+ * Sends an ABORT message to the server. By calling this method, the
+ * corresponding input and output streams will be closed along with this
+ * object.
+ *
+ * @exception IOException if the transaction has already ended or if an
+ * OBEX server called this method
+ */
+ public synchronized void abort() throws IOException {
+ ensureOpen();
+ // need check again .
+ // if(isDone) {
+ // throw new IOException("Operation has already ended");
+ // }
+
+ //no compatible with sun-ri
+ if ((isDone) && (replyHeaders.responseCode != OBEXConstants.OBEX_HTTP_CONTINUE)) {
+ throw new IOException("Operation has already ended");
+ }
+
+ exceptionMessage = "Operation aborted";
+ if ((!isDone) && (replyHeaders.responseCode == OBEXConstants.OBEX_HTTP_CONTINUE)) {
+ isDone = true;
+ /*
+ * Since we are not sending any headers or returning any headers then
+ * we just need to write and read the same bytes
+ */
+ parent.sendRequest(0xFF, null, replyHeaders, null);
+
+ if (replyHeaders.responseCode != ResponseCodes.OBEX_HTTP_OK) {
+ throw new IOException("Invalid response code from server");
+ }
+
+ exceptionMessage = null;
+ }
+
+ close();
+ }
+
+ /**
+ * Retrieves the response code retrieved from the server. Response codes
+ * are defined in the <code>ResponseCodes</code> interface.
+ *
+ * @return the response code retrieved from the server
+ *
+ * @exception IOException if an error occurred in the transport layer during
+ * the transaction; if this method is called on a <code>HeaderSet</code>
+ * object created by calling <code>createHeaderSet</code> in a
+ * <code>ClientSession</code> object
+ */
+ public synchronized int getResponseCode() throws IOException {
+ //avoid dup validateConnection
+ if ((replyHeaders.responseCode == -1)
+ || (replyHeaders.responseCode == OBEXConstants.OBEX_HTTP_CONTINUE)) {
+ validateConnection();
+ }
+
+ return replyHeaders.responseCode;
+ }
+
+ /**
+ * This method will always return <code>null</code>
+ *
+ * @return <code>null</code>
+ */
+ public String getEncoding() {
+ return null;
+ }
+
+ /**
+ * Returns the type of content that the resource connected to is providing.
+ * E.g. if the connection is via HTTP, then the value of the content-type
+ * header field is returned.
+ *
+ * @return the content type of the resource that the URL references, or
+ * <code>null</code> if not known
+ */
+ public String getType() {
+ try {
+ return (String)replyHeaders.getHeader(HeaderSet.TYPE);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the length of the content which is being provided. E.g. if the
+ * connection is via HTTP, then the value of the content-length header
+ * field is returned.
+ *
+ * @return the content length of the resource that this connection's URL
+ * references, or -1 if the content length is not known
+ */
+ public long getLength() {
+ try {
+ Long temp = (Long)replyHeaders.getHeader(HeaderSet.LENGTH);
+
+ if (temp == null) {
+ return -1;
+ } else {
+ return temp.longValue();
+ }
+ } catch (IOException e) {
+ return -1;
+ }
+ }
+
+ /**
+ * Open and return an input stream for a connection.
+ *
+ * @return an input stream
+ *
+ * @exception IOException if an I/O error occurs
+ */
+ public InputStream openInputStream() throws IOException {
+ // TODO: this mode is not set yet.
+ // if ((parent.mode & Connector.READ) == 0)
+ // throw new IOException("write-only connection");
+
+ ensureOpen();
+
+ if (inputStreamOpened)
+ throw new IOException("no more input streams available");
+ if (isGet) {
+ // send the GET request here
+ validateConnection();
+ isValidateConnected = true;
+ } else {
+ if (privateInput == null) {
+ privateInput = new PrivateInputStream(this);
+ }
+ }
+
+ inputStreamOpened = true;
+
+ return privateInput;
+ }
+
+ /**8
+ * Open and return a data input stream for a connection.
+ *
+ * @return an input stream
+ *
+ * @exception IOException if an I/O error occurs
+ */
+ public DataInputStream openDataInputStream() throws IOException {
+ return new DataInputStream(openInputStream());
+ }
+
+ /**
+ * Open and return an output stream for a connection.
+ *
+ * @return an output stream
+ *
+ * @exception IOException if an I/O error occurs
+ */
+ public OutputStream openOutputStream() throws IOException {
+ // TODO: this mode is not set yet.
+ // if ((parent.mode & Connector.WRITE) == 0)
+ // throw new IOException("read-only connection");
+ ensureOpen();
+ ensureNotDone();
+
+ if (outputStreamOpened)
+ throw new IOException("no more output streams available");
+
+ if (privateOutput == null) {
+ // there are 3 bytes operation headers and 3 bytes body headers //
+ privateOutput = new PrivateOutputStream(this, maxPacketSize - 6);
+ }
+
+ outputStreamOpened = true;
+
+ return privateOutput;
+ }
+
+ public int getMaxPacketSize() {
+ return maxPacketSize - 6;
+ }
+
+ /**
+ * Open and return a data output stream for a connection.
+ *
+ * @return an output stream
+ *
+ * @exception IOException if an I/O error occurs
+ */
+ public DataOutputStream openDataOutputStream() throws IOException {
+ return new DataOutputStream(openOutputStream());
+ }
+
+ /**
+ * Closes the connection and ends the transaction
+ *
+ * @exception IOException if the operation has already ended or is closed
+ */
+ public void close() throws IOException {
+ isClosed = true;
+ inputStreamOpened = false;
+ outputStreamOpened = false;
+ parent.setInactive();
+ }
+
+ /**
+ * Returns the headers that have been received during the operation.
+ * Modifying the object returned has no effect on the headers that are
+ * sent or retrieved.
+ *
+ * @return the headers received during this <code>Operation</code>
+ *
+ * @exception IOException if this <code>Operation</code> has been closed
+ */
+ public HeaderSet getReceivedHeaders() throws IOException {
+ ensureOpen();
+
+ return replyHeaders;
+ }
+
+ /**
+ * Specifies the headers that should be sent in the next OBEX message that
+ * is sent.
+ *
+ * @param headers the headers to send in the next message
+ *
+ * @exception IOException if this <code>Operation</code> has been closed
+ * or the transaction has ended and no further messages will be exchanged
+ *
+ * @exception IllegalArgumentException if <code>headers</code> was not created
+ * by a call to <code>ServerRequestHandler.createHeaderSet()</code>
+ *
+ * @exception NullPointerException if <code>headers</code> is <code>null</code>
+ */
+ public void sendHeaders(HeaderSet headers) throws IOException {
+ ensureOpen();
+ if (isDone) {
+ throw new IOException("Operation has already exchanged all data");
+ }
+
+ if (headers == null) {
+ throw new NullPointerException("Headers may not be null");
+ }
+
+ int[] headerList = headers.getHeaderList();
+ if (headerList != null) {
+ for (int i = 0; i < headerList.length; i++) {
+ requestHeaders.setHeader(headerList[i], headers.getHeader(headerList[i]));
+ }
+ }
+ }
+
+ /**
+ * Reads a response from the server. It will populate the appropriate body
+ * and headers.
+ *
+ * @return <code>true</code> if the transaction should end;
+ * <code>false</code> if the transaction should not end
+ *
+ * @exception IOException if an IO error occurred
+ */
+ private boolean readResponse() throws IOException {
+ replyHeaders.responseCode = socketInput.read();
+ int packetLength = socketInput.read();
+ packetLength = (packetLength << 8) + socketInput.read();
+
+ if (packetLength > OBEXConstants.MAX_PACKET_SIZE_INT) {
+ if (exceptionMessage != null) {
+ abort();
+ }
+ throw new IOException("Received a packet that was too big");
+ }
+
+ if (packetLength > BASE_PACKET_LENGTH) {
+ int dataLength = packetLength - BASE_PACKET_LENGTH;
+ byte[] data = new byte[dataLength];
+ int readLength = socketInput.read(data);
+ if (readLength != dataLength) {
+ throw new IOException("Received a packet without data as decalred length");
+ }
+ byte[] body = OBEXHelper.updateHeaderSet(replyHeaders, data);
+
+ if (body != null) {
+ privateInput.writeBytes(body, 1);
+
+ /*
+ * Determine if a body (0x48) header or an end of body (0x49)
+ * was received. If we received an end of body and
+ * a response code of OBEX_HTTP_OK, then the operation should
+ * end.
+ */
+ if ((body[0] == 0x49) && (replyHeaders.responseCode == ResponseCodes.OBEX_HTTP_OK)) {
+ return false;
+ }
+ }
+ }
+
+ if (replyHeaders.responseCode == OBEXConstants.OBEX_HTTP_CONTINUE) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Verifies that additional information may be sent. In other words, the
+ * operation is not done.
+ *
+ * @exception IOException if the operation is completed
+ */
+ public void ensureNotDone() throws IOException {
+ if (isDone) {
+ throw new IOException("Operation has completed");
+ }
+ }
+
+ /**
+ * Verifies that the connection is open and no exceptions should be thrown.
+ *
+ * @exception IOException if an exception needs to be thrown
+ */
+ public void ensureOpen() throws IOException {
+ parent.ensureOpen();
+
+ if (exceptionMessage != null) {
+ throw new IOException(exceptionMessage);
+ }
+ if (isClosed) {
+ throw new IOException("Operation has already ended");
+ }
+ }
+
+ /**
+ * Verifies that the connection is open and the proper data has been read.
+ *
+ * @exception IOException if an IO error occurs
+ */
+ private void validateConnection() throws IOException {
+ ensureOpen();
+
+ // to sure only one privateInput object exist.
+ if (privateInput == null) {
+ startProcessing();
+ }
+ }
+
+ /**
+ * Sends a request to the client of the specified type
+ *
+ * @param response the response code to send back to the client
+ *
+ * @return <code>true</code> if there is more data to send;
+ * <code>false</code> if there is no more data to send
+ *
+ * @exception IOException if an IO error occurs
+ */
+ protected boolean sendRequest(int type) throws IOException {
+ boolean returnValue = false;
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ int bodyLength = -1;
+ byte[] headerArray = OBEXHelper.createHeader(requestHeaders, true);
+ if (privateOutput != null) {
+ bodyLength = privateOutput.size();
+ }
+
+ /*
+ * Determine if there is space to add a body request. At present
+ * this method checks to see if there is room for at least a 17
+ * byte body header. This number needs to be at least 6 so that
+ * there is room for the header ID and length and the reply ID and
+ * length, but it is a waste of resources if we can't send much of
+ * the body.
+ */
+ if ((BASE_PACKET_LENGTH + headerArray.length) > maxPacketSize) {
+ int end = 0;
+ int start = 0;
+ // split & send the headerArray in multiple packets.
+
+ while (end != headerArray.length) {
+ //split the headerArray
+ end = OBEXHelper.findHeaderEnd(headerArray, start, maxPacketSize
+ - BASE_PACKET_LENGTH);
+ // can not split
+ if (end == -1) {
+ isDone = true;
+ abort();
+ // isDone = true;
+ exceptionMessage = "Header larger then can be sent in a packet";
+ isClosed = true;
+
+ if (privateInput != null) {
+ privateInput.close();
+ }
+
+ if (privateOutput != null) {
+ privateOutput.close();
+ }
+ throw new IOException("OBEX Packet exceeds max packet size");
+ }
+
+ byte[] sendHeader = new byte[end - start];
+ System.arraycopy(headerArray, start, sendHeader, 0, sendHeader.length);
+ if (!parent.sendRequest(type, sendHeader, replyHeaders, privateInput)) {
+ return false;
+ }
+
+ if (replyHeaders.responseCode != OBEXConstants.OBEX_HTTP_CONTINUE) {
+ return false;
+ }
+
+ start = end;
+ }
+
+ if (bodyLength > 0) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ out.write(headerArray);
+ }
+
+ if (bodyLength > 0) {
+ /*
+ * Determine if I can send the whole body or just part of
+ * the body. Remember that there is the 3 bytes for the
+ * response message and 3 bytes for the header ID and length
+ */
+ if (bodyLength > (maxPacketSize - headerArray.length - 6)) {
+ returnValue = true;
+
+ bodyLength = maxPacketSize - headerArray.length - 6;
+ }
+
+ byte[] body = privateOutput.readBytes(bodyLength);
+
+ /*
+ * Since this is a put request if the final bit is set or
+ * the output stream is closed we need to send the 0x49
+ * (End of Body) otherwise, we need to send 0x48 (Body)
+ */
+ if ((privateOutput.isClosed()) && (!returnValue) && (!isEndOfBodySent)
+ && ((type & 0x80) != 0)) {
+ out.write(0x49);
+ isEndOfBodySent = true;
+ } else {
+ out.write(0x48);
+ }
+
+ bodyLength += 3;
+ out.write((byte)(bodyLength >> 8));
+ out.write((byte)bodyLength);
+
+ if (body != null) {
+ out.write(body);
+ }
+ }
+
+ if (outputStreamOpened && bodyLength <= 0 && !isEndOfBodySent) {
+ // only 0x82 or 0x83 can send 0x49
+ if ((type & 0x80) == 0) {
+ out.write(0x48);
+ } else {
+ out.write(0x49);
+ isEndOfBodySent = true;
+
+ }
+
+ bodyLength = 3;
+ out.write((byte)(bodyLength >> 8));
+ out.write((byte)bodyLength);
+ }
+
+ if (out.size() == 0) {
+ if (!parent.sendRequest(type, null, replyHeaders, privateInput)) {
+ return false;
+ }
+ return returnValue;
+ }
+ if ((out.size() > 0)
+ && (!parent.sendRequest(type, out.toByteArray(), replyHeaders, privateInput))) {
+ return false;
+ }
+
+ // send all of the output data in 0x48,
+ // send 0x49 with empty body
+ if ((privateOutput != null) && (privateOutput.size() > 0))
+ returnValue = true;
+
+ return returnValue;
+ }
+
+ /**
+ * This method starts the processing thread results. It will send the
+ * initial request. If the response takes more then one packet, a thread
+ * will be started to handle additional requests
+ *
+ * @exception IOException if an IO error occurs
+ */
+ private synchronized void startProcessing() throws IOException {
+
+ if (privateInput == null) {
+ privateInput = new PrivateInputStream(this);
+ }
+ boolean more = true;
+
+ if (isGet) {
+ if (!isDone) {
+ replyHeaders.responseCode = OBEXConstants.OBEX_HTTP_CONTINUE;
+ while ((more) && (replyHeaders.responseCode == OBEXConstants.OBEX_HTTP_CONTINUE)) {
+ more = sendRequest(0x03);
+ }
+
+ if (replyHeaders.responseCode == OBEXConstants.OBEX_HTTP_CONTINUE) {
+ parent.sendRequest(0x83, null, replyHeaders, privateInput);
+ }
+ if (replyHeaders.responseCode != OBEXConstants.OBEX_HTTP_CONTINUE) {
+ isDone = true;
+ }
+ }
+ } else {
+
+ if (!isDone) {
+ replyHeaders.responseCode = OBEXConstants.OBEX_HTTP_CONTINUE;
+ while ((more) && (replyHeaders.responseCode == OBEXConstants.OBEX_HTTP_CONTINUE)) {
+ more = sendRequest(0x02);
+
+ }
+ }
+
+ if (replyHeaders.responseCode == OBEXConstants.OBEX_HTTP_CONTINUE) {
+ parent.sendRequest(0x82, null, replyHeaders, privateInput);
+ }
+
+ if (replyHeaders.responseCode != OBEXConstants.OBEX_HTTP_CONTINUE) {
+ isDone = true;
+ }
+ }
+ }
+
+ /**
+ * Continues the operation since there is no data to read.
+ *
+ * @param sendEmpty <code>true</code> if the operation should send an
+ * empty packet or not send anything if there is no data to send
+ * @param inStream <code>true</code> if the stream is input stream or
+ * is output stream
+ * @exception IOException if an IO error occurs
+ */
+ public synchronized boolean continueOperation(boolean sendEmpty, boolean inStream)
+ throws IOException {
+
+ if (isGet) {
+ if ((inStream) && (!isDone)) {
+ // to deal with inputstream in get operation
+ parent.sendRequest(0x83, null, replyHeaders, privateInput);
+ /*
+ * Determine if that was not the last packet in the operation
+ */
+ if (replyHeaders.responseCode != OBEXConstants.OBEX_HTTP_CONTINUE) {
+ isDone = true;
+ }
+
+ return true;
+
+ } else if ((!inStream) && (!isDone)) {
+ // to deal with outputstream in get operation
+
+ if (privateInput == null) {
+ privateInput = new PrivateInputStream(this);
+ }
+ sendRequest(0x03);
+ return true;
+
+ } else if (isDone) {
+ return false;
+ }
+
+ } else {
+ if ((!inStream) && (!isDone)) {
+ // to deal with outputstream in put operation
+ if (replyHeaders.responseCode == -1) {
+ replyHeaders.responseCode = OBEXConstants.OBEX_HTTP_CONTINUE;
+ }
+ sendRequest(0x02);
+ return true;
+ } else if ((inStream) && (!isDone)) {
+ // How to deal with inputstream in put operation ?
+ return false;
+
+ } else if (isDone) {
+ return false;
+ }
+
+ }
+ return false;
+ }
+
+ /**
+ * Called when the output or input stream is closed.
+ *
+ * @param inStream <code>true</code> if the input stream is closed;
+ * <code>false</code> if the output stream is closed
+ *
+ * @exception IOException if an IO error occurs
+ */
+ public void streamClosed(boolean inStream) throws IOException {
+ if (!isGet) {
+ if ((!inStream) && (!isDone)) {
+ // to deal with outputstream in put operation
+
+ boolean more = true;
+
+ if ((privateOutput != null) && (privateOutput.size() <= 0)) {
+ byte[] headerArray = OBEXHelper.createHeader(requestHeaders, false);
+ if (headerArray.length <= 0)
+ more = false;
+ }
+ // If have not sent any data so send all now
+ if (replyHeaders.responseCode == -1) {
+ replyHeaders.responseCode = OBEXConstants.OBEX_HTTP_CONTINUE;
+ }
+
+ while ((more) && (replyHeaders.responseCode == OBEXConstants.OBEX_HTTP_CONTINUE)) {
+ more = sendRequest(0x02);
+ }
+
+ /*
+ * According to the IrOBEX specification, after the final put, you
+ * only have a single reply to send. so we don't need the while
+ * loop.
+ */
+ while (replyHeaders.responseCode == OBEXConstants.OBEX_HTTP_CONTINUE) {
+
+ sendRequest(0x82);
+ }
+ isDone = true;
+ } else if ((inStream) && (isDone)) {
+ // how to deal with input stream in put stream ?
+ isDone = true;
+ }
+ } else {
+ isValidateConnected = false;
+ if ((inStream) && (!isDone)) {
+
+ // to deal with inputstream in get operation
+ // Have not sent any data so send it all now
+
+ if (replyHeaders.responseCode == -1) {
+ replyHeaders.responseCode = OBEXConstants.OBEX_HTTP_CONTINUE;
+ }
+
+ while (replyHeaders.responseCode == OBEXConstants.OBEX_HTTP_CONTINUE) {
+ if (!sendRequest(0x83)) {
+ break;
+ }
+ }
+ while (replyHeaders.responseCode == OBEXConstants.OBEX_HTTP_CONTINUE) {
+ parent.sendRequest(0x83, null, replyHeaders, privateInput);
+ }
+ isDone = true;
+ } else if ((!inStream) && (!isDone)) {
+ // to deal with outputstream in get operation
+ // part of the data may have been sent in continueOperation.
+
+ boolean more = true;
+
+ if ((privateOutput != null) && (privateOutput.size() <= 0)) {
+ byte[] headerArray = OBEXHelper.createHeader(requestHeaders, false);
+ if (headerArray.length <= 0)
+ more = false;
+ }
+
+ if (privateInput == null) {
+ privateInput = new PrivateInputStream(this);
+ }
+ if ((privateOutput != null) && (privateOutput.size() <= 0))
+ more = false;
+
+ replyHeaders.responseCode = OBEXConstants.OBEX_HTTP_CONTINUE;
+ while ((more) && (replyHeaders.responseCode == OBEXConstants.OBEX_HTTP_CONTINUE)) {
+ more = sendRequest(0x03);
+ }
+ sendRequest(0x83);
+ // parent.sendRequest(0x83, null, replyHeaders, privateInput);
+ if (replyHeaders.responseCode != OBEXConstants.OBEX_HTTP_CONTINUE) {
+ isDone = true;
+ }
+
+ }
+ }
+ }
+}