From f8d8895f743cd829ea2c1f8df2f2dc26a7b6df49 Mon Sep 17 00:00:00 2001 From: jansupol Date: Tue, 27 Aug 2024 00:02:17 +0200 Subject: [PATCH] Allow to disable JSON-B using System properties Signed-off-by: jansupol --- .../glassfish/jersey/ApplicationSupplier.java | 33 ++++ .../glassfish/jersey/CommonProperties.java | 13 ++ .../internal/util/PropertiesHelper.java | 23 ++- .../internal/util/PropertiesHelperTest.java | 13 +- .../jersey/server/ResourceConfig.java | 5 +- docs/src/main/docbook/appendix-properties.xml | 18 ++ docs/src/main/docbook/jersey.ent | 1 + .../jersey/jsonb/JsonBindingFeature.java | 89 ++++++++- .../jersey/jsonb/localization.properties | 4 +- .../jsonb/internal/JsonbDisabledTest.java | 178 +++++++++++++++++- 10 files changed, 360 insertions(+), 17 deletions(-) create mode 100644 core-common/src/main/java/org/glassfish/jersey/ApplicationSupplier.java diff --git a/core-common/src/main/java/org/glassfish/jersey/ApplicationSupplier.java b/core-common/src/main/java/org/glassfish/jersey/ApplicationSupplier.java new file mode 100644 index 0000000000..1eb9ca5c72 --- /dev/null +++ b/core-common/src/main/java/org/glassfish/jersey/ApplicationSupplier.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 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 + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + + +package org.glassfish.jersey; + +import javax.ws.rs.core.Application; + +/** + * Implementation of this interface is capable of returning {@link Application}. + */ +public interface ApplicationSupplier { + /** + * Get Application. + * + * @return Application. + */ + Application getApplication(); + +} diff --git a/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java b/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java index f1a713e246..efe56c7376 100644 --- a/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java +++ b/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java @@ -130,6 +130,19 @@ public final class CommonProperties { */ public static final String JSON_BINDING_FEATURE_DISABLE_SERVER = "jersey.config.server.disableJsonBinding"; + /** + * Disables configuration of Json Binding (JSR-367) feature for {@link javax.ws.rs.core.Application} subclasses whose + * package names are specified as a value. The value is comma-separated string defining prefixes of the application + * package names. + *

+ * By default, Json Binding is automatically enabled. + *

+ * The name of the configuration property is {@value}. + *

+ * @since 2.45 + */ + public static final String JSON_BINDING_FEATURE_DISABLE_APPLICATION = "jersey.config.application.disableJsonBinding"; + /** * If {@code true} then disable configuration of Json Processing (JSR-353) feature. *

diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/util/PropertiesHelper.java b/core-common/src/main/java/org/glassfish/jersey/internal/util/PropertiesHelper.java index cb1c87b864..45d28277c7 100644 --- a/core-common/src/main/java/org/glassfish/jersey/internal/util/PropertiesHelper.java +++ b/core-common/src/main/java/org/glassfish/jersey/internal/util/PropertiesHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -389,6 +389,27 @@ public static boolean isProperty(final Object value) { } } + /** + * Converts the property value to {@code boolean} and checks it is {@code true} or empty. + * Returns {@code true} if the value is {@code true} or empty but not {@code null}. + * + *

+ * The rationale behind this is that system property {@code -Dprop=true} is the same as {@code -Dprop}. + * The property {@code -Dprop=false} behaves as if the {@code -Dprop} is not set at all. + *

+ * + * @param value property value. + * @return {@code boolean} property value or {@code true} if the property value is not set or {@code false} if the property + * is otherwise not convertible. + */ + public static boolean isPropertyOrNotSet(final Object value) { + if (value instanceof Boolean) { + return Boolean.class.cast(value); + } else { + return value != null && ("".equals(value.toString()) || Boolean.parseBoolean(value.toString())); + } + } + /** * Faster replacement of {@code RuntimeType#name().toLowerCase(Locale.ROOT)} * @param runtimeType The runtime type to lower case diff --git a/core-common/src/test/java/org/glassfish/jersey/internal/util/PropertiesHelperTest.java b/core-common/src/test/java/org/glassfish/jersey/internal/util/PropertiesHelperTest.java index 68f6aac7d4..69acabf48b 100644 --- a/core-common/src/test/java/org/glassfish/jersey/internal/util/PropertiesHelperTest.java +++ b/core-common/src/test/java/org/glassfish/jersey/internal/util/PropertiesHelperTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -199,4 +199,15 @@ public void testconvertValue() { } + @Test + public void isPropertyOrNotSetTest() { + assertEquals(false, PropertiesHelper.isPropertyOrNotSet((Boolean) null)); + assertEquals(true, PropertiesHelper.isPropertyOrNotSet(Boolean.TRUE)); + assertEquals(false, PropertiesHelper.isPropertyOrNotSet(Boolean.FALSE)); + assertEquals(false, PropertiesHelper.isPropertyOrNotSet((String) null)); + assertEquals(true, PropertiesHelper.isPropertyOrNotSet("")); + assertEquals(false, PropertiesHelper.isPropertyOrNotSet("treu")); // false for non-boolean values + assertEquals(true, PropertiesHelper.isPropertyOrNotSet("TRUE")); + assertEquals(false, PropertiesHelper.isPropertyOrNotSet("false")); + } } diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java b/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java index 1b13d056e3..359363e4b4 100644 --- a/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java +++ b/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -37,6 +37,7 @@ import javax.ws.rs.core.Configuration; import javax.ws.rs.core.Feature; +import org.glassfish.jersey.ApplicationSupplier; import org.glassfish.jersey.internal.Errors; import org.glassfish.jersey.internal.config.ExternalPropertiesConfigurationFactory; import org.glassfish.jersey.internal.inject.Binder; @@ -67,7 +68,7 @@ * @author Michal Gajdos * @author Marek Potociar */ -public class ResourceConfig extends Application implements Configurable, ServerConfig { +public class ResourceConfig extends Application implements Configurable, ServerConfig, ApplicationSupplier { private static final Logger LOGGER = Logger.getLogger(ResourceConfig.class.getName()); diff --git a/docs/src/main/docbook/appendix-properties.xml b/docs/src/main/docbook/appendix-properties.xml index 13df68b5e0..f131fa7568 100644 --- a/docs/src/main/docbook/appendix-properties.xml +++ b/docs/src/main/docbook/appendix-properties.xml @@ -81,6 +81,24 @@ Disables configuration of Json Binding (JSR-367) feature. Default value is false. + Can also be set as a system property. + + + Since 2.45. + + + + + &jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION; + jersey.config.application.disableJsonBinding + + + Disables configuration of Json Binding (JSR-367) feature for javax.ws.rs.core.Application + subclasses whose package names are specified as a value. The value is comma-separated string + defining prefixes of the application package names. Can also be set as a system property. + + + By default, Json Binding is automatically enabled. Since 2.45. diff --git a/docs/src/main/docbook/jersey.ent b/docs/src/main/docbook/jersey.ent index c8022b9ad1..4cb70cc144 100644 --- a/docs/src/main/docbook/jersey.ent +++ b/docs/src/main/docbook/jersey.ent @@ -392,6 +392,7 @@ CommonProperties.JSON_BINDING_FEATURE_DISABLE" > CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT" > CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER" > +CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION" > CommonProperties.JSON_PROCESSING_FEATURE_DISABLE" > CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_CLIENT" > CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_SERVER" > diff --git a/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/JsonBindingFeature.java b/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/JsonBindingFeature.java index 005613842b..40a56c4204 100644 --- a/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/JsonBindingFeature.java +++ b/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/JsonBindingFeature.java @@ -16,16 +16,25 @@ package org.glassfish.jersey.jsonb; +import javax.ws.rs.RuntimeType; +import javax.ws.rs.core.Application; import javax.ws.rs.core.Configuration; import javax.ws.rs.core.Feature; import javax.ws.rs.core.FeatureContext; +import org.glassfish.jersey.ApplicationSupplier; import org.glassfish.jersey.CommonProperties; import org.glassfish.jersey.internal.InternalProperties; +import org.glassfish.jersey.internal.inject.InjectionManagerSupplier; import org.glassfish.jersey.internal.util.PropertiesHelper; import org.glassfish.jersey.jsonb.internal.JsonBindingAutoDiscoverable; import org.glassfish.jersey.jsonb.internal.JsonBindingProvider; +import java.security.AccessController; +import java.util.HashSet; +import java.util.Set; +import java.util.logging.Logger; + /** * Feature used to register JSON-B providers. *

@@ -50,17 +59,85 @@ */ public class JsonBindingFeature implements Feature { + private static final Logger LOGGER = Logger.getLogger(JsonBindingFeature.class.getName()); private static final String JSON_FEATURE = JsonBindingFeature.class.getSimpleName(); @Override public boolean configure(final FeatureContext context) { final Configuration config = context.getConfiguration(); - if (CommonProperties.getValue(config.getProperties(), config.getRuntimeType(), - CommonProperties.JSON_BINDING_FEATURE_DISABLE, Boolean.FALSE, Boolean.class)) { + // ---- Allow to disable for compatibility with Pre JAX-RS 2.1 Jersey. + + /* Either system properties */ + final String bindingDisabledBySystemProperty = AccessController.doPrivileged( + PropertiesHelper.getSystemProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE)); + + final String bindingDisabledBySystemPropertyClient = AccessController.doPrivileged( + PropertiesHelper.getSystemProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT)); + + final String bindingDisabledBySystemPropertyServer = AccessController.doPrivileged( + PropertiesHelper.getSystemProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER)); + + final RuntimeType runtimeType = config.getRuntimeType(); + + boolean bindingDisabledBySystem = PropertiesHelper.isPropertyOrNotSet(bindingDisabledBySystemProperty) + || (runtimeType == RuntimeType.CLIENT + && PropertiesHelper.isPropertyOrNotSet(bindingDisabledBySystemPropertyClient)) + || (runtimeType == RuntimeType.SERVER + && PropertiesHelper.isPropertyOrNotSet(bindingDisabledBySystemPropertyServer)); + + /* Or config property */ + final Boolean bindingDisabled = CommonProperties.getValue(config.getProperties(), runtimeType, + CommonProperties.JSON_BINDING_FEATURE_DISABLE, Boolean.class); + + /* Config property takes precedence */ + if ((bindingDisabledBySystem && !Boolean.FALSE.equals(bindingDisabled)) || Boolean.TRUE.equals(bindingDisabled)) { return false; } + final Set disabledPackageNames = new HashSet<>(); + + /* Only a certain package names */ + final String bindingDisabledPackageBySystemProperty = RuntimeType.SERVER == runtimeType + ? AccessController.doPrivileged(PropertiesHelper.getSystemProperty( + CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION)) + : null; + + final String bindingDisabledPackage = RuntimeType.SERVER == runtimeType + ? CommonProperties.getValue(config.getProperties(), runtimeType, + CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION, String.class) + : null; + + separatePackageNames(disabledPackageNames, bindingDisabledPackageBySystemProperty); + separatePackageNames(disabledPackageNames, bindingDisabledPackage); + + if (!disabledPackageNames.isEmpty() && !Boolean.FALSE.equals(bindingDisabled)) { + try { + Application app = null; + if (InjectionManagerSupplier.class.isInstance(context)) { + app = ((InjectionManagerSupplier) context).getInjectionManager().getInstance(Application.class); + if (app != null) { + while (ApplicationSupplier.class.isInstance(app) && ((ApplicationSupplier) app).getApplication() != app) { + app = ((ApplicationSupplier) app).getApplication(); + } + for (String disabledPackageName : disabledPackageNames) { + if (app.getClass().getName().startsWith(disabledPackageName)) { + return false; + } + } + } + } + if (app == null) { + LOGGER.warning(LocalizationMessages.ERROR_JSONB_DETECTING_APPLICATION( + LocalizationMessages.ERROR_JSONB_APPLICATION_NOT_FOUND())); + } + } catch (Throwable throwable) { + LOGGER.warning(LocalizationMessages.ERROR_JSONB_DETECTING_APPLICATION(throwable.getMessage())); + } + } + + // ---- End of disabling for compatibility with Pre JAX-RS 2.1 Jersey. + final String jsonFeature = CommonProperties.getValue( config.getProperties(), config.getRuntimeType(), @@ -79,4 +156,12 @@ public boolean configure(final FeatureContext context) { return true; } + + private static void separatePackageNames(Set set, String packages) { + if (packages != null) { + for (String packageName : packages.split(",")) { + set.add(packageName.trim()); + } + } + } } diff --git a/media/json-binding/src/main/resources/org/glassfish/jersey/jsonb/localization.properties b/media/json-binding/src/main/resources/org/glassfish/jersey/jsonb/localization.properties index 4eee493a70..371e641b3d 100644 --- a/media/json-binding/src/main/resources/org/glassfish/jersey/jsonb/localization.properties +++ b/media/json-binding/src/main/resources/org/glassfish/jersey/jsonb/localization.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 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 @@ -14,6 +14,8 @@ # SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 # +error.jsonb.application.not.found=Application not found. +error.jsonb.detecting.application=JSON-B could not detect the application name: {0}. error.jsonb.serialization=Error writing JSON-B serialized object. error.jsonb.deserialization=Error deserializing object from entity stream. error.jsonb.emptystream=JSON-B cannot parse empty input stream. diff --git a/media/json-binding/src/test/java/org/glassfish/jersey/jsonb/internal/JsonbDisabledTest.java b/media/json-binding/src/test/java/org/glassfish/jersey/jsonb/internal/JsonbDisabledTest.java index 4882fe88b0..c2b63779d6 100644 --- a/media/json-binding/src/test/java/org/glassfish/jersey/jsonb/internal/JsonbDisabledTest.java +++ b/media/json-binding/src/test/java/org/glassfish/jersey/jsonb/internal/JsonbDisabledTest.java @@ -17,6 +17,10 @@ package org.glassfish.jersey.jsonb.internal; import org.glassfish.jersey.CommonProperties; +import org.glassfish.jersey.internal.inject.AbstractBinder; +import org.glassfish.jersey.internal.inject.InjectionManager; +import org.glassfish.jersey.internal.inject.InjectionManagerSupplier; +import org.glassfish.jersey.internal.inject.Injections; import org.glassfish.jersey.jsonb.JsonBindingFeature; import org.glassfish.jersey.model.internal.CommonConfig; import org.glassfish.jersey.model.internal.ComponentBag; @@ -24,6 +28,7 @@ import org.junit.jupiter.api.Test; import javax.ws.rs.RuntimeType; +import javax.ws.rs.core.Application; import javax.ws.rs.core.FeatureContext; import java.lang.reflect.Proxy; import java.util.concurrent.atomic.AtomicReference; @@ -32,24 +37,177 @@ public class JsonbDisabledTest { @Test public void testDisabled() { AtomicReference configReference = new AtomicReference<>(); - FeatureContext featureContext1 = (FeatureContext) Proxy.newProxyInstance( - getClass().getClassLoader(), - new Class[] {FeatureContext.class}, (proxy, method, args) -> { - switch (method.getName()) { - case "getConfiguration": - return configReference.get(); - } - return null; - }); + FeatureContext featureContext1 = featureContextForConfig(configReference); CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); configReference.set(config1); Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); - CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); config2.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE, true); configReference.set(config2); Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1)); } + + @Test + public void testDisabledBySystemProperty() { + AtomicReference configReference = new AtomicReference<>(); + FeatureContext featureContext1 = featureContextForConfig(configReference); + + CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config1); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER, "true"); + configReference.set(config2); + Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1)); + System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER); + } + + @Test + public void testDisabledBySystemPropertyOverridenByConfigProperty() { + AtomicReference configReference = new AtomicReference<>(); + FeatureContext featureContext1 = featureContextForConfig(configReference); + + CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config1); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE, "true"); + config2.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE, false); + configReference.set(config2); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE); + } + + @Test + public void testDisabledByPropertyApplicationPackage() { + Application application = new Application() { + }; + InjectionManager injectionManager = Injections.createInjectionManager(); + injectionManager.register(new AbstractBinder() { + @Override + protected void configure() { + bind(application).to(Application.class); + } + }); + AtomicReference injectionManagerReference = new AtomicReference<>(injectionManager); + AtomicReference configReference = new AtomicReference<>(); + FeatureContext featureContext1 = featureContextForConfig(configReference, injectionManagerReference); + + CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config1); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION, + "some.does.not.matter, org.glassfish.jersey.jsonb.internal"); + CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config2); + Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1)); + System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION); + } + + @Test + public void disableOnClientOnlyTest() { + AtomicReference configReference = new AtomicReference<>(); + FeatureContext featureContext1 = featureContextForConfig(configReference); + + CommonConfig config1 = new CommonConfig(RuntimeType.CLIENT, ComponentBag.INCLUDE_ALL); + configReference.set(config1); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + config1.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER, true); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + config1.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT, true); + Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1)); + + CommonConfig config2 = new CommonConfig(RuntimeType.CLIENT, ComponentBag.INCLUDE_ALL); + System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER, "true"); + configReference.set(config2); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT, "true"); + Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1)); + + System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER); + System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT); + } + + @Test + public void testDisabledBySystemPropertyApplicationPackage() { + Application application = new Application() { + }; + InjectionManager injectionManager = Injections.createInjectionManager(); + injectionManager.register(new AbstractBinder() { + @Override + protected void configure() { + bind(application).to(Application.class); + } + }); + AtomicReference injectionManagerReference = new AtomicReference<>(injectionManager); + AtomicReference configReference = new AtomicReference<>(); + FeatureContext featureContext1 = featureContextForConfig(configReference, injectionManagerReference); + + System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION, + "some.does.not.matter, org.glassfish.jersey.jsonb.internal"); + + CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config1); + Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1)); + + CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config2); + Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1)); + System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION); + } + + @Test + public void testDisabledBySystemPropertyApplicationPackageEnabledByProperty() { + Application application = new Application() { + }; + InjectionManager injectionManager = Injections.createInjectionManager(); + injectionManager.register(new AbstractBinder() { + @Override + protected void configure() { + bind(application).to(Application.class); + } + }); + AtomicReference injectionManagerReference = new AtomicReference<>(injectionManager); + AtomicReference configReference = new AtomicReference<>(); + FeatureContext featureContext1 = featureContextForConfig(configReference, injectionManagerReference); + + CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config1); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION, + "some.does.not.matter, org.glassfish.jersey.jsonb.internal"); + + CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + config2.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE, Boolean.FALSE); + configReference.set(config2); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION); + } + + private static FeatureContext featureContextForConfig(AtomicReference configReference) { + return featureContextForConfig(configReference, new AtomicReference<>()); + } + private static FeatureContext featureContextForConfig(AtomicReference configReference, + AtomicReference injectionManager) { + return (FeatureContext) Proxy.newProxyInstance( + JsonbDisabledTest.class.getClassLoader(), + new Class[] {FeatureContext.class, InjectionManagerSupplier.class}, (proxy, method, args) -> { + switch (method.getName()) { + case "getConfiguration": + return configReference.get(); + case "getInjectionManager": + return injectionManager.get(); + } + return null; + }); + } }