simplify the provider lookup, add logging Signed-off-by: Lukas Jungmann <lukas.jungmann@oracle.com>
diff --git a/api/src/main/java/jakarta/json/spi/JsonProvider.java b/api/src/main/java/jakarta/json/spi/JsonProvider.java index 13f89db..02ca904 100644 --- a/api/src/main/java/jakarta/json/spi/JsonProvider.java +++ b/api/src/main/java/jakarta/json/spi/JsonProvider.java
@@ -23,11 +23,15 @@ import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Optional; import java.util.ServiceLoader; +import java.util.logging.Level; +import java.util.logging.Logger; import jakarta.json.JsonArray; import jakarta.json.JsonArrayBuilder; @@ -74,6 +78,9 @@ private static final String DEFAULT_PROVIDER = "org.eclipse.parsson.JsonProviderImpl"; + /** A logger */ + private static final Logger LOG = Logger.getLogger(JsonProvider.class.getName()); + /** * Default constructor. */ @@ -100,26 +107,55 @@ * @return a JSON provider */ public static JsonProvider provider() { - if (LazyFactoryLoader.JSON_PROVIDER != null) { - return newInstance(LazyFactoryLoader.JSON_PROVIDER); + LOG.log(Level.FINE, "Checking system property {0}", JSONP_PROVIDER_FACTORY); + final String factoryClassName = System.getSecurityManager() != null + ? AccessController.doPrivileged((PrivilegedAction<String>) () -> System.getProperty(JSONP_PROVIDER_FACTORY)) + : System.getProperty(JSONP_PROVIDER_FACTORY); + if (factoryClassName != null) { + JsonProvider provider = newInstance(factoryClassName); + LOG.log(Level.FINE, "System property used; returning object [{0}]", + provider.getClass().getName()); + return provider; } + + LOG.log(Level.FINE, "Checking ServiceLoader"); ServiceLoader<JsonProvider> loader = ServiceLoader.load(JsonProvider.class); Iterator<JsonProvider> it = loader.iterator(); if (it.hasNext()) { - return it.next(); + JsonProvider provider = it.next(); + LOG.log(Level.FINE, "ServiceLoader loading Facility used; returning object [{0}]", + provider.getClass().getName()); + return provider; } // handling OSGi (specific default) if (isOsgi()) { - JsonProvider result = lookupUsingOSGiServiceLoader(JsonProvider.class); - if (result != null) { - return result; + LOG.log(Level.FINE, "Checking OSGi"); + JsonProvider provider = lookupUsingOSGiServiceLoader(JsonProvider.class); + if (provider != null) { + LOG.log(Level.FINE, "OSGi loading facility used; returning object [{0}].", + provider.getClass().getName()); + return provider; } } + // else no provider found + LOG.fine("Trying to create the platform default provider"); + return newInstance(DEFAULT_PROVIDER); + } + + /** + * Creates a new instance from the specified class + * @param className class to instantiate + * @return the JsonProvider instance + * @throws IllegalArgumentException for reflection issues + */ + private static JsonProvider newInstance(String className) { try { - Class<?> clazz = Class.forName(DEFAULT_PROVIDER); - return (JsonProvider) clazz.getConstructor().newInstance(); + checkPackageAccess(className); + @SuppressWarnings({"unchecked"}) + Class<JsonProvider> clazz = (Class<JsonProvider>) Class.forName(className); + return clazz.getConstructor().newInstance(); } catch (ClassNotFoundException x) { throw new JsonException( "Provider " + DEFAULT_PROVIDER + " not found", x); @@ -131,21 +167,6 @@ } /** - * Creates a new instance from the specified class - * @param clazz class to instance - * @return the JsonProvider instance - * @throws IllegalArgumentException for reflection issues - */ - private static JsonProvider newInstance(Class<? extends JsonProvider> clazz) { - checkPackageAccess(clazz.getName()); - try { - return clazz.getConstructor().newInstance(); - } catch (ReflectiveOperationException e) { - throw new IllegalArgumentException("Unable to create " + clazz.getName(), e); - } - } - - /** * Make sure that the current thread has an access to the package of the given name. * @param className The class name to check. */ @@ -617,37 +638,10 @@ @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 + } catch (Exception ex) { + LOG.log(Level.FINE, "Unable to find from OSGi: [" + serviceClass.getName() + "]", ex); 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. - * In case of errors an IllegalStateException is thrown. - * - */ - @SuppressWarnings("unchecked") - private static class LazyFactoryLoader { - - /** - * JSON provider class - */ - private static final Class<? extends JsonProvider> JSON_PROVIDER; - - static { - String className = System.getProperty(JSONP_PROVIDER_FACTORY); - if (className != null) { - try { - JSON_PROVIDER = (Class<? extends JsonProvider>) Class.forName(className); - } catch (ReflectiveOperationException e) { - throw new IllegalStateException("Unable to create " + className, e); - } - } else { - JSON_PROVIDER = null; - } - } - } }
diff --git a/api/src/main/java/module-info.java b/api/src/main/java/module-info.java index 12cd6ba..4ff532f 100644 --- a/api/src/main/java/module-info.java +++ b/api/src/main/java/module-info.java
@@ -18,6 +18,7 @@ * Jakarta JSON Processing API. */ module jakarta.json { + requires java.logging; exports jakarta.json; exports jakarta.json.spi; exports jakarta.json.stream;