![JAR search and dependency download from the Maven repository](/logo.png)
com.intel.bluetooth.obex.OBEXClientOperation Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bluecove Show documentation
Show all versions of bluecove Show documentation
BlueCove is JSR-82 J2SE implementation that currently interfaces with the Mac OS X, WIDCOMM, BlueSoleil and Microsoft Bluetooth stack
The newest version!
/**
* BlueCove - Java library for Bluetooth
* Copyright (C) 2007-2008 Vlad Skarzhevskyy
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @version $Id: OBEXClientOperation.java 2645 2008-12-23 08:05:38Z skarzhevskyy $
*/
package com.intel.bluetooth.obex;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.obex.HeaderSet;
import javax.obex.Operation;
import javax.obex.ResponseCodes;
import com.intel.bluetooth.DebugLog;
abstract class OBEXClientOperation implements Operation, OBEXOperation, OBEXOperationReceive, OBEXOperationDelivery {
/**
* This is not 100% by JSR-82 doc. But some know implementations of OBEX are working this way. This solves the
* problems for Samsung phones that are sending nothing in response to GET request without final bit.
*
* Basically instead of sending at least two packets 'initial' and 'final' we are sending just 'final' one when
* applicable.
*/
final static boolean SHORT_REQUEST_PHASE = true;
protected OBEXClientSessionImpl session;
protected char operationId;
protected HeaderSet replyHeaders;
protected boolean isClosed;
protected boolean operationInProgress;
protected boolean operationInContinue;
protected OBEXOperationOutputStream outputStream;
protected boolean outputStreamOpened = false;
protected OBEXOperationInputStream inputStream;
protected boolean inputStreamOpened = false;
protected boolean errorReceived = false;
protected boolean requestEnded = false;
protected boolean finalBodyReceived = false;
protected OBEXHeaderSetImpl startOperationHeaders = null;
private boolean authenticationResponseCreated = false;
protected Object lock;
OBEXClientOperation(OBEXClientSessionImpl session, char operationId, OBEXHeaderSetImpl sendHeaders)
throws IOException {
this.session = session;
this.operationId = operationId;
this.isClosed = false;
this.operationInProgress = false;
this.lock = new Object();
this.inputStream = new OBEXOperationInputStream(this);
startOperation(sendHeaders);
}
static boolean isShortRequestPhase() {
return SHORT_REQUEST_PHASE;
}
protected void startOperation(OBEXHeaderSetImpl sendHeaders) throws IOException {
if (SHORT_REQUEST_PHASE) {
this.startOperationHeaders = sendHeaders;
} else {
this.operationInProgress = true;
exchangePacket(sendHeaders);
}
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.obex.OBEXOperationReceive#receiveData(com.intel.bluetooth.obex.OBEXOperationInputStream)
*/
public void receiveData(OBEXOperationInputStream is) throws IOException {
if (SHORT_REQUEST_PHASE) {
exchangePacket(this.startOperationHeaders);
this.startOperationHeaders = null;
} else {
exchangePacket(null);
}
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.obex.OBEXOperationDelivery#deliverPacket(boolean, byte[])
*/
public void deliverPacket(boolean finalPacket, byte[] buffer) throws IOException {
if (requestEnded) {
return;
}
if (SHORT_REQUEST_PHASE && (this.startOperationHeaders != null)) {
exchangePacket(this.startOperationHeaders);
this.startOperationHeaders = null;
}
int dataHeaderID = OBEXHeaderSetImpl.OBEX_HDR_BODY;
if (finalPacket) {
this.operationId |= OBEXOperationCodes.FINAL_BIT;
dataHeaderID = OBEXHeaderSetImpl.OBEX_HDR_BODY_END;
DebugLog.debug("client Request Phase ended");
requestEnded = true;
}
OBEXHeaderSetImpl dataHeaders = OBEXSessionBase.createOBEXHeaderSetImpl();
dataHeaders.setHeader(dataHeaderID, buffer);
exchangePacket(dataHeaders);
}
protected void endRequestPhase() throws IOException {
if (requestEnded) {
return;
}
DebugLog.debug("client ends Request Phase");
this.operationInProgress = false;
this.requestEnded = true;
this.operationId |= OBEXOperationCodes.FINAL_BIT;
if (SHORT_REQUEST_PHASE) {
exchangePacket(this.startOperationHeaders);
this.startOperationHeaders = null;
} else {
exchangePacket(null);
}
}
private void exchangePacket(OBEXHeaderSetImpl headers) throws IOException {
boolean success = false;
try {
session.writePacket(this.operationId, headers);
byte[] b = session.readPacket();
OBEXHeaderSetImpl dataHeaders = OBEXHeaderSetImpl.readHeaders(b[0], b, 3);
session.handleAuthenticationResponse(dataHeaders, null);
int responseCode = dataHeaders.getResponseCode();
DebugLog.debug0x("client operation got reply", OBEXUtils.toStringObexResponseCodes(responseCode), responseCode);
switch (responseCode) {
case ResponseCodes.OBEX_HTTP_UNAUTHORIZED:
if ((!authenticationResponseCreated) && (dataHeaders.hasAuthenticationChallenge())) {
DebugLog.debug("client resend request with auth response");
// Send the original data again, since it is not accepted
OBEXHeaderSetImpl retryHeaders = OBEXHeaderSetImpl.cloneHeaders(headers);
session.handleAuthenticationChallenge(dataHeaders, retryHeaders);
authenticationResponseCreated = true;
exchangePacket(retryHeaders);
} else {
this.errorReceived = true;
this.operationInContinue = false;
processIncommingHeaders(dataHeaders);
throw new IOException("Authentication Failure");
}
break;
case OBEXOperationCodes.OBEX_RESPONSE_SUCCESS:
processIncommingHeaders(dataHeaders);
processIncommingData(dataHeaders, true);
this.operationInProgress = false;
this.operationInContinue = false;
break;
case OBEXOperationCodes.OBEX_RESPONSE_CONTINUE:
processIncommingHeaders(dataHeaders);
processIncommingData(dataHeaders, false);
this.operationInContinue = true;
// if ((!authenticationResponseCreated) && (dataHeaders.hasAuthenticationChallenge())) {
// // Send the original data again, since it is not accepted = This is bug On Sony Ericsson
// DebugLog.debug("client resend request with auth response");
// OBEXHeaderSetImpl retryHeaders = OBEXHeaderSetImpl.cloneHeaders(headers);
// session.handleAuthenticationChallenge(dataHeaders, retryHeaders);
// authenticationResponseCreated = true;
// exchangePacket(retryHeaders);
// }
break;
default:
this.errorReceived = true;
this.operationInContinue = false;
// responseCode may be reported by getResponseCode()
processIncommingHeaders(dataHeaders);
processIncommingData(dataHeaders, true);
// OFF; Rely on getResponseCode() to report the error to the application.
// if ((this.operationId & OBEXOperationCodes.FINAL_BIT) == 0) {
// throw new IOException("Operation error, 0x" + Integer.toHexString(responseCode) + " "
// + OBEXUtils.toStringObexResponseCodes(responseCode));
// }
}
success = true;
} finally {
if (!success) {
errorReceived = true;
}
}
}
protected void processIncommingHeaders(HeaderSet dataHeaders) throws IOException {
if (replyHeaders != null) {
// accumulate all received headers.
OBEXHeaderSetImpl.appendHeaders(dataHeaders, replyHeaders);
}
// replyHeaders will contain responseCode from last reply
// The Body values are removed by cloneHeaders in getReceivedHeaders()
this.replyHeaders = dataHeaders;
}
protected void processIncommingData(HeaderSet dataHeaders, boolean eof) throws IOException {
byte[] data = (byte[]) dataHeaders.getHeader(OBEXHeaderSetImpl.OBEX_HDR_BODY);
if (data == null) {
data = (byte[]) dataHeaders.getHeader(OBEXHeaderSetImpl.OBEX_HDR_BODY_END);
if (data != null) {
finalBodyReceived = true;
eof = true;
}
}
if (data != null) {
DebugLog.debug("client received Data eof: " + eof + " len: ", data.length);
inputStream.appendData(data, eof);
} else if (eof) {
inputStream.appendData(null, eof);
}
}
/*
* (non-Javadoc)
*
* @see javax.obex.Operation#abort()
*/
public void abort() throws IOException {
validateOperationIsOpen();
if ((!this.operationInProgress) && (!this.operationInContinue)) {
throw new IOException("the transaction has already ended");
}
synchronized (lock) {
if (outputStream != null) {
outputStream.abort();
}
this.inputStream.close();
}
writeAbort();
}
private void writeAbort() throws IOException {
try {
session.writePacket(OBEXOperationCodes.ABORT, null);
requestEnded = true;
byte[] b = session.readPacket();
HeaderSet dataHeaders = OBEXHeaderSetImpl.readHeaders(b[0], b, 3);
if (dataHeaders.getResponseCode() != OBEXOperationCodes.OBEX_RESPONSE_SUCCESS) {
throw new IOException("Fails to abort operation, received "
+ OBEXUtils.toStringObexResponseCodes(dataHeaders.getResponseCode()));
}
} finally {
this.isClosed = true;
closeStream();
}
}
private void closeStream() throws IOException {
try {
receiveOperationEnd();
} finally {
this.operationInProgress = false;
inputStream.close();
closeOutputStream();
}
}
private void receiveOperationEnd() throws IOException {
while (!isClosed() && (operationInContinue)) {
DebugLog.debug("operation expects operation end");
receiveData(this.inputStream);
}
}
private void closeOutputStream() throws IOException {
if (outputStream != null) {
synchronized (lock) {
if (outputStream != null) {
outputStream.close();
}
outputStream = null;
}
}
}
protected void validateOperationIsOpen() throws IOException {
if (isClosed) {
throw new IOException("operation closed");
}
}
/*
* (non-Javadoc)
*
* @see javax.obex.Operation#getReceivedHeaders()
*/
public HeaderSet getReceivedHeaders() throws IOException {
validateOperationIsOpen();
endRequestPhase();
return OBEXHeaderSetImpl.cloneHeaders(this.replyHeaders);
}
/*
* (non-Javadoc)
*
* @see javax.obex.Operation#getResponseCode()
*
* A call will do an implicit close on the Stream and therefore signal that the request is done.
*/
public int getResponseCode() throws IOException {
validateOperationIsOpen();
endRequestPhase();
closeOutputStream();
receiveOperationEnd();
return this.replyHeaders.getResponseCode();
}
public void sendHeaders(HeaderSet headers) throws IOException {
if (headers == null) {
throw new NullPointerException("headers are null");
}
OBEXHeaderSetImpl.validateCreatedHeaderSet(headers);
validateOperationIsOpen();
if (this.requestEnded) {
throw new IOException("the request phase has already ended");
}
if (SHORT_REQUEST_PHASE && (this.startOperationHeaders != null)) {
exchangePacket(this.startOperationHeaders);
this.startOperationHeaders = null;
}
exchangePacket((OBEXHeaderSetImpl) headers);
}
/*
* (non-Javadoc)
*
* @see javax.microedition.io.ContentConnection#getEncoding() getEncoding()
will always return
* null
*/
public String getEncoding() {
return null;
}
/*
* (non-Javadoc)
*
* @see javax.microedition.io.ContentConnection#getLength() getLength()
will return the length
* specified by the OBEX Length header or -1 if the OBEX Length header was not included.
*/
public long getLength() {
Long len;
try {
len = (Long) replyHeaders.getHeader(HeaderSet.LENGTH);
} catch (IOException e) {
return -1;
}
if (len == null) {
return -1;
}
return len.longValue();
}
/*
* (non-Javadoc)
*
* @see javax.microedition.io.ContentConnection#getType() getType()
will return the value specified in
* the OBEX Type header or null
if the OBEX Type header was not included.
*/
public String getType() {
try {
return (String) replyHeaders.getHeader(HeaderSet.TYPE);
} catch (IOException e) {
return null;
}
}
public DataInputStream openDataInputStream() throws IOException {
return new DataInputStream(openInputStream());
}
public DataOutputStream openDataOutputStream() throws IOException {
return new DataOutputStream(openOutputStream());
}
/*
* (non-Javadoc)
*
* @see javax.microedition.io.Connection#close()
*/
public void close() throws IOException {
try {
endRequestPhase();
} finally {
closeStream();
if (!this.isClosed) {
this.isClosed = true;
DebugLog.debug("client operation closed");
}
}
}
public boolean isClosed() {
return this.isClosed || this.errorReceived;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy