Skip to content

Commit 6da18bd

Browse files
committed
Allow to disable JSON-B using System properties
Signed-off-by: jansupol <[email protected]>
1 parent b752b3c commit 6da18bd

File tree

10 files changed

+360
-17
lines changed

10 files changed

+360
-17
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
17+
18+
package org.glassfish.jersey;
19+
20+
import javax.ws.rs.core.Application;
21+
22+
/**
23+
* Implementation of this interface is capable of returning {@link Application}.
24+
*/
25+
public interface ApplicationSupplier {
26+
/**
27+
* Get Application.
28+
*
29+
* @return Application.
30+
*/
31+
Application getApplication();
32+
33+
}

core-common/src/main/java/org/glassfish/jersey/CommonProperties.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,19 @@ public final class CommonProperties {
130130
*/
131131
public static final String JSON_BINDING_FEATURE_DISABLE_SERVER = "jersey.config.server.disableJsonBinding";
132132

133+
/**
134+
* Disables configuration of Json Binding (JSR-367) feature for {@link javax.ws.rs.core.Application} subclasses whose
135+
* package names are specified as a value. The value is comma-separated string defining prefixes of the application
136+
* package names.
137+
* <p>
138+
* By default, Json Binding is automatically enabled.
139+
* <p>
140+
* The name of the configuration property is <tt>{@value}</tt>.
141+
* </p>
142+
* @since 2.45
143+
*/
144+
public static final String JSON_BINDING_FEATURE_DISABLE_APPLICATION = "jersey.config.application.disableJsonBinding";
145+
133146
/**
134147
* If {@code true} then disable configuration of Json Processing (JSR-353) feature.
135148
* <p>

core-common/src/main/java/org/glassfish/jersey/internal/util/PropertiesHelper.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -389,6 +389,27 @@ public static boolean isProperty(final Object value) {
389389
}
390390
}
391391

392+
/**
393+
* Converts the property value to {@code boolean} and checks it is {@code true} or empty.
394+
* Returns {@code true} if the value is {@code true} or empty but not {@code null}.
395+
*
396+
* <p>
397+
* The rationale behind this is that system property {@code -Dprop=true} is the same as {@code -Dprop}.
398+
* The property {@code -Dprop=false} behaves as if the {@code -Dprop} is not set at all.
399+
* </p>
400+
*
401+
* @param value property value.
402+
* @return {@code boolean} property value or {@code true} if the property value is not set or {@code false} if the property
403+
* is otherwise not convertible.
404+
*/
405+
public static boolean isPropertyOrNotSet(final Object value) {
406+
if (value instanceof Boolean) {
407+
return Boolean.class.cast(value);
408+
} else {
409+
return value != null && ("".equals(value.toString()) || Boolean.parseBoolean(value.toString()));
410+
}
411+
}
412+
392413
/**
393414
* Faster replacement of {@code RuntimeType#name().toLowerCase(Locale.ROOT)}
394415
* @param runtimeType The runtime type to lower case

core-common/src/test/java/org/glassfish/jersey/internal/util/PropertiesHelperTest.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -199,4 +199,15 @@ public void testconvertValue() {
199199

200200
}
201201

202+
@Test
203+
public void isPropertyOrNotSetTest() {
204+
assertEquals(false, PropertiesHelper.isPropertyOrNotSet((Boolean) null));
205+
assertEquals(true, PropertiesHelper.isPropertyOrNotSet(Boolean.TRUE));
206+
assertEquals(false, PropertiesHelper.isPropertyOrNotSet(Boolean.FALSE));
207+
assertEquals(false, PropertiesHelper.isPropertyOrNotSet((String) null));
208+
assertEquals(true, PropertiesHelper.isPropertyOrNotSet(""));
209+
assertEquals(false, PropertiesHelper.isPropertyOrNotSet("treu")); // false for non-boolean values
210+
assertEquals(true, PropertiesHelper.isPropertyOrNotSet("TRUE"));
211+
assertEquals(false, PropertiesHelper.isPropertyOrNotSet("false"));
212+
}
202213
}

core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -37,6 +37,7 @@
3737
import javax.ws.rs.core.Configuration;
3838
import javax.ws.rs.core.Feature;
3939

40+
import org.glassfish.jersey.ApplicationSupplier;
4041
import org.glassfish.jersey.internal.Errors;
4142
import org.glassfish.jersey.internal.config.ExternalPropertiesConfigurationFactory;
4243
import org.glassfish.jersey.internal.inject.Binder;
@@ -67,7 +68,7 @@
6768
* @author Michal Gajdos
6869
* @author Marek Potociar
6970
*/
70-
public class ResourceConfig extends Application implements Configurable<ResourceConfig>, ServerConfig {
71+
public class ResourceConfig extends Application implements Configurable<ResourceConfig>, ServerConfig, ApplicationSupplier {
7172

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

docs/src/main/docbook/appendix-properties.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,24 @@
8181
<entry>
8282
<para>
8383
Disables configuration of Json Binding (JSR-367) feature. Default value is <literal>false</literal>.
84+
Can also be set as a system property.
85+
</para>
86+
<para>
87+
Since 2.45.
88+
</para>
89+
</entry>
90+
</row>
91+
<row>
92+
<entry>&jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION; </entry>
93+
<entry><literal>jersey.config.application.disableJsonBinding</literal></entry>
94+
<entry>
95+
<para>
96+
Disables configuration of Json Binding (JSR-367) feature for <literal>javax.ws.rs.core.Application</literal>
97+
subclasses whose package names are specified as a value. The value is comma-separated string
98+
defining prefixes of the application package names. Can also be set as a system property.
99+
</para>
100+
<para>
101+
By default, Json Binding is automatically enabled.
84102
</para>
85103
<para>
86104
Since 2.45.

docs/src/main/docbook/jersey.ent

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@
392392
<!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>" >
393393
<!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>" >
394394
<!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>" >
395+
<!ENTITY jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_BINDING_FEATURE_DISABLE_APPLICATION'>CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION</link>" >
395396
<!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>" >
396397
<!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>" >
397398
<!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>" >

media/json-binding/src/main/java/org/glassfish/jersey/jsonb/JsonBindingFeature.java

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,25 @@
1616

1717
package org.glassfish.jersey.jsonb;
1818

19+
import javax.ws.rs.RuntimeType;
20+
import javax.ws.rs.core.Application;
1921
import javax.ws.rs.core.Configuration;
2022
import javax.ws.rs.core.Feature;
2123
import javax.ws.rs.core.FeatureContext;
2224

25+
import org.glassfish.jersey.ApplicationSupplier;
2326
import org.glassfish.jersey.CommonProperties;
2427
import org.glassfish.jersey.internal.InternalProperties;
28+
import org.glassfish.jersey.internal.inject.InjectionManagerSupplier;
2529
import org.glassfish.jersey.internal.util.PropertiesHelper;
2630
import org.glassfish.jersey.jsonb.internal.JsonBindingAutoDiscoverable;
2731
import org.glassfish.jersey.jsonb.internal.JsonBindingProvider;
2832

33+
import java.security.AccessController;
34+
import java.util.HashSet;
35+
import java.util.Set;
36+
import java.util.logging.Logger;
37+
2938
/**
3039
* Feature used to register JSON-B providers.
3140
* <p>
@@ -50,17 +59,85 @@
5059
*/
5160
public class JsonBindingFeature implements Feature {
5261

62+
private static final Logger LOGGER = Logger.getLogger(JsonBindingFeature.class.getName());
5363
private static final String JSON_FEATURE = JsonBindingFeature.class.getSimpleName();
5464

5565
@Override
5666
public boolean configure(final FeatureContext context) {
5767
final Configuration config = context.getConfiguration();
5868

59-
if (CommonProperties.getValue(config.getProperties(), config.getRuntimeType(),
60-
CommonProperties.JSON_BINDING_FEATURE_DISABLE, Boolean.FALSE, Boolean.class)) {
69+
// ---- Allow to disable for compatibility with Pre JAX-RS 2.1 Jersey.
70+
71+
/* Either system properties */
72+
final String bindingDisabledBySystemProperty = AccessController.doPrivileged(
73+
PropertiesHelper.getSystemProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE));
74+
75+
final String bindingDisabledBySystemPropertyClient = AccessController.doPrivileged(
76+
PropertiesHelper.getSystemProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT));
77+
78+
final String bindingDisabledBySystemPropertyServer = AccessController.doPrivileged(
79+
PropertiesHelper.getSystemProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER));
80+
81+
final RuntimeType runtimeType = config.getRuntimeType();
82+
83+
boolean bindingDisabledBySystem = PropertiesHelper.isPropertyOrNotSet(bindingDisabledBySystemProperty)
84+
|| (runtimeType == RuntimeType.CLIENT
85+
&& PropertiesHelper.isPropertyOrNotSet(bindingDisabledBySystemPropertyClient))
86+
|| (runtimeType == RuntimeType.SERVER
87+
&& PropertiesHelper.isPropertyOrNotSet(bindingDisabledBySystemPropertyServer));
88+
89+
/* Or config property */
90+
final Boolean bindingDisabled = CommonProperties.getValue(config.getProperties(), runtimeType,
91+
CommonProperties.JSON_BINDING_FEATURE_DISABLE, Boolean.class);
92+
93+
/* Config property takes precedence */
94+
if ((bindingDisabledBySystem && !Boolean.FALSE.equals(bindingDisabled)) || Boolean.TRUE.equals(bindingDisabled)) {
6195
return false;
6296
}
6397

98+
final Set<String> disabledPackageNames = new HashSet<>();
99+
100+
/* Only a certain package names */
101+
final String bindingDisabledPackageBySystemProperty = RuntimeType.SERVER == runtimeType
102+
? AccessController.doPrivileged(PropertiesHelper.getSystemProperty(
103+
CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION))
104+
: null;
105+
106+
final String bindingDisabledPackage = RuntimeType.SERVER == runtimeType
107+
? CommonProperties.getValue(config.getProperties(), runtimeType,
108+
CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION, String.class)
109+
: null;
110+
111+
separatePackageNames(disabledPackageNames, bindingDisabledPackageBySystemProperty);
112+
separatePackageNames(disabledPackageNames, bindingDisabledPackage);
113+
114+
if (!disabledPackageNames.isEmpty() && !Boolean.FALSE.equals(bindingDisabled)) {
115+
try {
116+
Application app = null;
117+
if (InjectionManagerSupplier.class.isInstance(context)) {
118+
app = ((InjectionManagerSupplier) context).getInjectionManager().getInstance(Application.class);
119+
if (app != null) {
120+
while (ApplicationSupplier.class.isInstance(app) && ((ApplicationSupplier) app).getApplication() != app) {
121+
app = ((ApplicationSupplier) app).getApplication();
122+
}
123+
for (String disabledPackageName : disabledPackageNames) {
124+
if (app.getClass().getName().startsWith(disabledPackageName)) {
125+
return false;
126+
}
127+
}
128+
}
129+
}
130+
if (app == null) {
131+
LOGGER.warning(LocalizationMessages.ERROR_JSONB_DETECTING_APPLICATION(
132+
LocalizationMessages.ERROR_JSONB_APPLICATION_NOT_FOUND()));
133+
}
134+
} catch (Throwable throwable) {
135+
LOGGER.warning(LocalizationMessages.ERROR_JSONB_DETECTING_APPLICATION(throwable.getMessage()));
136+
}
137+
}
138+
139+
// ---- End of disabling for compatibility with Pre JAX-RS 2.1 Jersey.
140+
64141
final String jsonFeature = CommonProperties.getValue(
65142
config.getProperties(),
66143
config.getRuntimeType(),
@@ -79,4 +156,12 @@ public boolean configure(final FeatureContext context) {
79156

80157
return true;
81158
}
159+
160+
private static void separatePackageNames(Set<String> set, String packages) {
161+
if (packages != null) {
162+
for (String packageName : packages.split(",")) {
163+
set.add(packageName.trim());
164+
}
165+
}
166+
}
82167
}

media/json-binding/src/main/resources/org/glassfish/jersey/jsonb/localization.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
33
#
44
# This program and the accompanying materials are made available under the
55
# terms of the Eclipse Public License v. 2.0, which is available at
@@ -14,6 +14,8 @@
1414
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1515
#
1616

17+
error.jsonb.application.not.found=Application not found.
18+
error.jsonb.detecting.application=JSON-B could not detect the application name: {0}.
1719
error.jsonb.serialization=Error writing JSON-B serialized object.
1820
error.jsonb.deserialization=Error deserializing object from entity stream.
1921
error.jsonb.emptystream=JSON-B cannot parse empty input stream.

0 commit comments

Comments
 (0)