27import java.io.IOException;
28import java.io.InputStream;
29import java.lang.reflect.InvocationTargetException;
30import java.lang.reflect.Method;
32import java.security.PrivilegedAction;
33import java.util.ArrayList;
34import java.util.Enumeration;
35import java.util.Iterator;
37import java.util.Properties;
39import java.util.concurrent.atomic.AtomicReference;
40import java.util.jar.Attributes;
41import java.util.jar.Manifest;
43import 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;
166 @SuppressWarnings({
"deprecation",
"removal" })
168 return java.security.AccessController.doPrivileged( o );
173 final String v = System.getProperty(
"org.direct_bt.debug",
"false");
174 DEBUG = Boolean.valueOf(v);
179 final String v = System.getProperty(
"org.direct_bt.verbose",
"false");
184 boolean isJaulibAvail =
false;
186 isJaulibAvail =
null != Class.forName(
"org.jau.sys.RuntimeProps",
true , BTFactory.class.getClassLoader());
187 }
catch(
final Throwable t ) {
189 System.err.println(
"BTFactory Caught: "+t.getMessage());
195 if( isJaulibAvail ) {
205 private static AtomicReference<ImplementationIdentifier> initializedID =
new AtomicReference<ImplementationIdentifier>(
null);
208 if(
null == initializedID.get() ) {
209 throw new IllegalStateException(
"Direct-BT not initialized.");
213 return null != initializedID.get();
216 private static synchronized void initLibrary(
final ImplementationIdentifier
id) {
217 if(
null != initializedID.get() ) {
218 if(
id != initializedID.get() ) {
219 throw new IllegalStateException(
"Direct-BT already initialized with "+initializedID.get()+
", can't override by "+
id);
224 final ClassLoader cl = BTFactory.class.getClassLoader();
225 boolean libsLoaded =
false;
229 org.jau.pkg.JNIJarLibrary.addNativeJarLibs(
new Class<?>[] { BTFactory.class },
null);
230 }
catch (
final Exception e0) {
231 System.err.println(
"BTFactory Caught "+e0.getClass().getSimpleName()+
": "+e0.getMessage()+
", while JNILibLoaderBase.addNativeJarLibs(..)");
233 e0.printStackTrace();
238 if(
null != org.jau.sys.dl.NativeLibrary.open(
id.ImplementationNativeLibraryBasename,
239 true ,
false , cl,
true ) )
241 org.jau.sys.JNILibrary.loadLibrary(
id.JavaNativeLibraryBasename,
false, cl);
244 }
catch (
final Throwable t) {
245 System.err.println(
"Caught "+t.getClass().getSimpleName()+
": "+t.getMessage()+
", while loading libs..");
251 System.err.println(
"Jaulib: Native libs loaded: "+ libsLoaded);
256 final Throwable[] t = {
null };
257 if( !PlatformToolkit.loadLibrary(
id.ImplementationNativeLibraryBasename, cl, t) ) {
258 throw new RuntimeException(
"Couldn't load native library with basename <"+
id.ImplementationNativeLibraryBasename+
">", t[0]);
260 if( !PlatformToolkit.loadLibrary(
id.JavaNativeLibraryBasename, cl, t) ) {
261 throw new RuntimeException(
"Couldn't load native library with basename <"+
id.JavaNativeLibraryBasename+
">", t[0]);
263 }
catch (
final Throwable e) {
264 System.err.println(
"Caught "+e.getClass().getSimpleName()+
": "+e.getMessage()+
", while loading libs (2) ..");
275 System.err.println(
"BlootoothFactory: Mapping '[org.|jau.]direct_bt.*' properties to native environment");
277 final Properties props =
doPrivileged(
new PrivilegedAction<Properties>() {
279 public Properties run() {
280 return System.getProperties();
283 final Enumeration<?> enums = props.propertyNames();
284 while (enums.hasMoreElements()) {
285 final String key = (String) enums.nextElement();
286 if( key.startsWith(
"org.direct_bt.") || key.startsWith(
"jau.direct_bt.") ||
287 key.startsWith(
"direct_bt.") )
289 final String value = props.getProperty(key);
291 System.err.println(
" <"+key+
"> := <"+value+
">");
293 setenv(key, value,
true );
296 }
catch (
final Throwable e) {
297 System.err.println(
"Caught exception while forwarding system properties: "+e.getMessage());
302 final Manifest manifest =
getManifest(cl,
new String[] {
"org.direct_bt" } );
303 final Attributes mfAttributes =
null != manifest ? manifest.getMainAttributes() :
null;
307 final String JAPIVersion =
null != mfAttributes ? mfAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION) :
null;
308 if (
null != JAPIVersion && JAPIVersion.equals(NAPIVersion) ==
false) {
309 final String[] NAPIVersionCode = NAPIVersion.split(
"\\D");
310 final String[] JAPIVersionCode = JAPIVersion.split(
"\\D");
311 if (JAPIVersionCode[0].equals(NAPIVersionCode[0]) ==
false) {
312 if (Integer.valueOf(JAPIVersionCode[0]) < Integer.valueOf(NAPIVersionCode[0])) {
313 throw new RuntimeException(
"Java library "+JAPIVersion+
" < native library "+NAPIVersion+
". Please update the Java library.");
315 throw new RuntimeException(
"Native library "+NAPIVersion+
" < java library "+JAPIVersion+
". Please update the native library.");
317 }
else if (JAPIVersionCode[1].equals(NAPIVersionCode[1]) ==
false) {
318 if (Integer.valueOf(JAPIVersionCode[1]) < Integer.valueOf(NAPIVersionCode[1])) {
319 throw new RuntimeException(
"Java library "+JAPIVersion+
" < native library "+NAPIVersion+
". Please update the Java library.");
321 throw new RuntimeException(
"Native library "+NAPIVersion+
" < java library "+JAPIVersion+
". Please update the native library.");
325 initializedID.set(
id );
327 APIVersion = JAPIVersion;
328 ImplVersion =
null != mfAttributes ? mfAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION) :
null;
330 System.err.println(
"Direct-BT loaded "+
id);
331 System.err.println(
"Direct-BT java api version "+JAPIVersion);
332 System.err.println(
"Direct-BT native api version "+NAPIVersion);
333 if(
null != mfAttributes ) {
334 final Attributes.Name[] versionAttributeNames =
new Attributes.Name[] {
335 Attributes.Name.SPECIFICATION_TITLE,
336 Attributes.Name.SPECIFICATION_VENDOR,
337 Attributes.Name.SPECIFICATION_VERSION,
338 Attributes.Name.IMPLEMENTATION_TITLE,
339 Attributes.Name.IMPLEMENTATION_VENDOR,
340 Attributes.Name.IMPLEMENTATION_VERSION,
341 new Attributes.Name(
"Implementation-Commit") };
342 for(
final Attributes.Name an : versionAttributeNames ) {
343 System.err.println(
" "+an+
": "+mfAttributes.getValue(an));
346 System.err.println(
" No Manifest available;");
349 }
catch (
final Throwable e) {
350 System.err.println(
"Error querying manifest information.");
356 private static synchronized BTManager getBTManager(
final Class<?> factoryImplClass)
357 throws BTException, NoSuchMethodException, SecurityException,
358 IllegalAccessException, IllegalArgumentException, InvocationTargetException
360 final Method m = factoryImplClass.getMethod(
"getManager");
361 return (BTManager)m.invoke(
null);
375 if( implIDs.contains(
id) ) {
378 return implIDs.add(
id);
387 if(
id.BluetoothManagerClassName.equals(fqBluetoothManagerImplementationClassName) ) {
416 throws BTException, NoSuchMethodException, SecurityException,
417 IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException
421 return getBTManager(
id);
447 throws BTException, NoSuchMethodException, SecurityException,
448 IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException
452 final Class<?> factoryImpl = Class.forName(
id.BluetoothManagerClassName);
453 return getBTManager(factoryImpl);
473 throws
BTException, NoSuchMethodException, SecurityException,
474 IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException
489 public static final Manifest
getManifest(
final ClassLoader cl,
final String[] extensions) {
490 final Manifest[] extManifests =
new Manifest[extensions.length];
492 final Enumeration<URL> resources = cl.getResources(
"META-INF/MANIFEST.MF");
493 while (resources.hasMoreElements()) {
494 final URL resURL = resources.nextElement();
496 System.err.println(
"resource: "+resURL);
498 final InputStream is = resURL.openStream();
499 final Manifest manifest;
501 manifest =
new Manifest(is);
505 }
catch (
final IOException e) {}
507 final Attributes attributes = manifest.getMainAttributes();
508 if(attributes !=
null) {
509 final String attributesExtName = attributes.getValue( Attributes.Name.EXTENSION_NAME );
510 for(
int i=0; i < extensions.length &&
null == extManifests[i]; i++) {
511 final String extension = extensions[i];
512 if( extension.equals( attributesExtName ) ) {
516 extManifests[i] = manifest;
521 }
catch (
final IOException ex) {
522 throw new RuntimeException(
"Unable to read manifest.", ex);
524 for(
int i=1; i<extManifests.length; i++) {
525 if(
null != extManifests[i] ) {
526 return extManifests[i];
532 public static void main(
final String args[]) {
535 System.err.println(VersionUtil.getPlatformInfo());
536 System.err.println(
"Version Info:");
538 System.err.println(v);
539 System.err.println(
"");
540 System.err.println(
"Full Manifest:");
541 System.err.println(v.getFullManifestInfo(
null));
543 System.err.println(
"Full Manifest:");
544 final Manifest manifest =
getManifest(
BTFactory.class.getClassLoader(),
new String[] {
"org.direct_bt" } );
545 final Attributes attr = manifest.getMainAttributes();
546 final Set<Object> keys = attr.keySet();
547 final StringBuilder sb =
new StringBuilder();
548 for(
final Iterator<Object> iter=keys.iterator(); iter.hasNext(); ) {
549 final Attributes.Name key = (Attributes.Name) iter.next();
550 final String val = attr.getValue(key);
555 sb.append(System.lineSeparator());
557 System.err.println(sb);
561 final List<BTAdapter> adapters = mngr.
getAdapters();
562 System.err.println(
"BTManager: adapters "+adapters.size());
564 for(
final Iterator<BTAdapter> iter = adapters.iterator(); iter.hasNext(); ++i) {
565 System.err.println(
"BTAdapter["+i+
"]: "+iter.next().toString());
567 }
catch (
BTException | NoSuchMethodException | SecurityException
568 | IllegalAccessException | IllegalArgumentException
569 | InvocationTargetException | ClassNotFoundException e) {
576 private native
static void setenv(String name, String value,
boolean overwrite);
Identifier names, allowing BTFactory#getBTManager(ImplementationIdentifier) to initialize the require...
final String JavaNativeLibraryBasename
Native library basename for the Java binding native library.
final String ImplementationNativeLibraryBasename
Native library basename for the implementation native library.
boolean equals(final Object other)
ImplementationIdentifier(final String BluetoothManagerClassName, final String ImplementationNativeLibraryBasename, final String JavaNativeLibraryBasename)
final String BluetoothManagerClassName
Fully qualified class name for the BTManager implementation.
One stop BTManager API entry point.
static synchronized BTManager getBTManager(final String fqBluetoothManagerImplementationClassName)
Returns an initialized BluetoothManager instance using the given fqBluetoothManagerImplementationClas...
static final boolean VERBOSE
Verbose logging enabled or disabled.
static native String getNativeVersion()
static synchronized BTManager getBTManager(final ImplementationIdentifier id)
Returns an initialized BluetoothManager instance using the given ImplementationIdentifier.
static synchronized boolean registerImplementationIdentifier(final ImplementationIdentifier id)
Registers a new ImplementationIdentifier to the internal list.
static void main(final String args[])
static void checkInitialized()
static final boolean DEBUG
Debug logging enabled or disabled.
static final boolean JAULIB_JARCACHE_USED
True if jaulib JAULIB_AVAILABLE and its org.jau.sys.PlatformProps#USE_TEMP_JAR_CACHE is true,...
static synchronized ImplementationIdentifier getImplementationIdentifier(final String fqBluetoothManagerImplementationClassName)
Returns the matching ImplementationIdentifier from the internal list or null if not found.
static final ImplementationIdentifier DirectBTImplementationID
ImplementationIdentifier for direct_bt implementation: {@value}
static final String getImplVersion()
Manifest's Attributes.Name#IMPLEMENTATION_VERSION or null if not available.
static boolean isInitialized()
static final String getAPIVersion()
Manifest's Attributes.Name#SPECIFICATION_VERSION or null if not available.
static native String getNativeAPIVersion()
static synchronized void initDirectBTLibrary()
Preloads the DirectBT native library w/o instantiating BTManager.
static final Manifest getManifest(final ClassLoader cl, final String[] extensions)
Helper function to retrieve a Manifest instance.
static final boolean JAULIB_AVAILABLE
True if jaulib org.jau.sys.PlatformProps has been detected.
static synchronized BTManager getDirectBTManager()
Returns an initialized BluetoothManager instance using the DirectBT implementation.
static< T > T doPrivileged(final PrivilegedAction< T > o)
Deprecated call to java.security.AccessController#doPrivileged(PrivilegedAction) w/o warnings.
This jaulib derived version info class is only usable when having jaulib available,...
static DirectBTVersion getInstance()
Returns a transient new instance.
A thread safe singleton handler of the BTAdapter manager, e.g.
List< BTAdapter > getAdapters()
Returns a list of BluetoothAdapters available in the system.