diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 25376ac8..5922b5a8 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -1,5 +1,5 @@ # -# Copyright (c) 2021 Contributors to the Eclipse Foundation +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation # # This program and the accompanying materials are made available under the # terms of the Eclipse Public License v. 2.0 which is available at @@ -16,6 +16,10 @@ on: pull_request: push: +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + jobs: build: name: Test on JDK ${{ matrix.java_version }} @@ -23,13 +27,13 @@ jobs: strategy: matrix: - java_version: [ 11, 17-ea ] + java_version: [ 11, 17, 21 ] steps: - name: Checkout for build - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3 - name: Set up JDK - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: 'zulu' java-version: ${{ matrix.java_version }} diff --git a/api/pom.xml b/api/pom.xml index 61599d92..2f76e074 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -1,7 +1,7 @@ + =1.0.0)(!(version>=2.0.0)))";resolution:=optional, + osgi.serviceloader; + filter:="(osgi.serviceloader=jakarta.json.spi.JsonProvider)"; + osgi.serviceloader="jakarta.json.spi.JsonProvider"; + cardinality:=multiple;resolution:=optional + ]]> + @@ -402,7 +406,6 @@ Use is subject to com.github.spotbugs spotbugs-maven-plugin - true true ${spotbugs.exclude} High diff --git a/api/src/main/java/jakarta/json/EmptyArray.java b/api/src/main/java/jakarta/json/EmptyArray.java index fcc3f5a7..1d627c3f 100644 --- a/api/src/main/java/jakarta/json/EmptyArray.java +++ b/api/src/main/java/jakarta/json/EmptyArray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -32,6 +32,9 @@ final class EmptyArray extends AbstractList implements JsonArray, Ser /** for serialization */ private static final long serialVersionUID = 7295439472061642859L; + /** Default constructor. */ + EmptyArray() {} + @Override public JsonValue get(int index) { throw new IndexOutOfBoundsException("Index: " + index); diff --git a/api/src/main/java/jakarta/json/EmptyObject.java b/api/src/main/java/jakarta/json/EmptyObject.java index f8c4aa8d..5210318b 100644 --- a/api/src/main/java/jakarta/json/EmptyObject.java +++ b/api/src/main/java/jakarta/json/EmptyObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -31,6 +31,9 @@ final class EmptyObject extends AbstractMap implements JsonOb /** for serialization */ private static final long serialVersionUID = -1461653546889072583L; + /** Default constructor. */ + EmptyObject() {} + @Override public Set> entrySet() { return Collections.>emptySet(); diff --git a/api/src/main/java/jakarta/json/Json.java b/api/src/main/java/jakarta/json/Json.java index 373ab4c5..736f7aa2 100644 --- a/api/src/main/java/jakarta/json/Json.java +++ b/api/src/main/java/jakarta/json/Json.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024 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 @@ -255,7 +255,7 @@ public static JsonArrayBuilder createArrayBuilder(JsonArray array) { /** * Creates a JSON array builder, initialized with the content of specified {@code collection}. - * If the @{code collection} contains {@link Optional}s then resulting JSON array builder + * If the {@code collection} contains {@link Optional}s then resulting JSON array builder * contains the value from the {@code collection} only if the {@link Optional} is not empty. * * @param collection the initial data for the builder diff --git a/api/src/main/java/jakarta/json/spi/JsonProvider.java b/api/src/main/java/jakarta/json/spi/JsonProvider.java index ee0ffa1e..666f99e3 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, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024 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 @@ -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 @@ public abstract class JsonProvider { private static final String DEFAULT_PROVIDER = "org.eclipse.parsson.JsonProviderImpl"; + /** A logger */ + private static final Logger LOG = Logger.getLogger(JsonProvider.class.getName()); + /** * Default constructor. */ @@ -103,7 +110,7 @@ protected JsonProvider() { public static JsonProvider provider() { return provider(null); } - + /** * Creates a JSON provider object. * @@ -126,54 +133,67 @@ public static JsonProvider provider() { * @param providerClassName The name of the class to be found from the {@link ServiceLoader#load(Class)}. * @return a JSON provider * - * @since 2.1.1 + * @since 2.2.0 */ public static JsonProvider provider(String providerClassName) { - 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) () -> 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 loader = ServiceLoader.load(JsonProvider.class); Iterator it = loader.iterator(); while (it.hasNext()) { JsonProvider provider = it.next(); if (providerClassName == null || provider.getClass().getName().equals(providerClassName)) { + 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; } } - try { - Class clazz = Class.forName(DEFAULT_PROVIDER); - return (JsonProvider) clazz.getConstructor().newInstance(); - } catch (ClassNotFoundException x) { - throw new JsonException( - "Provider " + DEFAULT_PROVIDER + " not found", x); - } catch (Exception x) { - throw new JsonException( - "Provider " + DEFAULT_PROVIDER + " could not be instantiated: " + x, - x); - } + // 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 clazz class to instance + * @param className name of the class to instantiate * @return the JsonProvider instance - * @throws IllegalArgumentException for reflection issues + * @throws JsonException for issues during creation of an instance of the JsonProvider */ - private static JsonProvider newInstance(Class clazz) { - checkPackageAccess(clazz.getName()); + private static JsonProvider newInstance(String className) { try { + checkPackageAccess(className); + @SuppressWarnings({"unchecked"}) + Class clazz = (Class) Class.forName(className); return clazz.getConstructor().newInstance(); - } catch (ReflectiveOperationException e) { - throw new IllegalArgumentException("Unable to create " + clazz.getName(), e); + } catch (ClassNotFoundException x) { + throw new JsonException( + "Provider " + className + " not found", x); + } catch (Exception x) { + throw new JsonException( + "Provider " + className + " could not be instantiated: " + x, + x); } } @@ -649,37 +669,10 @@ private static T lookupUsingOSGiServiceLoader(Class serviceClas @SuppressWarnings({"unchecked"}) Iterator iter = ((Iterable) 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 JSON_PROVIDER; - - static { - String className = System.getProperty(JSONP_PROVIDER_FACTORY); - if (className != null) { - try { - JSON_PROVIDER = (Class) 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/jakarta/json/stream/JsonParser.java b/api/src/main/java/jakarta/json/stream/JsonParser.java index 0f718492..bd41d204 100644 --- a/api/src/main/java/jakarta/json/stream/JsonParser.java +++ b/api/src/main/java/jakarta/json/stream/JsonParser.java @@ -128,7 +128,7 @@ * while (parser.hasNext() { * Event event = parser.next(); * if (event == JsonParser.Event.KEY_NAME ) { - * String key = getString(); + * String key = parser.getString(); * event = parser.next(); * if (key.equals("phoneNumber") { * JsonArray phones = parser.getArray(); diff --git a/api/src/main/java/jakarta/json/stream/JsonParsingException.java b/api/src/main/java/jakarta/json/stream/JsonParsingException.java index 06c52c6d..c657083e 100644 --- a/api/src/main/java/jakarta/json/stream/JsonParsingException.java +++ b/api/src/main/java/jakarta/json/stream/JsonParsingException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -30,7 +30,7 @@ public class JsonParsingException extends JsonException { /** * The location of the incorrect JSON. */ - private final JsonLocation location; + private transient final JsonLocation location; /** * Constructs a new runtime exception with the specified detail message. diff --git a/api/src/main/java/module-info.java b/api/src/main/java/module-info.java index 12cd6ba9..aad8a0e0 100644 --- a/api/src/main/java/module-info.java +++ b/api/src/main/java/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -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; diff --git a/impl-tck/pom.xml b/impl-tck/pom.xml deleted file mode 100644 index ebe4884a..00000000 --- a/impl-tck/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - 4.0.0 - - org.eclipse.jsonp - tck-project - 2.1.0-SNAPSHOT - pom - - - tck-tests - tck-tests-pluggability - - - - 2.1.0 - 1.1.0 - 2.1.0-SNAPSHOT - - - - - - - - org.eclipse.parsson - parsson - ${jsonp-impl.version} - test - - - - - - - - - - - diff --git a/impl-tck/tck-tests-pluggability/pom.xml b/impl-tck/tck-tests-pluggability/pom.xml deleted file mode 100644 index f5fa1650..00000000 --- a/impl-tck/tck-tests-pluggability/pom.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - 4.0.0 - - - org.eclipse.jsonp - tck-project - 2.1.0-SNAPSHOT - - - jakarta.json-tck-tests-pluggability - - - - jakarta.json - jakarta.json-tck-tests-pluggability - ${jsonp-tck.version} - test - - - jakarta.json - jakarta.json-tck-common - ${jsonp-tck.version} - test - - - - - - - maven-surefire-plugin - 3.0.0-M4 - - - jakarta.json:jakarta.json-tck-tests-pluggability - - false - true - - - - - diff --git a/impl-tck/tck-tests/pom.xml b/impl-tck/tck-tests/pom.xml deleted file mode 100644 index 3e376a4c..00000000 --- a/impl-tck/tck-tests/pom.xml +++ /dev/null @@ -1,122 +0,0 @@ - - - - - 4.0.0 - - - org.eclipse.jsonp - tck-project - 2.1.0-SNAPSHOT - - - jakarta.json-tck-tests - - - - jakarta.json - jakarta.json-tck-tests - ${jsonp-tck.version} - test - - - jakarta.json - jakarta.json-tck-common - ${jsonp-tck.version} - test - - - org.netbeans.tools - sigtest-maven-plugin - 1.4 - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.2.0 - - - copy - generate-test-sources - - copy - - - - - jakarta.json - jakarta.json-api - ${jsonp-api.version} - jar - true - ${project.build.directory}/signaturedirectory - jakarta.json-api.jar - - - - - - - - maven-surefire-plugin - 3.0.0-M4 - - - jakarta.json:jakarta.json-tck-tests - - false - true - 1 - false - - - - sigtests - - test - - - - **/JSONPSigTest.java - - - ${project.build.directory}/jdk11-bundle - ${project.build.directory}/signaturedirectory/jakarta.json-api.jar:${project.build.directory}/jdk11-bundle/java.base:${project.build.directory}/jdk11-bundle/java.rmi:${project.build.directory}/jdk11-bundle/java.sql:${project.build.directory}/jdk11-bundle/java.naming - - - - - default-test - - - **/JSONPSigTest.java - - - - - - - - diff --git a/tck/tck-dist-eftl/src/main/bin/pom.xml b/tck/tck-dist-eftl/src/main/bin/pom.xml index 09be95a5..7cf50b2b 100644 --- a/tck/tck-dist-eftl/src/main/bin/pom.xml +++ b/tck/tck-dist-eftl/src/main/bin/pom.xml @@ -16,47 +16,36 @@ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 --> - - + 4.0.0 - org.eclipse.ee4j project 1.0.7 - jakarta.json jakarta.json-tck-impl ${project.version} pom - jakarta.json jakarta.json-api 2.1.0 - org.eclipse.parsson parsson 1.1.0 - ${project.version} - UTF-8 \${project.build.directory}/jdk-bundle - 2.1.0 true - @@ -68,12 +57,10 @@ - tck-tests tck-tests-pluggability - \${jsonp-api.groupId} @@ -92,7 +79,6 @@ test - verify @@ -120,14 +106,14 @@ maven-surefire-plugin 3.0.0-M5 + false false \${impl.alltests} 1 false \${jimage.dir} - - \${project.build.directory}/signaturedirectory/jakarta.json-api.jar:\${jimage.dir}/java.base:\${jimage.dir}/java.rmi:\${jimage.dir}/java.sql:\${jimage.dir}/java.naming + \${project.build.directory}/signaturedirectory/jakarta.json-api.jar:\${jimage.dir}/java.base:\${jimage.dir}/java.rmi:\${jimage.dir}/java.sql:\${jimage.dir}/java.naming @@ -135,7 +121,6 @@ - single-test @@ -149,4 +134,4 @@ - + \ No newline at end of file diff --git a/tck/tck-dist-eftl/src/main/bin/tck-tests-pluggability/pom.xml b/tck/tck-dist-eftl/src/main/bin/tck-tests-pluggability/pom.xml index 61f8934e..80a0d74c 100644 --- a/tck/tck-dist-eftl/src/main/bin/tck-tests-pluggability/pom.xml +++ b/tck/tck-dist-eftl/src/main/bin/tck-tests-pluggability/pom.xml @@ -16,21 +16,15 @@ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 --> - - + 4.0.0 - jakarta.json jakarta.json-tck-impl ${project.version} ../pom.xml - tck-tests-pluggability - jakarta.json @@ -38,7 +32,6 @@ test - @@ -48,8 +41,9 @@ jakarta.json:jakarta.json-tck-tests-pluggability + false - + \ No newline at end of file diff --git a/tck/tck-tests/src/main/java/ee/jakarta/tck/jsonp/api/provider/JsonProviderTest.java b/tck/tck-tests/src/main/java/ee/jakarta/tck/jsonp/api/provider/JsonProviderTest.java index 6cb37497..17731d23 100644 --- a/tck/tck-tests/src/main/java/ee/jakarta/tck/jsonp/api/provider/JsonProviderTest.java +++ b/tck/tck-tests/src/main/java/ee/jakarta/tck/jsonp/api/provider/JsonProviderTest.java @@ -34,6 +34,8 @@ import jakarta.json.stream.JsonGeneratorFactory; import jakarta.json.stream.JsonParser; import jakarta.json.stream.JsonParserFactory; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -46,7 +48,23 @@ public class JsonProviderTest { private static final String JSONP_PROVIDER_FACTORY = "jakarta.json.provider"; - + private String factoryValue; + + @BeforeEach + public void setUp() { + factoryValue = System.getProperty(JSONP_PROVIDER_FACTORY); + System.clearProperty(JSONP_PROVIDER_FACTORY); + } + + @AfterEach + public void reset() { + if (factoryValue != null) { + System.setProperty(JSONP_PROVIDER_FACTORY, factoryValue); + } else { + System.clearProperty(JSONP_PROVIDER_FACTORY); + } + } + /** * Verifies it is possible to obtain the JsonProvider implementation from a System property. */