www.pudn.com > Bluegammon蓝牙的应用编程.rar > BackgammonBTConnection.java


// Copyright (c) 2005 Sony Ericsson Mobile Communications AB 
// 
// This software is provided "AS IS," without a warranty of any kind.  
// ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,  
// INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A  
// PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.  
// 
// THIS SOFTWARE IS COMPLEMENTARY OF JAYWAY AB (www.jayway.se) 
 
package bluegammon.io; 
 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
 
import javax.bluetooth.RemoteDevice; 
import javax.microedition.io.StreamConnection; 
 
/** 
 * Implementation of the interface BackgammonConnection for 
 * bluetooth bearer. 
 * @author Peter Andersson 
 */ 
public class BackgammonBTConnection implements BackgammonConnection 
{ 
  /** The service number of the game */ 
  protected static final String SERVICE_NBR = "1a88760401bac57a8806abc1ca900010"; 
  /** Bluetooth facade instance */ 
  protected static final BluetoothFacade BTFACADE = new BluetoothFacade(); 
 
  /** Flag indicating if server is actually awaiting a client */ 
  protected static boolean m_awaitingClient = false; 
  /** Flag indicating if server denies connection once it gets a client */ 
  protected static boolean m_fakeServerClosed = false; 
  /** Global server/client connection closed flag */ 
  protected static boolean m_closed = false; 
  /** The server/client StreamConnection */ 
  protected volatile static StreamConnection m_connection; 
  /** The server/client input stream */ 
  protected volatile static DataInputStream m_input; 
  /** The server/client output stream */ 
  protected volatile static DataOutputStream m_output; 
   
  /** 
   * 

* Waits for a client, the method blocks until client arrives * or IOException is thrown. The BT server cannot be interrupted - * call pretendServerClose to emulate this. Any client * that connects after a call to pretendServerClose will * immediately be shutdown. *

* Disable this state by calling waitForClient again, which * will make the client accepted when it connects. Any call to * waitForClient during an already active client wait will * just set flags and return directly, as there must be another thread still * waiting a client generated by the first call to waitForClient. *

*/ public void waitForClient() throws IOException { synchronized(this) { if (m_awaitingClient && m_fakeServerClosed) { // Some other thread is still awaiting client, // just set flags and return from this call m_fakeServerClosed = false; return; } m_awaitingClient = true; m_fakeServerClosed = false; } try { // Start listening for client m_closed = false; m_connection = BTFACADE.waitForClient(SERVICE_NBR); m_input = m_connection.openDataInputStream(); m_output = m_connection.openDataOutputStream(); } catch (IOException ioe) { synchronized(this) { if (!m_closed && !m_fakeServerClosed) { // Not interested in exception if we're closed throw ioe; } } } finally { synchronized(this) { m_awaitingClient = false; // Close connections if some thread closed while we // were waiting for client if (m_fakeServerClosed) { close(); } } } } public boolean connectClient(Object remote) throws IOException { synchronized(this) { m_closed = false; } boolean res = false; try { m_connection = BTFACADE.connect(SERVICE_NBR, (RemoteDevice) remote); if (m_connection != null) { m_input = m_connection.openDataInputStream(); m_output = m_connection.openDataOutputStream(); res = true; } } catch (IOException ioe) { synchronized(this) { if (!m_closed) { // Not interested in exception if we're closed throw ioe; } } } finally { synchronized(this) { if (m_closed) { close(); } } } return res; } public StreamConnection getConnection() throws IOException { return m_connection; } public DataInputStream getInput() { return m_input; } public DataOutputStream getOutput() { return m_output; } /** * The BT server cannot be interrupted, so lets just * pretend we close the server. If the server gets a client while * in pretended closed mode, or when it time out, * we close connections for real. */ public synchronized void pretendServerClose() { m_fakeServerClosed = true; } public synchronized boolean isAwaitingClient() { return m_awaitingClient; } public synchronized void close() throws IOException { IOException ioe = null; m_closed = true; // Close connection if (m_connection != null) { try { m_connection.close(); m_connection = null; } catch (IOException e) { ioe = e; } } // Close input stream if (m_input != null) { try { m_input.close(); m_input = null; } catch (IOException e) { ioe = e; } } // Close output stream if (m_output != null) { try { m_output.close(); m_output = null; } catch (IOException e) { ioe = e; } } // Close server try { BTFACADE.closeServer(SERVICE_NBR); m_awaitingClient = false; } catch (IOException e) { ioe = e; } // Throw exception if we got any if (ioe != null) { throw ioe; } } public synchronized boolean isClosed() { return m_closed || m_fakeServerClosed; } }