ServerForm.java
/*
* Copyright © 2011 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.btsppecho;
import java.util.Vector;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.ServiceRecord;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;
import com.nokia.example.btsppecho.server.ServerConnectionHandler;
import com.nokia.example.btsppecho.server.ServerConnectionHandlerListener;
class ServerForm
extends Form
implements ServerConnectionHandlerListener, CommandListener {
private final MIDletApplication midlet;
private final StringItem numConnectionsField;
private final TextField sendDataField;
private final StringItem receivedDataField;
private final StringItem statusField;
private final Command sendCommand;
private final Command addConnectionCommand;
private final Command searchCommand;
private final Command logCommand;
private final Command quitCommand;
private final Command clearStatusCommand;
private final Vector handlers;
private int maxConnections;
private StringItem btAddressField = null;
private volatile int numReceivedMessages = 0;
private volatile int numSentMessages = 0;
private int sendMessageId = 0;
ServerForm(MIDletApplication midlet) {
super("Server");
this.midlet = midlet;
handlers = new Vector();
String value =
LocalDevice.getProperty(
"bluetooth.connected.devices.max");
try {
maxConnections = Integer.parseInt(value);
} catch (NumberFormatException e) {
maxConnections = 0;
}
// 1. add Form items
try {
String address = LocalDevice.getLocalDevice().getBluetoothAddress();
btAddressField = new StringItem("My address", address);
append(btAddressField);
} catch (BluetoothStateException e) {
// nothing we can do, don't add field
}
numConnectionsField = new StringItem("Connections", "0");
append(numConnectionsField);
statusField = new StringItem("Status", "");
append(statusField);
sendDataField = new TextField("Send data",
"Server says: 'Hello, world.'",
64,
TextField.ANY);
append(sendDataField);
receivedDataField = new StringItem("Last received data",
null);
append(receivedDataField);
// 2. create commands
sendCommand = new Command("Send", Command.SCREEN, 1);
searchCommand = new Command("Search for more",
Command.SCREEN,
1);
addConnectionCommand = new Command("Add connection",
Command.SCREEN,
2);
logCommand = new Command("View log", Command.SCREEN, 3);
clearStatusCommand = new Command("Clear status", Command.SCREEN, 4);
quitCommand = new Command("Quit", Command.EXIT, 1);
// 3. add commands and set command listener
addCommand(searchCommand);
addCommand(addConnectionCommand);
addCommand(logCommand);
addCommand(clearStatusCommand);
addCommand(quitCommand);
// The 'sendCommand' is added later to screen,
// if at least one connection is open.
setCommandListener(this);
}
public void makeConnections(Vector serviceRecords, int security) {
for (int i = 0; i < serviceRecords.size(); i++) {
ServiceRecord serviceRecord =
(ServiceRecord) serviceRecords.elementAt(i);
boolean found = false;
for (int j = 0; j < handlers.size(); j++) {
ServerConnectionHandler old =
(ServerConnectionHandler) handlers.elementAt(j);
String oldAddr = old.getServiceRecord().
getHostDevice().
getBluetoothAddress();
String newAddr =
serviceRecord.getHostDevice().getBluetoothAddress();
if (oldAddr.equals(newAddr)) {
found = true;
break;
}
}
if (!found) {
ServerConnectionHandler newHandler =
new ServerConnectionHandler(
this,
serviceRecord,
security);
newHandler.start(); // start reader & writer
}
}
}
private void removeHandler(ServerConnectionHandler handler) {
if (handlers.contains(handler)) {
handlers.removeElement(handler);
String str = Integer.toString(handlers.size());
numConnectionsField.setText(str);
if (handlers.size() == 0) {
removeCommand(sendCommand);
addCommand(searchCommand);
}
}
}
void closeAll() {
for (int i = 0; i < handlers.size(); i++) {
ServerConnectionHandler handler =
(ServerConnectionHandler) handlers.elementAt(i);
handler.close();
removeHandler(handler);
}
}
public void commandAction(Command cmd, Displayable disp) {
if (cmd == addConnectionCommand) {
Vector v = new Vector();
for (int i = 0; i < handlers.size(); i++) {
ServerConnectionHandler handler =
(ServerConnectionHandler) handlers.elementAt(i);
String btAddress = handler.getServiceRecord().getHostDevice().getBluetoothAddress();
v.addElement(btAddress);
}
midlet.serverFormAddConnection(v);
} else if (cmd == clearStatusCommand) {
statusField.setText("");
} else if (cmd == logCommand) {
midlet.serverFormViewLog();
} else if (cmd == sendCommand) {
String sendData = sendDataField.getString();
Integer id = new Integer(sendMessageId++);
for (int i = 0; i < handlers.size(); i++) {
ServerConnectionHandler handler =
(ServerConnectionHandler) handlers.elementAt(i);
try {
handler.queueMessageForSending(
id,
sendData.getBytes());
statusField.setText(
"Queued a send message request");
} catch (IllegalArgumentException e) {
// Message length longer than
// ServerConnectionHandler.MAX_MESSAGE_LENGTH
String errorMessage =
"IllegalArgumentException while trying "
+ "to send a message: " + e.getMessage();
handleError(handler, errorMessage);
}
}
} else if (cmd == searchCommand) {
midlet.serverFormSearchRequest(handlers.size());
} else if (cmd == quitCommand) {
closeAll();
midlet.serverFormExitRequest();
}
// To keep this MIDlet simple, I didn't add any way
// to drop individual connections. But you might
// want to do so.
}
// ServerConnectionHandlerListener interface methods
public void handleOpen(ServerConnectionHandler handler) {
handlers.addElement(handler);
// for the first open connection
if (handlers.size() == 1) {
removeCommand(searchCommand);
removeCommand(sendCommand);
addCommand(sendCommand);
}
// Remove the 'Add connection' command
// when the device already has open the
// maximum number of connections it can
// support.
if (handlers.size() >= maxConnections) {
removeCommand(addConnectionCommand);
}
statusField.setText("Connection opened");
String str = Integer.toString(handlers.size());
numConnectionsField.setText(str);
}
public void handleOpenError(
ServerConnectionHandler handler,
String errorMessage) {
statusField.setText("Error opening outbound connection: "
+ errorMessage);
}
public void handleReceivedMessage(
ServerConnectionHandler handler,
byte[] messageBytes) {
numReceivedMessages++;
String message = new String(messageBytes);
receivedDataField.setText(message);
statusField.setText(
"# messages read: " + numReceivedMessages + " "
+ "sent: " + numSentMessages);
// Broadcast message to all clients
for (int i = 0; i < handlers.size(); i++) {
ServerConnectionHandler h =
(ServerConnectionHandler) handlers.elementAt(i);
Integer id = new Integer(sendMessageId++);
try {
h.queueMessageForSending(id, messageBytes);
} catch (IllegalArgumentException e) {
String errorMessage =
"IllegalArgumentException while trying to "
+ "send message: " + e.getMessage();
handleError(handler, errorMessage);
}
}
}
public void handleQueuedMessageWasSent(
ServerConnectionHandler handler,
Integer id) {
numSentMessages++;
statusField.setText("# messages read: "
+ numReceivedMessages + " "
+ "sent: " + numSentMessages);
}
public void handleClose(ServerConnectionHandler handler) {
removeHandler(handler);
if (handlers.size() == 0) {
removeCommand(sendCommand);
addCommand(searchCommand);
}
// If the number of currently open connections
// drops below the maximum number that this
// device could have open, restore
// 'Add connection' to the screen commands.
if (handlers.size() < maxConnections) {
removeCommand(addConnectionCommand);
addCommand(addConnectionCommand);
}
statusField.setText("Connection closed");
}
public void handleErrorClose(ServerConnectionHandler handler,
String errorMessage) {
removeHandler(handler);
if (handlers.size() == 0) {
removeCommand(sendCommand);
addCommand(searchCommand);
}
statusField.setText("Error (close): '" + errorMessage + "'");
}
public void handleError(ServerConnectionHandler handler,
String errorMessage) {
statusField.setText("Error: '" + errorMessage + "'");
}
}