/* * Copyright © 2013 Nokia Corporation. All rights reserved. * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation. * Oracle and Java are trademarks or registered trademarks of Oracle and/or its * affiliates. Other product and company names mentioned herein may be trademarks * or trade names of their respective owners. * See LICENSE.TXT for license information. */ package com.nokia.example.bcexchanger.comm; import java.io.IOException; import javax.bluetooth.DiscoveryAgent; import javax.bluetooth.LocalDevice; import javax.microedition.io.Connection; import javax.microedition.io.Connector; import javax.obex.HeaderSet; import javax.obex.Operation; import javax.obex.ServerRequestHandler; import javax.obex.SessionNotifier; /** * * This class is the central class in the OBEX communication module * (package bcexchanger.comm). * * Class implements interface ExchangerComm and realizes the methods * for controlling process of sending and receiving business cards. It * also is a parent for states of the BCExchanger communication state * machine. It keeps the current state of the state machine and * implements interface ExchangerStateParent. Using this interface * state classes access to the required functionality of the parent. * * This class waits for Bluetooth incoming connection in the separate * thread and therefore it implements Runnable interface. * * This class also works as a OBEX server. In order to serve OBEX * requests it extends the ServerRequestHandler class and overrides * some of its methods. * * @see bcexchanger.comm.ExchangerStateParent * bcexchanger.comm.ExchangerComm javax.obex.ServerRequestHandler * Design patterns: State * */ public class ExchangerCommImpl extends ServerRequestHandler implements ExchangerStateParent, ExchangerComm, Runnable { // Instance variables final private String uuid = "ed495afe28ed11da94d900e08161165f"; final private String serverURL = "btgoep://localhost:" + uuid; private boolean cancelWaitingInvoked = false; // becomes true if // cancelWaiting() is // called private Thread waitingThread; private ExchangeListener listener; private ExchangerState currentState; private SessionNotifier notifier = null; private Connection con = null; /** * Constructor * <p> * description * * @param _listener - * listener of the communication module events * @exception * @see */ public ExchangerCommImpl(ExchangeListener _listener) { listener = _listener; startWaiting(); setState(new IdleState(this)); } public void setState(ExchangerState state) { currentState = state; } public ExchangeListener getListener() { return listener; } public ExchangerState getState() { return currentState; } public void startSending(int oper) throws Exception { getState().startSending(oper); } public void startSending() throws Exception { getState().startSending(0); } public void cancelSending() { getState().cancelSending(); } public void startWaiting() { cancelWaitingInvoked = false; waitingThread = new Thread(this); waitingThread.start(); } public void cancelWaiting() { cancelWaitingInvoked = true; if (notifier != null) { try { notifier.close(); // indicate to acceptAndOpen that it is // canceled } catch (IOException e) { // Ignore, we're closing anyways } } } public synchronized void run() { // initialize stack and make the device discoverable try { LocalDevice local = LocalDevice.getLocalDevice(); local.setDiscoverable(DiscoveryAgent.GIAC); } catch (Exception e) { // catching notifier exception listener.onServerError(ExchangeListener.ERROR_BUETOOTH_OFF); return; } try { notifier = (SessionNotifier) Connector.open(serverURL); } catch (SecurityException e) { listener.onSecurityError(); return; } catch (IOException e) { listener.onServerError(ExchangeListener.ERROR_SERVER_IOEXCEPTION); } // the cycle stops only if cancelWaiting() was called while (!cancelWaitingInvoked) { try { con = notifier.acceptAndOpen(this); wait(); // wait until the remote peer disconnects try { con.close(); } catch (IOException e) { } } catch (Exception e) { listener.onServerError(ExchangeListener.ERROR_SERVER_IOEXCEPTION); return; } } } /* * This method is related to OBEX server functionality. This method * is delegating this execution to the current state * * @see javax.obex.ServerRequestHandler#onGet() */ public int onGet(Operation op) { return getState().onGet(op); } /* * This method is related to OBEX server functionality. This method * is delegating this execution to the current state * * @see javax.obex.ServerRequestHandler#onPut() */ public int onPut(Operation op) { return getState().onPut(op); } /* * This method is related to OBEX server functionality. This method * handles OBEX DISCONNECT command from the remote device. * * @see javax.obex.ServerRequestHandler#onDisconnect() */ public synchronized void onDisconnect(HeaderSet request, HeaderSet reply) { super.onDisconnect(request, reply); notify();// stops waiting in run() } public String getUUID() { return uuid; } }