/*
* Copyright 2016 LINE Corporation
*
* LINE Corporation licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.linecorp.armeria.server.http.file;
import static java.util.Objects.requireNonNull;
import java.net.URLConnection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import com.google.common.base.Ascii;
import com.linecorp.armeria.common.MediaType;
final class MimeTypeUtil {
/**
* A map from extension to MIME types, which is queried before
* {@link URLConnection#guessContentTypeFromName(String)}, so that
* important extensions are always mapped to the right MIME types.
*/
private static final Map<String, MediaType> EXTENSION_TO_MEDIA_TYPE;
static {
final Map<String, MediaType> map = new HashMap<>();
// Text files
add(map, MediaType.CSS_UTF_8, "css");
add(map, MediaType.HTML_UTF_8, "html", "htm");
add(map, MediaType.PLAIN_TEXT_UTF_8, "txt");
// Image files
add(map, MediaType.GIF, "gif");
add(map, MediaType.JPEG, "jpeg", "jpg");
add(map, MediaType.PNG, "png");
add(map, MediaType.SVG_UTF_8, "svg", "svgz");
add(map, MediaType.create("image", "x-icon"), "ico");
// Font files
add(map, MediaType.create("application", "x-font-ttf"), "ttc", "ttf");
add(map, MediaType.WOFF, "woff");
add(map, MediaType.create("application", "font-woff2"), "woff2");
add(map, MediaType.EOT, "eot");
add(map, MediaType.create("font", "opentype"), "otf");
// JavaScript, XML, etc
add(map, MediaType.JAVASCRIPT_UTF_8, "js");
add(map, MediaType.JSON_UTF_8, "json");
add(map, MediaType.PDF, "pdf");
add(map, MediaType.XHTML_UTF_8, "xhtml", "xhtm");
add(map, MediaType.APPLICATION_XML_UTF_8, "xml", "xsd");
add(map, MediaType.create("application", "xml-dtd"), "dtd");
EXTENSION_TO_MEDIA_TYPE = Collections.unmodifiableMap(map);
}
private static void add(Map<String, MediaType> extensionToMediaType,
MediaType mediaType, String... extensions) {
for (String e : extensions) {
assert Ascii.toLowerCase(e).equals(e);
extensionToMediaType.put(e, mediaType);
}
}
@Nullable
static MediaType guessFromPath(String path, boolean preCompressed) {
requireNonNull(path, "path");
// If the path is for a precompressed file, it will have an additional extension indicating the
// encoding, which we don't want to use when determining content type.
if (preCompressed) {
path = path.substring(0, path.lastIndexOf('.'));
}
final int dotIdx = path.lastIndexOf('.');
final int slashIdx = path.lastIndexOf('/');
if (dotIdx < 0 || slashIdx > dotIdx) {
// No extension
return null;
}
final String extension = Ascii.toLowerCase(path.substring(dotIdx + 1));
final MediaType mediaType = EXTENSION_TO_MEDIA_TYPE.get(extension);
if (mediaType != null) {
return mediaType;
}
final String guessedContentType = URLConnection.guessContentTypeFromName(path);
return guessedContentType != null ? MediaType.parse(guessedContentType) : null;
}
private MimeTypeUtil() {}
}