diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index 02713043a6..5f67aa54ea 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -32,7 +32,9 @@ import java.io.File; import java.io.InputStream; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; +import org.xml.sax.InputSource; /** * A tool for running the SBE parser, validator, and code generator. @@ -281,9 +283,16 @@ public static MessageSchema parseSchema(final String sbeSchemaFilename) .warningsFatal(Boolean.parseBoolean(System.getProperty(VALIDATION_WARNINGS_FATAL))) .suppressOutput(Boolean.parseBoolean(System.getProperty(VALIDATION_SUPPRESS_OUTPUT))); - try (InputStream in = new BufferedInputStream(Files.newInputStream(Paths.get(sbeSchemaFilename)))) + final Path filePath = Paths.get(sbeSchemaFilename); + try (InputStream in = new BufferedInputStream(Files.newInputStream(filePath))) { - return XmlSchemaParser.parse(in, optionsBuilder.build()); + final InputSource inputSource = new InputSource(in); + final Path parentPath = filePath.toAbsolutePath().getParent(); + if (parentPath != null) + { + inputSource.setSystemId(filePath.toUri().toString()); + } + return XmlSchemaParser.parse(inputSource, optionsBuilder.build()); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index a1f0dd5b88..08e494e7dd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -34,6 +34,7 @@ import java.nio.ByteOrder; import java.util.HashMap; import java.util.Map; +import org.xml.sax.InputSource; import static uk.co.real_logic.sbe.PrimitiveType.*; import static uk.co.real_logic.sbe.xml.Presence.REQUIRED; @@ -94,16 +95,16 @@ public static void validate(final String xsdFilename, final InputStream in, fina } /** - * Take an {@link InputStream} and parse it generating map of template ID to Message objects, types, and schema. + * Take an {@link InputSource} and parse it generating map of template ID to Message objects, types, and schema. *
* Exceptions are passed back up for any problems. * - * @param in stream from which schema is read. + * @param is inputSource from which schema is read. Ideally it will have the systemId property set to resolve relative references * @param options to be applied during parsing. * @return {@link MessageSchema} encoding for the schema. * @throws Exception on parsing error. */ - public static MessageSchema parse(final InputStream in, final ParserOptions options) throws Exception + public static MessageSchema parse(final InputSource is, final ParserOptions options) throws Exception { final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); @@ -114,7 +115,7 @@ public static MessageSchema parse(final InputStream in, final ParserOptions opti factory.setFeature("http://apache.org/xml/features/xinclude/fixup-base-uris", false); } - final Document document = factory.newDocumentBuilder().parse(in); + final Document document = factory.newDocumentBuilder().parse(is); final XPath xPath = XPathFactory.newInstance().newXPath(); final ErrorHandler errorHandler = new ErrorHandler(options); @@ -133,6 +134,25 @@ public static MessageSchema parse(final InputStream in, final ParserOptions opti return messageSchema; } + /** + * Wraps an {@link InputStream} into an {@link InputSource} and delegates to + * {@link #parse(org.xml.sax.InputSource, uk.co.real_logic.sbe.xml.ParserOptions) }. + *
Note: this method does not the the {@link InputSource#setSystemId(java.lang.String) } property, however. It is recommended to use the + * {@link #parse(org.xml.sax.InputSource, uk.co.real_logic.sbe.xml.ParserOptions) } method directly.
+ * + *
+ * Exceptions are passed back up for any problems.
+ *
+ * @param in stream from which schema is read.
+ * @param options to be applied during parsing.
+ * @return {@link MessageSchema} encoding for the schema.
+ * @throws Exception on parsing error.
+ */
+ public static MessageSchema parse(final InputStream in, final ParserOptions options) throws Exception
+ {
+ return parse(new InputSource(in), options);
+ }
+
/**
* Scan XML for all types (encodedDataType, compositeType, enumType, and setType) and save in map
*
diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java
new file mode 100644
index 0000000000..33b113055c
--- /dev/null
+++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013-2019 Real Logic Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package uk.co.real_logic.sbe.xml;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.junit.Test;
+
+import org.xml.sax.InputSource;
+import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse;
+
+public class RelativeXIncludeTest
+{
+ @Test
+ public void shouldParseFileInSubDir()
+ throws Exception
+ {
+ final ClassLoader classLoader = getClass().getClassLoader();
+ final URL testResource = classLoader.getResource("sub/basic-schema.xml");
+ final InputStream inStream = testResource.openStream();
+ final InputSource is = new InputSource(inStream);
+
+ final File file = new File(testResource.getFile());
+ is.setSystemId(file.toPath().toAbsolutePath().getParent().toUri().toString());
+ parse(is, ParserOptions.DEFAULT);
+ }
+
+}
\ No newline at end of file
diff --git a/sbe-tool/src/test/resources/sub/basic-schema.xml b/sbe-tool/src/test/resources/sub/basic-schema.xml
new file mode 100644
index 0000000000..54c728ca24
--- /dev/null
+++ b/sbe-tool/src/test/resources/sub/basic-schema.xml
@@ -0,0 +1,12 @@
+
+