1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package net.sf.bluecove.awt;
26
27 import java.awt.Dimension;
28 import java.awt.EventQueue;
29 import java.awt.Font;
30 import java.awt.Frame;
31 import java.awt.Menu;
32 import java.awt.MenuBar;
33 import java.awt.MenuItem;
34 import java.awt.MenuShortcut;
35 import java.awt.Rectangle;
36 import java.awt.TextArea;
37 import java.awt.Toolkit;
38 import java.awt.event.ActionEvent;
39 import java.awt.event.ActionListener;
40 import java.awt.event.KeyEvent;
41 import java.awt.event.KeyListener;
42 import java.awt.event.WindowAdapter;
43 import java.awt.event.WindowEvent;
44 import java.io.File;
45 import java.io.FileWriter;
46 import java.io.OutputStreamWriter;
47 import java.text.SimpleDateFormat;
48 import java.util.Date;
49 import java.util.Enumeration;
50 import java.util.Vector;
51
52 import javax.bluetooth.BluetoothStateException;
53 import javax.bluetooth.DiscoveryAgent;
54
55 import net.sf.bluecove.Configuration;
56 import net.sf.bluecove.Consts;
57 import net.sf.bluecove.Switcher;
58 import net.sf.bluecove.TestConcurrent;
59 import net.sf.bluecove.se.BlueCoveSpecific;
60 import net.sf.bluecove.se.FileStorage;
61 import net.sf.bluecove.se.JavaSECommon;
62 import net.sf.bluecove.se.LocalDeviceManager;
63 import net.sf.bluecove.se.RemoteDeviceManager;
64 import net.sf.bluecove.se.UIHelper;
65
66 import org.bluecove.tester.log.Logger;
67 import org.bluecove.tester.log.LoggerAppender;
68 import org.bluecove.tester.util.IOUtils;
69 import org.bluecove.tester.util.RuntimeDetect;
70 import org.bluecove.tester.util.TimeUtils;
71
72 import com.intel.bluetooth.BlueCoveImpl;
73
74
75
76
77
78 public class Main extends Frame implements LoggerAppender {
79
80 private static final long serialVersionUID = 1L;
81
82 private TextArea output = null;
83
84 private int outputLines = 0;
85
86 private Vector logLinesQueue = new Vector();
87
88 private boolean logUpdaterRunning = false;
89
90 int lastKeyCode;
91
92 MenuItem debugOn;
93
94 public static void main(String[] args) {
95
96
97
98
99 JavaSECommon.initOnce();
100 Configuration.storage = new FileStorage();
101
102 Main app = new Main();
103 app.setVisible(true);
104 Logger.debug("Stated app");
105 Logger.debug("OS:" + System.getProperty("os.name") + "|" + System.getProperty("os.version") + "|"
106 + System.getProperty("os.arch"));
107 Logger.debug("Java:" + System.getProperty("java.vendor") + " " + System.getProperty("java.version"));
108
109 for (int i = 0; i < args.length; i++) {
110 if (args[i].equalsIgnoreCase("--stack")) {
111
112
113 i++;
114 try {
115 BlueCoveImpl.instance().setBluetoothStack(args[i]);
116 } catch (BluetoothStateException e) {
117 Logger.error("can't init stack", e);
118 }
119 app.updateTitle();
120 } else if (args[i].equalsIgnoreCase("--runonce")) {
121 int rc = Switcher.runClient();
122 Logger.debug("Finished app " + rc);
123 System.exit(rc);
124 }
125 }
126 }
127
128 public Main() {
129 addWindowListener(new WindowAdapter() {
130 public void windowClosing(WindowEvent w) {
131 quit();
132 }
133 });
134
135 Logger.addAppender(this);
136 BlueCoveSpecific.addAppender(this);
137
138 Logger.debug("Stating app");
139
140 this.setTitle("BlueCove tester");
141
142 final MenuBar menuBar = new MenuBar();
143 Menu menuBluetooth = new Menu("Bluetooth");
144
145 final MenuItem serverStart = addMenu(menuBluetooth, "Server Start", new ActionListener() {
146 public void actionPerformed(ActionEvent e) {
147 Switcher.startServer();
148 updateTitle();
149 }
150 }, KeyEvent.VK_5);
151
152 final MenuItem serverStop = addMenu(menuBluetooth, "Server Stop", new ActionListener() {
153 public void actionPerformed(ActionEvent e) {
154 Switcher.serverShutdown();
155 }
156 }, KeyEvent.VK_6);
157
158 final MenuItem serverClientsStop = addMenu(menuBluetooth, "Server Clients close", new ActionListener() {
159 public void actionPerformed(ActionEvent e) {
160 Switcher.closeServerClientConnections();
161 }
162 });
163
164 final MenuItem clientStart = addMenu(menuBluetooth, "Client Start", new ActionListener() {
165 public void actionPerformed(ActionEvent e) {
166 Switcher.startClient();
167 updateTitle();
168 }
169 }, KeyEvent.VK_2);
170
171 final MenuItem clientStop = addMenu(menuBluetooth, "Client Stop", new ActionListener() {
172 public void actionPerformed(ActionEvent e) {
173 Switcher.clientShutdown();
174 }
175 }, KeyEvent.VK_3);
176
177 final MenuItem tckStart;
178 if (Configuration.likedTCKAgent) {
179 tckStart = addMenu(menuBluetooth, "Start TCK Agent", new ActionListener() {
180 public void actionPerformed(ActionEvent e) {
181 Switcher.startTCKAgent();
182 }
183 });
184 } else {
185 tckStart = null;
186 }
187
188 addMenu(menuBluetooth, "Discovery", new ActionListener() {
189 public void actionPerformed(ActionEvent e) {
190 Switcher.startDiscovery();
191 updateTitle();
192 }
193 }, KeyEvent.VK_MULTIPLY);
194
195 addMenu(menuBluetooth, "Services Search", new ActionListener() {
196 public void actionPerformed(ActionEvent e) {
197 Switcher.startServicesSearch();
198 updateTitle();
199 }
200 }, KeyEvent.VK_7);
201
202 addMenu(menuBluetooth, "Client Stress Start", new ActionListener() {
203 public void actionPerformed(ActionEvent e) {
204 Switcher.startClientStress();
205 updateTitle();
206 }
207 });
208
209 addMenu(menuBluetooth, "Client selectService Start", new ActionListener() {
210 public void actionPerformed(ActionEvent e) {
211 Switcher.startClientSelectService();
212 updateTitle();
213 }
214 });
215
216 addMenu(menuBluetooth, "Client Last service Start", new ActionListener() {
217 public void actionPerformed(ActionEvent e) {
218 Switcher.startClientLastURl();
219 updateTitle();
220 }
221 });
222
223 addMenu(menuBluetooth, "Client Last device Start", new ActionListener() {
224 public void actionPerformed(ActionEvent e) {
225 Switcher.startClientLastDevice();
226 updateTitle();
227 }
228 });
229
230 final MenuItem stop = addMenu(menuBluetooth, "Stop all work", new ActionListener() {
231 public void actionPerformed(ActionEvent e) {
232 Switcher.clientShutdown();
233 Switcher.serverShutdown();
234 }
235 }, KeyEvent.VK_S);
236
237 addMenu(menuBluetooth, "Quit", new ActionListener() {
238 public void actionPerformed(ActionEvent e) {
239 quit();
240 }
241 }, KeyEvent.VK_X);
242
243 menuBar.add(menuBluetooth);
244
245 Menu menuLogs = new Menu("Logs");
246
247 debugOn = addMenu(menuLogs, "BlueCove Debug ON", new ActionListener() {
248 public void actionPerformed(ActionEvent e) {
249 boolean dbg = BlueCoveSpecific.changeDebug();
250 if (dbg) {
251 debugOn.setLabel("BlueCove Debug OFF");
252 } else {
253 debugOn.setLabel("BlueCove Debug ON");
254 }
255 }
256 });
257
258 addMenu(menuLogs, "Clear Log", new ActionListener() {
259 public void actionPerformed(ActionEvent e) {
260 clear();
261
262 }
263 }, KeyEvent.VK_Z);
264
265 addMenu(menuLogs, "Print FailureLog", new ActionListenerRunnable() {
266 public void run() {
267 UIHelper.printFailureLog();
268 }
269 }, KeyEvent.VK_4);
270
271 addMenu(menuLogs, "Clear Stats", new ActionListenerRunnable() {
272 public void run() {
273 UIHelper.clearStats();
274 }
275 });
276
277 if (JavaSECommon.isJava5()) {
278 addMenu(menuLogs, "ThreadDump", new ActionListenerRunnable() {
279 public void run() {
280 JavaSECommon.threadDump();
281 }
282 });
283 }
284
285 addMenu(menuLogs, "Save to File", new ActionListenerRunnable() {
286 public void run() {
287 logSaveToFile();
288 }
289 });
290
291 menuBar.add(menuLogs);
292
293 Menu menuMore = new Menu("More");
294
295 addMenu(menuMore, "Configuration", new ActionListener() {
296 public void actionPerformed(ActionEvent e) {
297 (new ConfigurationDialog(Main.this)).setVisible(true);
298 }
299 });
300
301 addMenu(menuMore, "Client Connection", new ActionListener() {
302 public void actionPerformed(ActionEvent e) {
303 (new ClientConnectionDialog(Main.this)).setVisible(true);
304 }
305 });
306
307 addMenu(menuMore, "OBEX Client Connection", new ActionListener() {
308 public void actionPerformed(ActionEvent e) {
309 (new ObexClientConnectionDialog(Main.this)).setVisible(true);
310 }
311 });
312
313 addMenu(menuMore, "Two Clients Start", new ActionListener() {
314 public void actionPerformed(ActionEvent e) {
315 Switcher.startTwoClients();
316 updateTitle();
317 }
318 });
319
320 addMenu(menuMore, "Concurrent Services Search", new ActionListener() {
321 public void actionPerformed(ActionEvent e) {
322 TestConcurrent.startConcurrentServicesSearchClients();
323 }
324 });
325
326 Menu menuSpeedTests = new Menu("Speed tests");
327 addMenu(menuSpeedTests, "RFCOMM Read test", new ActionListenerRunnable() {
328 public void run() {
329 UIHelper.configurationForSpeedTest(Consts.TRAFFIC_GENERATOR_WRITE, false);
330 Switcher.startClient();
331 }
332 });
333
334 addMenu(menuSpeedTests, "RFCOMM Write test", new ActionListenerRunnable() {
335 public void run() {
336 UIHelper.configurationForSpeedTest(Consts.TRAFFIC_GENERATOR_READ, false);
337 Switcher.startClient();
338 }
339 });
340 addMenu(menuSpeedTests, "L2CAP Read test", new ActionListenerRunnable() {
341 public void run() {
342 UIHelper.configurationForSpeedTest(Consts.TRAFFIC_GENERATOR_WRITE, true);
343 Switcher.startClient();
344 }
345 });
346
347 addMenu(menuSpeedTests, "L2CAP Write test", new ActionListenerRunnable() {
348 public void run() {
349 UIHelper.configurationForSpeedTest(Consts.TRAFFIC_GENERATOR_READ, true);
350 Switcher.startClient();
351 }
352 });
353
354 menuMore.add(menuSpeedTests);
355
356 Menu menuLocalDevice = new Menu("LocalDevice");
357 addMenu(menuLocalDevice, "Get discoverable", new ActionListener() {
358 public void actionPerformed(ActionEvent e) {
359 LocalDeviceManager.getDiscoverable();
360 }
361 });
362
363 addMenu(menuLocalDevice, "Set NOT discoverable", new ActionListener() {
364 public void actionPerformed(ActionEvent e) {
365 LocalDeviceManager.setNotDiscoverable();
366 }
367 });
368
369 addMenu(menuLocalDevice, "Set discoverable GIAC", new ActionListener() {
370 public void actionPerformed(ActionEvent e) {
371 LocalDeviceManager.setDiscoverableGIAC();
372 }
373 });
374
375 addMenu(menuLocalDevice, "Set discoverable LIAC", new ActionListener() {
376 public void actionPerformed(ActionEvent e) {
377 LocalDeviceManager.setDiscoverableLIAC();
378 }
379 });
380
381 menuMore.add(menuLocalDevice);
382
383 Menu menuRemoteDevice = new Menu("RemoteDevice");
384 addMenu(menuRemoteDevice, "Retrieve CACHED", new ActionListener() {
385 public void actionPerformed(ActionEvent e) {
386 RemoteDeviceManager.retrieveDevices(DiscoveryAgent.CACHED);
387 }
388 });
389 addMenu(menuRemoteDevice, "Retrieve PREKNOWN", new ActionListener() {
390 public void actionPerformed(ActionEvent e) {
391 RemoteDeviceManager.retrieveDevices(DiscoveryAgent.PREKNOWN);
392 }
393 });
394 menuMore.add(menuRemoteDevice);
395
396 Menu threadLocalStack = new Menu("ThreadLocalStack");
397
398 MenuItem menuWinsock = addMenu(threadLocalStack, "Set 'winsock'", new ActionListener() {
399 public void actionPerformed(ActionEvent e) {
400 LocalDeviceManager.setUseWINSOCK();
401 updateTitle();
402 }
403 });
404 menuWinsock.setEnabled(Configuration.windows);
405
406 MenuItem menuWidcomm = addMenu(threadLocalStack, "Set 'widcomm'", new ActionListener() {
407 public void actionPerformed(ActionEvent e) {
408 LocalDeviceManager.setUseWIDCOMM();
409 updateTitle();
410 }
411 });
412 menuWidcomm.setEnabled(Configuration.windows);
413
414 addMenu(threadLocalStack, "Set 'deviceID=0'", new ActionListener() {
415 public void actionPerformed(ActionEvent e) {
416 LocalDeviceManager.setUseDevice(0);
417 updateTitle();
418 }
419 });
420
421 addMenu(threadLocalStack, "Set 'deviceID=1'", new ActionListener() {
422 public void actionPerformed(ActionEvent e) {
423 LocalDeviceManager.setUseDevice(1);
424 updateTitle();
425 }
426 });
427
428 if (Configuration.linux) {
429 try {
430 Vector ids = BlueCoveImpl.getLocalDevicesID();
431 for (Enumeration en = ids.elements(); en.hasMoreElements();) {
432 final int id = Integer.parseInt((String) en.nextElement());
433 if (id > 1) {
434 Configuration.hasManyDevices = true;
435 }
436 if (id >= 2) {
437 addMenu(threadLocalStack, "Set 'deviceID=" + id + "'", new ActionListener() {
438 public void actionPerformed(ActionEvent e) {
439 LocalDeviceManager.setUseDevice(id);
440 updateTitle();
441 }
442 });
443 }
444 }
445 } catch (Throwable e) {
446 Logger.debug("get device list error", e);
447 }
448 }
449
450 addMenu(threadLocalStack, "shutdown", new ActionListener() {
451 public void actionPerformed(ActionEvent e) {
452 LocalDeviceManager.shutdownThreadLocal();
453 }
454 });
455
456 menuMore.add(threadLocalStack);
457
458 addMenu(menuMore, "Shutdown BlueCove", new ActionListener() {
459 public void actionPerformed(ActionEvent e) {
460 LocalDeviceManager.shutdown();
461 }
462 });
463
464 menuBar.add(menuMore);
465
466 setMenuBar(menuBar);
467
468
469 output = new TextArea("");
470 output.setEditable(false);
471 this.add(output);
472
473 Runnable statusUpdateRunnable = new Runnable() {
474 public void run() {
475 while (true) {
476 try {
477 Thread.sleep(1000);
478 } catch (InterruptedException e) {
479 break;
480 }
481 if (isMainFrameActive()) {
482 serverStop.setEnabled(Switcher.isRunningServer());
483 serverStart.setEnabled(!Switcher.isRunningServer());
484 serverClientsStop.setEnabled(Switcher.isRunningServerClients());
485
486 clientStop.setEnabled(Switcher.isRunningClient());
487 clientStart.setEnabled(!Switcher.isRunningClient());
488 stop.setEnabled(Switcher.isRunningClient() || Switcher.isRunningServer());
489 if (tckStart != null) {
490 tckStart.setEnabled(!Switcher.isTCKRunning());
491 }
492 }
493 }
494 }
495 };
496 Thread statusUpdate = RuntimeDetect.cldcStub.createNamedThread(statusUpdateRunnable, "StatusUpdate");
497 statusUpdate.start();
498
499 output.addKeyListener(new KeyListener() {
500
501 public void keyPressed(KeyEvent e) {
502
503
504 Main.this.keyPressed(e.getKeyCode());
505 }
506
507 public void keyReleased(KeyEvent e) {
508 }
509
510 public void keyTyped(KeyEvent e) {
511 }
512 });
513
514 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
515 if (screenSize.height < 400) {
516 Configuration.screenSizeSmall = true;
517 }
518 Font logFont = new Font("Monospaced", Font.PLAIN, Configuration.screenSizeSmall ? 9 : 12);
519 output.setFont(logFont);
520
521 if (screenSize.width > 600) {
522 screenSize.setSize(600, 420);
523 }
524 if (this.isResizable()) {
525 Rectangle b = this.getBounds();
526 b.x = Integer.valueOf(Configuration.getStorageData("main.x", "0")).intValue();
527 b.y = Integer.valueOf(Configuration.getStorageData("main.y", "0")).intValue();
528 b.height = Integer.valueOf(Configuration.getStorageData("main.height", String.valueOf(screenSize.height)))
529 .intValue();
530 b.width = Integer.valueOf(Configuration.getStorageData("main.width", String.valueOf(screenSize.width)))
531 .intValue();
532 this.setBounds(b);
533 }
534 }
535
536 boolean isMainFrameActive() {
537 try {
538 return isActive();
539 } catch (Throwable j13) {
540 return true;
541 }
542 }
543
544 private void updateTitle() {
545 this.setTitle(UIHelper.getMainWindowTitle());
546 }
547
548 private MenuItem addMenu(Menu menu, String name, ActionListener l) {
549 return addMenu(menu, name, l, 0);
550 }
551
552 private MenuItem addMenu(Menu menu, String name, ActionListener l, int key) {
553 MenuItem menuItem = new MenuItem(name);
554 menuItem.addActionListener(l);
555 menu.add(menuItem);
556 if (key != 0) {
557 menuItem.setShortcut(new MenuShortcut(key, false));
558 }
559 return menuItem;
560 }
561
562 protected void keyPressed(int keyCode) {
563 switch (keyCode) {
564 case '1':
565
566 break;
567 case '4':
568 UIHelper.printFailureLog();
569 break;
570 case '0':
571
572
573 break;
574 case '*':
575 case KeyEvent.VK_MULTIPLY:
576 case 119:
577 Switcher.startDiscovery();
578 break;
579 case '7':
580 Switcher.startServicesSearch();
581 break;
582 case '2':
583 Switcher.startClient();
584 break;
585 case '3':
586 Switcher.clientShutdown();
587 break;
588 case '5':
589 Switcher.startServer();
590 break;
591 case '6':
592 Switcher.serverShutdown();
593 break;
594 case '8':
595
596 break;
597 case '9':
598
599 break;
600 case '#':
601 case 120:
602 if (lastKeyCode == keyCode) {
603 quit();
604 }
605 clear();
606 break;
607 default:
608
609 }
610 lastKeyCode = keyCode;
611 }
612
613 private void clear() {
614 if (output == null) {
615 return;
616 }
617 synchronized (logLinesQueue) {
618 logLinesQueue.clear();
619 }
620 output.setText("");
621 outputLines = 0;
622 }
623
624 private void quit() {
625 Logger.debug("quit");
626 Switcher.clientShutdown();
627 Switcher.serverShutdownOnExit();
628
629 Rectangle b = this.getBounds();
630 Configuration.storeData("main.x", String.valueOf(b.x));
631 Configuration.storeData("main.y", String.valueOf(b.y));
632 Configuration.storeData("main.height", String.valueOf(b.height));
633 Configuration.storeData("main.width", String.valueOf(b.width));
634
635 Logger.removeAppender(this);
636 BlueCoveSpecific.removeAppender();
637
638
639 System.exit(0);
640 }
641
642 private void logSaveToFile() {
643 SimpleDateFormat fmt = new SimpleDateFormat("MM-dd_HH-mm-ss");
644 OutputStreamWriter out = null;
645 try {
646 File file = new File("BlueCoveTester-" + fmt.format(new Date()) + ".log");
647 out = new FileWriter(file);
648 out.write(output.getText());
649 out.flush();
650 out.close();
651 out = null;
652 Logger.info("Log saved to file " + file.getAbsolutePath());
653 } catch (Throwable ignore) {
654 } finally {
655 IOUtils.closeQuietly(out);
656 }
657 }
658
659 public void appendLog(int level, String message, Throwable throwable) {
660 if (output == null) {
661 return;
662 }
663 final StringBuffer buf = new StringBuffer();
664
665 if (Configuration.logTimeStamp) {
666 String time = TimeUtils.timeNowToString();
667 buf.append(time).append(" ");
668 }
669
670 switch (level) {
671 case Logger.ERROR:
672
673 buf.append("e.");
674 break;
675 case Logger.WARN:
676 buf.append("w.");
677 break;
678 case Logger.INFO:
679 buf.append("i.");
680 break;
681 }
682 buf.append(message);
683 if (throwable != null) {
684 buf.append(' ');
685 String className = throwable.getClass().getName();
686 buf.append(className.substring(1 + className.lastIndexOf('.')));
687 if (throwable.getMessage() != null) {
688 buf.append(':');
689 buf.append(throwable.getMessage());
690 }
691 }
692 buf.append("\n");
693 boolean createUpdater = false;
694 synchronized (logLinesQueue) {
695 if (logLinesQueue.isEmpty()) {
696 createUpdater = true;
697 } else {
698 createUpdater = !logUpdaterRunning;
699 }
700 logLinesQueue.addElement(buf.toString());
701 }
702 if (createUpdater) {
703 try {
704 EventQueue.invokeLater(new AwtLogUpdater(true));
705 } catch (NoSuchMethodError java1) {
706 (new AwtLogUpdater(false)).run();
707 }
708 }
709 }
710
711 private class AwtLogUpdater implements Runnable {
712
713 boolean canRestart;
714
715 AwtLogUpdater(boolean canRestart) {
716 this.canRestart = canRestart;
717 }
718
719 private String getNextLines() {
720 synchronized (logLinesQueue) {
721 if (logLinesQueue.isEmpty()) {
722 return null;
723 }
724 StringBuffer buf = new StringBuffer();
725 for (int i = 0; i < 40; i++) {
726 try {
727 buf.append((String) logLinesQueue.firstElement());
728 } catch (Exception e) {
729
730 break;
731 }
732 logLinesQueue.removeElementAt(0);
733
734 }
735 return buf.toString();
736 }
737 }
738
739 public void run() {
740 int oneCallCount = 0;
741 boolean restart = false;
742 synchronized (logLinesQueue) {
743 logUpdaterRunning = true;
744 }
745 String lines;
746 try {
747 while ((lines = getNextLines()) != null) {
748 if (outputLines > 5000) {
749 clear();
750 }
751 output.append(lines);
752 outputLines++;
753 oneCallCount++;
754 if (oneCallCount > 10) {
755 restart = true;
756 break;
757 }
758 }
759 } finally {
760 if (restart && canRestart) {
761 EventQueue.invokeLater(new AwtLogUpdater(true));
762 } else {
763 synchronized (logLinesQueue) {
764 logUpdaterRunning = false;
765 }
766 }
767 }
768 }
769 }
770
771 }