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