25 package org.direct_bt;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.lang.reflect.InvocationTargetException;
30 import java.lang.reflect.Method;
32 import java.security.AccessController;
33 import java.security.PrivilegedAction;
34 import java.util.ArrayList;
35 import java.util.Enumeration;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Properties;
40 import java.util.jar.Attributes;
41 import java.util.jar.Manifest;
43 import org.jau.util.VersionUtil;
95 public boolean equals(
final Object other) {
119 private static final List<ImplementationIdentifier> implIDs =
new ArrayList<ImplementationIdentifier>();
125 private static String APIVersion;
131 private static String ImplVersion;
171 final String v = System.getProperty(
"org.direct_bt.debug",
"false");
172 DEBUG = Boolean.valueOf(v);
177 final String v = System.getProperty(
"org.direct_bt.verbose",
"false");
181 final String v = System.getProperty(
"org.direct_bt.btmode",
"DUAL");
185 }
catch (
final IllegalArgumentException ex) {
186 System.err.println(
"Invalid BTMode '"+v+
"': "+ex.getMessage());
192 boolean isJaulibAvail =
false;
194 isJaulibAvail =
null != Class.forName(
"org.jau.sys.PlatformProps",
true ,
BTFactory.class.getClassLoader());
195 }
catch(
final Throwable t ) {
197 System.err.println(
"BTFactory Caught: "+t.getMessage());
203 if( isJaulibAvail ) {
213 private static ImplementationIdentifier initializedID =
null;
216 if(
null == initializedID ) {
217 throw new IllegalStateException(
"BluetoothFactory not initialized.");
221 return null == initializedID;
224 private static synchronized void initLibrary(
final ImplementationIdentifier
id) {
225 if(
null != initializedID ) {
226 if(
id != initializedID ) {
227 throw new IllegalStateException(
"BluetoothFactory already initialized with "+initializedID+
", can't override by "+
id);
232 final ClassLoader cl = BTFactory.class.getClassLoader();
233 boolean libsLoaded =
false;
237 org.jau.pkg.JNIJarLibrary.addNativeJarLibs(
new Class<?>[] { BTFactory.class },
null);
238 }
catch (
final Exception e0) {
239 System.err.println(
"BTFactory Caught "+e0.getClass().getSimpleName()+
": "+e0.getMessage()+
", while JNILibLoaderBase.addNativeJarLibs(..)");
241 e0.printStackTrace();
246 if(
null !=
org.jau.sys.dl.NativeLibrary.open(
id.ImplementationNativeLibraryBasename,
247 true ,
false , cl,
true ) )
249 org.jau.sys.JNILibrary.loadLibrary(
id.JavaNativeLibraryBasename,
false, cl);
252 }
catch (
final Throwable t) {
253 System.err.println(
"Caught "+t.getClass().getSimpleName()+
": "+t.getMessage()+
", while loading libs..");
259 System.err.println(
"Jaulib: Native libs loaded: "+ libsLoaded);
264 final Throwable[] t = {
null };
265 if( !PlatformToolkit.loadLibrary(
id.ImplementationNativeLibraryBasename, cl, t) ) {
266 throw new RuntimeException(
"Couldn't load native library with basename <"+
id.ImplementationNativeLibraryBasename+
">", t[0]);
268 if( !PlatformToolkit.loadLibrary(
id.JavaNativeLibraryBasename, cl, t) ) {
269 throw new RuntimeException(
"Couldn't load native library with basename <"+
id.JavaNativeLibraryBasename+
">", t[0]);
271 }
catch (
final Throwable e) {
272 System.err.println(
"Caught "+e.getClass().getSimpleName()+
": "+e.getMessage()+
", while loading libs (2) ..");
283 System.err.println(
"BlootoothFactory: Mapping '[org.|jau.]direct_bt.*' properties to native environment");
285 final Properties props = AccessController.doPrivileged(
new PrivilegedAction<Properties>() {
287 public Properties run() {
288 return System.getProperties();
291 final Enumeration<?> enums = props.propertyNames();
292 while (enums.hasMoreElements()) {
293 final String key = (String) enums.nextElement();
294 if( key.startsWith(
"org.direct_bt.") || key.startsWith(
"jau.direct_bt.") ||
295 key.startsWith(
"direct_bt.") )
297 final String value = props.getProperty(key);
299 System.err.println(
" <"+key+
"> := <"+value+
">");
301 setenv(key, value,
true );
304 }
catch (
final Throwable e) {
305 System.err.println(
"Caught exception while forwarding system properties: "+e.getMessage());
310 final Manifest manifest = getManifest(cl,
new String[] {
"org.direct_bt" } );
311 final Attributes mfAttributes =
null != manifest ? manifest.getMainAttributes() :
null;
315 final String JAPIVersion =
null != mfAttributes ? mfAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION) :
null;
316 if (
null != JAPIVersion && JAPIVersion.equals(NAPIVersion) ==
false) {
317 final String[] NAPIVersionCode = NAPIVersion.split(
"\\D");
318 final String[] JAPIVersionCode = JAPIVersion.split(
"\\D");
319 if (JAPIVersionCode[0].equals(NAPIVersionCode[0]) ==
false) {
320 if (Integer.valueOf(JAPIVersionCode[0]) < Integer.valueOf(NAPIVersionCode[0])) {
321 throw new RuntimeException(
"Java library "+JAPIVersion+
" < native library "+NAPIVersion+
". Please update the Java library.");
323 throw new RuntimeException(
"Native library "+NAPIVersion+
" < java library "+JAPIVersion+
". Please update the native library.");
325 }
else if (JAPIVersionCode[1].equals(NAPIVersionCode[1]) ==
false) {
326 if (Integer.valueOf(JAPIVersionCode[1]) < Integer.valueOf(NAPIVersionCode[1])) {
327 throw new RuntimeException(
"Java library "+JAPIVersion+
" < native library "+NAPIVersion+
". Please update the Java library.");
329 throw new RuntimeException(
"Native library "+NAPIVersion+
" < java library "+JAPIVersion+
". Please update the native library.");
335 APIVersion = JAPIVersion;
336 ImplVersion =
null != mfAttributes ? mfAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION) :
null;
338 System.err.println(
"direct_bt loaded "+
id);
339 System.err.println(
"direct_bt java api version "+JAPIVersion);
340 System.err.println(
"direct_bt native api version "+NAPIVersion);
341 if(
null != mfAttributes ) {
342 final Attributes.Name[] versionAttributeNames =
new Attributes.Name[] {
343 Attributes.Name.SPECIFICATION_TITLE,
344 Attributes.Name.SPECIFICATION_VENDOR,
345 Attributes.Name.SPECIFICATION_VERSION,
346 Attributes.Name.IMPLEMENTATION_TITLE,
347 Attributes.Name.IMPLEMENTATION_VENDOR,
348 Attributes.Name.IMPLEMENTATION_VERSION,
349 new Attributes.Name(
"Implementation-Commit") };
350 for(
final Attributes.Name an : versionAttributeNames ) {
351 System.err.println(
" "+an+
": "+mfAttributes.getValue(an));
354 System.err.println(
" No Manifest available;");
357 }
catch (
final Throwable e) {
358 System.err.println(
"Error querying manifest information.");
364 private static synchronized BTManager getBTManager(
final Class<?> factoryImplClass)
365 throws BTException, NoSuchMethodException, SecurityException,
366 IllegalAccessException, IllegalArgumentException, InvocationTargetException
368 final Method m = factoryImplClass.getMethod(
"getManager");
369 return (BTManager)m.invoke(
null);
383 if( implIDs.contains(
id) ) {
386 return implIDs.add(
id);
395 if(
id.BluetoothManagerClassName.equals(fqBluetoothManagerImplementationClassName) ) {
424 throws BTException, NoSuchMethodException, SecurityException,
425 IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException
429 return getBTManager(
id);
455 throws BTException, NoSuchMethodException, SecurityException,
456 IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException
460 final Class<?> factoryImpl = Class.forName(
id.BluetoothManagerClassName);
461 return getBTManager(factoryImpl);
481 throws
BTException, NoSuchMethodException, SecurityException,
482 IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException
487 private static final Manifest getManifest(
final ClassLoader cl,
final String[] extensions) {
488 final Manifest[] extManifests =
new Manifest[extensions.length];
490 final Enumeration<URL> resources = cl.getResources(
"META-INF/MANIFEST.MF");
491 while (resources.hasMoreElements()) {
492 final URL resURL = resources.nextElement();
494 System.err.println(
"resource: "+resURL);
496 final InputStream is = resURL.openStream();
497 final Manifest manifest;
499 manifest =
new Manifest(is);
503 }
catch (
final IOException e) {}
505 final Attributes attributes = manifest.getMainAttributes();
506 if(attributes !=
null) {
507 final String attributesExtName = attributes.getValue( Attributes.Name.EXTENSION_NAME );
508 for(
int i=0; i < extensions.length &&
null == extManifests[i]; i++) {
509 final String extension = extensions[i];
510 if( extension.equals( attributesExtName ) ) {
514 extManifests[i] = manifest;
519 }
catch (
final IOException ex) {
520 throw new RuntimeException(
"Unable to read manifest.", ex);
522 for(
int i=1; i<extManifests.length; i++) {
523 if(
null != extManifests[i] ) {
524 return extManifests[i];
530 public static void main(
final String args[]) {
533 System.err.println(VersionUtil.getPlatformInfo());
534 System.err.println(
"Version Info:");
536 System.err.println(v);
537 System.err.println(
"");
538 System.err.println(
"Full Manifest:");
539 System.err.println(v.getFullManifestInfo(
null));
541 System.err.println(
"Full Manifest:");
542 final Manifest manifest = getManifest(
BTFactory.class.getClassLoader(),
new String[] {
"org.direct_bt" } );
543 final Attributes attr = manifest.getMainAttributes();
544 final Set<Object> keys = attr.keySet();
545 final StringBuilder sb =
new StringBuilder();
546 for(
final Iterator<Object> iter=keys.iterator(); iter.hasNext(); ) {
547 final Attributes.Name key = (Attributes.Name) iter.next();
548 final String val = attr.getValue(key);
553 sb.append(System.lineSeparator());
555 System.err.println(sb);
559 final List<BTAdapter> adapters = mngr.
getAdapters();
560 System.err.println(
"BTManager: Settings "+mngr.
getSettings().
toString()+
", adapters "+adapters.size());
563 for(
final Iterator<BTAdapter> iter = adapters.iterator(); iter.hasNext(); ++i) {
565 System.err.println(
"BTAdapter["+i+
"]: "+iter.next().toString());
571 }
catch (
BTException | NoSuchMethodException | SecurityException
572 | IllegalAccessException | IllegalArgumentException
573 | InvocationTargetException | ClassNotFoundException e) {
580 private native
static void setenv(String name, String value,
boolean overwrite);