FileContentResolver.java

package net.morimekta.providence.config.util;

import javax.annotation.Nonnull;
import javax.annotation.WillNotClose;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;

import static net.morimekta.util.FileUtil.readCanonicalPath;

public class FileContentResolver implements ContentResolver {
    @Nonnull
    @Override
    public Path canonical(Path file) throws IOException {
        file = file.normalize().toAbsolutePath();
        file = readCanonicalPath(file);
        if (!Files.exists(file)) {
            throw new FileNotFoundException(file.toString());
        }
        return file;
    }

    @Nonnull
    @Override
    public Path reference(Path referenceLocation, Path from, String reference) {
        if (reference.startsWith(".." + File.separator)) {
            // if navigating "up" use the reference originating location,
            // not the file's actual location.
            return referenceLocation.resolve(reference).normalize();
        } else {
            return from.getParent().resolve(reference).normalize();
        }
    }

    @Nonnull
    @Override
    public Path referenceLocationPath(Path referenceLocation, Path from, String reference) {
        if (reference.contains(File.separator)) {
            // if not the same folder, use reference location as base for resolving,
            // otherwise keep.
            return referenceLocation.resolve(reference).normalize().getParent();
        } else {
            return referenceLocation;
        }
    }

    @Nonnull
    @Override
    @WillNotClose
    public InputStream open(Path file) throws IOException {
        return new FileInputStream(readCanonicalPath(file).toFile());
    }
}