#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));
+            }
+        }
+    }
 }