1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.documentsui.archives;
18 
19 import static org.apache.commons.compress.archivers.ArchiveStreamFactory.TAR;
20 import static org.apache.commons.compress.compressors.CompressorStreamFactory.BROTLI;
21 import static org.apache.commons.compress.compressors.CompressorStreamFactory.BZIP2;
22 import static org.apache.commons.compress.compressors.CompressorStreamFactory.GZIP;
23 import static org.apache.commons.compress.compressors.CompressorStreamFactory.XZ;
24 
25 import androidx.annotation.Nullable;
26 
27 import java.util.HashMap;
28 import java.util.Map;
29 import java.util.Set;
30 
31 import org.apache.commons.compress.compressors.brotli.BrotliUtils;
32 import org.apache.commons.compress.compressors.xz.XZUtils;
33 
34 /**
35  * To query how to generate ArchiveHandle, how to create CompressInputStream and how to create
36  * ArchiveInputStream by using MIME type in ArchiveRegistry.
37  */
38 final class ArchiveRegistry {
39     static final int COMMON_ARCHIVE_TYPE = 1;
40     static final int ZIP_TYPE = 2;
41     static final int SEVEN_Z_TYPE = 3;
42 
43     /**
44      * The mapping between MIME type and how to create ArchiveHandle instance.
45      * key - MIME type
46      * value - the integer value used in ArchiveHandle.create
47      */
48     private static final Map<String, Integer> sHandleArchiveMap = new HashMap<>();
49 
50     /**
51      * The mapping between MIME type and the archive name that is used by ArchiveStreamFactory.
52      * key - MIME type
53      * value - the archive name is used as the 1st parameter of ArchiveStreamFactory
54      *                 .createArchiveInputStream
55      */
56     private static final Map<String, String> sMimeTypeArchiveNameMap = new HashMap<>();
57 
58     /**
59      * The mapping between MIME type and the compress name that is used by CompressorStreamFactory.
60      * key - MIME type
61      * value - the compress name is used as the 1st parameter of CompressorStreamFactory
62      *                 .createCompressorInputStream
63      */
64     private static final Map<String, String> sMimeTypeCompressNameMap = new HashMap<>();
65 
66     static {
67         /* initial sHandleArchiveMap */
68         sHandleArchiveMap.put("application/zip", ZIP_TYPE);
69         sHandleArchiveMap.put("application/x-zip", ZIP_TYPE);
70         sHandleArchiveMap.put("application/x-zip-compressed", ZIP_TYPE);
71         sHandleArchiveMap.put("application/x-7z-compressed", SEVEN_Z_TYPE);
72         sHandleArchiveMap.put("application/x-gtar", COMMON_ARCHIVE_TYPE);
73         sHandleArchiveMap.put("application/x-tar", COMMON_ARCHIVE_TYPE);
74         sHandleArchiveMap.put("application/x-compressed-tar", COMMON_ARCHIVE_TYPE);
75         sHandleArchiveMap.put("application/x-gtar-compressed", COMMON_ARCHIVE_TYPE);
76         sHandleArchiveMap.put("application/x-bzip-compressed-tar", COMMON_ARCHIVE_TYPE);
77         if (BrotliUtils.isBrotliCompressionAvailable()) {
78             sHandleArchiveMap.put("application/x-brotli-compressed-tar", COMMON_ARCHIVE_TYPE);
79         }
80         if (XZUtils.isXZCompressionAvailable()) {
81             sHandleArchiveMap.put("application/x-xz-compressed-tar", COMMON_ARCHIVE_TYPE);
82         }
83 
84         /* initial sMimeTypeArchiveNameMap */
85         sMimeTypeArchiveNameMap.put("application/x-gtar", TAR);
86         sMimeTypeArchiveNameMap.put("application/x-tar", TAR);
87         sMimeTypeArchiveNameMap.put("application/x-compressed-tar", TAR);
88         sMimeTypeArchiveNameMap.put("application/x-gtar-compressed", TAR);
89         sMimeTypeArchiveNameMap.put("application/x-bzip-compressed-tar", TAR);
90         sMimeTypeArchiveNameMap.put("application/x-brotli-compressed-tar", TAR);
91         sMimeTypeArchiveNameMap.put("application/x-xz-compressed-tar", TAR);
92 
93         /* initial sMimeTypeCompressNameMap */
94         sMimeTypeCompressNameMap.put("application/x-compressed-tar", GZIP);
95         sMimeTypeCompressNameMap.put("application/x-gtar-compressed", GZIP);
96         sMimeTypeCompressNameMap.put("application/x-bzip-compressed-tar", BZIP2);
97         if (BrotliUtils.isBrotliCompressionAvailable()) {
98             sMimeTypeCompressNameMap.put("application/x-brotli-compressed-tar", BROTLI);
99         }
100         if (XZUtils.isXZCompressionAvailable()) {
101             sMimeTypeCompressNameMap.put("application/x-xz-compressed-tar", XZ);
102         }
103     }
104 
105     /**
106      * To query the archive name by passing MIME type is used by
107      * ArchiveStreamFactory.createArchiveInputStream.
108      *
109      * @param mimeType the MIME type of the archive file
110      * @return the archive name to tell ArchiveStreamFactory how to extract archive
111      */
112     @Nullable
getArchiveName(String mimeType)113     static String getArchiveName(String mimeType) {
114         return sMimeTypeArchiveNameMap.get(mimeType);
115     }
116 
117     /**
118      * To query the compress name by passing MIME type is used by
119      * CompressorStreamFactory.createCompressorInputStream.
120      *
121      * @param mimeType the MIME type of the compressed file
122      * @return the compress name to tell CompressorStreamFactory how to uncompress
123      */
124     @Nullable
getCompressName(String mimeType)125     static String getCompressName(String mimeType) {
126         return sMimeTypeCompressNameMap.get(mimeType);
127     }
128 
129     /**
130      * To query the method to uncompress the compressed file by MIME type.
131      *
132      * @param mimeType the MIME type of the compressed file
133      * @return the method describe how to uncompress the compressed file
134      */
135     @Nullable
getArchiveType(String mimeType)136     static Integer getArchiveType(String mimeType) {
137         return sHandleArchiveMap.get(mimeType);
138     }
139 
getSupportList()140     static Set<String> getSupportList() {
141         return sHandleArchiveMap.keySet();
142     }
143 }
144