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
26 package com.intel.bluetooth;
27
28 import java.security.AccessControlContext;
29 import java.security.AccessController;
30 import java.security.PrivilegedActionException;
31 import java.security.PrivilegedExceptionAction;
32 import java.util.Enumeration;
33 import java.util.Hashtable;
34 import java.util.Vector;
35
36 import javax.bluetooth.BluetoothStateException;
37
38 import com.intel.bluetooth.BluetoothStack.LibraryInformation;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public class BlueCoveImpl {
66
67 public static final String BLUETOOTH_API_VERSION = "1.1.1";
68
69 public static final String OBEX_API_VERSION = BLUETOOTH_API_VERSION;
70
71 public static final int versionMajor1 = 2;
72
73 public static final int versionMajor2 = 1;
74
75 public static final int versionMinor = 0;
76
77 public static final int versionBuild = 51;
78
79 public static final String versionSufix = "";
80
81 public static final String version = String.valueOf(versionMajor1) + "." + String.valueOf(versionMajor2) + "."
82 + String.valueOf(versionMinor) + versionSufix;
83
84 public static final int nativeLibraryVersionExpected = versionMajor1 * 1000000 + versionMajor2 * 10000
85 + versionMinor * 100 + versionBuild;
86
87 public static final String STACK_WINSOCK = "winsock";
88
89 public static final String STACK_WIDCOMM = "widcomm";
90
91 public static final String STACK_BLUESOLEIL = "bluesoleil";
92
93 public static final String STACK_TOSHIBA = "toshiba";
94
95 public static final String STACK_BLUEZ = "bluez";
96
97 public static final String STACK_OSX = "mac";
98
99 public static final String STACK_EMULATOR = "emulator";
100
101
102
103
104
105 private static final boolean oneDLLbuild = false;
106
107 public static final String NATIVE_LIB_MS = "intelbth";
108
109 public static final String NATIVE_LIB_WIDCOMM = oneDLLbuild ? NATIVE_LIB_MS : "bluecove";
110
111 public static final String NATIVE_LIB_TOSHIBA = "bluecove";
112
113 public static final String NATIVE_LIB_BLUEZ = "bluecove";
114
115 public static final String NATIVE_LIB_OSX = "bluecove";
116
117
118
119
120 public static final String NATIVE_LIB_BLUESOLEIL = NATIVE_LIB_MS;
121
122 static final int BLUECOVE_STACK_DETECT_MICROSOFT = 1;
123
124 static final int BLUECOVE_STACK_DETECT_WIDCOMM = 1 << 1;
125
126 static final int BLUECOVE_STACK_DETECT_BLUESOLEIL = 1 << 2;
127
128 static final int BLUECOVE_STACK_DETECT_TOSHIBA = 1 << 3;
129
130 static final int BLUECOVE_STACK_DETECT_OSX = 1 << 4;
131
132 public static final int BLUECOVE_STACK_DETECT_BLUEZ = 1 << 5;
133
134 public static final int BLUECOVE_STACK_DETECT_EMULATOR = 1 << 6;
135
136 static final String TRUE = "true";
137
138 static final String FALSE = "false";
139
140 private static final String FQCN = BlueCoveImpl.class.getName();
141
142 private static final Vector fqcnSet = new Vector();
143
144
145 private Object accessControlContext;
146
147 private static ShutdownHookThread shutdownHookRegistered;
148
149 private static BlueCoveImpl instance;
150
151 private static BluetoothStackHolder singleStack;
152
153 private static ThreadLocalWrapper threadStack;
154
155 private static BluetoothStackHolder threadStackIDDefault;
156
157 private static Hashtable resourceConfigProperties = new Hashtable();
158
159 private static Hashtable
160
161 private static Vector initializationProperties = new Vector();
162
163 static {
164 fqcnSet.addElement(FQCN);
165 for (int i = 0; i < BlueCoveConfigProperties.INITIALIZATION_PROPERTIES.length; i++) {
166 initializationProperties.addElement(BlueCoveConfigProperties.INITIALIZATION_PROPERTIES[i]);
167 }
168 }
169
170
171
172
173 private static class BluetoothStackHolder {
174
175 private BluetoothStack bluetoothStack;
176
177 Hashtable configProperties = new Hashtable();
178
179 private static BluetoothStack getBluetoothStack() throws BluetoothStateException {
180 return instance().getBluetoothStack();
181 }
182
183 public String toString() {
184 if (bluetoothStack == null) {
185 return "not initialized";
186 }
187 return bluetoothStack.toString();
188 }
189 }
190
191
192
193
194 private class AsynchronousShutdownThread extends Thread {
195
196 final Object monitor = new Object();
197
198 int shutdownStart = 0;
199
200 AsynchronousShutdownThread() {
201 super("BluecoveAsynchronousShutdownThread");
202 }
203
204 public void run() {
205 synchronized (monitor) {
206 while (shutdownStart == 0) {
207 try {
208 monitor.wait();
209 } catch (InterruptedException e) {
210 return;
211 }
212 }
213 }
214 if (shutdownStart == -1) {
215 return;
216 }
217 if (!stacks.isEmpty()) {
218 for (Enumeration en = stacks.elements(); en.hasMoreElements();) {
219 BluetoothStackHolder s = (BluetoothStackHolder) en.nextElement();
220 if (s.bluetoothStack != null) {
221 try {
222 s.bluetoothStack.destroy();
223 } finally {
224 s.bluetoothStack = null;
225 }
226 }
227 }
228 stacks.clear();
229 System.out.println("BlueCove stack shutdown completed");
230 }
231 synchronized (monitor) {
232 monitor.notifyAll();
233 }
234 }
235
236 void deRegister() {
237 shutdownStart = -1;
238 synchronized (monitor) {
239 monitor.notifyAll();
240 }
241 }
242 }
243
244 private class ShutdownHookThread extends Thread {
245
246 AsynchronousShutdownThread shutdownHookThread;
247
248 ShutdownHookThread(AsynchronousShutdownThread shutdownHookThread) {
249 super("BluecoveShutdownHookThread");
250 this.shutdownHookThread = shutdownHookThread;
251 }
252
253 public void run() {
254 final Object monitor = shutdownHookThread.monitor;
255 synchronized (monitor) {
256 shutdownHookThread.shutdownStart = 1;
257 monitor.notifyAll();
258 if (!stacks.isEmpty()) {
259 try {
260 monitor.wait(7000);
261 } catch (InterruptedException e) {
262 }
263 }
264 }
265 }
266
267 void deRegister() {
268 shutdownHookRegistered = null;
269 UtilsJavaSE.runtimeRemoveShutdownHook(this);
270 shutdownHookThread.deRegister();
271 }
272 }
273
274
275
276
277
278
279
280 public static synchronized BlueCoveImpl instance() {
281 if (instance == null) {
282 instance = new BlueCoveImpl();
283 }
284 return instance;
285 }
286
287 private BlueCoveImpl() {
288 try {
289 accessControlContext = AccessController.getContext();
290 } catch (Throwable javaME) {
291 }
292
293 DebugLog.isDebugEnabled();
294 copySystemProperties(null);
295 }
296
297 static int getNativeLibraryVersion() {
298 return nativeLibraryVersionExpected;
299 }
300
301 private synchronized void createShutdownHook() {
302 if (shutdownHookRegistered != null) {
303 return;
304 }
305 AsynchronousShutdownThread shutdownHookThread = new AsynchronousShutdownThread();
306 if (UtilsJavaSE.runtimeAddShutdownHook(shutdownHookRegistered = new ShutdownHookThread(shutdownHookThread))) {
307 UtilsJavaSE.threadSetDaemon(shutdownHookThread);
308 shutdownHookThread.start();
309 }
310 }
311
312 private int getStackId(String stack) {
313 if (STACK_WIDCOMM.equalsIgnoreCase(stack)) {
314 return BLUECOVE_STACK_DETECT_WIDCOMM;
315 } else if (STACK_BLUESOLEIL.equalsIgnoreCase(stack)) {
316 return BLUECOVE_STACK_DETECT_BLUESOLEIL;
317 } else if (STACK_TOSHIBA.equalsIgnoreCase(stack)) {
318 return BLUECOVE_STACK_DETECT_TOSHIBA;
319 } else if (STACK_WINSOCK.equalsIgnoreCase(stack)) {
320 return BLUECOVE_STACK_DETECT_MICROSOFT;
321 } else if (STACK_BLUEZ.equalsIgnoreCase(stack)) {
322 return BLUECOVE_STACK_DETECT_BLUEZ;
323 } else if (STACK_WINSOCK.equalsIgnoreCase(stack)) {
324 return BLUECOVE_STACK_DETECT_OSX;
325 } else if (STACK_EMULATOR.equalsIgnoreCase(stack)) {
326 return BLUECOVE_STACK_DETECT_EMULATOR;
327 } else {
328 return 0;
329 }
330 }
331
332 private Class loadStackClass(String classPropertyName, String classNameDefault) throws BluetoothStateException {
333 String className = getConfigProperty(classPropertyName);
334 if (className == null) {
335 className = classNameDefault;
336 }
337 try {
338 return Class.forName(className);
339 } catch (ClassNotFoundException e) {
340 DebugLog.error(className, e);
341 }
342 throw new BluetoothStateException("BlueCove " + className + " not available");
343 }
344
345 private BluetoothStack newStackInstance(Class ctackClass) throws BluetoothStateException {
346 String className = ctackClass.getName();
347 try {
348 return (BluetoothStack) ctackClass.newInstance();
349 } catch (InstantiationException e) {
350 DebugLog.error(className, e);
351 } catch (IllegalAccessException e) {
352 DebugLog.error(className, e);
353 }
354 throw new BluetoothStateException("BlueCove " + className + " can't instantiate");
355 }
356
357 private BluetoothStack loadStack(String classPropertyName, String classNameDefault) throws BluetoothStateException {
358 return newStackInstance(loadStackClass(classPropertyName, classNameDefault));
359 }
360
361 static void loadNativeLibraries(BluetoothStack stack) throws BluetoothStateException {
362
363 try {
364 if ((UtilsJavaSE.canCallNotLoadedNativeMethod) && (stack.isNativeCodeLoaded())) {
365 return;
366 }
367 } catch (Error e) {
368
369 }
370 LibraryInformation[] libs = stack.requireNativeLibraries();
371 if ((libs == null) || (libs.length == 0)) {
372
373 return;
374 }
375 for (int i = 0; i < libs.length; i++) {
376 Class c = libs[i].stackClass;
377 if (c == null) {
378 c = stack.getClass();
379 }
380 if (!NativeLibLoader.isAvailable(libs[i].libraryName, c)) {
381 throw new BluetoothStateException("BlueCove library " + libs[i].libraryName + " not available");
382 }
383 }
384 }
385
386 private static boolean isNativeLibrariesAvailable(BluetoothStack stack) {
387 try {
388 if (UtilsJavaSE.canCallNotLoadedNativeMethod) {
389 return stack.isNativeCodeLoaded();
390 }
391 } catch (Error e) {
392
393 }
394 LibraryInformation[] libs = stack.requireNativeLibraries();
395 if ((libs == null) || (libs.length == 0)) {
396
397 return true;
398 }
399 for (int i = 0; i < libs.length; i++) {
400 Class c = libs[i].stackClass;
401 if (c == null) {
402 c = stack.getClass();
403 }
404 if (!NativeLibLoader.isAvailable(libs[i].libraryName, c)) {
405 return false;
406 }
407 }
408 return true;
409 }
410
411 private BluetoothStack detectStack() throws BluetoothStateException {
412
413 BluetoothStack detectorStack = null;
414
415 String stackFirstDetector = getConfigProperty(BlueCoveConfigProperties.PROPERTY_STACK_FIRST);
416
417 String stackSelected = getConfigProperty(BlueCoveConfigProperties.PROPERTY_STACK);
418
419 if (stackFirstDetector == null) {
420 stackFirstDetector = stackSelected;
421 }
422 if (STACK_EMULATOR.equals(stackSelected)) {
423 detectorStack = loadStack("bluecove.emulator.class", "com.intel.bluetooth.BluetoothEmulator");
424 } else {
425 switch (NativeLibLoader.getOS()) {
426 case NativeLibLoader.OS_LINUX:
427 Class stackClass = loadStackClass("bluecove.bluez.class", "com.intel.bluetooth.BluetoothStackBlueZ");
428 detectorStack = newStackInstance(stackClass);
429 loadNativeLibraries(detectorStack);
430 stackSelected = detectorStack.getStackID();
431 break;
432 case NativeLibLoader.OS_MAC_OS_X:
433 detectorStack = new BluetoothStackOSX();
434 loadNativeLibraries(detectorStack);
435 stackSelected = detectorStack.getStackID();
436 break;
437 case NativeLibLoader.OS_WINDOWS:
438 case NativeLibLoader.OS_WINDOWS_CE:
439 detectorStack = createDetectorOnWindows(stackFirstDetector);
440 if (DebugLog.isDebugEnabled()) {
441 detectorStack.enableNativeDebug(DebugLog.class, true);
442 }
443 break;
444 default:
445 throw new BluetoothStateException("BlueCove not available");
446
447 }
448 }
449
450 int libraryVersion = detectorStack.getLibraryVersion();
451 if (nativeLibraryVersionExpected != libraryVersion) {
452 DebugLog.fatal("BlueCove native library version mismatch " + libraryVersion + " expected "
453 + nativeLibraryVersionExpected);
454 throw new BluetoothStateException("BlueCove native library version mismatch");
455 }
456
457 if (stackSelected == null) {
458
459 int aval = detectorStack.detectBluetoothStack();
460 DebugLog.debug("BluetoothStack detected", aval);
461 int detectorID = getStackId(detectorStack.getStackID());
462 if ((aval & detectorID) != 0) {
463 stackSelected = detectorStack.getStackID();
464 } else if ((aval & BLUECOVE_STACK_DETECT_MICROSOFT) != 0) {
465 stackSelected = STACK_WINSOCK;
466 } else if ((aval & BLUECOVE_STACK_DETECT_WIDCOMM) != 0) {
467 stackSelected = STACK_WIDCOMM;
468 } else if ((aval & BLUECOVE_STACK_DETECT_BLUESOLEIL) != 0) {
469 stackSelected = STACK_BLUESOLEIL;
470 } else if ((aval & BLUECOVE_STACK_DETECT_TOSHIBA) != 0) {
471 stackSelected = STACK_TOSHIBA;
472 } else if ((aval & BLUECOVE_STACK_DETECT_OSX) != 0) {
473 stackSelected = STACK_OSX;
474 } else {
475 DebugLog.fatal("BluetoothStack not detected");
476 throw new BluetoothStateException("BluetoothStack not detected");
477 }
478 } else {
479 DebugLog.debug("BluetoothStack selected", stackSelected);
480 }
481
482 BluetoothStack stack = setBluetoothStack(stackSelected, detectorStack);
483 stackSelected = stack.getStackID();
484 copySystemProperties(stack);
485 if (!stackSelected.equals(STACK_EMULATOR)) {
486 System.out.println("BlueCove version " + version + " on " + stackSelected);
487 }
488 return stack;
489 }
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505 public static Vector getLocalDevicesID() throws BluetoothStateException {
506 Vector v = new Vector();
507 String ids = BluetoothStackHolder.getBluetoothStack().getLocalDeviceProperty(
508 BlueCoveLocalDeviceProperties.LOCAL_DEVICE_DEVICES_LIST);
509 if (ids != null) {
510 UtilsStringTokenizer tok = new UtilsStringTokenizer(ids, ",");
511 while (tok.hasMoreTokens()) {
512 v.addElement(tok.nextToken());
513 }
514 }
515 return v;
516 }
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583 public static synchronized void useThreadLocalBluetoothStack() {
584 if (threadStack == null) {
585 threadStack = new ThreadLocalWrapper();
586 }
587 BluetoothStackHolder s = ((BluetoothStackHolder) threadStack.get());
588 if (s == null) {
589
590 if (singleStack != null) {
591 s = singleStack;
592 singleStack = null;
593 } else {
594 s = new BluetoothStackHolder();
595 }
596 threadStack.set(s);
597 }
598 }
599
600
601
602
603
604
605
606
607
608
609 public static synchronized Object getThreadBluetoothStackID() throws BluetoothStateException {
610 useThreadLocalBluetoothStack();
611 BluetoothStackHolder.getBluetoothStack();
612 return threadStack.get();
613 }
614
615
616
617
618
619
620
621 public static synchronized Object getCurrentThreadBluetoothStackID() {
622 if (threadStack == null) {
623 return null;
624 }
625 return threadStack.get();
626 }
627
628
629
630
631
632
633
634
635
636 public static synchronized void setThreadBluetoothStackID(Object stackID) {
637 if ((stackID != null) && (!(stackID instanceof BluetoothStackHolder))) {
638 throw new IllegalArgumentException("stackID is not valid");
639 }
640 if (threadStack == null) {
641 throw new IllegalArgumentException("ThreadLocal configuration is not initialized");
642 }
643 threadStack.set(stackID);
644 }
645
646
647
648
649
650 public static synchronized void releaseThreadBluetoothStack() {
651 if (threadStack == null) {
652 throw new IllegalArgumentException("ThreadLocal configuration is not initialized");
653 }
654 threadStack.set(null);
655 }
656
657
658
659
660
661
662
663
664
665 public static synchronized void setDefaultThreadBluetoothStackID(Object stackID) {
666 if ((stackID != null) && (!(stackID instanceof BluetoothStackHolder))) {
667 throw new IllegalArgumentException("stackID is not valid");
668 }
669 if (threadStack == null) {
670 throw new IllegalArgumentException("ThreadLocal configuration is not initialized");
671 }
672 threadStackIDDefault = (BluetoothStackHolder) stackID;
673 }
674
675 static synchronized void setThreadBluetoothStack(BluetoothStack bluetoothStack) {
676 if (threadStack == null) {
677 return;
678 }
679 BluetoothStackHolder s = ((BluetoothStackHolder) threadStack.get());
680 if ((s != null) && (s.bluetoothStack == bluetoothStack)) {
681 return;
682 }
683
684 BluetoothStackHolder sh = (BluetoothStackHolder) stacks.get(bluetoothStack);
685 if (sh == null) {
686 throw new RuntimeException("ThreadLocal not found for BluetoothStack");
687 }
688 threadStack.set(sh);
689 }
690
691
692
693
694 public static synchronized void shutdownThreadBluetoothStack() {
695
696 if (threadStack == null) {
697 return;
698 }
699 BluetoothStackHolder s = ((BluetoothStackHolder) threadStack.get());
700 if (s == null) {
701 return;
702 }
703 if (threadStackIDDefault == s) {
704 threadStackIDDefault = null;
705 }
706 s.configProperties.clear();
707 if (s.bluetoothStack != null) {
708 BluetoothConnectionNotifierBase.shutdownConnections(s.bluetoothStack);
709 RemoteDeviceHelper.shutdownConnections(s.bluetoothStack);
710 s.bluetoothStack.destroy();
711 stacks.remove(s.bluetoothStack);
712 s.bluetoothStack = null;
713 }
714 }
715
716
717
718
719 public static synchronized void shutdown() {
720 for (Enumeration en = stacks.elements(); en.hasMoreElements();) {
721 BluetoothStackHolder s = (BluetoothStackHolder) en.nextElement();
722 s.configProperties.clear();
723 if (s.bluetoothStack != null) {
724 BluetoothConnectionNotifierBase.shutdownConnections(s.bluetoothStack);
725 RemoteDeviceHelper.shutdownConnections(s.bluetoothStack);
726 try {
727 s.bluetoothStack.destroy();
728 } finally {
729 s.bluetoothStack = null;
730 }
731 }
732 }
733 stacks.clear();
734 singleStack = null;
735 threadStackIDDefault = null;
736 if (shutdownHookRegistered != null) {
737 shutdownHookRegistered.deRegister();
738 }
739 clearSystemProperties();
740 }
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757 public static void setConfigProperty(String name, String value) {
758 if (name == null) {
759 throw new NullPointerException("key is null");
760 }
761 BluetoothStackHolder sh = currentStackHolder(true);
762 if ((sh.bluetoothStack != null) && (initializationProperties.contains(name))) {
763 throw new IllegalArgumentException("BlueCove Stack already initialized");
764 }
765 if (value == null) {
766 sh.configProperties.remove(name);
767 } else {
768 sh.configProperties.put(name, value);
769 }
770 }
771
772 static String getConfigProperty(String key) {
773 if (key == null) {
774 throw new NullPointerException("key is null");
775 }
776 String value = null;
777 BluetoothStackHolder sh = currentStackHolder(false);
778 if (sh != null) {
779 value = (String) sh.configProperties.get(key);
780 }
781 if (value == null) {
782 try {
783 value = System.getProperty(key);
784 } catch (SecurityException webstart) {
785 }
786 }
787 if (value == null) {
788 synchronized (resourceConfigProperties) {
789 Object casheValue = resourceConfigProperties.get(key);
790 if (casheValue != null) {
791 if (casheValue instanceof String) {
792 value = (String) casheValue;
793 }
794 } else {
795 value = Utils.getResourceProperty(BlueCoveImpl.class, key);
796 if (value == null) {
797 resourceConfigProperties.put(key, new Object());
798 } else {
799 resourceConfigProperties.put(key, value);
800 }
801 }
802 }
803 }
804 return value;
805 }
806
807 static boolean getConfigProperty(String key, boolean defaultValue) {
808 String value = getConfigProperty(key);
809 if (value != null) {
810 return TRUE.equals(value) || "1".equals(value);
811 } else {
812 return defaultValue;
813 }
814 }
815
816 static int getConfigProperty(String key, int defaultValue) {
817 String value = getConfigProperty(key);
818 if (value != null) {
819 return Integer.parseInt(value);
820 } else {
821 return defaultValue;
822 }
823 }
824
825 static String[] getSystemPropertiesList() {
826 String[] p = { BluetoothConsts.PROPERTY_BLUETOOTH_MASTER_SWITCH, BluetoothConsts.PROPERTY_BLUETOOTH_SD_ATTR_RETRIEVABLE_MAX,
827 BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_DEVICES_MAX, BluetoothConsts.PROPERTY_BLUETOOTH_L2CAP_RECEIVEMTU_MAX,
828 BluetoothConsts.PROPERTY_BLUETOOTH_SD_TRANS_MAX, BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_INQUIRY_SCAN,
829 BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_PAGE_SCAN, BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_INQUIRY,
830 BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_PAGE };
831 return p;
832 }
833
834 static void clearSystemProperties() {
835 UtilsJavaSE.setSystemProperty(BluetoothConsts.PROPERTY_BLUETOOTH_API_VERSION, null);
836 UtilsJavaSE.setSystemProperty(BluetoothConsts.PROPERTY_OBEX_API_VERSION, null);
837 String[] property = getSystemPropertiesList();
838 for (int i = 0; i < property.length; i++) {
839 UtilsJavaSE.setSystemProperty(property[i], null);
840 }
841 }
842
843 void copySystemProperties(BluetoothStack bluetoothStack) {
844 UtilsJavaSE.setSystemProperty(BluetoothConsts.PROPERTY_BLUETOOTH_API_VERSION, BlueCoveImpl.BLUETOOTH_API_VERSION);
845 UtilsJavaSE.setSystemProperty(BluetoothConsts.PROPERTY_OBEX_API_VERSION, BlueCoveImpl.OBEX_API_VERSION);
846 if (bluetoothStack != null) {
847 String[] property = getSystemPropertiesList();
848 for (int i = 0; i < property.length; i++) {
849 UtilsJavaSE.setSystemProperty(property[i], bluetoothStack.getLocalDeviceProperty(property[i]));
850 }
851 }
852 }
853
854 public String getLocalDeviceFeature(int featureID) throws BluetoothStateException {
855 return ((BluetoothStackHolder.getBluetoothStack().getFeatureSet() & featureID) != 0) ? TRUE : FALSE;
856 }
857
858 private BluetoothStack createDetectorOnWindows(String stackFirst) throws BluetoothStateException {
859 if (stackFirst != null) {
860 DebugLog.debug("detector stack", stackFirst);
861 BluetoothStack detectorStack;
862 if (STACK_WIDCOMM.equalsIgnoreCase(stackFirst)) {
863 detectorStack = new BluetoothStackWIDCOMM();
864 if (isNativeLibrariesAvailable(detectorStack)) {
865 return detectorStack;
866 }
867 } else if (STACK_BLUESOLEIL.equalsIgnoreCase(stackFirst)) {
868 detectorStack = new BluetoothStackBlueSoleil();
869 if (isNativeLibrariesAvailable(detectorStack)) {
870 return detectorStack;
871 }
872 } else if (STACK_WINSOCK.equalsIgnoreCase(stackFirst)) {
873 detectorStack = new BluetoothStackMicrosoft();
874 if (isNativeLibrariesAvailable(detectorStack)) {
875 return detectorStack;
876 }
877 } else if (STACK_TOSHIBA.equalsIgnoreCase(stackFirst)) {
878 detectorStack = new BluetoothStackToshiba();
879 if (isNativeLibrariesAvailable(detectorStack)) {
880 return detectorStack;
881 }
882 } else {
883 throw new IllegalArgumentException("Invalid BlueCove detector stack [" + stackFirst + "]");
884 }
885 }
886 BluetoothStack stack = new BluetoothStackMicrosoft();
887 if (isNativeLibrariesAvailable(stack)) {
888 return stack;
889 }
890
891 stack = new BluetoothStackWIDCOMM();
892 if (isNativeLibrariesAvailable(stack)) {
893 return stack;
894 }
895
896 throw new BluetoothStateException("BlueCove libraries not available");
897 }
898
899
900
901
902
903
904
905
906 public String setBluetoothStack(String stack) throws BluetoothStateException {
907 return setBluetoothStack(stack, null).getStackID();
908 }
909
910 private synchronized BluetoothStack setBluetoothStack(String stack, BluetoothStack detectorStack)
911 throws BluetoothStateException {
912 if (singleStack != null) {
913 if (singleStack.bluetoothStack != null) {
914 singleStack.bluetoothStack.destroy();
915 stacks.remove(singleStack.bluetoothStack);
916 singleStack.bluetoothStack = null;
917 }
918 } else if (threadStack != null) {
919 BluetoothStackHolder s = ((BluetoothStackHolder) threadStack.get());
920 if ((s != null) && (s.bluetoothStack != null)) {
921 s.bluetoothStack.destroy();
922 stacks.remove(s.bluetoothStack);
923 s.bluetoothStack = null;
924 }
925 }
926 BluetoothStack newStack;
927 if ((detectorStack != null) && (detectorStack.getStackID()).equalsIgnoreCase(stack)) {
928 newStack = detectorStack;
929 } else if (STACK_WIDCOMM.equalsIgnoreCase(stack)) {
930 newStack = new BluetoothStackWIDCOMM();
931 } else if (STACK_BLUESOLEIL.equalsIgnoreCase(stack)) {
932 newStack = new BluetoothStackBlueSoleil();
933 } else if (STACK_TOSHIBA.equalsIgnoreCase(stack)) {
934 newStack = new BluetoothStackToshiba();
935 } else {
936 newStack = new BluetoothStackMicrosoft();
937 }
938 loadNativeLibraries(newStack);
939 int libraryVersion = newStack.getLibraryVersion();
940 if (nativeLibraryVersionExpected != libraryVersion) {
941 DebugLog.fatal("BlueCove native library version mismatch " + libraryVersion + " expected "
942 + nativeLibraryVersionExpected);
943 throw new BluetoothStateException("BlueCove native library version mismatch");
944 }
945
946 if (DebugLog.isDebugEnabled()) {
947 newStack.enableNativeDebug(DebugLog.class, true);
948 }
949 newStack.initialize();
950 createShutdownHook();
951
952
953 BluetoothStackHolder sh = currentStackHolder(true);
954 sh.bluetoothStack = newStack;
955 stacks.put(newStack, sh);
956 if (threadStack != null) {
957 threadStack.set(sh);
958 }
959 return newStack;
960 }
961
962 public void enableNativeDebug(boolean on) {
963 BluetoothStackHolder s = currentStackHolder(false);
964 if ((s != null) && (s.bluetoothStack != null)) {
965 s.bluetoothStack.enableNativeDebug(DebugLog.class, on);
966 }
967 }
968
969 private static BluetoothStackHolder currentStackHolder(boolean create) {
970 if (threadStack != null) {
971 BluetoothStackHolder s = ((BluetoothStackHolder) threadStack.get());
972 if ((s == null) && (threadStackIDDefault != null)) {
973 return threadStackIDDefault;
974 }
975 if ((s == null) && create) {
976 s = new BluetoothStackHolder();
977 threadStack.set(s);
978 }
979 return s;
980 } else {
981 if ((singleStack == null) && create) {
982 singleStack = new BluetoothStackHolder();
983 }
984 return singleStack;
985 }
986 }
987
988
989
990
991
992
993
994
995
996
997
998 public synchronized BluetoothStack getBluetoothStack() throws BluetoothStateException {
999 Utils.isLegalAPICall(fqcnSet);
1000 BluetoothStackHolder sh = currentStackHolder(false);
1001 if ((sh != null) && (sh.bluetoothStack != null)) {
1002 return sh.bluetoothStack;
1003 } else if ((sh == null) && (threadStack != null)) {
1004 throw new BluetoothStateException("No BluetoothStack or Adapter for current thread");
1005 }
1006
1007 BluetoothStack stack;
1008 if (accessControlContext == null) {
1009 stack = detectStack();
1010 } else {
1011 stack = detectStackPrivileged();
1012 }
1013 return stack;
1014 }
1015
1016 private BluetoothStack detectStackPrivileged() throws BluetoothStateException {
1017 try {
1018 return (BluetoothStack) AccessController.doPrivileged(new PrivilegedExceptionAction() {
1019 public Object run() throws BluetoothStateException {
1020 return detectStack();
1021 }
1022 }, (AccessControlContext) accessControlContext);
1023 } catch (PrivilegedActionException e) {
1024 Throwable cause = UtilsJavaSE.getCause(e);
1025 if (cause instanceof BluetoothStateException) {
1026 throw (BluetoothStateException) cause;
1027 }
1028 throw (BluetoothStateException) UtilsJavaSE.initCause(new BluetoothStateException(e.getMessage()), cause);
1029 }
1030 }
1031
1032 }