/* * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.nio.fs; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.util.Map; import java.util.HashMap; import java.util.regex.Pattern; import java.util.regex.Matcher; import java.util.List; /** * File type detector that uses a file extension to look up its MIME type * by checking the mappings recorded in a mime.types file. */ class MimeTypesFileTypeDetector extends AbstractFileTypeDetector { private Map mimeTypeMap; private final Path mimeTypesFile; public MimeTypesFileTypeDetector(final Path filePath) { mimeTypesFile = filePath; } @Override protected String implProbeContentType(final Path file) { if (file == null || file.getFileName() == null) { return null; } final String extension = getExtension(file.getFileName().toString()); if (extension.isEmpty()) { return null; } loadMimeTypes(); if (mimeTypeMap == null || mimeTypeMap.isEmpty()) { return null; } String mimeType = null; // Case-sensitive search String ext = extension; do { mimeType = mimeTypeMap.get(ext); if (mimeType == null) { ext = getExtension(ext); } } while (mimeType == null && !ext.isEmpty()); // Case-insensitive search if no mime type is found if (mimeType == null) { ext = extension; do { for (String key : mimeTypeMap.keySet()) { if (ext.equalsIgnoreCase(key)) { mimeType = mimeTypeMap.get(key); break; } } if (mimeType == null) { ext = getExtension(ext); } } while (mimeType == null && !ext.isEmpty()); } return mimeType; } // Get the extension of a file name. private static String getExtension(final String name) { String ext = ""; if (name != null && !name.isEmpty()) { int dot = name.indexOf('.'); if ((dot >= 0) && (dot < name.length() - 1)) { ext = name.substring(dot + 1); } } return ext; } // Parse the mime types file, and store the type-extension // mappings into mimeTypeMap. private void loadMimeTypes() { if (mimeTypeMap != null || mimeTypesFile == null || !mimeTypesFile.toFile().isFile()) { return; } List lines = null; try { lines = Files.readAllLines(mimeTypesFile, Charset.defaultCharset()); } catch (IOException|SecurityException ex) { } if (lines != null && !lines.isEmpty()) { mimeTypeMap = new HashMap<>(lines.size()); String command = ""; for (String line : lines) { command += line; if (command.endsWith("\\")) { command = command.substring(0, command.length() - 1); continue; } parseMimeCommand(command); command = ""; } if (!command.isEmpty()) { parseMimeCommand(command); } } } /* * Parse a mime-types command, which can have the following formats: * 1) Simple space-delimited format * image/jpeg jpeg jpg jpe JPG * * 2) Netscape key-value format * type=application/x-java-jnlp-file desc="Java Web Start" exts="jnlp" * or * type=text/html exts=htm,html */ private void parseMimeCommand(String command) { command = command.trim(); if (command.isEmpty() || command.charAt(0) == '#') { return; } command = command.replaceAll("\\s*#.*", ""); int equalIdx = command.indexOf('='); if (equalIdx > 0) { // Parse a mime-types command having the key-value format final String TypeSign = "type="; String typeRegex = "\\b" + TypeSign + "(\"\\p{Graph}+?/\\p{Graph}+?\"|\\p{Graph}+/\\p{Graph}+\\b)"; Pattern typePattern = Pattern.compile(typeRegex); Matcher typeMatcher = typePattern.matcher(command); if (typeMatcher.find()) { String type = typeMatcher.group().substring(TypeSign.length()); if (type.charAt(0) == '"') { type = type.substring(1, type.length() - 1); } final String ExtSign = "exts="; String extRegex = "\\b" + ExtSign + "(\"[\\p{Graph}|\\p{Blank}]+?\"|\\p{Graph}+\\b)"; Pattern extPattern = Pattern.compile(extRegex); Matcher extMatcher = extPattern.matcher(command); if (extMatcher.find()) { String exts = extMatcher.group().substring(ExtSign.length()); if (exts.charAt(0) == '"') { exts = exts.substring(1, exts.length() - 1); } String[] extList = exts.split("[\\p{Blank}|\\p{Punct}]+"); for (String ext : extList) { putIfAbsent(ext, type); } } } } else { // Parse a mime-types command having the space-delimited format String[] elements = command.split("\\s+"); int i = 1; while (i < elements.length) { putIfAbsent(elements[i++], elements[0]); } } } private void putIfAbsent(String key, String value) { if (key != null && !key.isEmpty() && value != null && !value.isEmpty() && !mimeTypeMap.containsKey(key)) { mimeTypeMap.put(key, value); } } }