Skip to content

Commit

Permalink
Allow to disable JSON-B using System properties
Browse files Browse the repository at this point in the history
Signed-off-by: jansupol <jan.supol@oracle.com>
  • Loading branch information
jansupol committed Aug 26, 2024
1 parent e254ae8 commit 3e0bb58
Show file tree
Hide file tree
Showing 10 changed files with 376 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -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();

}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* <p>
* By default, Json Binding is automatically enabled.
* <p>
* The name of the configuration property is <tt>{@value}</tt>.
* </p>
* @since 2.45
*/
public static final String JSON_BINDING_FEATURE_DISABLE_PACKAGE = "jersey.config.disableJsonBinding.package";

/**
* If {@code true} then disable configuration of Json Processing (JSR-353) feature.
* <p>
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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}.
*
* <p>
* 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.
* </p>
*
* @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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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"));
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -67,7 +68,7 @@
* @author Michal Gajdos
* @author Marek Potociar
*/
public class ResourceConfig extends Application implements Configurable<ResourceConfig>, ServerConfig {
public class ResourceConfig extends Application implements Configurable<ResourceConfig>, ServerConfig, ApplicationSupplier {

private static final Logger LOGGER = Logger.getLogger(ResourceConfig.class.getName());

Expand Down
18 changes: 18 additions & 0 deletions docs/src/main/docbook/appendix-properties.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,24 @@
<entry>
<para>
Disables configuration of Json Binding (JSR-367) feature. Default value is <literal>false</literal>.
Can also be set as a system property.
</para>
<para>
Since 2.45.
</para>
</entry>
</row>
<row>
<entry>&jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_PACKAGE; </entry>
<entry><literal>jersey.config.disableJsonBinding.package</literal></entry>
<entry>
<para>
Disables configuration of Json Binding (JSR-367) feature for <literal>javax.ws.rs.core.Application</literal>
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.
</para>
<para>
By default, Json Binding is automatically enabled.
</para>
<para>
Since 2.45.
Expand Down
1 change: 1 addition & 0 deletions docs/src/main/docbook/jersey.ent
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@
<!ENTITY jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_BINDING_FEATURE_DISABLE'>CommonProperties.JSON_BINDING_FEATURE_DISABLE</link>" >
<!ENTITY jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_BINDING_FEATURE_DISABLE_CLIENT'>CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT</link>" >
<!ENTITY jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_BINDING_FEATURE_DISABLE_SERVER'>CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER</link>" >
<!ENTITY jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_PACKAGE "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_BINDING_FEATURE_DISABLE_PACKAGE'>CommonProperties.JSON_BINDING_FEATURE_DISABLE_PACKAGE</link>" >
<!ENTITY jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_PROCESSING_FEATURE_DISABLE'>CommonProperties.JSON_PROCESSING_FEATURE_DISABLE</link>" >
<!ENTITY jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_CLIENT "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_PROCESSING_FEATURE_DISABLE_CLIENT'>CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_CLIENT</link>" >
<!ENTITY jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_SERVER "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_PROCESSING_FEATURE_DISABLE_SERVER'>CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_SERVER</link>" >
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,26 @@

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.internal.util.ReflectionHelper;
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.
* <p>
Expand All @@ -50,17 +60,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<String> disabledPackageNames = new HashSet<>();

/* Only a certain package names */
final String bindingDisabledPackageBySystemProperty = RuntimeType.SERVER == runtimeType
? AccessController.doPrivileged(PropertiesHelper.getSystemProperty(
CommonProperties.JSON_BINDING_FEATURE_DISABLE_PACKAGE))
: null;

final String bindingDisabledPackage = RuntimeType.SERVER == runtimeType
? CommonProperties.getValue(config.getProperties(), runtimeType,
CommonProperties.JSON_BINDING_FEATURE_DISABLE_PACKAGE, 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(),
Expand All @@ -79,4 +157,12 @@ public boolean configure(final FeatureContext context) {

return true;
}

private static void separatePackageNames(Set<String> set, String packages) {
if (packages != null) {
for (String packageName : packages.split(",")) {
set.add(packageName.trim());
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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.
Loading

0 comments on commit 3e0bb58

Please sign in to comment.