Class MimeTypeDetector
The Opendesktop shared mime database contains glob rules and magic number lookup information to enable applications to detect the mime types of files.
For a complete description of the information contained in this file please see shared-mime-info-spec
-
Nested Class Summary
Nested Classes -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate final ByteBufferMimeCache file content, as a ByteBuffer.private final byte[]MimeCache file content, as an array of bytes.private static final String -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprivate StringaliasLookup(String alias) bytesToMimeTypes(byte[] data) private StringcompareToMagicData(int offset, byte[] data) detectMimeType(File file) Determines the MIME type of file.detectMimeType(String filename, InputStream is) Determines the MIME type of file with a given input stream.detectMimeType(String filename, Callable<byte[]> getBytes) Synchronously detects a MIME type from a filename and bytes.detectMimeType(Path path) Determines the MIME type of file.detectMimeTypeAsync(String filename, Supplier<CompletionStage<byte[]>> getBytesAsync) Detects a MIME type from a filename and bytes.detectMimeTypeAsync(Path path) Determines the MIME type of file.filenameToWmtOrNullByLiteral(String filename) private Set<MimeTypeDetector.WeightedMimeType> filenameToWmts(String filename) private Set<MimeTypeDetector.WeightedMimeType> filenameToWmtsByGlob(String filename) private Set<MimeTypeDetector.WeightedMimeType> filenameToWmtsOrNullBySuffixAndIgnoreCase(String filename, boolean ignoreCase) findBestMimeTypes(Collection<MimeTypeDetector.WeightedMimeType> weightedMimeTypes) private intprivate intprivate intprivate intprivate intintReturns the number of bytes the magic number sniffers may read.private StringgetMimeType(int offset) private intprivate StringgetRegex(int offset) private intprivate StringgetString(int offset) private StringgetStringOrRegex(int offset, boolean regularExpression) private byte[]private byte[]private booleanisEncodedText(byte[] bytes) private booleanisMimeTypeEqualOrSubclass(String child, String parent) private booleanisText(byte[] bytes) private voidlookupGlobNodeSuffix(String fileName, int numEntries, int offset, boolean ignoreCase, int len, Set<MimeTypeDetector.WeightedMimeType> mimeTypes, StringBuilder pattern) private booleanmatchletMagicCompare(int offset, byte[] data) Returns whether data satisfies the matchlet and its children.private booleanmatchletMagicCompareOr(int nMatchlets, int firstMatchletOffset, byte[] data) Returns whether one of the specified matchlets matches the data.private booleanoneMatchletMagicEquals(int offset, byte[] data) Tests whether one matchlet (but not its children) matches data.private booleansubArraysEqual(byte[] a, int aStart, byte[] b, int bStart, int len) Returns true if subarrays are equal.private booleansubArraysEqualWithMask(byte[] a, int aStart, byte[] b, int bStart, byte[] mask, int maskStart, int len) Returns true if subarrays are equal, with the given mask.private StringunaliasMimeType(String mimeType) private static StringunwrapFutureString(CompletionStage<String> future) Waits for a CompletionStage, for non-async methods.
-
Field Details
-
MIME_CACHE
- See Also:
-
MimeCache file content, as a ByteBuffer.
-
contentBytes
private final byte[] contentBytesMimeCache file content, as an array of bytes.
-
-
Constructor Details
-
MimeTypeDetector
public MimeTypeDetector()Creates a new MimeTypeDetector.This class is thread-safe. You should create it once and reuse it, as it allocates a bit of memory (hundreds of kilobytes) on load.
-
-
Method Details
-
inputStreamToByteArray
- Throws:
IOException
-
unwrapFutureString
Waits for a CompletionStage, for non-async methods.- Throws:
GetBytesException
-
detectMimeTypeAsync
public CompletionStage<String> detectMimeTypeAsync(String filename, Supplier<CompletionStage<byte[]>> getBytesAsync) Detects a MIME type from a filename and bytes.This method follows the Shared Mime Info database's Recommended Checking Order. The only difference: it tests for
text/plainthoroughly, both by scanning more of the file and by supporting many character sets.getBytes() is a
Callablebecause it may or may not be needed. A file namedREADMEwill always be detected astext/plain, for instance; a file namedfoo.docwill need a magic-number check because it may be plain text or it may be a Word document.If you are creating your own
getBytesAsyncmethod, ensure its return value is unpadded. (UseArrays.copyOf(byte[],int)to truncate it.) It needn't be any longer thangetMaxGetBytesLength()bytes.The CompletionStage may return a
ExecutionExceptionwhich is caused by aGetBytesException. (That, in turn, will wrap aIOExceptionor other exception that prevented getBytesAsync() from working.- Parameters:
filename- Filename. To skip filename globbing, pass""getBytesAsync- Supplier that eventually returns abyte[]- Returns:
- Eventual MIME type String, falling back to
"application/octet-stream"
-
detectMimeType
Synchronously detects a MIME type from a filename and bytes.This method follows the Shared Mime Info database's Recommended Checking Order. The only difference: it tests for
text/plainthoroughly, both by scanning more of the file and by supporting many character sets.getBytes() is a
Callablebecause it may or may not be needed. A file namedREADMEwill always be detected astext/plain, for instance; a file namedfoo.docwill need a magic-number check because it may be plain text or it may be a Word document.If you are creating your own
getBytesmethod, ensure its return value is unpadded. (UseArrays.copyOf(byte[],int)to truncate it.) It needn't be any longer thangetMaxGetBytesLength()bytes.- Parameters:
filename- Filename. To skip filename globbing, pass""getBytes- Callable that returns abyte[]- Returns:
- a MIME type such as
"text/plain" - Throws:
GetBytesException- ifgetBytes.call()throws an Exception
-
detectMimeType
Determines the MIME type of file with a given input stream.The InputStream must exist. It must point to the beginning of the file contents. And
InputStream.markSupported()must returntrue. When in doubt, pass aBufferedInputStream.- Parameters:
filename- Name of file. To skip filename globbing, pass""is- InputStream that supports mark and reset.- Returns:
- a MIME type such as
"text/plain" - Throws:
GetBytesException- if marking, reading or resetting the InputStream fails.- See Also:
-
detectMimeType
Determines the MIME type of file.The file must exist and be readable.
- Parameters:
file- A file that exists and is readable- Returns:
- a MIME type such as
"text/plain" - Throws:
GetBytesException- if reading the file fails.- See Also:
-
detectMimeType
Determines the MIME type of file.The file must exist and be readable.
- Parameters:
path- A file that exists and is readable- Returns:
- a MIME type such as
"text/plain" - Throws:
GetBytesException- if reading the file fails.- See Also:
-
detectMimeTypeAsync
Determines the MIME type of file.The file must exist and be readable.
The CompletionStage may return a
ExecutionExceptionwhich is caused by aGetBytesException. (That, in turn, will wrap aIOExceptionor other exception that prevented getBytesAsync() from working.- Parameters:
path- A file that exists and is readable- Returns:
- a MIME type such as
"text/plain" - See Also:
-
isText
private boolean isText(byte[] bytes) -
isEncodedText
private boolean isEncodedText(byte[] bytes) -
inputStreamToFirstBytes
- Throws:
IOException
-
bytesToMimeTypes
-
compareToMagicData
-
matchletMagicCompareOr
private boolean matchletMagicCompareOr(int nMatchlets, int firstMatchletOffset, byte[] data) Returns whether one of the specified matchlets matches the data. -
subArraysEqual
private boolean subArraysEqual(byte[] a, int aStart, byte[] b, int bStart, int len) Returns true if subarrays are equal. -
subArraysEqualWithMask
private boolean subArraysEqualWithMask(byte[] a, int aStart, byte[] b, int bStart, byte[] mask, int maskStart, int len) Returns true if subarrays are equal, with the given mask.The mask must have length
len. -
oneMatchletMagicEquals
private boolean oneMatchletMagicEquals(int offset, byte[] data) Tests whether one matchlet (but not its children) matches data. -
matchletMagicCompare
private boolean matchletMagicCompare(int offset, byte[] data) Returns whether data satisfies the matchlet and its children. -
filenameToWmtOrNullByLiteral
-
filenameToWmtsByGlob
-
findBestMimeTypes
private Set<String> findBestMimeTypes(Collection<MimeTypeDetector.WeightedMimeType> weightedMimeTypes) -
filenameToWmts
-
filenameToWmtsOrNullBySuffixAndIgnoreCase
private Set<MimeTypeDetector.WeightedMimeType> filenameToWmtsOrNullBySuffixAndIgnoreCase(String filename, boolean ignoreCase) -
lookupGlobNodeSuffix
private void lookupGlobNodeSuffix(String fileName, int numEntries, int offset, boolean ignoreCase, int len, Set<MimeTypeDetector.WeightedMimeType> mimeTypes, StringBuilder pattern) -
getMaxExtents
private int getMaxExtents() -
getMaxGetBytesLength
public int getMaxGetBytesLength()Returns the number of bytes the magic number sniffers may read.If you are crafting your own getBytes() method, you may use this as a hint. getBytes() may return an Array with any number of bytes you like, but MimeTypeDetector will not read more than this many.
- Returns:
- The most bytes getBytes() could ever possibly need to return.
-
aliasLookup
-
unaliasMimeType
-
isMimeTypeEqualOrSubclass
-
getMagicListOffset
private int getMagicListOffset() -
getGlobListOffset
private int getGlobListOffset() -
getReverseSuffixTreeOffset
private int getReverseSuffixTreeOffset() -
getLiteralListOffset
private int getLiteralListOffset() -
getParentListOffset
private int getParentListOffset() -
getAliasListOffset
private int getAliasListOffset() -
getMimeType
-
getString
-
getRegex
-
getStringOrRegex
-