Skip to content

Commit 5fcc2cf

Browse files
authored
Slim mode support (#420)
Making sure that the library is usable (with limitiations) if the following dependencies are excluded: * com.damnhandy:handy-uri-templates * commons-validator:commons-validator
1 parent 2903f54 commit 5fcc2cf

File tree

21 files changed

+546
-643
lines changed

21 files changed

+546
-643
lines changed

README.md

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
* [Format validators](#format-validators)
1818
* [Example](#example)
1919
* [$ref resolution](#ref-resolution)
20+
* [Excluding dependencies](#excluding-dependencies)
2021
* [Javadoc](#javadoc)
2122

2223
This project is an implementation of the JSON Schema [Draft v4][draft-zyp-json-schema-04], [Draft v6](https://tools.ietf.org/html/draft-wright-json-schema-01) and [Draft v7](https://tools.ietf.org/html/draft-handrews-json-schema-validation-00) specifications.
@@ -498,17 +499,12 @@ Notes:
498499
to a URI, there will be no network call made. This can be a caching strategy (though defining your own `SchemaClient`
499500
implementation works too, or you can even utilize the extensible [protocol handling](https://stackoverflow.com/questions/26363573/registering-and-using-a-custom-java-net-url-protocol) of the `java.net` package)
500501

502+
## Excluding dependencies
501503

504+
Some of the dependencies can be excluded from the library, and it still remains usable, with some limitations:
505+
* if you exclude the `com.damnhandy:handy-uri-templates` dependency, then your schema shouldn't use the `"uri-template"` format
506+
* if you exclude the `commons-validator:commons-validator` dependency, then your schema shouldn't use the following formats: `"email"`, `"ipv4"`, `"ipv6"`, `"hostname"`
502507

503-
[ASL 2.0 badge]: https://img.shields.io/:license-Apache%202.0-blue.svg
504-
[ASL 2.0]: https://www.apache.org/licenses/LICENSE-2.0
505-
[Travis badge master]: https://travis-ci.org/everit-org/json-schema.svg?branch=master
506-
[Travis]: https://travis-ci.org/everit-org/json-schema
507-
[Coveralls.io badge master]: https://coveralls.io/repos/github/everit-org/json-schema/badge.svg?branch=master
508-
[Coveralls.io]: https://coveralls.io/github/everit-org/json-schema?branch=master
509-
[java-json-tools/json-schema-validator]: https://github.com/java-json-tools/json-schema-validator
510-
[draft-zyp-json-schema-04]: https://tools.ietf.org/html/draft-zyp-json-schema-04
511-
[draft-fge-json-schema-validation-00 format]: https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-7
512508

513509
## Javadoc
514510

@@ -525,3 +521,16 @@ By library version:
525521
The generated javadoc of versions 1.0.0 - 1.5.1 is available at [javadoc.io](http://javadoc.io/doc/org.everit.json/org.everit.json.schema/1.5.1)
526522

527523
For the versions in between (1.6.0 - 1.9.1) it isn't published anywhere.
524+
525+
526+
527+
[ASL 2.0 badge]: https://img.shields.io/:license-Apache%202.0-blue.svg
528+
[ASL 2.0]: https://www.apache.org/licenses/LICENSE-2.0
529+
[Travis badge master]: https://travis-ci.org/everit-org/json-schema.svg?branch=master
530+
[Travis]: https://travis-ci.org/everit-org/json-schema
531+
[Coveralls.io badge master]: https://coveralls.io/repos/github/everit-org/json-schema/badge.svg?branch=master
532+
[Coveralls.io]: https://coveralls.io/github/everit-org/json-schema?branch=master
533+
[java-json-tools/json-schema-validator]: https://github.com/java-json-tools/json-schema-validator
534+
[draft-zyp-json-schema-04]: https://tools.ietf.org/html/draft-zyp-json-schema-04
535+
[draft-fge-json-schema-validation-00 format]: https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-7
536+

core/src/main/java/org/everit/json/schema/internal/URITemplateFormatValidator.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,21 @@ public class URITemplateFormatValidator implements FormatValidator {
1515
try {
1616
UriTemplate.fromTemplate(subject);
1717
return Optional.empty();
18-
} catch (MalformedUriTemplateException e) {
19-
return Optional.of(format("[%s] is not a valid URI template", subject));
18+
} catch (RuntimeException e) {
19+
// intentionally not catching MalformedUriTemplateException, because in that case, if
20+
// com.damnhandy:handy-uri-templates is not on the classpath, a NoClassDefFoundError is thrown
21+
// from SpecificationVersion line 159, even if there are no uri-template schemas used. The reason is that (most
22+
// probably) during loading URITemplateFormatValidator, the exception handlers are verified as per section 4.10.1.6
23+
// of the Java Virtual Machine Specification (version 11). This means that all caught exceptions are checked if they
24+
// are subclasses of Throwable, so to do it, the JVM has to look into the MalformedUriTemplateException class file,
25+
// even if the class doesn't actually get loaded. So to work this around, here we first catch a RuntimeException and
26+
// then check with instanceof if it is a MalformedUriTemplateException, so that this way the
27+
// MalformedUriTemplateException does not appear in the exception table of the method.
28+
if (e instanceof MalformedUriTemplateException) {
29+
return Optional.of(format("[%s] is not a valid URI template", subject));
30+
} else {
31+
throw new RuntimeException(e);
32+
}
2033
}
2134
}
2235

tests/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<modules>
1515
<module>vanilla</module>
1616
<module>android</module>
17+
<module>slim</module>
1718
</modules>
1819

1920
</project>

tests/slim/pom.xml

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>org.everit.json.schema.tests.parent</artifactId>
7+
<groupId>org.everit.json</groupId>
8+
<version>0.0.0-develop</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>org.everit.json.schema.tests.slim</artifactId>
13+
14+
<build>
15+
<plugins>
16+
<plugin>
17+
<groupId>org.apache.maven.plugins</groupId>
18+
<artifactId>maven-compiler-plugin</artifactId>
19+
<version>3.3</version>
20+
<configuration>
21+
<source>1.8</source>
22+
<target>1.8</target>
23+
</configuration>
24+
</plugin>
25+
<plugin>
26+
<groupId>org.apache.maven.plugins</groupId>
27+
<artifactId>maven-surefire-plugin</artifactId>
28+
<version>2.22.2</version>
29+
<configuration>
30+
<dependenciesToScan>
31+
<dependency>org.everit.json:org.everit.json.schema.tests.vanilla</dependency>
32+
</dependenciesToScan>
33+
</configuration>
34+
35+
</plugin>
36+
</plugins>
37+
</build>
38+
39+
<dependencies>
40+
<dependency>
41+
<groupId>org.everit.json</groupId>
42+
<artifactId>org.everit.json.schema</artifactId>
43+
<version>${project.version}</version>
44+
<exclusions>
45+
<exclusion>
46+
<groupId>com.damnhandy</groupId>
47+
<artifactId>handy-uri-templates</artifactId>
48+
</exclusion>
49+
<exclusion>
50+
<groupId>commons-validator</groupId>
51+
<artifactId>commons-validator</artifactId>
52+
</exclusion>
53+
</exclusions>
54+
</dependency>
55+
<dependency>
56+
<groupId>${project.groupId}</groupId>
57+
<artifactId>org.everit.json.schema.tests.vanilla</artifactId>
58+
<version>${project.version}</version>
59+
</dependency>
60+
<dependency>
61+
<groupId>commons-io</groupId>
62+
<artifactId>commons-io</artifactId>
63+
<version>2.6</version>
64+
<scope>test</scope>
65+
</dependency>
66+
<dependency>
67+
<groupId>org.junit.jupiter</groupId>
68+
<artifactId>junit-jupiter</artifactId>
69+
<version>5.7.0</version>
70+
<scope>test</scope>
71+
</dependency>
72+
<dependency>
73+
<groupId>org.reflections</groupId>
74+
<artifactId>reflections</artifactId>
75+
<version>0.9.10</version>
76+
<scope>test</scope>
77+
</dependency>
78+
<dependency>
79+
<groupId>org.eclipse.jetty</groupId>
80+
<artifactId>jetty-servlet</artifactId>
81+
<version>9.3.4.RC0</version>
82+
<scope>test</scope>
83+
</dependency>
84+
</dependencies>
85+
86+
</project>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package org.everit.json.schema;
2+
3+
import java.util.List;
4+
5+
import org.everit.json.schema.loader.SchemaLoader;
6+
7+
import org.junit.jupiter.api.AfterAll;
8+
import org.junit.jupiter.api.BeforeAll;
9+
import org.junit.jupiter.params.ParameterizedTest;
10+
import org.junit.jupiter.params.provider.Arguments;
11+
import org.junit.jupiter.params.provider.MethodSource;
12+
13+
import static java.util.Arrays.asList;
14+
15+
public class V4TestSuiteTest {
16+
17+
private static JettyWrapper server;
18+
19+
public static List<Arguments> params() {
20+
return TestCase.loadAsParamsFromPackage("org.everit.json.schema.draft4", asList("hostname", "ipv6", "ipv4", "email"));
21+
}
22+
23+
@BeforeAll
24+
public static void startJetty() throws Exception {
25+
(server = new JettyWrapper("/org/everit/json/schema/remotes")).start();
26+
}
27+
28+
@AfterAll
29+
public static void stopJetty() throws Exception {
30+
server.stop();
31+
}
32+
33+
@ParameterizedTest
34+
@MethodSource("params")
35+
public void testInCollectingMode(TestCase tc) {
36+
tc.loadSchema(SchemaLoader.builder());
37+
tc.runTestInCollectingMode();
38+
}
39+
40+
@ParameterizedTest
41+
@MethodSource("params")
42+
public void testInEarlyFailingMode(TestCase tc) {
43+
tc.loadSchema(SchemaLoader.builder());
44+
tc.runTestInEarlyFailureMode();
45+
}
46+
47+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package org.everit.json.schema;
2+
3+
import java.util.List;
4+
5+
import org.everit.json.schema.loader.SchemaLoader;
6+
7+
import org.junit.jupiter.api.AfterAll;
8+
import org.junit.jupiter.api.BeforeAll;
9+
import org.junit.jupiter.params.ParameterizedTest;
10+
import org.junit.jupiter.params.provider.Arguments;
11+
import org.junit.jupiter.params.provider.MethodSource;
12+
13+
import static java.util.Arrays.asList;
14+
import static java.util.Collections.singletonList;
15+
16+
/**
17+
* @author erosb
18+
*/
19+
public class V6TestSuiteTest {
20+
21+
private static JettyWrapper server;
22+
23+
public static List<Arguments> params() {
24+
return TestCase.loadAsParamsFromPackage("org.everit.json.schema.draft6", asList("uri-template",
25+
"ipv6", "email", "hostname", "ipv4"));
26+
}
27+
28+
@BeforeAll
29+
public static void startJetty() throws Exception {
30+
(server = new JettyWrapper("/org/everit/json/schema/remotes")).start();
31+
}
32+
33+
@AfterAll
34+
public static void stopJetty() throws Exception {
35+
server.stop();
36+
}
37+
38+
@ParameterizedTest
39+
@MethodSource("params")
40+
public void testInCollectingMode(TestCase tc) {
41+
tc.loadSchema(SchemaLoader.builder().draftV6Support());
42+
tc.runTestInCollectingMode();
43+
}
44+
45+
@ParameterizedTest
46+
@MethodSource("params")
47+
public void testInEarlyFailingMode(TestCase tc) {
48+
tc.loadSchema(SchemaLoader.builder().draftV6Support());
49+
tc.runTestInEarlyFailureMode();
50+
}
51+
52+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package org.everit.json.schema;
2+
3+
import java.util.List;
4+
5+
import org.everit.json.schema.loader.SchemaLoader;
6+
7+
import org.junit.jupiter.api.AfterAll;
8+
import org.junit.jupiter.api.BeforeAll;
9+
import org.junit.jupiter.params.ParameterizedTest;
10+
import org.junit.jupiter.params.provider.Arguments;
11+
import org.junit.jupiter.params.provider.MethodSource;
12+
13+
import static java.util.Arrays.asList;
14+
import static java.util.Collections.singletonList;
15+
16+
/**
17+
* @author erosb
18+
*/
19+
public class V7TestSuiteTest {
20+
21+
private static JettyWrapper server;
22+
23+
public static List<Arguments> params() {
24+
return TestCase.loadAsParamsFromPackage("org.everit.json.schema.draft7", asList("uri-template",
25+
"ipv6", "email", "hostname", "ipv4"));
26+
}
27+
28+
@BeforeAll
29+
public static void startJetty() throws Exception {
30+
(server = new JettyWrapper("/org/everit/json/schema/remotes")).start();
31+
}
32+
33+
@AfterAll
34+
public static void stopJetty() throws Exception {
35+
server.stop();
36+
}
37+
38+
@ParameterizedTest
39+
@MethodSource("params")
40+
public void testInCollectingMode(TestCase tc) {
41+
tc.loadSchema(SchemaLoader.builder().draftV7Support());
42+
tc.runTestInCollectingMode();
43+
}
44+
45+
@ParameterizedTest
46+
@MethodSource("params")
47+
public void testInEarlyFailingMode(TestCase tc) {
48+
tc.loadSchema(SchemaLoader.builder().draftV7Support());
49+
tc.runTestInEarlyFailureMode();
50+
}
51+
}

tests/vanilla/src/main/java/org/everit/json/schema/TestCase.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import java.io.InputStreamReader;
66
import java.io.UncheckedIOException;
77
import java.util.ArrayList;
8+
import java.util.Collection;
9+
import java.util.Collections;
810
import java.util.List;
911
import java.util.Optional;
1012
import java.util.Set;
@@ -20,6 +22,7 @@
2022
import org.reflections.Reflections;
2123
import org.reflections.scanners.ResourcesScanner;
2224

25+
import static java.util.Collections.emptyList;
2326
import static org.junit.jupiter.api.Assertions.assertNotEquals;
2427

2528
/**
@@ -36,6 +39,10 @@ private static JSONArray loadTests(InputStream input) {
3639
}
3740

3841
static List<Arguments> loadAsParamsFromPackage(String packageName) {
42+
return loadAsParamsFromPackage(packageName, emptyList());
43+
}
44+
45+
static List<Arguments> loadAsParamsFromPackage(String packageName, Collection<String> excludePatterns) {
3946
List<Arguments> rval = new ArrayList<>();
4047
Reflections refs = new Reflections(packageName,
4148
new ResourcesScanner());
@@ -45,7 +52,10 @@ static List<Arguments> loadAsParamsFromPackage(String packageName) {
4552
continue;
4653
}
4754
String fileName = path.substring(path.lastIndexOf('/') + 1);
48-
JSONArray arr = loadTests(TestSuiteTest.class.getResourceAsStream("/" + path));
55+
if (excludePatterns.stream().anyMatch(fileName::contains)) {
56+
continue;
57+
}
58+
JSONArray arr = loadTests(V4TestSuiteTest.class.getResourceAsStream("/" + path));
4959
for (int i = 0; i < arr.length(); ++i) {
5060
JSONObject schemaTest = arr.getJSONObject(i);
5161
JSONArray testcaseInputs = schemaTest.getJSONArray("tests");
@@ -130,4 +140,8 @@ public void runTestInCollectingMode() {
130140
testWithValidator(Validator.builder().build(), schema);
131141
}
132142

143+
@Override
144+
public String toString() {
145+
return schemaDescription + "/" + inputDescription;
146+
}
133147
}

tests/vanilla/src/main/java/org/everit/json/schema/TestSuiteTest.java renamed to tests/vanilla/src/main/java/org/everit/json/schema/V4TestSuiteTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import org.junit.jupiter.params.provider.Arguments;
1111
import org.junit.jupiter.params.provider.MethodSource;
1212

13-
public class TestSuiteTest {
13+
public class V4TestSuiteTest {
1414

1515
private static JettyWrapper server;
1616

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[
2+
{
3+
"description": "validation of e-mail addresses",
4+
"schema": {
5+
"format": "email"
6+
},
7+
"tests": [
8+
{
9+
"description": "a valid e-mail address",
10+
"data": "[email protected]",
11+
"valid": true
12+
},
13+
{
14+
"description": "an invalid e-mail address",
15+
"data": "2962",
16+
"valid": false
17+
}
18+
]
19+
}
20+
]

0 commit comments

Comments
 (0)