#384: 2.0.1 API imports org.eclipse.jsonp by OSGi headers
Signed-off-by: Lukas Jungmann <lukas.jungmann@oracle.com>
diff --git a/api/pom.xml b/api/pom.xml
index b077e66..b9980fb 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -341,6 +341,12 @@
<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,
+ !org.glassfish.json,
+ *
+ </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 ea56275..15d7aee 100644
--- a/api/src/main/java/jakarta/json/spi/JsonProvider.java
+++ b/api/src/main/java/jakarta/json/spi/JsonProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -25,6 +25,7 @@
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
+import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
@@ -68,9 +69,19 @@
if (it.hasNext()) {
return it.next();
}
+
+ // handling OSGi (specific default)
+ if (isOsgi()) {
+ JsonProvider result = lookupUsingOSGiServiceLoader(JsonProvider.class);
+ if (result != null) {
+ return result;
+ }
+ }
+
try {
+ checkPackageAccess(DEFAULT_PROVIDER);
Class<?> clazz = Class.forName(DEFAULT_PROVIDER);
- return (JsonProvider) clazz.newInstance();
+ return (JsonProvider) clazz.getConstructor().newInstance();
} catch (ClassNotFoundException x) {
throw new JsonException(
"Provider " + DEFAULT_PROVIDER + " not found", x);
@@ -477,4 +488,58 @@
public JsonNumber createValue(BigInteger value) {
throw new UnsupportedOperationException();
}
+
+ /** 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() {
+ checkPackageAccess(OSGI_SERVICE_LOADER_CLASS_NAME);
+ 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;
+ }
+ }
+
+ /**
+ * Make sure that the current thread has an access to the package of the given name.
+ * @param className The class name to check.
+ */
+ private static void checkPackageAccess(String className) {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null) {
+ int i = className.lastIndexOf('.');
+ if (i != -1) {
+ s.checkPackageAccess(className.substring(0, i));
+ }
+ }
+ }
}