/**
* BlueCove - Java library for Bluetooth
* Copyright (C) 2006-2009 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.
*
* @author vlads
* @version $Id$
*/
package net.sf.bluecove;
import java.util.Enumeration;
import java.util.Random;
import java.util.Vector;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
import org.bluecove.tester.log.Logger;
import org.bluecove.tester.util.RuntimeDetect;
import net.sf.bluecove.util.BluetoothTypesInfo;
import net.sf.bluecove.util.CollectionUtils;
public class Switcher implements Runnable {
public static TestResponderClient client;
private static Vector runningClients = new Vector();
public static TestResponderServer server;
private static Vector runningServers = new Vector();
public static int clientStartCount = 0;
public static int serverStartCount = 0;
private boolean stoped = false;
public Thread thread;
boolean isRunning = false;
private static Switcher instance;
Random random = new Random();
static Thread tckRFCOMMThread;
static Thread tckL2CALthread;
static Thread tckGOEPThread;
static Thread tckOBEXThread;
public Switcher() {
instance = this;
}
public static synchronized void clear() {
clientStartCount = 0;
serverStartCount = 0;
}
public static void yield(TestResponderClient client) {
if (instance != null) {
clientShutdown();
synchronized (instance) {
instance.notifyAll();
}
}
}
public static void yield(TestResponderServer server) {
if (instance != null) {
while (server.hasRunningConnections()) {
try {
Thread.sleep(2000);
} catch (Exception e) {
break;
}
}
serverShutdown();
}
}
public static boolean isRunning() {
return (instance != null) && instance.isRunning;
}
public static boolean isRunningClient() {
return ((client != null) && client.isRunning) || (!runningClients.isEmpty());
}
public static boolean isRunningServer() {
return isTCKRunning() || ((server != null) && server.isRunning());
}
public static boolean isRunningServerClients() {
return ((server != null) && (server.countClientConnections() > 0));
}
public void run() {
Logger.debug("Switcher started...");
isRunning = true;
try {
if (!isRunningClient()) {
startClient();
}
while (!stoped) {
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
break;
}
}
if (stoped) {
break;
}
try {
Thread.sleep(2000);
} catch (Exception e) {
break;
}
if (stoped) {
break;
}
startServer();
if (stoped) {
break;
}
try {
int sec = randomTTL(30, Configuration.serverMAXTimeSec);
Logger.info("switch to client in " + sec + " sec");
Thread.sleep(sec * 1000);
} catch (Exception e) {
break;
}
yield(server);
if (stoped) {
break;
}
try {
Thread.sleep(2000);
} catch (Exception e) {
break;
}
if (stoped) {
break;
}
startClient();
}
} finally {
isRunning = false;
Logger.info("Switcher finished!");
}
}
public int randomTTL(int min, int max) {
int d = random.nextInt() % (max - min);
if (d < 0) {
d = -d;
}
return min + d;
}
public void shutdown() {
Logger.info("shutdownSwitcher");
stoped = true;
interruptThread(thread);
synchronized (this) {
notifyAll();
}
instance = null;
}
public static void clientStarted(CanShutdown t) {
runningClients.addElement(t);
}
public static void clientEnds(CanShutdown t) {
runningClients.removeElement(t);
}
public static void interruptThread(Thread thread) {
if (RuntimeDetect.cldcStub != null) {
RuntimeDetect.cldcStub.interruptThread(thread);
}
}
public static Thread createThreadByName(String className) {
try {
Class c = Class.forName(className);
return (Thread) c.newInstance();
} catch (Throwable e) {
Logger.debug(className, e);
return null;
}
}
public static void startTCKAgent() {
try {
LocalDevice localDevice = LocalDevice.getLocalDevice();
Logger.info("address:" + localDevice.getBluetoothAddress());
Logger.info("name:" + localDevice.getFriendlyName());
Logger.info("class:" + BluetoothTypesInfo.toString(localDevice.getDeviceClass()));
localDevice.setDiscoverable(DiscoveryAgent.GIAC);
} catch (BluetoothStateException e) {
Logger.error("start", e);
return;
}
if (Configuration.likedTCKAgent) {
try {
SwitcherTck.startTCKAgent();
} catch (Throwable e) {
Logger.error("Error", e);
}
}
}
public static boolean isTCKRunning() {
return (tckRFCOMMThread != null) || (tckL2CALthread != null) || (tckGOEPThread != null)
|| (tckOBEXThread != null);
}
static void stopTCK() {
interruptThread(tckRFCOMMThread);
tckRFCOMMThread = null;
interruptThread(tckL2CALthread);
tckL2CALthread = null;
interruptThread(tckGOEPThread);
tckGOEPThread = null;
interruptThread(tckOBEXThread);
tckOBEXThread = null;
}
public static TestResponderClient createClient() {
return createClient(false);
}
public static TestResponderClient createClient(boolean force) {
try {
TestResponderClient c;
if ((client == null) || (force)) {
c = new TestResponderClient(!force);
client = c;
} else {
c = client;
}
if (!c.isRunning) {
c.config.logID = "";
c.configured = false;
c.config.discoveryOnce = false;
c.config.connectDevice = null;
c.config.searchServiceRetry = true;
c.config.useDiscoveredDevices = false;
c.config.searchOnlyBluecoveUuid = Configuration.searchOnlyBluecoveUuid;
String name = "Client" + clientStartCount++;
c.thread = RuntimeDetect.cldcStub.createNamedThread(c, name);
c.thread.start();
return c;
} else {
if (RuntimeDetect.isJ2ME) {
BlueCoveTestMIDlet.message("Warn", "Client is already Running");
} else {
Logger.warn("Client is already Running");
}
return null;
}
} catch (Throwable e) {
Logger.error("start error ", e);
return null;
}
}
public static void startTwoClients() {
try {
client = new TestResponderClient();
client.configured = false;
client.config.discoveryOnce = false;
client.config.useDiscoveredDevices = false;
client.config.searchOnlyBluecoveUuid = Configuration.searchOnlyBluecoveUuid;
client.thread = new Thread(client);
client.configured();
TestResponderClient client2 = new TestResponderClient();
client2.configured = false;
client2.config.discoveryOnce = false;
client2.config.useDiscoveredDevices = false;
client2.config.searchOnlyBluecoveUuid = Configuration.searchOnlyBluecoveUuid;
client2.thread = new Thread(client2);
client2.configured();
client.thread.start();
client2.thread.start();
} catch (Throwable e) {
Logger.error("start error ", e);
}
}
public static void startDiscovery() {
TestResponderClient client = createClient();
if (client != null) {
client.config.discoveryOnce = true;
client.config.useDiscoveredDevices = false;
client.config.searchOnlyBluecoveUuid = Configuration.discoverySearchOnlyBluecoveUuid;
client.configured();
}
}
public static void startServicesSearch() {
TestResponderClient client = createClient();
if (client != null) {
client.config.discoveryOnce = true;
client.config.useDiscoveredDevices = true;
client.config.searchOnlyBluecoveUuid = Configuration.discoverySearchOnlyBluecoveUuid;
client.configured();
}
}
public static void startClient() {
try {
createClient();
if (client != null) {
client.configured();
}
} catch (Throwable e) {
Logger.error("startClient", e);
}
}
public static int runClient() {
createClient();
if (client != null) {
client.config.connectOnce = true;
client.configured();
try {
client.thread.join();
} catch (InterruptedException e) {
return 2;
}
if (TestResponderClient.failure.countFailure > 0) {
return 2;
} else if (TestResponderClient.countSuccess == 0) {
return 3;
}
return 1;
} else {
return 2;
}
}
public static void startClientStress() {
if ((client != null) && client.isRunning) {
Logger.warn("Client is already Running");
return;
}
createClient();
if (client != null) {
client.runStressTest = true;
client.configured();
}
}
public static void startClientLastURl() {
if (Configuration.storage == null) {
Logger.warn("no storage");
return;
}
if ((client != null) && client.isRunning) {
Logger.warn("Client is already Running");
return;
}
String lastURL = Configuration.getLastServerURL();
if (lastURL != null) {
createClient();
if (client != null) {
client.config.connectURL = lastURL;
client.configured();
}
} else {
Logger.warn("no recent Connections");
}
}
public static void startClientSelectService() {
if ((client != null) && client.isRunning) {
Logger.warn("Client is already Running");
return;
}
createClient();
if (client != null) {
client.config.connectURL = "";
client.configured();
}
}
public static void startClientLastDevice() {
if (Configuration.storage == null) {
Logger.warn("no storage");
return;
}
if ((client != null) && client.isRunning) {
Logger.warn("Client is already Running");
return;
}
String lastURL = Configuration.getLastServerURL();
if (lastURL != null) {
createClient();
if (client != null) {
client.config.connectDevice = BluetoothTypesInfo.extractBluetoothAddress(lastURL);
client.configured();
}
} else {
Logger.warn("no recent Connections");
}
}
public static void clientShutdown() {
if (client != null) {
client.shutdown();
client = null;
}
Vector runningClientsCopy = CollectionUtils.copy(runningClients);
for (Enumeration iter = runningClientsCopy.elements(); iter.hasMoreElements();) {
CanShutdown t = (CanShutdown) iter.nextElement();
t.shutdown();
}
}
public static void startServer() {
try {
if (server == null) {
server = new TestResponderServer();
}
if (!server.isRunning()) {
String name = "Server" + serverStartCount++;
server.thread = RuntimeDetect.cldcStub.createNamedThread(server, name);
server.thread.start();
} else {
if (Configuration.canCloseServer) {
if (RuntimeDetect.isJ2ME) {
BlueCoveTestMIDlet.message("Warn", "Server is already running");
} else {
Logger.warn("Server is already running");
}
} else {
serverStartCount++;
server.updateServiceRecord();
TestResponderServer.setDiscoverable();
}
}
} catch (Throwable e) {
Logger.error("start error ", e);
}
}
public static void updateServiceRecord() {
if (server != null) {
server.updateServiceRecord();
} else {
Logger.error("Service not started");
}
}
public static void serverShutdown() {
if (Configuration.canCloseServer) {
serverShutdownForce();
} else {
TestResponderServer.setNotDiscoverable();
}
stopTCK();
}
public static void serverShutdownOnExit() {
serverShutdownForce();
}
public static void serverShutdownForce() {
if (server != null) {
server.shutdown();
server = null;
}
}
public static void closeServerClientConnections() {
if (server != null) {
server.closeServerClientConnections();
}
}
}