/* * Copyright 2007-2009 Medsea Business Solutions S.L. * * 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 eu.medsea.mimeutil; import java.io.File; import java.io.InputStream; import java.net.URL; import java.nio.ByteOrder; import java.util.Collection; import java.util.Set; import eu.medsea.mimeutil.detector.MimeDetector; /** * <p> * NOTE: Since version 2.1 this class delegates ALL calls to a static instance of the new MimeUtil2 implementation. * @see eu.medsea.mimeutil.MimeUtil2 * </p> * <p> * The <code>MimeUtil</code> utility is a utility class that allows applications to detect, work with and manipulate MIME types. * </p> * <p> * A MIME or "Multipurpose Internet Mail Extension" type is an Internet standard that is important outside of just e-mail use. * MIME is used extensively in other communications protocols such as HTTP for web communications. * IANA "Internet Assigned Numbers Authority" is responsible for the standardisation and publication of MIME types. Basically any * resource on any computer that can be located via a URI can be assigned a mime type. So for instance, JPEG images have a MIME type * of image/jpg. Some resources can have multiple MIME types associated with them such as files with an XML extension have the MIME types * text/xml and application/xml and even specialised versions of xml such as image/svg+xml for SVG image files. * </p> * <p> * To do this <code>MimeUtil</code> uses registered <code>MimeDetector</code>(s) that are delegated to in sequence to actually * perform the detection. There a several <code>MimeDetector</code> implementations that come with the utility and * you can register and unregister them to perform detection based on file extensions, file globing and magic number detection.<br/> * Their is also a fourth MimeDetector that is registered by default that detects text files and encodings. Unlike the other * MimeDetector(s) or any MimeDetector(s) you may choose to implement, the TextMimeDetector cannot be registered or * unregistered by your code. It is advisable that you read the java doc for the TextMimeDetector as it can be modified in * several ways to make it perform better and or detect more specific types.<br/> * * Please refer to the java doc for each of these <code>MimeDetector</code>(s) for a description of how they * actually perform their particular detection process. * </p> * <p> * It is important to note that MIME matching is not an exact science, meaning * that a positive match does not guarantee that the returned MIME type is actually correct. * It is a best guess method of matching and the matched MIME types should be used with this in * mind. * </p> * <p> * New <code>MimeDetector</code>(s) can easily be created and registered with <code>MimeUtil</code> to extend it's * functionality beyond these initial detection strategies by extending the <code>AbstractMimeDetector</code> class. * To see how to implement your own <code>MimeDetector</code> take a look * at the java doc and source code for the {@link ExtensionMimeDetector}, {@link MagicMimeMimeDetector} and * {@link OpendesktopMimeDetector} classes. To register and unregister MimeDetector(s) use the * [un]registerMimeDetector(...) methods of this class. * </p> * <p> * The order that the <code>MimeDetector</code>(s) are executed is defined by the order each <code>MimeDetector</code> is registered. * </p> * <p> * The resulting <code>Collection</code> of MIME types returned in response to a getMimeTypes(...) call is a normalised list of the * accumulation of MIME types returned by each of the registered <code>MimeDetector</code>(s) that implement the specified getMimeTypesXXX(...) * methods. * </p> * <p> * All methods in this class that return a Collection object containing MimeType(s) actually return a {@link MimeTypeHashSet} * that implements both the {@link Set} and {@link Collection} interfaces. * </p> * * @author Steven McArdle. * */ public class MimeUtil { private static MimeUtil2 mimeUtil = new MimeUtil2(); /** * While MimeType(s) are being loaded by the MimeDetector(s) they should be * added to the list of known MIME types. It is not mandatory for MimeDetector(s) * to do so but they should where possible so that the list is as complete as possible. * You can add other MIME types to this list using this method. You can then use the * isMimeTypeKnown(...) utility methods to see if a MIME type you have * matches one that the utility has already seen. * <p> * This can be used to limit the mime types you work with i.e. if its not been loaded * then don't bother using it as it won't match. This is no guarantee that a match will not * be found as it is possible that a particular MimeDetector does not have an initialisation * phase that loads all of the MIME types it will match. * </p> * <p> * For instance if you had a MIME type of abc/xyz and passed this to * isMimeTypeKnown(...) it would return false unless you specifically add * this to the know MIME types using this method. * </p> * * @param mimeType * a MIME type you want to add to the known MIME types. * Duplicates are ignored. * @see #isMimeTypeKnown(String mimeType) * @see #isMimeTypeKnown(MimeType mimetType) */ public static void addKnownMimeType(final MimeType mimeType) { MimeUtil2.addKnownMimeType(mimeType); } /** * While MimeType(s) are being loaded by the MimeDetector(s) they should be * added to the list of known MIME types. It is not mandatory for MimeDetector(s) * to do so but they should where possible so that the list is as complete as possible. * You can add other MIME types to this list using this method. You can then use the * isMimeTypeKnown(...) utility methods to see if a MIME type you have * matches one that the utility has already seen. * <p> * This can be used to limit the mime types you work with i.e. if its not been loaded * then don't bother using it as it won't match. This is no guarantee that a match will not * be found as it is possible that a particular MimeDetector does not have an initialisation * phase that loads all of the MIME types it will match. * </p> * <p> * For instance if you had a MIME type of abc/xyz and passed this to * isMimeTypeKnown(...) it would return false unless you specifically add * this to the know MIME types using this method. * </p> * * @param mimeType * a MIME type you want to add to the known MIME types. * Duplicates are ignored. * @see #isMimeTypeKnown(String mimetype) * @see #isMimeTypeKnown(MimeType mimetType) */ public static void addKnownMimeType(final String mimeType) { MimeUtil2.addKnownMimeType(mimeType); } /** * Register a MimeDetector and add it to the MimeDetector registry. * MimeDetector(s) are effectively singletons as they are keyed against their * fully qualified class name. * @param mimeDetector. This must be the fully qualified name of a concrete instance of an * AbstractMimeDetector class. * This enforces that all custom MimeDetector(s) extend the AbstractMimeDetector. * @see MimeDetector */ public static MimeDetector registerMimeDetector(final String mimeDetector) { return mimeUtil.registerMimeDetector(mimeDetector); } /** * Get the extension part of a file name defined by the file parameter. * * @param file * a file object * @return the file extension or null if it does not have one. */ public static String getExtension(final File file) { return MimeUtil2.getExtension(file); } /** * Get the extension part of a file name defined by the fileName parameter. * There may be no extension or it could be a single part extension such as * .bat or a multi-part extension such as .tar.gz * * @param fileName * a relative or absolute path to a file * @return the file extension or null if it does not have one. */ public static String getExtension(final String fileName) { return MimeUtil2.getExtension(fileName); } /** * Get the first in a comma separated list of mime types. Useful when using * extension mapping that can return multiple mime types separate by commas * and you only want the first one. * * @param mimeTypes * comma separated list of mime types * @return first in a comma separated list of mime types or null if the mimeTypes string is null or empty */ public static MimeType getFirstMimeType(final String mimeTypes) { return MimeUtil2.getFirstMimeType(mimeTypes); } /** * Utility method to get the major or media part of a mime type * i.e. the part before the '/' character * * @param mimeType * you want to get the media part from * @return media type of the mime type * @throws MimeException * if you pass in an invalid mime type structure */ public static String getMediaType(final String mimeType) throws MimeException { return MimeUtil2.getMediaType(mimeType); } /** * * Utility method to get the quality part of a mime type. If it does not * exist then it is always set to q=1.0 unless it's a wild card. For the * major component wild card the value is set to 0.01 For the minor * component wild card the value is set to 0.02 * <p> * Thanks to the Apache organisation for these settings. * * @param mimeType * a valid mime type string with or without a valid q parameter * @return the quality value of the mime type either calculated from the * rules above or the actual value defined. * @throws MimeException * this is thrown if the mime type pattern is invalid. */ public static double getMimeQuality(final String mimeType) throws MimeException { return MimeUtil2.getMimeQuality(mimeType); } /** * Get a registered MimeDetector by name. * @param name the name of a registered MimeDetector. This is always the fully qualified * name of the class implementing the MimeDetector. * @return */ public static MimeDetector getMimeDetector(final String name) { return mimeUtil.getMimeDetector(name); } /** * Get a Collection of possible MimeType(s) that this byte array could represent * according to the registered MimeDetector(s). If no MimeType(s) are detected * then the returned Collection will contain only the UNKNOWN_MIME_TYPE * @param data * @return all matching MimeType(s) * @throws MimeException */ public static final Collection getMimeTypes(final byte [] data) throws MimeException { return mimeUtil.getMimeTypes(data); } /** * Get a Collection of possible MimeType(s) that this byte array could represent * according to the registered MimeDetector(s). If no MimeType(s) are detected * then the returned Collection will contain only the passed in unknownMimeType * @param data * @param unknownMimeType used if the registered MimeDetector(s) fail to match any MimeType(s) * @return all matching MimeType(s) * @throws MimeException */ public static final Collection getMimeTypes(final byte [] data, final MimeType unknownMimeType) throws MimeException { return mimeUtil.getMimeTypes(data, unknownMimeType); } /** * Get all of the matching mime types for this file object. * The method delegates down to each of the registered MimeHandler(s) and returns a * normalised list of all matching mime types. If no matching mime types are found the returned * Collection will contain the default UNKNOWN_MIME_TYPE * @param file the File object to detect. * @return collection of matching MimeType(s) * @throws MimeException if there are problems such as reading files generated when the MimeHandler(s) * executed. */ public static final Collection getMimeTypes(final File file) throws MimeException { return mimeUtil.getMimeTypes(file); } /** * Get all of the matching mime types for this file object. * The method delegates down to each of the registered MimeHandler(s) and returns a * normalised list of all matching mime types. If no matching mime types are found the returned * Collection will contain the unknownMimeType passed in. * @param file the File object to detect. * @param unknownMimeType. * @return the Collection of matching mime types. If the collection would be empty i.e. no matches then this will * contain the passed in parameter unknownMimeType * @throws MimeException if there are problems such as reading files generated when the MimeHandler(s) * executed. */ public static final Collection getMimeTypes(final File file, final MimeType unknownMimeType) throws MimeException { return mimeUtil.getMimeTypes(file, unknownMimeType); } /** * Get all of the matching mime types for this InputStream object. * The method delegates down to each of the registered MimeHandler(s) and returns a * normalised list of all matching mime types. If no matching mime types are found the returned * Collection will contain the default UNKNOWN_MIME_TYPE * @param in InputStream to detect. * @return * @throws MimeException if there are problems such as reading files generated when the MimeHandler(s) * executed. */ public static final Collection getMimeTypes(final InputStream in) throws MimeException { return mimeUtil.getMimeTypes(in); } /** * Get all of the matching mime types for this InputStream object. * The method delegates down to each of the registered MimeHandler(s) and returns a * normalised list of all matching mime types. If no matching mime types are found the returned * Collection will contain the unknownMimeType passed in. * @param in the InputStream object to detect. * @param unknownMimeType. * @return the Collection of matching mime types. If the collection would be empty i.e. no matches then this will * contain the passed in parameter unknownMimeType * @throws MimeException if there are problems such as reading files generated when the MimeHandler(s) * executed. */ public static final Collection getMimeTypes(final InputStream in, final MimeType unknownMimeType) throws MimeException { return mimeUtil.getMimeTypes(in, unknownMimeType); } /** * Get all of the matching mime types for this file name. * The method delegates down to each of the registered MimeHandler(s) and returns a * normalised list of all matching mime types. If no matching mime types are found the returned * Collection will contain the default UNKNOWN_MIME_TYPE * @param fileName the name of a file to detect. * @return collection of matching MimeType(s) * @throws MimeException if there are problems such as reading files generated when the MimeHandler(s) * executed. */ public static final Collection getMimeTypes(final String fileName) throws MimeException { return mimeUtil.getMimeTypes(fileName); } /** * Get all of the matching mime types for this file name . * The method delegates down to each of the registered MimeHandler(s) and returns a * normalised list of all matching mime types. If no matching mime types are found the returned * Collection will contain the unknownMimeType passed in. * @param fileName the name of a file to detect. * @param unknownMimeType. * @return the Collection of matching mime types. If the collection would be empty i.e. no matches then this will * contain the passed in parameter unknownMimeType * @throws MimeException if there are problems such as reading files generated when the MimeHandler(s) * executed. */ public static final Collection getMimeTypes(final String fileName, final MimeType unknownMimeType) throws MimeException { return mimeUtil.getMimeTypes(fileName, unknownMimeType); } /** * Get all of the matching mime types for this URL object. * The method delegates down to each of the registered MimeHandler(s) and returns a * normalised list of all matching mime types. If no matching mime types are found the returned * Collection will contain the default UNKNOWN_MIME_TYPE * @param url a URL to detect. * @return Collection of matching MimeType(s) * @throws MimeException if there are problems such as reading files generated when the MimeHandler(s) * executed. */ public static final Collection getMimeTypes(final URL url) throws MimeException { return mimeUtil.getMimeTypes(url); } public static final Collection getMimeTypes(final URL url, final MimeType unknownMimeType) throws MimeException { return mimeUtil.getMimeTypes(url, unknownMimeType); } /** * Get the native byte order of the OS on which you are running. It will be * either big or little endian. This is used internally for the magic mime * rules mapping. * * @return ByteOrder */ public static ByteOrder getNativeOrder() { return MimeUtil2.getNativeOrder(); } /** * Gives you the best match for your requirements. * <p> * You can pass the accept header from a browser request to this method * along with a comma separated list of possible mime types returned from * say getExtensionMimeTypes(...) and the best match according to the accept * header will be returned. * </p> * <p> * The following is typical of what may be specified in an HTTP Accept * header: * </p> * <p> * Accept: text/xml, application/xml, application/xhtml+xml, * text/html;q=0.9, text/plain;q=0.8, video/x-mng, image/png, image/jpeg, * image/gif;q=0.2, text/css, */*;q=0.1 * </p> * <p> * The quality parameter (q) indicates how well the user agent handles the * MIME type. A value of 1 indicates the MIME type is understood perfectly, * and a value of 0 indicates the MIME type isn't understood at all. * </p> * <p> * The reason the image/gif MIME type contains a quality parameter of 0.2, * is to indicate that PNG & JPEG are preferred over GIF if the server is * using content negotiation to deliver either a PNG or a GIF to user * agents. Similarly, the text/html quality parameter has been lowered a * little, to ensure that the XML MIME types are given in preference if * content negotiation is being used to serve an XHTML document. * </p> * * @param accept * is a comma separated list of mime types you can accept * including QoS parameters. Can pass the Accept: header * directly. * @param canProvide * is a comma separated list of mime types that can be provided * such as that returned from a call to * getExtensionMimeTypes(...) * @return the best matching mime type possible. */ public static MimeType getPreferedMimeType(String accept, final String canProvide) { return MimeUtil2.getPreferedMimeType(accept, canProvide); } /** * Get the most specific match of the Collection of mime types passed in. * The Collection * @param mimeTypes this should be the Collection of mime types returned * from a getMimeTypes(...) call. * @return the most specific MimeType. If more than one of the mime types in the Collection * have the same value then the first one found with this value in the Collection is returned. */ public static MimeType getMostSpecificMimeType(final Collection mimeTypes) { return MimeUtil2.getMostSpecificMimeType(mimeTypes); } /** * Utility method to get the minor part of a mime type i.e. the bit after * the '/' character * * @param mimeType * you want to get the minor part from * @return sub type of the mime type * @throws MimeException * if you pass in an invalid mime type structure */ public static String getSubType(final String mimeType) throws MimeException { return MimeUtil2.getSubType(mimeType); } /** * Check to see if this mime type is one of the types seen during * initialisation or has been added at some later stage using * addKnownMimeType(...) * * @param mimeType * @return true if the mimeType is in the list else false is returned * @see #addKnownMimeType(String mimetype) */ public static boolean isMimeTypeKnown(final MimeType mimeType) { return MimeUtil2.isMimeTypeKnown(mimeType); } /** * Check to see if this mime type is one of the types seen during * initialisation or has been added at some later stage using * addKnownMimeType(...) * * @param mimeType * @return true if the mimeType is in the list else false is returned * @see #addKnownMimeType(String mimetype) */ public static boolean isMimeTypeKnown(final String mimeType) { return MimeUtil2.isMimeTypeKnown(mimeType); } /** * Utility convenience method to check if a particular MimeType instance is actually a TextMimeType. * Used when iterating over a collection of MimeType's to help with casting to enable access * the the TextMimeType methods not available to a standard MimeType. Can also use instanceof. * @param mimeType * @return true if the passed in instance is a TextMimeType * @see MimeType * @see TextMimeType */ public static boolean isTextMimeType(final MimeType mimeType) { return MimeUtil2.isTextMimeType(mimeType); } /** * Remove a previously registered MimeDetector * @param mimeDetector * @return the MimeDetector that was removed from the registry else null. */ public static MimeDetector unregisterMimeDetector(final MimeDetector mimeDetector) { return mimeUtil.unregisterMimeDetector(mimeDetector); } /** * Remove a previously registered MimeDetector * @param mimeDetector * @return the MimeDetector that was removed from the registry else null. */ public static MimeDetector unregisterMimeDetector(final String mimeDetector) { return mimeUtil.unregisterMimeDetector(mimeDetector); } /** * Get the quality parameter of this mime type i.e. the <code>q=</code> property. * This method implements a value system similar to that used by the apache server i.e. * if the media type is a * then it's <code>q</code> value is set to 0.01 and if the sub type is * a * then the <code>q</code> value is set to 0.02 unless a specific <code>q</code> * value is specified. If a <code>q</code> property is set it is limited to a max value of 1.0 * * @param mimeType * @return the quality value as a double between 0.0 and 1.0 * @throws MimeException */ public static double getQuality(final String mimeType) throws MimeException { return MimeUtil2.getQuality(mimeType); } /** * Utility method to get the InputStream from a URL. Handles several schemes, for instance, if the URL points to a jar * entry it will get a proper usable stream from the URL * @param url * @return */ public static InputStream getInputStreamForURL(URL url) throws Exception { return MimeUtil2.getInputStreamForURL(url); } }