package org.limewire.util;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
import org.limewire.i18n.I18nMarker;
/**
* A generic type of media, i.e., "video" or "audio".
* Many different file formats can be of the same media type.
* MediaType's are immutable.
*<p>
* See http://www.mrc-cbu.cam.ac.uk/Help/mimedefault.html
* <p>
* Implementation note: Since MediaType implements serialization and there
* are inner anonymous classes be careful where to add new inner classes
* and fields.
*/
public class MediaType implements Serializable {
private static final long serialVersionUID = 3999062781289258389L;
// These values should match standard MIME content-type
// categories and/or XSD Mime Type names.
public static final String SCHEMA_ANY_TYPE = "*";
public static final String SCHEMA_CUSTOM = "custom";
public static final String SCHEMA_DOCUMENTS = "document";
public static final String SCHEMA_PROGRAMS = "application";
public static final String SCHEMA_AUDIO = "audio";
public static final String SCHEMA_VIDEO = "video";
public static final String SCHEMA_IMAGES = "image";
public static final String SCHEMA_OTHER = "other";
// These are used as resource keys to retreive descriptions in the GUI
public static final String ANY_TYPE = I18nMarker.marktr("All Types");
public static final String DOCUMENTS = I18nMarker.marktr("Documents");
public static final String PROGRAMS = I18nMarker.marktr("Programs");
public static final String AUDIO = I18nMarker.marktr("Audio");
public static final String VIDEO = I18nMarker.marktr("Video");
public static final String IMAGES = I18nMarker.marktr("Images");
public static final String OTHER = I18nMarker.marktr("Other");
/**
* Type for 'any file'.
*/
private static final MediaType TYPE_ANY =
new MediaType(SCHEMA_ANY_TYPE, ANY_TYPE, null) {
// required SVUID because we're constructing an anonymous class.
// the id is taken from old limewire builds, versions 4.4 to 4.12
private static final long serialVersionUID = 8621997774686329539L; //3728385699213635375L;
@Override
public boolean matches(String ext) {
return true;
}
};
/**
* Type for 'documents'.
*/
private static final MediaType TYPE_DOCUMENTS =
new MediaType(SCHEMA_DOCUMENTS, DOCUMENTS,
new String[] {
"123", "abw", "accdb", "accde", "accdr", "accdt", "ans", "asc", "asp",
"bdr", "chm", "css", "csv", "dat", "db", "dif", "diz", "doc", "docm", "docx",
"dotm", "dotx", "dvi", "eml", "eps", "epsf", "fm", "grv", "gsa", "gts", "hlp",
"htm", "html", "idb", "idx", "iif", "info", "js", "jsp", "kfl", "kwd", "latex", "lif",
"lit", "log", "man", "mcw", "mdb", "mht", "mhtml", "mny", "msg", "obi", "odp", "ods",
"odt", "ofx", "one", "onepkg", "ost", "pages", "pdf", "php", "pot", "potm", "potx", "pps", "ppsm",
"ppsx", "ppt", "pptm", "pptx", "ps", "pub", "qba", "qbb", "qdb", "qbi", "qbm", "qbw", "qbx", "qdf",
"qel", "qfp", "qpd", "qph", "qmd", "qsd", "rtf", "scd", "sdc", "sdd", "sdp", "sdw", "shw", "sldx",
"sxc", "sxd", "sxp", "sxw", "t01", "t02", "t03", "t04", "t05", "t06", "t07", "t08", "t09", "t98",
"t99", "ta0", "ta1", "ta2", "ta3", "ta4", "ta5", "ta6", "ta7", "ta8", "ta9", "tax", "tax2008",
"tex", "texi", "toc", "tsv", "tvl", "txf", "txt", "wk1", "wk3", "wk4", "wks", "wp", "wp5", "wpd",
"wps", "wri", "xhtml", "xlam", "xls", "xlsb", "xlsm", "xlsx", "xltm", "xltx", "xml",
"xsf", "xsn", "qfx", "qif", "bud", "ofc", "pst", "mbf", "mn1", "mn2", "mn3", "mn4", "mn5",
"mn6", "mn7", "mn8", "mn9", "m10", "m11", "m12", "m13", "m14", "m15", "m16",
"boe", "box", "bri", "cnm", "dbx", "eml", "emlx", "idb", "idx", "maildb", "mbg", "mbs", "mbx",
"mht", "msb", "msf", "msg", "nws", "pmi", "pmm", "pmx", "tbb", "toc", "vfb", "zmc",
"stw", "odm", "ott", "wpt"
});
/**
* Type for linux/osx programs, used for Aggregator.
*/
private static final MediaType TYPE_LINUX_OSX_PROGRAMS =
new MediaType(SCHEMA_PROGRAMS, PROGRAMS,
new String[] {
"app", "bin", "mdb", "sh", "csh", "awk", "pl",
"rpm", "deb", "gz", "gzip", "z", "bz2", "zoo", "tar", "tgz",
"taz", "shar", "hqx", "sit", "dmg", "7z", "jar", "zip", "nrg",
"cue", "iso", "jnlp", "rar", "sh"
});
/**
* Type for windows programs, used for Aggregator.
*/
private static final MediaType TYPE_WINDOWS_PROGRAMS =
new MediaType(SCHEMA_PROGRAMS, PROGRAMS,
new String[] {
"exe", "zip", "jar", "cab", "msi", "msp",
"arj", "rar", "ace", "lzh", "lha", "bin", "nrg", "cue",
"iso", "jnlp", "bat", "lnk", "vbs"
});
/**
* Type for 'programs'.
*/
private static final MediaType TYPE_PROGRAMS =
new MediaType(SCHEMA_PROGRAMS, PROGRAMS,
makeArray(TYPE_LINUX_OSX_PROGRAMS.exts,
TYPE_WINDOWS_PROGRAMS.exts)
);
/**
* Type for 'audio'.
*/
private static final MediaType TYPE_AUDIO =
new MediaType(SCHEMA_AUDIO, AUDIO,
new String[] {
"mp3", "mpa", "mp1", "mpga", "mp2",
"ra", "rm", "ram", "rmj",
"wma", "wav", "m4a", "m4p","mp4",
"lqt", "ogg", "med",
"aif", "aiff", "aifc",
"au", "snd", "s3m", "aud",
"mid", "midi", "rmi", "mod", "kar",
"ac3", "shn", "fla", "flac", "cda",
"mka"
});
/**
* Type for 'video'.
*/
private static final MediaType TYPE_VIDEO =
new MediaType(SCHEMA_VIDEO, VIDEO,
new String[] {
"mpg", "mpeg", "mpe", "mng", "mpv", "m1v",
"vob", "mp2", "mpv2", "mp2v", "m2p", "m2v", "mpgv",
"vcd", "mp4", "dv", "dvd", "div", "divx", "dvx",
"smi", "smil", "rm", "ram", "rv", "rmm", "rmvb",
"avi", "asf", "asx", "wmv", "qt", "mov",
"fli", "flc", "flx", "flv",
"wml", "vrml", "swf", "dcr", "jve", "nsv",
"mkv", "ogm",
"cdg", "srt", "sub", "flv"
});
/**
* Type for 'images'.
*/
private static final MediaType TYPE_IMAGES =
new MediaType(SCHEMA_IMAGES, IMAGES,
new String[] {
"gif", "png", "bmp",
"jpg", "jpeg", "jpe", "jif", "jiff", "jfif",
"tif", "tiff", "iff", "lbm", "ilbm", "eps",
"mac", "drw", "pct", "img",
"bmp", "dib", "rle", "ico", "ani", "icl", "cur",
"emf", "wmf", "pcx",
"pcd", "tga", "pic", "fig",
"psd", "wpg", "dcx", "cpt", "mic",
"pbm", "pnm", "ppm", "xbm", "xpm", "xwd",
"sgi", "fax", "rgb", "ras"
});
/**
* Type for 'other'.
*/
private static final MediaType TYPE_OTHER =
new MediaType(SCHEMA_OTHER, OTHER, null) {
// required SVUID because we're constructing an anonymous class.
private static final long serialVersionUID = 2041997774686329401L;
@Override
public boolean matches(String ext) {
return !TYPE_DOCUMENTS.matches(ext) && !TYPE_PROGRAMS.matches(ext) &&
!TYPE_AUDIO.matches(ext) && !TYPE_VIDEO.matches(ext) &&
!TYPE_IMAGES.matches(ext);
}
};
/**
* All media types.
*/
private static final MediaType[] ALL_MEDIA_TYPES =
new MediaType[] { TYPE_ANY, TYPE_DOCUMENTS, TYPE_PROGRAMS,
TYPE_AUDIO, TYPE_VIDEO, TYPE_IMAGES, TYPE_OTHER };
/**
* The description of this MediaType.
*/
private final String schema;
/**
* The key to look up this MediaType.
*/
private final String descriptionKey;
/**
* The list of extensions within this MediaType.
*/
private final Set<String> exts;
/**
* Whether or not this is one of the default media types.
*/
private final boolean isDefault;
/**
* Constructs a MediaType with only a MIME-Type.
*/
public MediaType(String schema) {
if (schema == null) {
throw new NullPointerException("schema must not be null");
}
this.schema = schema;
this.descriptionKey = null;
this.exts = Collections.emptySet();
this.isDefault = false;
}
/**
* @param schema a MIME compliant non-localizable identifier,
* that matches file categories (and XSD schema names).
* @param descriptionKey a media identifier that can be used
* to retrieve a localizable descriptive text.
* @param extensions a list of all file extensions of this
* type. Must be all lowercase. If null, this matches
* any file.
*/
public MediaType(String schema, String descriptionKey,
String[] extensions) {
if (schema == null) {
throw new NullPointerException("schema must not be null");
}
this.schema = schema;
this.descriptionKey = descriptionKey;
this.isDefault = true;
if (extensions == null) {
this.exts = Collections.emptySet();
} else {
Set<String> set = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
set.addAll(Arrays.asList(extensions));
this.exts = set;
}
}
/**
* Returns true if a file with the given name is of this
* media type, i.e., the suffix of the filename matches
* one of this' extensions.
*/
public boolean matches(String filename) {
if (exts == null)
return true;
//Get suffix of filename.
int j = filename.lastIndexOf(".");
if (j == -1 || j == filename.length())
return false;
String suffix = filename.substring(j+1);
// Match with extensions.
return exts.contains(suffix);
}
/**
* Returns this' media-type (a MIME content-type category)
* (previously returned a description key).
*/
@Override
public String toString() {
return schema;
}
/**
* Returns this' description key in localizable resources
* (now distinct from the result of the toString method).
*/
public String getDescriptionKey() {
return descriptionKey;
}
/**
* Returns the MIME-Type of this.
*/
public String getSchema() {
return schema;
}
/**
* Determines whether or not this is a default media type.
*/
public boolean isDefault() {
return isDefault;
}
/**
* Returns the extensions for this media type.
*/
public Set<String> getExtensions() {
return exts;
}
/**
* Returns all default media types.
*/
public static MediaType[] getDefaultMediaTypes() {
return ALL_MEDIA_TYPES;
}
/**
* Retrieves the media type for the specified schema's description.
*/
public static MediaType getMediaTypeForSchema(String schema) {
for (int i = ALL_MEDIA_TYPES.length; --i >= 0;)
if (schema.equals(ALL_MEDIA_TYPES[i].schema))
return ALL_MEDIA_TYPES[i];
return null;
}
/**
* Retrieves the media type for the specified extension.
*/
public static MediaType getMediaTypeForExtension(String ext) {
for (int i = ALL_MEDIA_TYPES.length; --i >= 0;)
if (ALL_MEDIA_TYPES[i].exts.contains(ext))
return ALL_MEDIA_TYPES[i];
return null;
}
/**
* Determines whether or not the specified schema is a default.
*/
public static boolean isDefaultType(String schema) {
for (int i = ALL_MEDIA_TYPES.length; --i >= 0;)
if (schema.equals(ALL_MEDIA_TYPES[i].schema))
return true;
return false;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MediaType) {
MediaType type = (MediaType)obj;
return schema.equals(type.schema)
&& exts.equals(type.exts)
&& isDefault == type.isDefault;
}
return false;
}
@Override
public int hashCode() {
int hash = 7;
hash = 41*hash + (schema != null ? schema.hashCode() : 0);
hash = 41*hash + (descriptionKey != null ? descriptionKey.hashCode() : 0);
hash = 41*hash + (exts != null ? exts.hashCode() : 0);
hash = 41*hash + (isDefault ? 1 : 0);
return hash;
}
/*
* We canonicalize the default mediatypes, but since MediaType has
* a public constructor only 'equals' comparisons should be used.
*/
Object readResolve() throws ObjectStreamException {
for (MediaType type : ALL_MEDIA_TYPES) {
if (equals(type)) {
return type;
}
}
return this;
}
/**
* Retrieves the any media type.
*/
public static MediaType getAnyTypeMediaType() {
return TYPE_ANY;
}
/**
* Retrieves the audio media type.
*/
public static MediaType getAudioMediaType() {
return TYPE_AUDIO;
}
/**
* Retrieves the video media type.
*/
public static MediaType getVideoMediaType() {
return TYPE_VIDEO;
}
/**
* Retrieves the image media type.
*/
public static MediaType getImageMediaType() {
return TYPE_IMAGES;
}
/**
* Retrieves the document media type.
*/
public static MediaType getDocumentMediaType() {
return TYPE_DOCUMENTS;
}
/**
* Retrieves the programs media type.
*/
public static MediaType getProgramMediaType() {
return TYPE_PROGRAMS;
}
/**
* Retrieves the program type specific for OS X & Linux.
*/
public static MediaType getOsxAndLinuxProgramMediaType() {
return TYPE_LINUX_OSX_PROGRAMS;
}
/**
* Retrieves the program type specific to Windows.
*/
public static MediaType getWindowsProgramMediaType() {
return TYPE_WINDOWS_PROGRAMS;
}
/** Retrieves the 'Other' media type. */
public static MediaType getOtherMediaType() {
return TYPE_OTHER;
}
/**
* Utility that makes an array out of two sets.
*/
private static String[] makeArray(Set<String> one, Set<String> two) {
Set<String> all = new HashSet<String>(one);
all.addAll(two);
return all.toArray(new String[all.size()]);
}
}