From 6d485411f95c29c4c5f64152cc673abfd8a9bc11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kenneth=20Waldenstr=C3=B8m?= Date: Thu, 12 Oct 2017 14:19:50 +0200 Subject: [PATCH 1/2] Replaced 'new URL' with a call to a new URLFactory which also handles related schema files that is only available in the classpath --- .../networknt/schema/BaseJsonValidator.java | 11 ++- .../com/networknt/schema/RefValidator.java | 5 +- .../schema/url/ClasspathURLStreamHandler.java | 85 +++++++++++++++++++ .../com/networknt/schema/url/URLFactory.java | 28 ++++++ 4 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/networknt/schema/url/ClasspathURLStreamHandler.java create mode 100644 src/main/java/com/networknt/schema/url/URLFactory.java diff --git a/src/main/java/com/networknt/schema/BaseJsonValidator.java b/src/main/java/com/networknt/schema/BaseJsonValidator.java index e9af87adf..11ec376f1 100644 --- a/src/main/java/com/networknt/schema/BaseJsonValidator.java +++ b/src/main/java/com/networknt/schema/BaseJsonValidator.java @@ -17,6 +17,7 @@ package com.networknt.schema; import com.fasterxml.jackson.databind.JsonNode; +import com.networknt.schema.url.URLFactory; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -77,8 +78,14 @@ protected JsonSchema obainSubSchemaNode(JsonNode schemaNode){ try { JsonSchemaFactory factory = new JsonSchemaFactory(); - URL url = new URL(node.textValue()); - return factory.getSchema(url); + String text = node.textValue(); + if (text == null) { + return null; + } + else { + URL url = URLFactory.toURL(node.textValue()); + return factory.getSchema(url); + } } catch (MalformedURLException e) { return null; } diff --git a/src/main/java/com/networknt/schema/RefValidator.java b/src/main/java/com/networknt/schema/RefValidator.java index dc861a776..90bc67807 100644 --- a/src/main/java/com/networknt/schema/RefValidator.java +++ b/src/main/java/com/networknt/schema/RefValidator.java @@ -18,6 +18,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.networknt.schema.url.URLFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,7 +54,7 @@ public RefValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSch JsonSchemaFactory factory = new JsonSchemaFactory(mapper); try { - URL url = new URL(schemaUrl); + URL url = URLFactory.toURL(schemaUrl); parentSchema = factory.getSchema(url); } catch (MalformedURLException e) { InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(schemaUrl); @@ -89,7 +90,7 @@ private String obtainAbsolutePath(JsonSchema parentSchema, String schemaUrl) { if(schemaRef.startsWith(REF_DOMAIN)){ // from domain add ref try { - URL url = new URL(baseSchemaUrl); + URL url = URLFactory.toURL(baseSchemaUrl); baseSchemaUrl = url.getProtocol()+"//"+url.getHost(); } catch (MalformedURLException e) { e.printStackTrace(); diff --git a/src/main/java/com/networknt/schema/url/ClasspathURLStreamHandler.java b/src/main/java/com/networknt/schema/url/ClasspathURLStreamHandler.java new file mode 100644 index 000000000..f856b3e63 --- /dev/null +++ b/src/main/java/com/networknt/schema/url/ClasspathURLStreamHandler.java @@ -0,0 +1,85 @@ +package com.networknt.schema.url; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; + +/** + * An {@link URLStreamHandler} capable of loading resources from the classpath. + * + * @author Kenneth Waldenstrom + */ +class ClasspathURLStreamHandler extends URLStreamHandler { + private final static String CLASSPATH_PREFIX = "classpath:"; + private final static String RESOURCE_PREFIX = "resource:"; + + boolean supports(final String pURL) { + return pURL.startsWith(CLASSPATH_PREFIX) || pURL.startsWith(RESOURCE_PREFIX); + } + + @Override + protected URLConnection openConnection(final URL pURL) throws IOException { + return new ClassPathURLConnection(pURL); + } + + class ClassPathURLConnection extends URLConnection { + + private Class mHost = null; + + protected ClassPathURLConnection(URL pURL) { + super(pURL); + } + + @Override + public final void connect() throws IOException { + String className = url.getHost(); + try { + if (className != null && className.length() > 0) { + mHost = Class.forName(className); + } + connected = true; + } + catch (ClassNotFoundException e) { + throw new IOException("Class not found: " + e.toString()); + } + } + + @Override + public final InputStream getInputStream() throws IOException { + if (!connected) { + connect(); + } + return getResourceAsStream(url); + } + + private InputStream getResourceAsStream(URL pURL) throws IOException { + String path = pURL.getPath(); + + if (path.startsWith("/")) { + path = path.substring(1); + } + + InputStream stream; + if (mHost != null) { + stream = mHost.getClassLoader().getResourceAsStream(path); + } + else { + stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(path); + if (stream == null) { + stream = getClass().getClassLoader().getResourceAsStream(path); + } + if (stream == null) { + stream = ClassLoader.getSystemResourceAsStream(path); + } + } + if (stream == null) { + throw new IOException("Resource " + path + " not found in classpath."); + } + return stream; + } + } + + +} diff --git a/src/main/java/com/networknt/schema/url/URLFactory.java b/src/main/java/com/networknt/schema/url/URLFactory.java new file mode 100644 index 000000000..38ecc3071 --- /dev/null +++ b/src/main/java/com/networknt/schema/url/URLFactory.java @@ -0,0 +1,28 @@ +package com.networknt.schema.url; + +import java.net.MalformedURLException; +import java.net.URL; + +/** + * A factory for creating {@link URL}'s. This factory creates {@link URL}'s that in additional to the standard {@link URL}'s + * capability of loading resources using http, https, file, etc. also makes it possible to load resources from + * the applications classpath. To load a resource from classpath, the url must be prefixed either with classpath: + * or resource: + * + * To ensure that we support classpath resources, this class should be used instead of new URL(pURL) + * + * @author Kenneth Waldenstrom + */ +public class URLFactory { + private static final ClasspathURLStreamHandler sClasspathURLStreamHandler = new ClasspathURLStreamHandler(); + + /** + * Creates an {@link URL} based on the provided string + * @param pURL the url + * @return a {@link URL} + * @throws MalformedURLException if the url is not a proper URL + */ + public static URL toURL(final String pURL) throws MalformedURLException { + return new URL(null, pURL, sClasspathURLStreamHandler.supports(pURL) ? sClasspathURLStreamHandler : null); + } +} \ No newline at end of file From 4bb14fb8f1b595f5d2ace9eba6a7c68b7013a5ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kenneth=20Waldenstr=C3=B8m?= Date: Fri, 13 Oct 2017 08:00:38 +0200 Subject: [PATCH 2/2] Bumped version number --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index aa7eb46e6..35bb777da 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 4.0.0 com.networknt json-schema-validator - 0.1.10 + 0.1.10-escenic A json schema validator that supports draft v4 https://github.com/networknt/json-schema-validator JsonSchemaValidator