Skip to content
Snippets Groups Projects
Commit 32434914 authored by Tobias Thierer's avatar Tobias Thierer
Browse files

Introduce vendor.mime.types

Like mime.types and android.mime.types, this file specifies mappings
between MIME types and file extensions. Unlike those files, it can
only be used to define _additional_ mapping but not modify (change,
remove) any mappings defined by those files.

This is done by prepending '?' to every line element from
vendor.mime.types that doesn't already have one; when there is a
leading "?", it is ignored so that it's okay to move a line from
{android,vendor}.mime.types without necessarily changing it.

Test: Checked manually that vendor.mime.types works as expected.
  Specifically, after adding these lines to vendor.mime.type:

    audio/mpeg testmpeg
    audio/testmpeg mp3
    ?mime/foo ?fooext

  the following test passes:

    MimeTypeMap map = MimeTypeMap.getSingleton();
    // Original mapping is unchanged
    assertEquals("mp3", map.getExtensionFromMimeType("audio/mpeg"));
    assertEquals("audio/mpeg", map.getMimeTypeFromExtension("mp3"));

    // Map from the key to existing value is added
    assertEquals("audio/mpeg", map.getMimeTypeFromExtension("testmpeg"));
    assertEquals("mp3", map.getExtensionFromMimeType("audio/testmpeg"));

    // Completely new mapping is added both ways
    assertEquals("mime/foo", map.getMimeTypeFromExtension("fooext"));
    assertEquals("fooext", map.getExtensionFromMimeType("mime/foo"));

Bug: 141842825
Change-Id: Iaf918ce39324709ff58a8e0f9612e4827a673323
parent e25c54f3
No related branches found
No related tags found
No related merge requests found
......@@ -26,6 +26,7 @@ java_library {
java_resources: [
":debian.mime.types",
":android.mime.types",
":vendor.mime.types",
],
sdk_version: "core_platform",
......@@ -41,3 +42,14 @@ filegroup {
"java-res/android.mime.types",
],
}
filegroup {
name: "vendor.mime.types",
visibility: [
"//visibility:private",
],
path: "java-res/",
srcs: [
"java-res/vendor.mime.types",
],
}
###############################################################################
#
# Vendor-specific MIME type <-> extension mappings
#
# Each line below defines a mapping from one MIME type to the first of the
# listed extensions, and from listed extension back to the MIME type.
#
# This file can _add_ additional mappings that are not in the default set,
# but it it cannot _modify_ (replace or remove) any platform default mapping
# (defined in files mime.types and android.mime.types).
#
###############################################################################
#
# EXAMPLES
#
# A line of the form (without the leading '#''):
#
# mime ext1 ext2 ext3
#
# affects the current mappings along the lines of the following pseudo code:
#
# mimeToExt.putIfAbsent("mime", "ext1");
# extToMime.putIfAbsent("ext1", "mime");
# extToMime.putIfAbsent("ext2", "mime");
# extToMime.putIfAbsent("ext3", "mime");
#
# Optionally, MIME types or extensions may be prefixed by a single '?', which
# will be ignored. I.e., the following example lines all have the same semantics:
#
# mime ext1 ext2 ext3
# ?mime ext1 ext2 ext3
# mime ?ext1 ext2 ?ext3
# ?mime ?ext1 ?ext2 ?ext3
#
# By default, this file contains no mappings (which means that the platform
# default mapping is used unmodified).
#
###############################################################################
#
# Add your custom mappings below this line (with no "#" at the start of the line):
......@@ -21,6 +21,7 @@ import libcore.net.MimeMap;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
......@@ -44,20 +45,17 @@ public class DefaultMimeMapFactory {
* Android's default mapping between MIME types and extensions.
*/
public static MimeMap create() {
return parseFromResources("/mime.types", "/android.mime.types");
}
private static final Pattern SPLIT_PATTERN = Pattern.compile("\\s+");
static MimeMap parseFromResources(String... resourceNames) {
MimeMap.Builder builder = MimeMap.builder();
for (String resourceName : resourceNames) {
parseTypes(builder, resourceName);
}
parseTypes(builder, true, "/mime.types");
parseTypes(builder, true, "/android.mime.types");
parseTypes(builder, false, "/vendor.mime.types");
return builder.build();
}
private static void parseTypes(MimeMap.Builder builder, String resource) {
private static final Pattern SPLIT_PATTERN = Pattern.compile("\\s+");
private static void parseTypes(MimeMap.Builder builder, boolean allowOverwrite,
String resource) {
try (BufferedReader r = new BufferedReader(
new InputStreamReader(DefaultMimeMapFactory.class.getResourceAsStream(resource)))) {
String line;
......@@ -71,6 +69,12 @@ public class DefaultMimeMapFactory {
continue;
}
List<String> specs = Arrays.asList(SPLIT_PATTERN.split(line));
if (!allowOverwrite) {
// Pretend that the mimeType and each file extension listed in the line
// carries a "?" prefix, which means that it can add new mappings but
// not modify existing mappings (putIfAbsent() semantics).
specs = ensurePrefix("?", specs);
}
builder.put(specs.get(0), specs.subList(1, specs.size()));
}
} catch (IOException | RuntimeException e) {
......@@ -78,4 +82,15 @@ public class DefaultMimeMapFactory {
}
}
private static List<String> ensurePrefix(String prefix, List<String> strings) {
List<String> result = new ArrayList<>(strings.size());
for (String s : strings) {
if (!s.startsWith(prefix)) {
s = prefix + s;
}
result.add(s);
}
return result;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment