/**
* 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.awt;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.MenuShortcut;
import java.awt.Rectangle;
import java.awt.TextArea;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DiscoveryAgent;
import net.sf.bluecove.Configuration;
import net.sf.bluecove.Consts;
import net.sf.bluecove.Switcher;
import net.sf.bluecove.TestConcurrent;
import net.sf.bluecove.TestResponderCommon;
import net.sf.bluecove.se.BlueCoveSpecific;
import net.sf.bluecove.se.FileStorage;
import net.sf.bluecove.se.JavaSECommon;
import net.sf.bluecove.se.LocalDeviceManager;
import net.sf.bluecove.se.RemoteDeviceManager;
import net.sf.bluecove.se.UIHelper;
import org.bluecove.tester.log.Logger;
import org.bluecove.tester.log.LoggerAppender;
import org.bluecove.tester.util.IOUtils;
import org.bluecove.tester.util.RuntimeDetect;
import org.bluecove.tester.util.TimeUtils;
import com.intel.bluetooth.BlueCoveImpl;
/**
*
*
*/
public class Main extends Frame implements LoggerAppender {
private static final long serialVersionUID = 1L;
private TextArea output = null;
private int outputLines = 0;
private Vector logLinesQueue = new Vector();
private boolean logUpdaterRunning = false;
int lastKeyCode;
MenuItem debugOn;
public static void main(String[] args) {
// System.setProperty("bluecove.debug", "true");
// System.getProperties().put("bluecove.debug", "true");
// BlueCoveImpl.instance().getBluetoothPeer().enableNativeDebug(true);
JavaSECommon.initOnce();
Configuration.storage = new FileStorage();
Main app = new Main();
app.setVisible(true);
Logger.debug("Stated app");
Logger.debug("OS:" + System.getProperty("os.name") + "|" + System.getProperty("os.version") + "|"
+ System.getProperty("os.arch"));
Logger.debug("Java:" + System.getProperty("java.vendor") + " " + System.getProperty("java.version") + "; " +System.getProperty("java.vm.version"));
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
if (Configuration.windowsCE || Configuration.screenSizeSmall) {
Logger.debug("Screen:" + screenSize.width + "x" + screenSize.height + (Configuration.screenSizeSmall?" small":""));
}
for (int i = 0; i < args.length; i++) {
if (args[i].equalsIgnoreCase("--stack")) {
// This is used in WebStart when system properties can't be
// defined.
i++;
try {
BlueCoveImpl.instance().setBluetoothStack(args[i]);
} catch (BluetoothStateException e) {
Logger.error("can't init stack", e);
}
app.updateTitle();
} else if (args[i].equalsIgnoreCase("--runonce")) {
int rc = Switcher.runClient();
Logger.debug("Finished app " + rc);
System.exit(rc);
}
}
}
public Main() {
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent w) {
quit();
}
});
Logger.addAppender(this);
BlueCoveSpecific.addAppender(this);
Logger.debug("Stating app");
this.setTitle("BlueCove tester");
final MenuBar menuBar = new MenuBar();
Menu menuBluetooth = new Menu("Bluetooth");
final MenuItem serverStart = addMenu(menuBluetooth, "Server Start", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.startServer();
updateTitle();
}
}, KeyEvent.VK_5);
final MenuItem serverStop = addMenu(menuBluetooth, "Server Stop", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.serverShutdown();
}
}, KeyEvent.VK_6);
final MenuItem serverClientsStop = addMenu(menuBluetooth, "Server Clients close", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.closeServerClientConnections();
}
});
final MenuItem clientStart = addMenu(menuBluetooth, "Client Start", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.startClient();
updateTitle();
}
}, KeyEvent.VK_2);
final MenuItem clientStop = addMenu(menuBluetooth, "Client Stop", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.clientShutdown();
}
}, KeyEvent.VK_3);
final MenuItem tckStart;
if (Configuration.likedTCKAgent) {
tckStart = addMenu(menuBluetooth, "Start TCK Agent", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.startTCKAgent();
}
});
} else {
tckStart = null;
}
addMenu(menuBluetooth, "Discovery", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.startDiscovery();
updateTitle();
}
}, KeyEvent.VK_MULTIPLY);
addMenu(menuBluetooth, "Services Search", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.startServicesSearch();
updateTitle();
}
}, KeyEvent.VK_7);
addMenu(menuBluetooth, "Client Stress Start", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.startClientStress();
updateTitle();
}
});
addMenu(menuBluetooth, "Client selectService Start", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.startClientSelectService();
updateTitle();
}
});
addMenu(menuBluetooth, "Client Last service Start", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.startClientLastURl();
updateTitle();
}
});
addMenu(menuBluetooth, "Client Last device Start", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.startClientLastDevice();
updateTitle();
}
});
final MenuItem stop = addMenu(menuBluetooth, "Stop all work", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.clientShutdown();
Switcher.serverShutdown();
}
}, KeyEvent.VK_S);
addMenu(menuBluetooth, "Quit", new ActionListener() {
public void actionPerformed(ActionEvent e) {
quit();
}
}, KeyEvent.VK_X);
menuBar.add(menuBluetooth);
Menu menuLogs = new Menu("Logs");
debugOn = addMenu(menuLogs, "BlueCove Debug ON", new ActionListener() {
public void actionPerformed(ActionEvent e) {
boolean dbg = BlueCoveSpecific.changeDebug();
if (dbg) {
debugOn.setLabel("BlueCove Debug OFF");
} else {
debugOn.setLabel("BlueCove Debug ON");
}
}
});
addMenu(menuLogs, "Clear Log", new ActionListener() {
public void actionPerformed(ActionEvent e) {
clear();
}
}, KeyEvent.VK_Z);
addMenu(menuLogs, "Print FailureLog", new ActionListenerRunnable() {
public void run() {
UIHelper.printFailureLog();
}
}, KeyEvent.VK_4);
addMenu(menuLogs, "Clear Stats", new ActionListenerRunnable() {
public void run() {
UIHelper.clearStats();
}
});
if (JavaSECommon.isJava5()) {
addMenu(menuLogs, "ThreadDump", new ActionListenerRunnable() {
public void run() {
JavaSECommon.threadDump();
}
});
}
addMenu(menuLogs, "Save to File", new ActionListenerRunnable() {
public void run() {
logSaveToFile();
}
});
addMenu(menuLogs, "System.getProperties", new ActionListenerRunnable() {
public void run() {
JavaSECommon.logSystemProperties();
}
});
menuBar.add(menuLogs);
Menu menuMore = new Menu("More");
addMenu(menuMore, "Configuration", new ActionListener() {
public void actionPerformed(ActionEvent e) {
(new ConfigurationDialog(Main.this)).setVisible(true);
}
});
addMenu(menuMore, "Client Connection", new ActionListener() {
public void actionPerformed(ActionEvent e) {
(new ClientConnectionDialog(Main.this)).setVisible(true);
}
});
addMenu(menuMore, "OBEX Client Connection", new ActionListener() {
public void actionPerformed(ActionEvent e) {
(new ObexClientConnectionDialog(Main.this)).setVisible(true);
}
});
addMenu(menuMore, "Two Clients Start", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.startTwoClients();
updateTitle();
}
});
addMenu(menuMore, "Concurrent Services Search", new ActionListener() {
public void actionPerformed(ActionEvent e) {
TestConcurrent.startConcurrentServicesSearchClients();
}
});
Menu menuSpeedTests = new Menu("Speed tests");
addMenu(menuSpeedTests, "RFCOMM Read test", new ActionListenerRunnable() {
public void run() {
UIHelper.configurationForSpeedTest(Consts.TRAFFIC_GENERATOR_WRITE, false);
Switcher.startClient();
}
});
addMenu(menuSpeedTests, "RFCOMM Write test", new ActionListenerRunnable() {
public void run() {
UIHelper.configurationForSpeedTest(Consts.TRAFFIC_GENERATOR_READ, false);
Switcher.startClient();
}
});
addMenu(menuSpeedTests, "L2CAP Read test", new ActionListenerRunnable() {
public void run() {
UIHelper.configurationForSpeedTest(Consts.TRAFFIC_GENERATOR_WRITE, true);
Switcher.startClient();
}
});
addMenu(menuSpeedTests, "L2CAP Write test", new ActionListenerRunnable() {
public void run() {
UIHelper.configurationForSpeedTest(Consts.TRAFFIC_GENERATOR_READ, true);
Switcher.startClient();
}
});
menuMore.add(menuSpeedTests);
Menu menuLocalDevice = new Menu("LocalDevice");
addMenu(menuLocalDevice, "LocalDevice.getProperties", new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
TestResponderCommon.printLocalDeviceInfo();
} catch (BluetoothStateException t) {
Logger.error("can't read LocalDevice", t);
}
}
});
addMenu(menuLocalDevice, "Get discoverable", new ActionListener() {
public void actionPerformed(ActionEvent e) {
LocalDeviceManager.getDiscoverable();
}
});
addMenu(menuLocalDevice, "Set NOT discoverable", new ActionListener() {
public void actionPerformed(ActionEvent e) {
LocalDeviceManager.setNotDiscoverable();
}
});
addMenu(menuLocalDevice, "Set discoverable GIAC", new ActionListener() {
public void actionPerformed(ActionEvent e) {
LocalDeviceManager.setDiscoverableGIAC();
}
});
addMenu(menuLocalDevice, "Set discoverable LIAC", new ActionListener() {
public void actionPerformed(ActionEvent e) {
LocalDeviceManager.setDiscoverableLIAC();
}
});
addMenu(menuLocalDevice, "Update ServiceRecord", new ActionListener() {
public void actionPerformed(ActionEvent e) {
Switcher.updateServiceRecord();
}
});
menuMore.add(menuLocalDevice);
Menu menuRemoteDevice = new Menu("RemoteDevice");
addMenu(menuRemoteDevice, "Retrieve CACHED", new ActionListenerRunnable() {
public void run() {
RemoteDeviceManager.retrieveDevices(DiscoveryAgent.CACHED);
}
});
addMenu(menuRemoteDevice, "Retrieve PREKNOWN", new ActionListenerRunnable() {
public void run() {
RemoteDeviceManager.retrieveDevices(DiscoveryAgent.PREKNOWN);
}
});
menuMore.add(menuRemoteDevice);
Menu threadLocalStack = new Menu("ThreadLocalStack");
MenuItem menuWinsock = addMenu(threadLocalStack, "Set 'winsock'", new ActionListener() {
public void actionPerformed(ActionEvent e) {
LocalDeviceManager.setUseWINSOCK();
updateTitle();
}
});
menuWinsock.setEnabled(Configuration.windows);
MenuItem menuWidcomm = addMenu(threadLocalStack, "Set 'widcomm'", new ActionListener() {
public void actionPerformed(ActionEvent e) {
LocalDeviceManager.setUseWIDCOMM();
updateTitle();
}
});
menuWidcomm.setEnabled(Configuration.windows);
addMenu(threadLocalStack, "Set 'deviceID=0'", new ActionListener() {
public void actionPerformed(ActionEvent e) {
LocalDeviceManager.setUseDevice(0);
updateTitle();
}
});
addMenu(threadLocalStack, "Set 'deviceID=1'", new ActionListener() {
public void actionPerformed(ActionEvent e) {
LocalDeviceManager.setUseDevice(1);
updateTitle();
}
});
if (Configuration.linux) {
try {
Vector ids = BlueCoveImpl.getLocalDevicesID();
int countDevices = 0;
for (Enumeration en = ids.elements(); en.hasMoreElements();) {
final String id = (String) en.nextElement();
final int deviceID = countDevices;
countDevices++;
if (countDevices > 1) {
Configuration.hasManyDevices = true;
}
if (countDevices > 2) {
addMenu(threadLocalStack, "Set 'deviceID=" + id + "'", new ActionListener() {
public void actionPerformed(ActionEvent e) {
LocalDeviceManager.setUseDevice(deviceID);
updateTitle();
}
});
}
}
} catch (Throwable e) {
Logger.debug("get device list error", e);
}
}
addMenu(threadLocalStack, "shutdown", new ActionListener() {
public void actionPerformed(ActionEvent e) {
LocalDeviceManager.shutdownThreadLocal();
}
});
menuMore.add(threadLocalStack);
addMenu(menuMore, "Shutdown BlueCove", new ActionListener() {
public void actionPerformed(ActionEvent e) {
LocalDeviceManager.shutdown();
}
});
menuBar.add(menuMore);
setMenuBar(menuBar);
// Create a scrolled text area.
output = new TextArea("");
output.setEditable(false);
this.add(output);
Runnable statusUpdateRunnable = new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
if (isMainFrameActive()) {
serverStop.setEnabled(Switcher.isRunningServer());
serverStart.setEnabled(!Switcher.isRunningServer());
serverClientsStop.setEnabled(Switcher.isRunningServerClients());
clientStop.setEnabled(Switcher.isRunningClient());
clientStart.setEnabled(!Switcher.isRunningClient());
stop.setEnabled(Switcher.isRunningClient() || Switcher.isRunningServer());
if (tckStart != null) {
tckStart.setEnabled(!Switcher.isTCKRunning());
}
}
}
}
};
Thread statusUpdate = RuntimeDetect.cldcStub.createNamedThread(statusUpdateRunnable, "StatusUpdate");
statusUpdate.start();
output.addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
// Logger.debug("key:" + e.getKeyCode() + " " +
// KeyEvent.getKeyText(e.getKeyCode()));
Main.this.keyPressed(e.getKeyCode());
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
});
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
if ((screenSize.height < 500) || (screenSize.width < 500)) {
Configuration.screenSizeSmall = true;
}
output.setFont( new Font("Monospaced", Font.PLAIN, Configuration.screenSizeSmall ? 9 : 12));
if (screenSize.width > 640) {
screenSize.setSize(600, 420);
}
if (isResizable()) {
Rectangle b = getBounds();
b.x = Integer.valueOf(Configuration.getStorageData("main.x", "0")).intValue();
b.y = Integer.valueOf(Configuration.getStorageData("main.y", "0")).intValue();
b.height = Integer.valueOf(Configuration.getStorageData("main.height", String.valueOf(screenSize.height)))
.intValue();
b.width = Integer.valueOf(Configuration.getStorageData("main.width", String.valueOf(screenSize.width)))
.intValue();
setBounds(b);
}
}
boolean isMainFrameActive() {
try {
return isActive();
} catch (Throwable j13) {
return true;
}
}
private void updateTitle() {
this.setTitle(UIHelper.getMainWindowTitle());
}
private MenuItem addMenu(Menu menu, String name, ActionListener l) {
return addMenu(menu, name, l, 0);
}
private MenuItem addMenu(Menu menu, String name, ActionListener l, int key) {
MenuItem menuItem = new MenuItem(name);
menuItem.addActionListener(l);
menu.add(menuItem);
if (key != 0) {
menuItem.setShortcut(new MenuShortcut(key, false));
}
return menuItem;
}
protected void keyPressed(int keyCode) {
switch (keyCode) {
case '1':
// printStats();
break;
case '4':
UIHelper.printFailureLog();
break;
case '0':
// logScrollX = 0;
// setLogEndLine();
break;
case '*':
case KeyEvent.VK_MULTIPLY:
case 119:
Switcher.startDiscovery();
break;
case '7':
Switcher.startServicesSearch();
break;
case '2':
Switcher.startClient();
break;
case '3':
Switcher.clientShutdown();
break;
case '5':
Switcher.startServer();
break;
case '6':
Switcher.serverShutdown();
break;
case '8':
// startSwitcher();
break;
case '9':
// stopSwitcher();
break;
case '#':
case 120:
if (lastKeyCode == keyCode) {
quit();
}
clear();
break;
default:
// Logger.debug("keyCode " + keyCode);
}
lastKeyCode = keyCode;
}
private void clear() {
if (output == null) {
return;
}
synchronized (logLinesQueue) {
logLinesQueue.clear();
}
output.setText("");
outputLines = 0;
}
private void quit() {
Logger.debug("quit");
Switcher.clientShutdown();
Switcher.serverShutdownOnExit();
Rectangle b = this.getBounds();
Configuration.storeData("main.x", String.valueOf(b.x));
Configuration.storeData("main.y", String.valueOf(b.y));
Configuration.storeData("main.height", String.valueOf(b.height));
Configuration.storeData("main.width", String.valueOf(b.width));
Logger.removeAppender(this);
BlueCoveSpecific.removeAppender();
// this.dispose();
System.exit(0);
}
private void logSaveToFile() {
SimpleDateFormat fmt = new SimpleDateFormat("MM-dd_HH-mm-ss");
OutputStreamWriter out = null;
try {
File file = new File("BlueCoveTester-" + fmt.format(new Date()) + ".log");
out = new FileWriter(file);
out.write(output.getText());
out.flush();
out.close();
out = null;
Logger.info("Log saved to file " + file.getAbsolutePath());
} catch (Throwable ignore) {
} finally {
IOUtils.closeQuietly(out);
}
}
public void appendLog(int level, String message, Throwable throwable) {
if (output == null) {
return;
}
final StringBuffer buf = new StringBuffer();
if (Configuration.logTimeStamp) {
String time = TimeUtils.timeNowToString();
buf.append(time).append(" ");
}
switch (level) {
case Logger.ERROR:
// errorCount ++;
buf.append("e.");
break;
case Logger.WARN:
buf.append("w.");
break;
case Logger.INFO:
buf.append("i.");
break;
}
buf.append(message);
if (throwable != null) {
buf.append(' ');
String className = throwable.getClass().getName();
buf.append(className.substring(1 + className.lastIndexOf('.')));
if (throwable.getMessage() != null) {
buf.append(':');
buf.append(throwable.getMessage());
}
}
buf.append("\n");
boolean createUpdater = false;
synchronized (logLinesQueue) {
if (logLinesQueue.isEmpty()) {
createUpdater = true;
} else {
createUpdater = !logUpdaterRunning;
}
logLinesQueue.addElement(buf.toString());
}
if (createUpdater) {
try {
EventQueue.invokeLater(new AwtLogUpdater(true));
} catch (NoSuchMethodError java1) {
(new AwtLogUpdater(false)).run();
}
}
}
private class AwtLogUpdater implements Runnable {
boolean canRestart;
AwtLogUpdater(boolean canRestart) {
this.canRestart = canRestart;
}
private String getNextLines() {
synchronized (logLinesQueue) {
if (logLinesQueue.isEmpty()) {
return null;
}
StringBuffer buf = new StringBuffer();
for (int i = 0; i < 40; i++) {
try {
buf.append((String) logLinesQueue.firstElement());
} catch (Exception e) {
// NoSuchElementException
break;
}
logLinesQueue.removeElementAt(0);
}
return buf.toString();
}
}
public void run() {
int oneCallCount = 0;
boolean restart = false;
synchronized (logLinesQueue) {
logUpdaterRunning = true;
}
String lines;
try {
while ((lines = getNextLines()) != null) {
if (outputLines > 5000) {
clear();
}
output.append(lines);
outputLines++;
oneCallCount++;
if (oneCallCount > 10) {
restart = true;
break;
}
}
} finally {
if (restart && canRestart) {
EventQueue.invokeLater(new AwtLogUpdater(true));
} else {
synchronized (logLinesQueue) {
logUpdaterRunning = false;
}
}
}
}
}
}