001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io;
003
004import java.io.File;
005import java.io.FileInputStream;
006import java.io.FileOutputStream;
007import java.io.IOException;
008import java.io.InputStream;
009import java.io.OutputStream;
010import java.net.URL;
011import java.nio.charset.StandardCharsets;
012import java.util.zip.GZIPOutputStream;
013import java.util.zip.ZipOutputStream;
014
015import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
016import org.openstreetmap.josm.tools.Utils;
017
018/**
019 * An enum representing the compression type of a resource.
020 */
021public enum Compression {
022    /**
023     * no compression
024     */
025    NONE,
026    /**
027     * bzip2 compression
028     */
029    BZIP2,
030    /**
031     * gzip compression
032     */
033    GZIP,
034    /**
035     * zip compression
036     */
037    ZIP;
038
039    /**
040     * Determines the compression type depending on the suffix of {@code name}.
041     * @param name File name including extension
042     * @return the compression type
043     */
044    public static Compression byExtension(String name) {
045        return name != null && name.endsWith(".gz")
046                ? GZIP
047                : name != null && (name.endsWith(".bz2") || name.endsWith(".bz"))
048                ? BZIP2
049                : name != null && name.endsWith(".zip")
050                ? ZIP
051                : NONE;
052    }
053
054    /**
055     * Determines the compression type based on the content type (MIME type).
056     * @param contentType the content type
057     * @return the compression type
058     */
059    public static Compression forContentType(String contentType) {
060        switch (contentType) {
061        case "application/zip":
062            return ZIP;
063        case "application/x-gzip":
064            return GZIP;
065        case "application/x-bzip2":
066            return BZIP2;
067        default:
068            return NONE;
069        }
070    }
071
072    /**
073     * Returns an un-compressing {@link InputStream} for {@code in}.
074     * @param in raw input stream
075     * @return un-compressing input stream
076     *
077     * @throws IOException if any I/O error occurs
078     */
079    public InputStream getUncompressedInputStream(InputStream in) throws IOException {
080        switch (this) {
081            case BZIP2:
082                return Utils.getBZip2InputStream(in);
083            case GZIP:
084                return Utils.getGZipInputStream(in);
085            case ZIP:
086                return Utils.getZipInputStream(in);
087            case NONE:
088            default:
089                return in;
090        }
091    }
092
093    /**
094     * Returns an un-compressing {@link InputStream} for the {@link File} {@code file}.
095     * @param file file
096     * @return un-compressing input stream
097     * @throws IOException if any I/O error occurs
098     */
099    @SuppressWarnings("resource")
100    public static InputStream getUncompressedFileInputStream(File file) throws IOException {
101        return byExtension(file.getName()).getUncompressedInputStream(new FileInputStream(file));
102    }
103
104    /**
105     * Returns an un-compressing {@link InputStream} for the {@link URL} {@code url}.
106     * @param url URL
107     * @return un-compressing input stream
108     *
109     * @throws IOException if any I/O error occurs
110     * @deprecated Use {@link org.openstreetmap.josm.tools.HttpClient} instead
111     */
112    @Deprecated
113    public static InputStream getUncompressedURLInputStream(URL url) throws IOException {
114        return Utils.openURLAndDecompress(url, true);
115    }
116
117    /**
118     * Returns a compressing {@link OutputStream} for {@code out}.
119     * @param out raw output stream
120     * @return compressing output stream
121     *
122     * @throws IOException if any I/O error occurs
123     */
124    public OutputStream getCompressedOutputStream(OutputStream out) throws IOException {
125        switch (this) {
126            case BZIP2:
127                return new BZip2CompressorOutputStream(out);
128            case GZIP:
129                return new GZIPOutputStream(out);
130            case ZIP:
131                return new ZipOutputStream(out, StandardCharsets.UTF_8);
132            case NONE:
133            default:
134                return out;
135        }
136    }
137
138    /**
139     * Returns a compressing {@link OutputStream} for the {@link File} {@code file}.
140     * @param file file
141     * @return compressing output stream
142     *
143     * @throws IOException if any I/O error occurs
144     */
145    @SuppressWarnings("resource")
146    public static OutputStream getCompressedFileOutputStream(File file) throws IOException {
147        return byExtension(file.getName()).getCompressedOutputStream(new FileOutputStream(file));
148    }
149}