/* * Copyright 2000-2016 Vaadin Ltd. * * Licensed 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.vaadin.util; import java.io.File; import java.io.Serializable; import java.util.Collections; import java.util.Map; import java.util.StringTokenizer; import java.util.concurrent.ConcurrentHashMap; import com.vaadin.server.Resource; import com.vaadin.server.ThemeResource; /** * Utility class that can figure out mime-types and icons related to files. * <p> * Note : The icons are associated purely to mime-types, so a file may not have * a custom icon accessible with this class. * </p> * * @author Vaadin Ltd. * @since 3.0 */ @SuppressWarnings("serial") public class FileTypeResolver implements Serializable { /** * Default icon given if no icon is specified for a mime-type. */ static public Resource DEFAULT_ICON = new ThemeResource( "../runo/icons/16/document.png"); /** * Default mime-type. */ static public String DEFAULT_MIME_TYPE = "application/octet-stream"; /** * Initial file extension to mime-type mapping. */ private static final String initialExtToMIMEMap = "application/cu-seeme csm cu," + "application/dsptype tsp," + "application/futuresplash spl," + "application/mac-binhex40 hqx," + "application/msaccess mdb," + "application/msword doc dot," + "application/octet-stream bin," + "application/oda oda," + "application/pdf pdf," + "application/pgp-signature pgp," + "application/postscript ps ai eps," + "application/rtf rtf," + "application/vnd.ms-excel xls xlb," + "application/vnd.ms-powerpoint ppt pps pot," + "application/vnd.wap.wmlc wmlc," + "application/vnd.wap.wmlscriptc wmlsc," + "application/wordperfect5.1 wp5," + "application/zip zip," + "application/x-123 wk," + "application/x-bcpio bcpio," + "application/x-chess-pgn pgn," + "application/x-cpio cpio," + "application/x-debian-package deb," + "application/x-director dcr dir dxr," + "application/x-dms dms," + "application/x-dvi dvi," + "application/x-xfig fig," + "application/x-font pfa pfb gsf pcf pcf.Z," + "application/x-gnumeric gnumeric," + "application/x-gtar gtar tgz taz," + "application/x-hdf hdf," + "application/x-httpd-php phtml pht php," + "application/x-httpd-php3 php3," + "application/x-httpd-php3-source phps," + "application/x-httpd-php3-preprocessed php3p," + "application/x-httpd-php4 php4," + "application/x-ica ica," + "application/x-java-archive jar," + "application/x-java-serialized-object ser," + "application/x-java-vm class," + "application/x-javascript js," + "application/x-kchart chrt," + "application/x-killustrator kil," + "application/x-kpresenter kpr kpt," + "application/x-kspread ksp," + "application/x-kword kwd kwt," + "application/x-latex latex," + "application/x-lha lha," + "application/x-lzh lzh," + "application/x-lzx lzx," + "application/x-maker frm maker frame fm fb book fbdoc," + "application/x-mif mif," + "application/x-msdos-program com exe bat dll," + "application/x-msi msi," + "application/x-netcdf nc cdf," + "application/x-ns-proxy-autoconfig pac," + "application/x-object o," + "application/x-ogg ogg," + "application/x-oz-application oza," + "application/x-perl pl pm," + "application/x-pkcs7-crl crl," + "application/x-redhat-package-manager rpm," + "application/x-shar shar," + "application/x-shockwave-flash swf swfl," + "application/x-star-office sdd sda," + "application/x-stuffit sit," + "application/x-sv4cpio sv4cpio," + "application/x-sv4crc sv4crc," + "application/x-tar tar," + "application/x-tex-gf gf," + "application/x-tex-pk pk PK," + "application/x-texinfo texinfo texi," + "application/x-trash ~ % bak old sik," + "application/x-troff t tr roff," + "application/x-troff-man man," + "application/x-troff-me me," + "application/x-troff-ms ms," + "application/x-ustar ustar," + "application/x-wais-source src," + "application/x-wingz wz," + "application/x-x509-ca-cert crt," + "audio/basic au snd," + "audio/midi mid midi," + "audio/mpeg mpga mpega mp2 mp3," + "audio/mpegurl m3u," + "audio/prs.sid sid," + "audio/x-aiff aif aiff aifc," + "audio/x-gsm gsm," + "audio/x-pn-realaudio ra rm ram," + "audio/x-scpls pls," + "audio/x-wav wav," + "audio/ogg ogg," + "audio/mp4 m4a," + "audio/x-aac aac," + "image/bitmap bmp," + "image/gif gif," + "image/ief ief," + "image/jpeg jpeg jpg jpe," + "image/pcx pcx," + "image/png png," + "image/svg+xml svg svgz," + "image/tiff tiff tif," + "image/vnd.wap.wbmp wbmp," + "image/x-cmu-raster ras," + "image/x-coreldraw cdr," + "image/x-coreldrawpattern pat," + "image/x-coreldrawtemplate cdt," + "image/x-corelphotopaint cpt," + "image/x-jng jng," + "image/x-portable-anymap pnm," + "image/x-portable-bitmap pbm," + "image/x-portable-graymap pgm," + "image/x-portable-pixmap ppm," + "image/x-rgb rgb," + "image/x-xbitmap xbm," + "image/x-xpixmap xpm," + "image/x-xwindowdump xwd," + "text/comma-separated-values csv," + "text/css css," + "text/html htm html xhtml," + "text/mathml mml," + "text/plain txt text diff," + "text/richtext rtx," + "text/tab-separated-values tsv," + "text/vnd.wap.wml wml," + "text/vnd.wap.wmlscript wmls," + "text/xml xml," + "text/x-c++hdr h++ hpp hxx hh," + "text/x-c++src c++ cpp cxx cc," + "text/x-chdr h," + "text/x-csh csh," + "text/x-csrc c," + "text/x-java java," + "text/x-moc moc," + "text/x-pascal p pas," + "text/x-setext etx," + "text/x-sh sh," + "text/x-tcl tcl tk," + "text/x-tex tex ltx sty cls," + "text/x-vcalendar vcs," + "text/x-vcard vcf," + "video/dl dl," + "video/fli fli," + "video/gl gl," + "video/mpeg mpeg mpg mpe," + "video/quicktime qt mov," + "video/x-mng mng," + "video/x-ms-asf asf asx," + "video/x-msvideo avi," + "video/x-sgi-movie movie," + "video/ogg ogv," + "video/mp4 mp4," + "x-world/x-vrml vrm vrml wrl"; /** * File extension to MIME type mapping. All extensions are in lower case. */ private static final Map<String, String> EXT_TO_MIME_MAP = new ConcurrentHashMap<>(); /** * MIME type to Icon mapping. */ private static final Map<String, Resource> MIME_TO_ICON_MAP = new ConcurrentHashMap<>(); static { // Initialize extension to MIME map final StringTokenizer lines = new StringTokenizer(initialExtToMIMEMap, ","); while (lines.hasMoreTokens()) { final String line = lines.nextToken(); final StringTokenizer exts = new StringTokenizer(line); final String type = exts.nextToken(); while (exts.hasMoreTokens()) { final String ext = exts.nextToken(); addExtension(ext, type); } } // Initialize Icons ThemeResource folder = new ThemeResource("../runo/icons/16/folder.png"); addIcon("inode/drive", folder); addIcon("inode/directory", folder); } /** * Gets the mime-type of a file. Currently the mime-type is resolved based * only on the file name extension. * * @param fileName * the name of the file whose mime-type is requested. * @return mime-type <code>String</code> for the given filename */ public static String getMIMEType(String fileName) { // Checks for nulls if (fileName == null) { throw new NullPointerException("Filename can not be null"); } // Calculates the extension of the file int dotIndex = fileName.indexOf('.'); while (dotIndex >= 0 && fileName.indexOf('.', dotIndex + 1) >= 0) { dotIndex = fileName.indexOf('.', dotIndex + 1); } dotIndex++; if (fileName.length() > dotIndex) { String ext = fileName.substring(dotIndex); // Ignore any query parameters int queryStringStart = ext.indexOf('?'); if (queryStringStart > 0) { ext = ext.substring(0, queryStringStart); } // Return type from extension map, if found final String type = EXT_TO_MIME_MAP.get(ext.toLowerCase()); if (type != null) { return type; } } return DEFAULT_MIME_TYPE; } /** * Gets the descriptive icon representing file, based on the filename. First * the mime-type for the given filename is resolved, and then the * corresponding icon is fetched from the internal icon storage. If it is * not found the default icon is returned. * * @param fileName * the name of the file whose icon is requested. * @return the icon corresponding to the given file */ public static Resource getIcon(String fileName) { return getIconByMimeType(getMIMEType(fileName)); } private static Resource getIconByMimeType(String mimeType) { final Resource icon = MIME_TO_ICON_MAP.get(mimeType); if (icon != null) { return icon; } // If nothing is known about the file-type, general file // icon is used return DEFAULT_ICON; } /** * Gets the descriptive icon representing a file. First the mime-type for * the given file name is resolved, and then the corresponding icon is * fetched from the internal icon storage. If it is not found the default * icon is returned. * * @param file * the file whose icon is requested. * @return the icon corresponding to the given file */ public static Resource getIcon(File file) { return getIconByMimeType(getMIMEType(file)); } /** * Gets the mime-type for a file. Currently the returned file type is * resolved by the filename extension only. * * @param file * the file whose mime-type is requested. * @return the files mime-type <code>String</code> */ public static String getMIMEType(File file) { // Checks for nulls if (file == null) { throw new NullPointerException("File can not be null"); } // Directories if (file.isDirectory()) { // Drives if (file.getParentFile() == null) { return "inode/drive"; } else { return "inode/directory"; } } // Return type from extension return getMIMEType(file.getName()); } /** * Adds a mime-type mapping for the given filename extension. If the * extension is already in the internal mapping it is overwritten. * * @param extension * the filename extension to be associated with * <code>MIMEType</code>. * @param MIMEType * the new mime-type for <code>extension</code>. */ public static void addExtension(String extension, String MIMEType) { EXT_TO_MIME_MAP.put(extension.toLowerCase(), MIMEType); } /** * Adds a icon for the given mime-type. If the mime-type also has a * corresponding icon, it is replaced with the new icon. * * @param MIMEType * the mime-type whose icon is to be changed. * @param icon * the new icon to be associated with <code>MIMEType</code>. */ public static void addIcon(String MIMEType, Resource icon) { MIME_TO_ICON_MAP.put(MIMEType, icon); } /** * Gets the internal file extension to mime-type mapping. * * @return unmodifiable map containing the current file extension to * mime-type mapping */ public static Map<String, String> getExtensionToMIMETypeMapping() { return Collections.unmodifiableMap(EXT_TO_MIME_MAP); } /** * Gets the internal mime-type to icon mapping. * * @return unmodifiable map containing the current mime-type to icon mapping */ public static Map<String, Resource> getMIMETypeToIconMapping() { return Collections.unmodifiableMap(MIME_TO_ICON_MAP); } private FileTypeResolver() { } }