Add compatibility with HK2 service locator lookup Signed-off-by: Lukas Jungmann <lukas.jungmann@oracle.com>
diff --git a/api/pom.xml b/api/pom.xml index 4395bb1..cf6547f 100644 --- a/api/pom.xml +++ b/api/pom.xml
@@ -331,6 +331,11 @@ <Bundle-Description>Jakarta JSON Processing API ${spec.version}</Bundle-Description> <Specification-Vendor>${vendor.name}</Specification-Vendor> <Implementation-Build-Id>${buildNumber}</Implementation-Build-Id> + <DynamicImport-Package>*</DynamicImport-Package> + <Import-Package> + !org.glassfish.hk2.osgiresourcelocator, + * + </Import-Package> </instructions> </configuration> <executions>
diff --git a/api/src/main/java/jakarta/json/spi/JsonProvider.java b/api/src/main/java/jakarta/json/spi/JsonProvider.java index 4a01d27..3cfbee6 100644 --- a/api/src/main/java/jakarta/json/spi/JsonProvider.java +++ b/api/src/main/java/jakarta/json/spi/JsonProvider.java
@@ -20,6 +20,7 @@ import java.io.OutputStream; import java.io.Reader; import java.io.Writer; +import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Collection; @@ -107,6 +108,15 @@ if (it.hasNext()) { return it.next(); } + + // handling OSGi (specific default) + if (isOsgi()) { + JsonProvider result = lookupUsingOSGiServiceLoader(JsonProvider.class); + if (result != null) { + return result; + } + } + try { Class<?> clazz = Class.forName(DEFAULT_PROVIDER); return (JsonProvider) clazz.getConstructor().newInstance(); @@ -573,7 +583,46 @@ throw new UnsupportedOperationException(number + " type is not known"); } } - + + /** OSGI aware service loader by HK2 */ + private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "org.glassfish.hk2.osgiresourcelocator.ServiceLoader"; + + /** + * Check availability of HK2 service loader. + * + * @return true if HK2 service locator is available + */ + private static boolean isOsgi() { + try { + Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME); + return true; + } catch (ClassNotFoundException ignored) { + } + return false; + } + + /** + * Lookup the service class by the HK2 service locator. + * + * @param serviceClass service class + * @param <T> type of the service + * @return a provider + */ + private static <T> T lookupUsingOSGiServiceLoader(Class<? extends T> serviceClass) { + try { + // Use reflection to avoid having any dependendcy on HK2 ServiceLoader class + Class<?>[] args = new Class<?>[]{serviceClass}; + Class<?> target = Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME); + Method m = target.getMethod("lookupProviderInstances", Class.class); + @SuppressWarnings({"unchecked"}) + Iterator<? extends T> iter = ((Iterable<? extends T>) m.invoke(null, (Object[]) args)).iterator(); + return iter.hasNext() ? iter.next() : null; + } catch (Exception ignored) { + // log and continue + return null; + } + } + /** * Lazy loads the class specified in System property with the key JSONP_PROVIDER_FACTORY. * If no property is set, the value of {@link #JSON_PROVIDER} will be null.