Skip to content

Commit 0fdee4a

Browse files
author
Dirk Rudolph
committed
Split the PatternValidator into 2 classes.
This is necessary to guarantee that classes from org.joni and org.jcodings are only loaded when the ecma262 configuration is set. Having both in the same class and one of the class' members being a class from the before mentioned packages fails with a NoClassDefFoundException when running in an OSGI environments with the imports of the packages being optional and not present.
1 parent 5dadf03 commit 0fdee4a

File tree

1 file changed

+107
-50
lines changed

1 file changed

+107
-50
lines changed

src/main/java/com/networknt/schema/PatternValidator.java

Lines changed: 107 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@
1616

1717
package com.networknt.schema;
1818

19-
import com.fasterxml.jackson.databind.JsonNode;
19+
import java.util.Collections;
20+
import java.util.Set;
21+
import java.util.regex.Pattern;
22+
import java.util.regex.PatternSyntaxException;
23+
2024
import org.jcodings.specific.UTF8Encoding;
2125
import org.joni.Option;
2226
import org.joni.Regex;
@@ -25,78 +29,131 @@
2529
import org.slf4j.Logger;
2630
import org.slf4j.LoggerFactory;
2731

28-
import java.util.Collections;
29-
import java.util.Set;
30-
import java.util.regex.Matcher;
31-
import java.util.regex.Pattern;
32-
import java.util.regex.PatternSyntaxException;
32+
import com.fasterxml.jackson.databind.JsonNode;
3333

34-
public class PatternValidator extends BaseJsonValidator implements JsonValidator {
35-
private static final Logger logger = LoggerFactory.getLogger(PatternValidator.class);
34+
public class PatternValidator implements JsonValidator {
3635

37-
private String pattern;
38-
private Pattern compiledPattern;
39-
private Regex compiledRegex;
36+
private final JsonValidator delegate;
4037

4138
public PatternValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext) {
39+
if (validationContext.getConfig() != null && validationContext.getConfig().isEcma262Validator()) {
40+
delegate = new PatternValidatorEcma262(schemaPath, schemaNode, parentSchema, validationContext);
41+
} else {
42+
delegate = new PatternValidatorJava(schemaPath, schemaNode, parentSchema, validationContext);
43+
}
44+
}
45+
46+
@Override
47+
public Set<ValidationMessage> validate(JsonNode rootNode) {
48+
return delegate.validate(rootNode);
49+
}
50+
51+
@Override
52+
public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String at) {
53+
return delegate.validate(node, rootNode, at);
54+
}
55+
56+
private static class PatternValidatorJava extends BaseJsonValidator implements JsonValidator {
57+
private static final Logger logger = LoggerFactory.getLogger(PatternValidator.class);
58+
59+
private String pattern;
60+
private Pattern compiledPattern;
61+
62+
public PatternValidatorJava(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext) {
63+
64+
super(schemaPath, schemaNode, parentSchema, ValidatorTypeCode.PATTERN, validationContext);
65+
pattern = "";
66+
if (schemaNode != null && schemaNode.isTextual()) {
67+
pattern = schemaNode.textValue();
68+
try {
69+
compiledPattern = Pattern.compile(pattern);
70+
} catch (PatternSyntaxException pse) {
71+
logger.error("Failed to compile pattern : Invalid syntax [" + pattern + "]", pse);
72+
throw pse;
73+
}
74+
}
75+
76+
parseErrorCode(getValidatorType().getErrorCodeKey());
77+
}
78+
79+
private boolean matches(String value) {
80+
return compiledPattern == null || compiledPattern.matcher(value).find();
81+
}
82+
83+
public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String at) {
84+
debug(logger, node, rootNode, at);
85+
86+
JsonType nodeType = TypeFactory.getValueNodeType(node);
87+
if (nodeType != JsonType.STRING) {
88+
return Collections.emptySet();
89+
}
4290

43-
super(schemaPath, schemaNode, parentSchema, ValidatorTypeCode.PATTERN, validationContext);
44-
pattern = "";
45-
if (schemaNode != null && schemaNode.isTextual()) {
46-
pattern = schemaNode.textValue();
4791
try {
48-
compileRegexPattern(pattern, validationContext.getConfig() != null && validationContext.getConfig().isEcma262Validator());
92+
if (!matches(node.asText())) {
93+
return Collections.singleton(buildValidationMessage(at, pattern));
94+
}
4995
} catch (PatternSyntaxException pse) {
50-
logger.error("Failed to compile pattern : Invalid syntax [" + pattern + "]", pse);
51-
throw pse;
52-
} catch (SyntaxException se) {
53-
logger.error("Failed to compile pattern : Invalid syntax [" + pattern + "]", se);
54-
throw se;
96+
logger.error("Failed to apply pattern on " + at + ": Invalid syntax [" + pattern + "]", pse);
5597
}
56-
}
5798

58-
parseErrorCode(getValidatorType().getErrorCodeKey());
99+
return Collections.emptySet();
100+
}
59101
}
60102

61-
private void compileRegexPattern(String regex, boolean useEcma262Validator) {
62-
if (useEcma262Validator) {
103+
private static class PatternValidatorEcma262 extends BaseJsonValidator implements JsonValidator {
104+
private static final Logger logger = LoggerFactory.getLogger(PatternValidator.class);
105+
106+
private String pattern;
107+
private Regex compiledRegex;
108+
109+
public PatternValidatorEcma262(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext) {
110+
111+
super(schemaPath, schemaNode, parentSchema, ValidatorTypeCode.PATTERN, validationContext);
112+
pattern = "";
113+
if (schemaNode != null && schemaNode.isTextual()) {
114+
pattern = schemaNode.textValue();
115+
try {
116+
compileRegexPattern(pattern, validationContext.getConfig() != null && validationContext.getConfig().isEcma262Validator());
117+
} catch (SyntaxException se) {
118+
logger.error("Failed to compile pattern : Invalid syntax [" + pattern + "]", se);
119+
throw se;
120+
}
121+
}
122+
123+
parseErrorCode(getValidatorType().getErrorCodeKey());
124+
}
125+
126+
private void compileRegexPattern(String regex, boolean useEcma262Validator) {
63127
byte[] regexBytes = regex.getBytes();
64128
this.compiledRegex = new Regex(regexBytes, 0, regexBytes.length, Option.NONE, UTF8Encoding.INSTANCE, Syntax.ECMAScript);
65-
} else {
66-
compiledPattern = Pattern.compile(pattern);
67129
}
68-
}
69130

70-
private boolean matches(String value) {
71-
if (compiledRegex == null && compiledPattern == null) {
72-
return true;
73-
}
131+
private boolean matches(String value) {
132+
if (compiledRegex == null) {
133+
return true;
134+
}
74135

75-
if (compiledPattern == null) {
76136
byte[] bytes = value.getBytes();
77137
return compiledRegex.matcher(bytes).search(0, bytes.length, Option.NONE) >= 0;
78-
} else {
79-
return compiledPattern.matcher(value).find();
80138
}
81139

82-
}
140+
public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String at) {
141+
debug(logger, node, rootNode, at);
83142

84-
public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String at) {
85-
debug(logger, node, rootNode, at);
86-
87-
JsonType nodeType = TypeFactory.getValueNodeType(node);
88-
if (nodeType != JsonType.STRING) {
89-
return Collections.emptySet();
90-
}
143+
JsonType nodeType = TypeFactory.getValueNodeType(node);
144+
if (nodeType != JsonType.STRING) {
145+
return Collections.emptySet();
146+
}
91147

92-
try {
93-
if (!matches(node.asText())) {
94-
return Collections.singleton(buildValidationMessage(at, pattern));
148+
try {
149+
if (!matches(node.asText())) {
150+
return Collections.singleton(buildValidationMessage(at, pattern));
151+
}
152+
} catch (PatternSyntaxException pse) {
153+
logger.error("Failed to apply pattern on " + at + ": Invalid syntax [" + pattern + "]", pse);
95154
}
96-
} catch (PatternSyntaxException pse) {
97-
logger.error("Failed to apply pattern on " + at + ": Invalid syntax [" + pattern + "]", pse);
98-
}
99155

100-
return Collections.emptySet();
156+
return Collections.emptySet();
157+
}
101158
}
102159
}

0 commit comments

Comments
 (0)