Skip to content

Commit 1591160

Browse files
authored
fix: stop mutating JsonPath JVM-global defaults (#191)
1 parent f79691a commit 1591160

10 files changed

Lines changed: 78 additions & 53 deletions
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
*
3+
*
4+
* * Licensed under the EUPL, Version 1.2 or – as soon they will be approved by
5+
* * the European Commission - subsequent versions of the EUPL (the "Licence");
6+
* * You may not use this work except in compliance with the Licence.
7+
* * You may obtain a copy of the Licence at:
8+
* *
9+
* * https://joinup.ec.europa.eu/software/page/eupl
10+
* *
11+
* * Unless required by applicable law or agreed to in writing, software
12+
* * distributed under the Licence is distributed on an "AS IS" basis,
13+
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* * See the Licence for the specific language governing permissions and
15+
* * limitations under the Licence.
16+
*
17+
*/
18+
19+
package org.mobilitydata.gbfs.validation.validator;
20+
21+
import com.jayway.jsonpath.Configuration;
22+
import com.jayway.jsonpath.DocumentContext;
23+
import com.jayway.jsonpath.JsonPath;
24+
import com.jayway.jsonpath.spi.json.JsonOrgJsonProvider;
25+
import com.jayway.jsonpath.spi.mapper.JsonOrgMappingProvider;
26+
27+
/**
28+
* Thin facade over {@link JsonPath} that always uses {@link JsonOrgJsonProvider}
29+
* and {@link JsonOrgMappingProvider}. All schema-patching code in this library
30+
* operates on {@code org.json.JSONObject} / {@code JSONArray}, which the default
31+
* JsonPath provider does not recognise.
32+
*
33+
* <p>Use {@link #parse(Object)} instead of {@code JsonPath.parse(...)} so that
34+
* we never depend on {@link Configuration#setDefaults(Configuration.Defaults)} —
35+
* mutating that JVM-wide default would silently break any other JsonPath user
36+
* in the same process (e.g. Spring's GraphQL test tooling).
37+
*/
38+
public final class SchemaJsonPath {
39+
40+
private static final Configuration CONFIGURATION = Configuration
41+
.builder()
42+
.jsonProvider(new JsonOrgJsonProvider())
43+
.mappingProvider(new JsonOrgMappingProvider())
44+
.build();
45+
46+
private SchemaJsonPath() {}
47+
48+
/**
49+
* Parse an {@code org.json.JSONObject}, {@code JSONArray} or JSON string into a
50+
* {@link DocumentContext} configured to read and write {@code org.json} types.
51+
*/
52+
public static DocumentContext parse(Object json) {
53+
return JsonPath.using(CONFIGURATION).parse(json);
54+
}
55+
}

gbfs-validator-java/src/main/java/org/mobilitydata/gbfs/validation/validator/rules/NoInvalidReferenceToPricingPlansInVehicleStatus.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
package org.mobilitydata.gbfs.validation.validator.rules;
2222

2323
import com.jayway.jsonpath.DocumentContext;
24-
import com.jayway.jsonpath.JsonPath;
2524
import java.util.Map;
2625
import org.json.JSONArray;
2726
import org.json.JSONObject;
27+
import org.mobilitydata.gbfs.validation.validator.SchemaJsonPath;
2828

2929
/**
3030
* A vehicle's pricing_plan_id must exist in the system's system_pricing_plan file
@@ -63,7 +63,7 @@ public DocumentContext addRule(
6363
);
6464

6565
JSONArray pricingPlanIds = pricingPlansFeed != null
66-
? JsonPath.parse(pricingPlansFeed).read("$.data.plans[*].plan_id")
66+
? SchemaJsonPath.parse(pricingPlansFeed).read("$.data.plans[*].plan_id")
6767
: new JSONArray();
6868
pricingPlanIdSchema.put("enum", pricingPlanIds);
6969

gbfs-validator-java/src/main/java/org/mobilitydata/gbfs/validation/validator/rules/NoInvalidReferenceToPricingPlansInVehicleTypes.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
package org.mobilitydata.gbfs.validation.validator.rules;
2222

2323
import com.jayway.jsonpath.DocumentContext;
24-
import com.jayway.jsonpath.JsonPath;
2524
import java.util.Map;
2625
import org.json.JSONArray;
2726
import org.json.JSONObject;
27+
import org.mobilitydata.gbfs.validation.validator.SchemaJsonPath;
2828

2929
/**
3030
* A vehicle's default_pricing_plan_id, and all pricing_plan_ids must exist in the system's system_pricing_plan file
@@ -54,7 +54,7 @@ public DocumentContext addRule(
5454
);
5555

5656
JSONArray pricingPlanIds = pricingPlansFeed != null
57-
? JsonPath.parse(pricingPlansFeed).read("$.data.plans[*].plan_id")
57+
? SchemaJsonPath.parse(pricingPlansFeed).read("$.data.plans[*].plan_id")
5858
: new JSONArray();
5959
defaultPricingPlanIdSchema.put("enum", pricingPlanIds);
6060
pricingPlanIdsSchema.put("enum", pricingPlanIds);

gbfs-validator-java/src/main/java/org/mobilitydata/gbfs/validation/validator/rules/NoInvalidReferenceToRegionInStationInformation.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
package org.mobilitydata.gbfs.validation.validator.rules;
2222

2323
import com.jayway.jsonpath.DocumentContext;
24-
import com.jayway.jsonpath.JsonPath;
2524
import java.util.Map;
2625
import org.json.JSONArray;
2726
import org.json.JSONObject;
27+
import org.mobilitydata.gbfs.validation.validator.SchemaJsonPath;
2828

2929
/**
3030
* References to regions in station_information must exist in the system's system_regions file
@@ -49,7 +49,9 @@ public DocumentContext addRule(
4949
);
5050

5151
JSONArray regionIds = systemRegionsFeed != null
52-
? JsonPath.parse(systemRegionsFeed).read("$.data.regions[*].region_id")
52+
? SchemaJsonPath
53+
.parse(systemRegionsFeed)
54+
.read("$.data.regions[*].region_id")
5355
: new JSONArray();
5456

5557
regionIdSchema.put("enum", regionIds);

gbfs-validator-java/src/main/java/org/mobilitydata/gbfs/validation/validator/rules/NoInvalidReferenceToStation.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
package org.mobilitydata.gbfs.validation.validator.rules;
2222

2323
import com.jayway.jsonpath.DocumentContext;
24-
import com.jayway.jsonpath.JsonPath;
2524
import java.util.Map;
2625
import org.json.JSONArray;
2726
import org.json.JSONObject;
27+
import org.mobilitydata.gbfs.validation.validator.SchemaJsonPath;
2828

2929
/**
3030
* References to stations in station_information must exist in station_status file and vice versa.
@@ -55,7 +55,7 @@ public DocumentContext addRule(
5555
);
5656

5757
JSONArray stationIds = stationReferenceFeed != null
58-
? JsonPath
58+
? SchemaJsonPath
5959
.parse(stationReferenceFeed)
6060
.read("$.data.stations[*].station_id")
6161
: new JSONArray();

gbfs-validator-java/src/main/java/org/mobilitydata/gbfs/validation/validator/rules/NoInvalidReferenceToVehicleTypesInStationStatus.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
package org.mobilitydata.gbfs.validation.validator.rules;
2222

2323
import com.jayway.jsonpath.DocumentContext;
24-
import com.jayway.jsonpath.JsonPath;
2524
import java.util.Map;
2625
import org.json.JSONArray;
2726
import org.json.JSONObject;
27+
import org.mobilitydata.gbfs.validation.validator.SchemaJsonPath;
2828

2929
/**
3030
* References to vehicle types in station_status must exist in the system's vehicle_types file
@@ -57,7 +57,7 @@ public DocumentContext addRule(
5757

5858
// If no vehicle_types feed is defined, then any vehicle_type_id would be invalid
5959
JSONArray vehicleTypeIds = vehicleTypesFeed != null
60-
? JsonPath
60+
? SchemaJsonPath
6161
.parse(vehicleTypesFeed)
6262
.read("$.data.vehicle_types[*].vehicle_type_id")
6363
: new JSONArray();

gbfs-validator-java/src/main/java/org/mobilitydata/gbfs/validation/validator/rules/NoMissingCurrentRangeMetersInVehicleStatusForMotorizedVehicles.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@
2424

2525
import com.jayway.jsonpath.DocumentContext;
2626
import com.jayway.jsonpath.Filter;
27-
import com.jayway.jsonpath.JsonPath;
2827
import java.util.List;
2928
import java.util.Map;
3029
import org.json.JSONArray;
3130
import org.json.JSONObject;
31+
import org.mobilitydata.gbfs.validation.validator.SchemaJsonPath;
3232

3333
/**
3434
* It is required to provide the current_range_meters property in vehicle_status for motorized vehicles
@@ -64,7 +64,7 @@ public DocumentContext addRule(
6464

6565
if (vehicleTypesFeed != null) {
6666
motorizedVehicleTypeIds =
67-
JsonPath
67+
SchemaJsonPath
6868
.parse(vehicleTypesFeed)
6969
.read(
7070
"$.data.vehicle_types[?].vehicle_type_id",

gbfs-validator-java/src/main/java/org/mobilitydata/gbfs/validation/validator/rules/NoMissingOrInvalidVehicleTypeIdInVehicleStatusWhenVehicleTypesExist.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
package org.mobilitydata.gbfs.validation.validator.rules;
2222

2323
import com.jayway.jsonpath.DocumentContext;
24-
import com.jayway.jsonpath.JsonPath;
2524
import java.util.Map;
2625
import org.json.JSONArray;
2726
import org.json.JSONObject;
27+
import org.mobilitydata.gbfs.validation.validator.SchemaJsonPath;
2828

2929
/**
3030
* Bikes / vehicles must refer to a vehicle type when vehicle_types exists
@@ -64,7 +64,7 @@ public DocumentContext addRule(
6464
vehicleItemsSchema.append("required", "vehicle_type_id");
6565
}
6666
JSONArray vehicleTypeIds = vehicleTypesFeed != null
67-
? JsonPath
67+
? SchemaJsonPath
6868
.parse(vehicleTypesFeed)
6969
.read("$.data.vehicle_types[*].vehicle_type_id")
7070
: new JSONArray();

gbfs-validator-java/src/main/java/org/mobilitydata/gbfs/validation/validator/rules/NoMissingStoreUriInSystemInformation.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
package org.mobilitydata.gbfs.validation.validator.rules;
2222

2323
import com.jayway.jsonpath.DocumentContext;
24-
import com.jayway.jsonpath.JsonPath;
2524
import java.util.Map;
2625
import org.json.JSONArray;
2726
import org.json.JSONObject;
27+
import org.mobilitydata.gbfs.validation.validator.SchemaJsonPath;
2828

2929
/**
3030
* It is required to provide ios and android store uris in system_information if vehicle_status
@@ -61,7 +61,7 @@ public DocumentContext addRule(
6161

6262
if (
6363
!(
64-
(JSONArray) JsonPath
64+
(JSONArray) SchemaJsonPath
6565
.parse(vehicleStatusFeed)
6666
.read("$.data." + vehiclesKey + "[:1].rental_uris.ios")
6767
).isEmpty()
@@ -71,7 +71,7 @@ public DocumentContext addRule(
7171

7272
if (
7373
!(
74-
(JSONArray) JsonPath
74+
(JSONArray) SchemaJsonPath
7575
.parse(vehicleStatusFeed)
7676
.read("$.data." + vehiclesKey + "[:1].rental_uris.android")
7777
).isEmpty()
@@ -85,7 +85,7 @@ public DocumentContext addRule(
8585
if (stationInformationFeed != null) {
8686
if (
8787
!(
88-
(JSONArray) JsonPath
88+
(JSONArray) SchemaJsonPath
8989
.parse(stationInformationFeed)
9090
.read("$.data.stations[:1].rental_uris.ios")
9191
).isEmpty()
@@ -95,7 +95,7 @@ public DocumentContext addRule(
9595

9696
if (
9797
!(
98-
(JSONArray) JsonPath
98+
(JSONArray) SchemaJsonPath
9999
.parse(stationInformationFeed)
100100
.read("$.data.stations[:1].rental_uris.android")
101101
).isEmpty()

gbfs-validator-java/src/main/java/org/mobilitydata/gbfs/validation/validator/versions/AbstractVersion.java

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,19 @@
1818

1919
package org.mobilitydata.gbfs.validation.validator.versions;
2020

21-
import com.jayway.jsonpath.Configuration;
22-
import com.jayway.jsonpath.JsonPath;
23-
import com.jayway.jsonpath.Option;
24-
import com.jayway.jsonpath.spi.json.JsonOrgJsonProvider;
25-
import com.jayway.jsonpath.spi.json.JsonProvider;
26-
import com.jayway.jsonpath.spi.mapper.JsonOrgMappingProvider;
27-
import com.jayway.jsonpath.spi.mapper.MappingProvider;
2821
import java.io.InputStream;
2922
import java.util.Collections;
30-
import java.util.EnumSet;
3123
import java.util.List;
3224
import java.util.Map;
3325
import java.util.Optional;
34-
import java.util.Set;
3526
import java.util.concurrent.ConcurrentHashMap;
3627
import org.everit.json.schema.Schema;
3728
import org.everit.json.schema.ValidationException;
3829
import org.everit.json.schema.loader.SchemaLoader;
3930
import org.json.JSONObject;
4031
import org.json.JSONTokener;
4132
import org.mobilitydata.gbfs.validation.validator.FileValidator;
33+
import org.mobilitydata.gbfs.validation.validator.SchemaJsonPath;
4234
import org.mobilitydata.gbfs.validation.validator.URIFormatValidator;
4335
import org.mobilitydata.gbfs.validation.validator.rules.CustomRuleSchemaPatcher;
4436
import org.slf4j.Logger;
@@ -54,30 +46,6 @@ public abstract class AbstractVersion implements Version {
5446
private final Map<String, JSONObject> schemas = new ConcurrentHashMap<>();
5547
private final Map<String, List<CustomRuleSchemaPatcher>> customRules;
5648

57-
static {
58-
Configuration.setDefaults(
59-
new Configuration.Defaults() {
60-
final JsonProvider jsonProvider = new JsonOrgJsonProvider();
61-
final MappingProvider mappingProvider = new JsonOrgMappingProvider();
62-
63-
@Override
64-
public JsonProvider jsonProvider() {
65-
return jsonProvider;
66-
}
67-
68-
@Override
69-
public Set<Option> options() {
70-
return EnumSet.noneOf(Option.class);
71-
}
72-
73-
@Override
74-
public MappingProvider mappingProvider() {
75-
return mappingProvider;
76-
}
77-
}
78-
);
79-
}
80-
8149
protected AbstractVersion(
8250
String versionString,
8351
List<String> feeds,
@@ -157,7 +125,7 @@ private JSONObject applyRule(
157125
) {
158126
// Must make a copy of the schema, otherwise it will be mutated by json-path
159127
return patcher
160-
.addRule(JsonPath.parse(new JSONObject(schema.toMap())), feedMap)
128+
.addRule(SchemaJsonPath.parse(new JSONObject(schema.toMap())), feedMap)
161129
.json();
162130
}
163131

0 commit comments

Comments
 (0)