summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2020-02-09 14:48:51 +0100
committerSven Gothel <[email protected]>2020-02-09 14:48:51 +0100
commit4a656b0ee13332dd635f8f88b8a5c9d564a63f81 (patch)
tree5ea1c546e6ce2d7d6b30df90c56efd4c4d135f95
parentb253c12a17b4501dbc44ad0400e7edae619ec895 (diff)
BluetoothFactory handles API verification via native-API and Manifest attributes; Fix manifest.txt.in ...v2.0.0
Also show Manifest specification + implementation details incl git-commit-sha1 when run in '-Dorg.tinyb.verbose=true' mode.
-rw-r--r--java/manifest.txt.in16
-rw-r--r--java/org/tinyb/BluetoothFactory.java155
-rw-r--r--java/tinyb/dbus/DBusManager.java28
-rw-r--r--java/tinyb/dbus/DBusObject.java9
4 files changed, 175 insertions, 33 deletions
diff --git a/java/manifest.txt.in b/java/manifest.txt.in
index 40bd5d85..bac86421 100644
--- a/java/manifest.txt.in
+++ b/java/manifest.txt.in
@@ -6,8 +6,6 @@ Bundle-SymbolicName: org.tinyb
Bundle-Version: @VERSION_SHORT@
Export-Package: org.tinyb
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
-
-Name: tinyb/
Package-Title: org.tinyb
Package-Vendor: ZAFENA AB
Package-Version: @VERSION_SHORT@
@@ -19,3 +17,17 @@ Implementation-Vendor: ZAFENA AB
Implementation-Version: @VERSION@
Implementation-Commit: @VERSION_SHA1@
Implementation-URL: http://www.zafena.se/
+Extension-Name: org.tinyb
+Trusted-Library: true
+Permissions: all-permissions
+Application-Library-Allowable-Codebase: *
+
+Name: org/tinyb/
+Sealed: true
+
+Name: tinyb/dbus/
+Sealed: true
+
+Name: tinyb/hci/
+Sealed: true
+
diff --git a/java/org/tinyb/BluetoothFactory.java b/java/org/tinyb/BluetoothFactory.java
index b2b90384..8f01db15 100644
--- a/java/org/tinyb/BluetoothFactory.java
+++ b/java/org/tinyb/BluetoothFactory.java
@@ -24,11 +24,112 @@
*/
package org.tinyb;
+import java.io.IOException;
+import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
public class BluetoothFactory {
/**
+ * Name of the native implementation native library basename: {@value}
+ */
+ public static final String ImplNativeLibBasename = "tinyb";
+
+ /**
+ * Name of the Jave native library basename: {@value}
+ */
+ public static final String JavaNativeLibBasename = "javatinyb";
+
+ /**
+ * Manifest's {@link Attributes.Name#SPECIFICATION_VERSION} or {@code null} if not available.
+ */
+ public static final String APIVersion;
+
+ /**
+ * Manifest's {@link Attributes.Name#IMPLEMENTATION_VERSION} or {@code null} if not available.
+ */
+ public static final String ImplVersion;
+
+ static final boolean VERBOSE;
+
+ static {
+ {
+ final String v = System.getProperty("org.tinyb.verbose", "false");
+ VERBOSE = Boolean.valueOf(v);
+ }
+ try {
+ System.loadLibrary(ImplNativeLibBasename);
+ } catch (final Throwable e) {
+ System.err.println("Failed to load native library "+ImplNativeLibBasename);
+ e.printStackTrace();
+ throw e; // fwd exception - end here
+ }
+ try {
+ System.loadLibrary(JavaNativeLibBasename);
+ } catch (final Throwable e) {
+ System.err.println("Failed to load native library "+JavaNativeLibBasename);
+ e.printStackTrace();
+ throw e; // fwd exception - end here
+ }
+ try {
+ final Manifest manifest = getManifest(BluetoothFactory.class.getClassLoader(), new String[] { "org.tinyb" } );
+ final Attributes mfAttributes = null != manifest ? manifest.getMainAttributes() : null;
+
+ // major.minor must match!
+ final String NAPIVersion = getNativeAPIVersion();
+ final String JAPIVersion = null != mfAttributes ? mfAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION) : null;
+ if ( null != JAPIVersion && JAPIVersion.equals(NAPIVersion) == false) {
+ final String[] NAPIVersionCode = NAPIVersion.split("\\D");
+ final String[] JAPIVersionCode = JAPIVersion.split("\\D");
+ if (JAPIVersionCode[0].equals(NAPIVersionCode[0]) == false) {
+ if (Integer.valueOf(JAPIVersionCode[0]) < Integer.valueOf(NAPIVersionCode[0])) {
+ throw new RuntimeException("Java library "+JAPIVersion+" < native library "+NAPIVersion+". Please update the Java library.");
+ } else {
+ throw new RuntimeException("Native library "+NAPIVersion+" < java library "+JAPIVersion+". Please update the native library.");
+ }
+ } else if (JAPIVersionCode[1].equals(NAPIVersionCode[1]) == false) {
+ if (Integer.valueOf(JAPIVersionCode[1]) < Integer.valueOf(NAPIVersionCode[1])) {
+ throw new RuntimeException("Java library "+JAPIVersion+" < native library "+NAPIVersion+". Please update the Java library.");
+ } else {
+ throw new RuntimeException("Native library "+NAPIVersion+" < java library "+JAPIVersion+". Please update the native library.");
+ }
+ }
+ }
+ APIVersion = JAPIVersion;
+ ImplVersion = null != mfAttributes ? mfAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION) : null;
+ if( VERBOSE ) {
+ System.err.println("tinyb2 java api version "+JAPIVersion);
+ System.err.println("tinyb2 native api version "+NAPIVersion);
+ if( null != mfAttributes ) {
+ final Attributes.Name[] versionAttributeNames = new Attributes.Name[] {
+ Attributes.Name.SPECIFICATION_TITLE,
+ Attributes.Name.SPECIFICATION_VENDOR,
+ Attributes.Name.SPECIFICATION_VERSION,
+ Attributes.Name.IMPLEMENTATION_TITLE,
+ Attributes.Name.IMPLEMENTATION_VENDOR,
+ Attributes.Name.IMPLEMENTATION_VERSION,
+ new Attributes.Name("Implementation-Commit") };
+ for( final Attributes.Name an : versionAttributeNames ) {
+ System.err.println(" "+an+": "+mfAttributes.getValue(an));
+ }
+ } else {
+ System.err.println(" No Manifest available;");
+ }
+ }
+ } catch (final Throwable e) {
+ System.err.println("Error querying manifest information.");
+ e.printStackTrace();
+ throw e; // fwd exception - end here
+ }
+ }
+
+ /**
* Fully qualified factory class name for D-Bus implementation: {@value}
* <p>
* This value is exposed for convenience, user implementations are welcome.
@@ -105,5 +206,59 @@ public class BluetoothFactory {
return tinyb.dbus.DBusManager.getBluetoothManager();
}
+ private static final boolean debug = false;
+
+ private static final Manifest getManifest(final ClassLoader cl, final String[] extensions) {
+ final Manifest[] extManifests = new Manifest[extensions.length];
+ try {
+ final Enumeration<URL> resources = cl.getResources("META-INF/MANIFEST.MF");
+ while (resources.hasMoreElements()) {
+ final URL resURL = resources.nextElement();
+ if( debug ) {
+ System.err.println("resource: "+resURL);
+ }
+ final InputStream is = resURL.openStream();
+ final Manifest manifest;
+ try {
+ manifest = new Manifest(is);
+ } finally {
+ try {
+ is.close();
+ } catch (final IOException e) {}
+ }
+ final Attributes attributes = manifest.getMainAttributes();
+ if(attributes != null) {
+ final String attributesExtName = attributes.getValue( Attributes.Name.EXTENSION_NAME );
+ if( debug ) {
+ System.err.println("resource: "+resURL+", attributes extName "+attributesExtName+", count "+attributes.size());
+ final Set<Object> keys = attributes.keySet();
+ for(final Iterator<Object> iter=keys.iterator(); iter.hasNext(); ) {
+ final Attributes.Name key = (Attributes.Name) iter.next();
+ final String val = attributes.getValue(key);
+ System.err.println(" "+key+": "+val);
+ }
+ }
+ for(int i=0; i < extensions.length && null == extManifests[i]; i++) {
+ final String extension = extensions[i];
+ if( extension.equals( attributesExtName ) ) {
+ if( 0 == i ) {
+ return manifest; // 1st one has highest prio - done
+ }
+ extManifests[i] = manifest;
+ }
+ }
+ }
+ }
+ } catch (final IOException ex) {
+ throw new RuntimeException("Unable to read manifest.", ex);
+ }
+ for(int i=1; i<extManifests.length; i++) {
+ if( null != extManifests[i] ) {
+ return extManifests[i];
+ }
+ }
+ return null;
+ }
+
private native static String getNativeAPIVersion();
}
diff --git a/java/tinyb/dbus/DBusManager.java b/java/tinyb/dbus/DBusManager.java
index e3e86ab6..2b5efe65 100644
--- a/java/tinyb/dbus/DBusManager.java
+++ b/java/tinyb/dbus/DBusManager.java
@@ -43,15 +43,6 @@ public class DBusManager implements BluetoothManager
private long nativeInstance;
private static DBusManager inst;
- static {
- try {
- System.loadLibrary("tinyb");
- System.loadLibrary("javatinyb");
- } catch (final UnsatisfiedLinkError e) {
- System.err.println("Native code library failed to load.\n" + e);
- }
- }
-
private native static String getNativeAPIVersion();
public native BluetoothType getBluetoothType();
@@ -132,25 +123,6 @@ public class DBusManager implements BluetoothManager
{
if (inst == null)
{
- final String nativeAPIVersion = getNativeAPIVersion();
- final String APIVersion = DBusManager.class.getPackage().getSpecificationVersion();
- if ( null != APIVersion && APIVersion.equals(nativeAPIVersion) == false) {
- final String[] nativeAPIVersionCode = nativeAPIVersion.split("\\D");
- final String[] APIVersionCode = APIVersion.split("\\D");
- if (APIVersionCode[0].equals(nativeAPIVersionCode[0]) == false) {
- if (Integer.valueOf(APIVersionCode[0]) < Integer.valueOf(nativeAPIVersionCode[0]))
- throw new RuntimeException("Java library is out of date. Please update the Java library.");
- else throw new RuntimeException("Native library is out of date. Please update the native library.");
- }
- else if (APIVersionCode[0].equals("0") == true) {
- if (Integer.valueOf(APIVersionCode[1]) < Integer.valueOf(nativeAPIVersionCode[1]))
- throw new RuntimeException("Java library is out of date. Please update the Java library.");
- else throw new RuntimeException("Native library is out of date. Please update the native library.");
- }
- else if (Integer.valueOf(APIVersionCode[1]) < Integer.valueOf(nativeAPIVersionCode[1]))
- System.err.println("Java library is out of date. Please update the Java library.");
- else System.err.println("Native library is out of date. Please update the native library.");
- }
inst = new DBusManager();
inst.init();
}
diff --git a/java/tinyb/dbus/DBusObject.java b/java/tinyb/dbus/DBusObject.java
index a9095d1a..66cdde30 100644
--- a/java/tinyb/dbus/DBusObject.java
+++ b/java/tinyb/dbus/DBusObject.java
@@ -28,6 +28,7 @@
package tinyb.dbus;
+import org.tinyb.BluetoothFactory;
import org.tinyb.BluetoothObject;
import org.tinyb.BluetoothType;
@@ -38,9 +39,11 @@ public class DBusObject implements BluetoothObject
static {
try {
- System.loadLibrary("javatinyb");
- } catch (final UnsatisfiedLinkError e) {
- System.err.println("Native code library failed to load.\n" + e);
+ System.loadLibrary(BluetoothFactory.JavaNativeLibBasename);
+ } catch (final Throwable e) {
+ System.err.println("Failed to load native library "+BluetoothFactory.JavaNativeLibBasename);
+ e.printStackTrace();
+ throw e; // fwd exception - end here
}
}