001// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
002//
003// SPDX-License-Identifier: Apache-2.0
004
005package sop.cli.picocli;
006
007import java.io.File;
008import java.io.FileInputStream;
009import java.io.FileNotFoundException;
010import java.io.IOException;
011
012import sop.exception.SOPGPException;
013
014public class FileUtil {
015
016    private static final String ERROR_AMBIGUOUS = "File name '%s' is ambiguous. File with the same name exists on the filesystem.";
017    private static final String ERROR_ENV_FOUND = "Environment variable '%s' not set.";
018    private static final String ERROR_OUTPUT_EXISTS = "Output file '%s' already exists.";
019    private static final String ERROR_INPUT_NOT_EXIST = "File '%s' does not exist.";
020    private static final String ERROR_CANNOT_CREATE_FILE = "Output file '%s' cannot be created: %s";
021
022    public static final String PRFX_ENV = "@ENV:";
023    public static final String PRFX_FD = "@FD:";
024
025    private static EnvironmentVariableResolver envResolver = System::getenv;
026
027    public static void setEnvironmentVariableResolver(EnvironmentVariableResolver envResolver) {
028        if (envResolver == null) {
029            throw new NullPointerException("Variable envResolver cannot be null.");
030        }
031        FileUtil.envResolver = envResolver;
032    }
033
034    public interface EnvironmentVariableResolver {
035        /**
036         * Resolve the value of the given environment variable.
037         * Return null if the variable is not present.
038         *
039         * @param name name of the variable
040         * @return variable value or null
041         */
042        String resolveEnvironmentVariable(String name);
043    }
044
045    public static File getFile(String fileName) {
046        if (fileName == null) {
047            throw new NullPointerException("File name cannot be null.");
048        }
049
050        if (fileName.startsWith(PRFX_ENV)) {
051
052            if (new File(fileName).exists()) {
053                throw new SOPGPException.AmbiguousInput(String.format(ERROR_AMBIGUOUS, fileName));
054            }
055
056            String envName = fileName.substring(PRFX_ENV.length());
057            String envValue = envResolver.resolveEnvironmentVariable(envName);
058            if (envValue == null) {
059                throw new IllegalArgumentException(String.format(ERROR_ENV_FOUND, envName));
060            }
061            return new File(envValue);
062        } else if (fileName.startsWith(PRFX_FD)) {
063
064            if (new File(fileName).exists()) {
065                throw new SOPGPException.AmbiguousInput(String.format(ERROR_AMBIGUOUS, fileName));
066            }
067
068            throw new IllegalArgumentException("File descriptors not supported.");
069        }
070
071        return new File(fileName);
072    }
073
074    public static FileInputStream getFileInputStream(String fileName) {
075        File file = getFile(fileName);
076        try {
077            FileInputStream inputStream = new FileInputStream(file);
078            return inputStream;
079        } catch (FileNotFoundException e) {
080            throw new SOPGPException.MissingInput(String.format(ERROR_INPUT_NOT_EXIST, fileName), e);
081        }
082    }
083
084    public static File createNewFileOrThrow(File file) throws IOException {
085        if (file == null) {
086            throw new NullPointerException("File cannot be null.");
087        }
088
089        try {
090            if (!file.createNewFile()) {
091                throw new SOPGPException.OutputExists(String.format(ERROR_OUTPUT_EXISTS, file.getAbsolutePath()));
092            }
093        } catch (IOException e) {
094            throw new IOException(String.format(ERROR_CANNOT_CREATE_FILE, file.getAbsolutePath(), e.getMessage()));
095        }
096        return file;
097    }
098}