--- /dev/null 2012-11-29 00:32:57.270518291 -0800 +++ new/src/solaris/classes/sun/nio/fs/MimeTypesFileTypeDetector.java 2012-11-29 01:02:55.434540468 -0800 @@ -0,0 +1,210 @@ +/* + * 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); + } + } +}