001// Generated by delombok at Sat Feb 25 17:58:34 UTC 2023
002package io.cui.tools.io;
003
004import static io.cui.tools.string.MoreStrings.isEmpty;
005import static java.util.Objects.requireNonNull;
006import java.io.IOException;
007import java.io.InputStream;
008import java.io.OutputStream;
009import java.net.MalformedURLException;
010import java.net.URL;
011import java.nio.file.Files;
012import java.nio.file.Path;
013import java.nio.file.Paths;
014import io.cui.tools.base.Preconditions;
015import io.cui.tools.logging.CuiLogger;
016import io.cui.tools.string.MoreStrings;
017
018/**
019 * File-system based variant. Responsible for all non {@link FileTypePrefix#CLASSPATH} files.
020 *
021 * @author Oliver Wolff
022 */
023public class FileSystemLoader implements FileReaderWriter {
024    private static final long serialVersionUID = -1278929108857440808L;
025    private static final CuiLogger LOG = new CuiLogger(FileSystemLoader.class);
026    private final String normalizedPathName;
027    private final boolean readable;
028    private final boolean writable;
029    private final StructuredFilename fileName;
030
031    /**
032     * @param pathName must not be null nor empty, must not start with the prefix
033     *            "classpath:" but may start with the prefix
034     *            "file:" and contain at least one character despite the prefix. On all other cases
035     *            a {@link IllegalArgumentException} will be
036     *            thrown.
037     */
038    public FileSystemLoader(final String pathName) {
039        requireNonNull(pathName);
040        normalizedPathName = checkPathName(pathName);
041        Preconditions.checkArgument(!isEmpty(normalizedPathName), "\'%s\' can not be normalized", pathName);
042        final var path = getPath();
043        readable = MorePaths.checkReadablePath(path, false, true);
044        writable = MorePaths.checkAccessiblePath(path, false, false);
045        fileName = new StructuredFilename(path.toAbsolutePath().getFileName().toString());
046    }
047
048    /**
049     * Variant that uses a path as the constructor argument
050     *
051     * @param path must not be null
052     */
053    public FileSystemLoader(final Path path) {
054        this(requireNonNull(path).toFile().getAbsolutePath());
055    }
056
057    /**
058     * @return the path
059     */
060    public Path getPath() {
061        return Paths.get(normalizedPathName);
062    }
063
064    @Override
065    public InputStream inputStream() throws IOException {
066        if (!isReadable()) {
067            throw new IllegalStateException("\'" + normalizedPathName + "\' is not readable");
068        }
069        return Files.newInputStream(getPath());
070    }
071
072    /**
073     * Checks and modifies a given pathName
074     *
075     * @param pathName must not be null nor empty, must not start with the prefix
076     *            "classpath:" but may start with the prefix
077     *            "file:" and contain at least one character despite the prefix. On all other cases
078     *            a {@link IllegalArgumentException} will be
079     *            thrown.
080     *
081     * @return the normalized pathname without prefix
082     */
083    public static String checkPathName(final String pathName) {
084        MoreStrings.requireNotEmpty(pathName, "pathName");
085        if (pathName.startsWith(FileTypePrefix.CLASSPATH.getPrefix())) {
086            throw new IllegalArgumentException("Invalid path name, must start not start with " + FileTypePrefix.CLASSPATH + " but was: " + pathName);
087        }
088        var newPathName = pathName;
089        if (pathName.startsWith(FileTypePrefix.FILE.getPrefix())) {
090            newPathName = FileTypePrefix.FILE.removePrefix(pathName);
091        } else if (pathName.startsWith(FileTypePrefix.EXTERNAL.getPrefix())) {
092            try {
093                newPathName = new java.io.File(".").getCanonicalPath() + FileTypePrefix.EXTERNAL.removePrefix(pathName);
094                LOG.debug("Loading config file from external path: {}", newPathName);
095            } catch (final IOException e) {
096                LOG.error("Retrieving the current dir failed: ", e);
097            }
098        }
099        if (isEmpty(newPathName)) {
100            throw new IllegalArgumentException("Filename " + pathName + " is invalid");
101        }
102        return MorePaths.getRealPathSafely(newPathName).toString();
103    }
104
105    @Override
106    public boolean isFilesystemLoader() {
107        return true;
108    }
109
110    @Override
111    public URL getURL() {
112        try {
113            return getPath().toUri().toURL();
114        } catch (final MalformedURLException e) {
115            throw new IllegalStateException(e);
116        }
117    }
118
119    /**
120     * Truncate and overwrite an existing file, or create the file if it doesn't initially exist.
121     */
122    @Override
123    public OutputStream outputStream() throws IOException {
124        if (!isWritable()) {
125            throw new IllegalStateException(normalizedPathName + " is not writable");
126        }
127        return Files.newOutputStream(getPath());
128    }
129
130    @java.lang.Override
131    @java.lang.SuppressWarnings("all")
132    @lombok.Generated
133    public boolean equals(final java.lang.Object o) {
134        if (o == this) return true;
135        if (!(o instanceof FileSystemLoader)) return false;
136        final FileSystemLoader other = (FileSystemLoader) o;
137        if (!other.canEqual((java.lang.Object) this)) return false;
138        final java.lang.Object this$normalizedPathName = this.normalizedPathName;
139        final java.lang.Object other$normalizedPathName = other.normalizedPathName;
140        if (this$normalizedPathName == null ? other$normalizedPathName != null : !this$normalizedPathName.equals(other$normalizedPathName)) return false;
141        return true;
142    }
143
144    @java.lang.SuppressWarnings("all")
145    @lombok.Generated
146    protected boolean canEqual(final java.lang.Object other) {
147        return other instanceof FileSystemLoader;
148    }
149
150    @java.lang.Override
151    @java.lang.SuppressWarnings("all")
152    @lombok.Generated
153    public int hashCode() {
154        final int PRIME = 59;
155        int result = 1;
156        final java.lang.Object $normalizedPathName = this.normalizedPathName;
157        result = result * PRIME + ($normalizedPathName == null ? 43 : $normalizedPathName.hashCode());
158        return result;
159    }
160
161    @java.lang.Override
162    @java.lang.SuppressWarnings("all")
163    @lombok.Generated
164    public java.lang.String toString() {
165        return "FileSystemLoader(normalizedPathName=" + this.normalizedPathName + ", readable=" + this.isReadable() + ", writable=" + this.isWritable() + ", fileName=" + this.getFileName() + ")";
166    }
167
168    @java.lang.SuppressWarnings("all")
169    @lombok.Generated
170    public boolean isReadable() {
171        return this.readable;
172    }
173
174    @java.lang.SuppressWarnings("all")
175    @lombok.Generated
176    public boolean isWritable() {
177        return this.writable;
178    }
179
180    @java.lang.SuppressWarnings("all")
181    @lombok.Generated
182    public StructuredFilename getFileName() {
183        return this.fileName;
184    }
185}