diff options
author | Jon Marius Venstad <venstad@gmail.com> | 2020-09-03 13:57:51 +0200 |
---|---|---|
committer | Jon Marius Venstad <venstad@gmail.com> | 2020-09-03 13:57:51 +0200 |
commit | 046dac504b19012a099b40ed40e95e2c8aaa6ac2 (patch) | |
tree | b0c5c6a68fd5a5168ac1a5c303ddf0b46e609ad5 | |
parent | bd92ef3cdb7db5eb03b466913b335bc5cc7faf41 (diff) |
Wrap xml files in a file(system)wrapper in preprocessing
4 files changed, 79 insertions, 9 deletions
diff --git a/config-application-package/src/main/java/com/yahoo/config/application/FileSystemWrapper.java b/config-application-package/src/main/java/com/yahoo/config/application/FileSystemWrapper.java new file mode 100644 index 00000000000..8a08c56b3c0 --- /dev/null +++ b/config-application-package/src/main/java/com/yahoo/config/application/FileSystemWrapper.java @@ -0,0 +1,50 @@ +package com.yahoo.config.application; + +import com.yahoo.yolean.function.ThrowingFunction; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Optional; +import java.util.function.Predicate; + +/** + * Wraps a real or virtual file system — essentially a mapping from paths to bytes. + * + * @author jonmv + */ +public class FileSystemWrapper { + + Predicate<Path> existence; + ThrowingFunction<Path, byte[], IOException> reader; + + private FileSystemWrapper(Predicate<Path> existence, ThrowingFunction<Path, byte[], IOException> reader) { + this.existence = existence; + this.reader = reader; + } + + public static FileSystemWrapper ofFiles(Predicate<Path> existence, ThrowingFunction<Path, byte[], IOException> reader) { + return new FileSystemWrapper(existence, reader); + } + + public static FileSystemWrapper getDefault() { + return ofFiles(Files::exists, Files::readAllBytes); + } + + public FileWrapper wrap(Path path) { + return new FileWrapper(path); + } + + + public class FileWrapper { + private final Path path; + private FileWrapper(Path path) { this.path = path; } + + public Path path() { return path; } + public boolean exists() { return existence.test(path); } + public byte[] content() throws IOException { return reader.apply(path); } + public Optional<FileWrapper> parent() { return Optional.ofNullable(path.getParent()).map(path -> wrap(path)); } + public FileWrapper child(String name) { return wrap(path.resolve(name)); } + } + +} diff --git a/config-application-package/src/main/java/com/yahoo/config/application/IncludeProcessor.java b/config-application-package/src/main/java/com/yahoo/config/application/IncludeProcessor.java index c2da2a55b48..b09953c738c 100644 --- a/config-application-package/src/main/java/com/yahoo/config/application/IncludeProcessor.java +++ b/config-application-package/src/main/java/com/yahoo/config/application/IncludeProcessor.java @@ -1,7 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.application; -import com.yahoo.io.IOUtils; +import com.yahoo.config.application.FileSystemWrapper.FileWrapper; import com.yahoo.text.XML; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -14,6 +14,9 @@ import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.util.List; +import java.util.NoSuchElementException; + +import static java.nio.charset.StandardCharsets.UTF_8; /** * Handles preprocess:include statements and returns a Document which has all the include statements resolved @@ -23,10 +26,14 @@ import java.util.List; */ class IncludeProcessor implements PreProcessor { - private final File application; + private final FileWrapper application; + public IncludeProcessor(File application) { - this.application = application; + this(FileSystemWrapper.getDefault().wrap(application.toPath())); + } + public IncludeProcessor(FileWrapper application) { + this.application = application; } public Document process(Document input) throws IOException, TransformerException { @@ -35,17 +42,18 @@ class IncludeProcessor implements PreProcessor { return doc; } - private static void includeFile(File currentFolder, Element currentElement) throws IOException { + private static void includeFile(FileWrapper currentFolder, Element currentElement) throws IOException { NodeList list = currentElement.getElementsByTagNameNS(XmlPreProcessor.preprocessNamespaceUri, "include"); while (list.getLength() > 0) { Element elem = (Element) list.item(0); Element parent = (Element) elem.getParentNode(); String filename = elem.getAttribute("file"); boolean required = ! elem.hasAttribute("required") || Boolean.parseBoolean(elem.getAttribute("required")); - File file = new File(currentFolder, filename); + FileWrapper file = currentFolder.child(filename); Document subFile = IncludeProcessor.parseIncludeFile(file, parent.getTagName(), required); - includeFile(file.getParentFile(), subFile.getDocumentElement()); + includeFile(file.parent().orElseThrow(() -> new NoSuchElementException(file + " has no parent")), + subFile.getDocumentElement()); //System.out.println("document before merging: " + documentAsString(doc)); IncludeProcessor.mergeInto(parent, XML.getChildren(subFile.getDocumentElement())); @@ -65,12 +73,12 @@ class IncludeProcessor implements PreProcessor { } } - private static Document parseIncludeFile(File file, String parentTagName, boolean required) throws IOException { + private static Document parseIncludeFile(FileWrapper file, String parentTagName, boolean required) throws IOException { StringWriter w = new StringWriter(); final String startTag = "<" + parentTagName + " " + XmlPreProcessor.deployNamespace + "='" + XmlPreProcessor.deployNamespaceUri + "' " + XmlPreProcessor.preprocessNamespace + "='" + XmlPreProcessor.preprocessNamespaceUri + "'>"; w.append(startTag); if (file.exists() || required) { - w.append(IOUtils.readFile(file)); + w.append(new String(file.content(), UTF_8)); } final String endTag = "</" + parentTagName + ">"; w.append(endTag); diff --git a/config-application-package/src/main/java/com/yahoo/config/application/XmlPreProcessor.java b/config-application-package/src/main/java/com/yahoo/config/application/XmlPreProcessor.java index c49a799f2b7..61b67dfb5c6 100644 --- a/config-application-package/src/main/java/com/yahoo/config/application/XmlPreProcessor.java +++ b/config-application-package/src/main/java/com/yahoo/config/application/XmlPreProcessor.java @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.application; +import com.yahoo.config.application.FileSystemWrapper.FileWrapper; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.RegionName; @@ -31,7 +32,7 @@ public class XmlPreProcessor { final static String preprocessNamespace = "xmlns:preprocess"; final static String preprocessNamespaceUri = "properties"; //TODO - private final File applicationDir; + private final FileWrapper applicationDir; private final Reader xmlInput; private final InstanceName instance; private final Environment environment; @@ -43,6 +44,10 @@ public class XmlPreProcessor { } public XmlPreProcessor(File applicationDir, Reader xmlInput, InstanceName instance, Environment environment, RegionName region) { + this(FileSystemWrapper.getDefault().wrap(applicationDir.toPath()), xmlInput, instance, environment, region); + } + + public XmlPreProcessor(FileWrapper applicationDir, Reader xmlInput, InstanceName instance, Environment environment, RegionName region) { this.applicationDir = applicationDir; this.xmlInput = xmlInput; this.instance = instance; diff --git a/controller-server/pom.xml b/controller-server/pom.xml index 158c1b5cd39..0ddc1ecd8be 100644 --- a/controller-server/pom.xml +++ b/controller-server/pom.xml @@ -28,6 +28,13 @@ <dependency> <groupId>com.yahoo.vespa</groupId> + <artifactId>config-application-package</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>com.yahoo.vespa</groupId> <artifactId>container-dev</artifactId> <version>${project.version}</version> <scope>provided</scope> |