/**
* Copyright 2005-2014 Restlet
*
* The contents of this file are subject to the terms of one of the following
* open source licenses: Apache 2.0 or or EPL 1.0 (the "Licenses"). You can
* select the license that you prefer but you may not use this file except in
* compliance with one of these Licenses.
*
* You can obtain a copy of the Apache 2.0 license at
* http://www.opensource.org/licenses/apache-2.0
*
* You can obtain a copy of the EPL 1.0 license at
* http://www.opensource.org/licenses/eclipse-1.0
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royalty free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://restlet.com/products/restlet-framework
*
* Restlet is a registered trademark of Restlet S.A.S.
*/
package org.restlet.data;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import org.restlet.Context;
import org.restlet.engine.header.HeaderWriter;
import org.restlet.engine.util.SystemUtils;
import org.restlet.util.Series;
/**
* Metadata used to specify the format of representations. The
* {@link #getName()} method returns a full String representation of the media
* type including the parameters.
*
* @see <a href="http://en.wikipedia.org/wiki/MIME">MIME types on Wikipedia</a>
* @author Jerome Louvel
*/
public final class MediaType extends Metadata {
/**
* Illegal ASCII characters as defined in RFC 1521.<br>
* Keep the underscore for the ordering
*
* @see http://www.ietf.org/rfc/rfc1521.txt
*/
private static final String _TSPECIALS = "()<>@,;:/[]?=\\\"";
/**
* The known media types registered with {@link #register(String, String)},
* retrievable using {@link #valueOf(String)}.<br>
* Keep the underscore for the ordering.
*/
private static volatile Map<String, MediaType> _types = null;
public static final MediaType ALL = register("*/*", "All media");
public static final MediaType APPLICATION_ALL = register("application/*",
"All application documents");
public static final MediaType APPLICATION_ALL_JSON = register(
"application/*+json", "All application/*+json documents");
public static final MediaType APPLICATION_ALL_XML = register(
"application/*+xml", "All application/*+xml documents");
public static final MediaType APPLICATION_ATOM = register(
"application/atom+xml", "Atom document");
// [ifndef gwt] member
public static final MediaType APPLICATION_ATOMPUB_CATEGORY = register(
"application/atomcat+xml", "Atom category document");
// [ifndef gwt] member
public static final MediaType APPLICATION_ATOMPUB_SERVICE = register(
"application/atomsvc+xml", "Atom service document");
// [ifndef gwt] member
public static final MediaType APPLICATION_CAB = register(
"application/vnd.ms-cab-compressed", "Microsoft Cabinet archive");
// [ifndef gwt] member
public static final MediaType APPLICATION_CBOR = register(
"application/cbor", "Concise Binary Object Representation document");
// [ifndef gwt] member
public static final MediaType APPLICATION_COMPRESS = register(
"application/x-compress", "Compressed file");
// [ifndef gwt] member
public static final MediaType APPLICATION_ECORE = register(
"application/x-ecore+xmi+xml", "EMOF ECore metamodel");
// [ifndef gwt] member
public static final MediaType APPLICATION_EXCEL = register(
"application/vnd.ms-excel", "Microsoft Excel document");
// [ifndef gwt] member
public static final MediaType APPLICATION_FLASH = register(
"application/x-shockwave-flash", "Shockwave Flash object");
// [ifndef gwt] member
public static final MediaType APPLICATION_GNU_TAR = register(
"application/x-gtar", "GNU Tar archive");
// [ifndef gwt] member
public static final MediaType APPLICATION_GNU_ZIP = register(
"application/x-gzip", "GNU Zip archive");
// [ifndef gwt] member
public static final MediaType APPLICATION_HTTP_COOKIES = register(
"application/x-http-cookies", "HTTP cookies");
// [ifndef gwt] member
public static final MediaType APPLICATION_JAVA = register(
"application/java", "Java class");
// [ifndef gwt] member
public static final MediaType APPLICATION_JAVA_ARCHIVE = register(
"application/java-archive", "Java archive");
// [ifndef gwt] member
public static final MediaType APPLICATION_JAVA_OBJECT = register(
"application/x-java-serialized-object", "Java serialized object");
public static final MediaType APPLICATION_JAVA_OBJECT_GWT = register(
"application/x-java-serialized-object+gwt",
"Java serialized object (using GWT-RPC encoder)");
// [ifndef gwt] member
public static final MediaType APPLICATION_JAVA_OBJECT_XML = register(
"application/x-java-serialized-object+xml",
"Java serialized object (using JavaBeans XML encoder)");
public static final MediaType APPLICATION_JAVASCRIPT = register(
"application/x-javascript", "Javascript document");
// [ifndef gwt] member
public static final MediaType APPLICATION_JNLP = register(
"application/x-java-jnlp-file", "JNLP");
public static final MediaType APPLICATION_JSON = register(
"application/json", "JavaScript Object Notation document");
// [ifndef gwt] member
public static final MediaType APPLICATION_JSON_ACTIVITY = register(
"application/activity+json", "Activity Streams JSON document");
// [ifndef gwt] member
public static final MediaType APPLICATION_JSON_PATCH = register(
"application/json-patch", "JSON patch document");
public static final MediaType APPLICATION_JSON_SMILE = register(
"application/x-json-smile",
"JavaScript Object Notation smile document");
// [ifndef gwt] member
public static final MediaType APPLICATION_KML = register(
"application/vnd.google-earth.kml+xml",
"Google Earth/Maps KML document");
// [ifndef gwt] member
public static final MediaType APPLICATION_KMZ = register(
"application/vnd.google-earth.kmz",
"Google Earth/Maps KMZ document");
// [ifndef gwt] member
public static final MediaType APPLICATION_LATEX = register(
"application/x-latex", "LaTeX");
// [ifndef gwt] member
public static final MediaType APPLICATION_MAC_BINHEX40 = register(
"application/mac-binhex40", "Mac binhex40");
// [ifndef gwt] member
public static final MediaType APPLICATION_MATHML = register(
"application/mathml+xml", "MathML XML document");
public static final MediaType APPLICATION_MSML = register(
"application/msml+xml", "Media Server Markup Language");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_DOCM = register(
"application/vnd.ms-word.document.macroEnabled.12",
"Office Word 2007 macro-enabled document");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_DOCX = register(
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"Microsoft Office Word 2007 document");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_DOTM = register(
"application/vnd.ms-word.template.macroEnabled.12",
"Office Word 2007 macro-enabled document template");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_DOTX = register(
"application/vnd.openxmlformats-officedocument.wordprocessingml.template",
"Office Word 2007 template");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_ONETOC = register(
"application/onenote", "Microsoft Office OneNote 2007 TOC");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_ONETOC2 = register(
"application/onenote", "Office OneNote 2007 TOC");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_POTM = register(
"application/vnd.ms-powerpoint.template.macroEnabled.12",
"Office PowerPoint 2007 macro-enabled presentation template");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_POTX = register(
"application/vnd.openxmlformats-officedocument.presentationml.template",
"Office PowerPoint 2007 template");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_PPAM = register(
"application/vnd.ms-powerpoint.addin.macroEnabled.12",
"Office PowerPoint 2007 add-in");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_PPSM = register(
"application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
"Office PowerPoint 2007 macro-enabled slide show");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_PPSX = register(
"application/vnd.openxmlformats-officedocument.presentationml.slideshow",
"Office PowerPoint 2007 slide show");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_PPTM = register(
"application/vnd.ms-powerpoint.presentation.macroEnabled.12",
"Office PowerPoint 2007 macro-enabled presentation");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_PPTX = register(
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"Microsoft Office PowerPoint 2007 presentation");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_SLDM = register(
"application/vnd.ms-powerpoint.slide.macroEnabled.12",
"Office PowerPoint 2007 macro-enabled slide");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_SLDX = register(
"application/vnd.openxmlformats-officedocument.presentationml.slide",
"Office PowerPoint 2007 slide");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_XLAM = register(
"application/vnd.ms-excel.addin.macroEnabled.12",
"Office Excel 2007 add-in");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_XLSB = register(
"application/vnd.ms-excel.sheet.binary.macroEnabled.12",
"Office Excel 2007 binary workbook");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_XLSM = register(
"application/vnd.ms-excel.sheet.macroEnabled.12",
"Office Excel 2007 macro-enabled workbook");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_XLSX = register(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"Microsoft Office Excel 2007 workbook");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_XLTM = register(
"application/vnd.ms-excel.template.macroEnabled.12",
"Office Excel 2007 macro-enabled workbook template");
// [ifndef gwt] member
public static final MediaType APPLICATION_MSOFFICE_XLTX = register(
"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
"Office Excel 2007 template");
// [ifndef gwt] member
public static final MediaType APPLICATION_OCTET_STREAM = register(
"application/octet-stream", "Raw octet stream");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_ODB = register(
"application/vnd.oasis.opendocument.database",
"OpenDocument Database");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_ODC = register(
"application/vnd.oasis.opendocument.chart", "OpenDocument Chart");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_ODF = register(
"application/vnd.oasis.opendocument.formula",
"OpenDocument Formula");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_ODG = register(
"application/vnd.oasis.opendocument.graphics",
"OpenDocument Drawing");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_ODI = register(
"application/vnd.oasis.opendocument.image", "OpenDocument Image ");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_ODM = register(
"application/vnd.oasis.opendocument.text-master",
"OpenDocument Master Document");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_ODP = register(
"application/vnd.oasis.opendocument.presentation",
"OpenDocument Presentation ");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_ODS = register(
"application/vnd.oasis.opendocument.spreadsheet",
"OpenDocument Spreadsheet");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_ODT = register(
"application/vnd.oasis.opendocument.text ", "OpenDocument Text");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_OTG = register(
"application/vnd.oasis.opendocument.graphics-template",
"OpenDocument Drawing Template");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_OTH = register(
"application/vnd.oasis.opendocument.text-web",
"HTML Document Template");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_OTP = register(
"application/vnd.oasis.opendocument.presentation-template",
"OpenDocument Presentation Template");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_OTS = register(
"application/vnd.oasis.opendocument.spreadsheet-template",
"OpenDocument Spreadsheet Template");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_OTT = register(
"application/vnd.oasis.opendocument.text-template",
"OpenDocument Text Template");
// [ifndef gwt] member
public static final MediaType APPLICATION_OPENOFFICE_OXT = register(
"application/vnd.openofficeorg.extension",
"OpenOffice.org extension");
// [ifndef gwt] member
public static final MediaType APPLICATION_PDF = register("application/pdf",
"Adobe PDF document");
// [ifndef gwt] member
public static final MediaType APPLICATION_POSTSCRIPT = register(
"application/postscript", "Postscript document");
// [ifndef gwt] member
public static final MediaType APPLICATION_POWERPOINT = register(
"application/vnd.ms-powerpoint", "Microsoft Powerpoint document");
// [ifndef gwt] member
public static final MediaType APPLICATION_PROJECT = register(
"application/vnd.ms-project", "Microsoft Project document");
// [ifndef gwt] member
public static final MediaType APPLICATION_RDF_TRIG = register(
"application/x-trig",
"Plain text serialized Resource Description Framework document");
// [ifndef gwt] member
public static final MediaType APPLICATION_RDF_TRIX = register(
"application/trix",
"Simple XML serialized Resource Description Framework document");
// [ifndef gwt] member
/**
* @deprecated Replaced by the official {@link #TEXT_TURTLE} media type.
*/
@Deprecated
public static final MediaType APPLICATION_RDF_TURTLE = register(
"application/x-turtle",
"Plain text serialized Resource Description Framework document");
// [ifndef gwt] member
public static final MediaType APPLICATION_RDF_XML = register(
"application/rdf+xml",
"Normalized XML serialized Resource Description Framework document");
// [ifndef gwt] member
public static final MediaType APPLICATION_RELAXNG_COMPACT = register(
"application/relax-ng-compact-syntax",
"Relax NG Schema document, Compact syntax");
// [ifndef gwt] member
public static final MediaType APPLICATION_RELAXNG_XML = register(
"application/x-relax-ng+xml",
"Relax NG Schema document, XML syntax");
// [ifndef gwt] member
public static final MediaType APPLICATION_RSS = register(
"application/rss+xml", "Really Simple Syndication document");
// [ifndef gwt] member
public static final MediaType APPLICATION_RTF = register("application/rtf",
"Rich Text Format document");
public static final MediaType APPLICATION_SDP = register("application/sdp",
"Session Description Protocol");
// [ifndef gwt] member
public static final MediaType APPLICATION_SPARQL_RESULTS_JSON = register(
"application/sparql-results+json",
"SPARQL Query Results JSON document");
// [ifndef gwt] member
public static final MediaType APPLICATION_SPARQL_RESULTS_XML = register(
"application/sparql-results+xml",
"SPARQL Query Results XML document");
// [ifndef gwt] member
public static final MediaType APPLICATION_SPSS_SAV = register(
"application/x-spss-sav", "SPSS Data");
// [ifndef gwt] member
public static final MediaType APPLICATION_SPSS_SPS = register(
"application/x-spss-sps", "SPSS Script Syntax");
// [ifndef gwt] member
public static final MediaType APPLICATION_STATA_STA = register(
"application/x-stata", "Stata data file");
// [ifndef gwt] member
public static final MediaType APPLICATION_STUFFIT = register(
"application/x-stuffit", "Stuffit archive");
// [ifndef gwt] member
public static final MediaType APPLICATION_TAR = register(
"application/x-tar", "Tar archive");
// [ifndef gwt] member
public static final MediaType APPLICATION_TEX = register(
"application/x-tex", "Tex file");
// [ifndef gwt] member
public static final MediaType APPLICATION_TROFF_MAN = register(
"application/x-troff-man", "LaTeX");
// [ifndef gwt] member
public static final MediaType APPLICATION_VOICEXML = register(
"application/voicexml+xml", "VoiceXML");
// [ifndef gwt] member
public static final MediaType APPLICATION_W3C_SCHEMA = register(
"application/x-xsd+xml", "W3C XML Schema document");
// [ifndef gwt] member
public static final MediaType APPLICATION_W3C_XSLT = register(
"application/xslt+xml", "W3C XSLT Stylesheet");
// [ifndef gwt] member
public static final MediaType APPLICATION_WADL = register(
"application/vnd.sun.wadl+xml",
"Web Application Description Language document");
// [ifndef gwt] member
public static final MediaType APPLICATION_WORD = register(
"application/msword", "Microsoft Word document");
public static final MediaType APPLICATION_WWW_FORM = register(
"application/x-www-form-urlencoded", "Web form (URL encoded)");
public static final MediaType APPLICATION_XHTML = register(
"application/xhtml+xml", "XHTML document");
public static final MediaType APPLICATION_XMI = register(
"application/xmi+xml", "XMI document");
public static final MediaType APPLICATION_XML = register("application/xml",
"XML document");
// [ifndef gwt] member
public static final MediaType APPLICATION_XML_DTD = register(
"application/xml-dtd", "XML DTD");
// [ifndef gwt] member
public static final MediaType APPLICATION_XQUERY = register(
"application/xquery", "XQuery document");
// [ifndef gwt] member
public static final MediaType APPLICATION_XUL = register(
"application/vnd.mozilla.xul+xml", "XUL document");
// [ifndef gwt] member
public static final MediaType APPLICATION_YAML = register(
"application/x-yaml", "YAML document");
// [ifndef gwt] member
public static final MediaType APPLICATION_ZIP = register("application/zip",
"Zip archive");
// [ifndef gwt] member
public static final MediaType AUDIO_ALL = register("audio/*", "All audios");
// [ifndef gwt] member
public static final MediaType AUDIO_BASIC = register("audio/basic",
"AU audio");
// [ifndef gwt] member
public static final MediaType AUDIO_MIDI = register("audio/midi",
"MIDI audio");
// [ifndef gwt] member
public static final MediaType AUDIO_MPEG = register("audio/mpeg",
"MPEG audio (MP3)");
// [ifndef gwt] member
public static final MediaType AUDIO_REAL = register("audio/x-pn-realaudio",
"Real audio");
// [ifndef gwt] member
public static final MediaType AUDIO_WAV = register("audio/x-wav",
"Waveform audio");
// [ifndef gwt] member
public static final MediaType IMAGE_ALL = register("image/*", "All images");
// [ifndef gwt] member
public static final MediaType IMAGE_BMP = register("image/bmp",
"Windows bitmap");
// [ifndef gwt] member
public static final MediaType IMAGE_GIF = register("image/gif", "GIF image");
// [ifndef gwt] member
public static final MediaType IMAGE_ICON = register("image/x-icon",
"Windows icon (Favicon)");
// [ifndef gwt] member
public static final MediaType IMAGE_JPEG = register("image/jpeg",
"JPEG image");
// [ifndef gwt] member
public static final MediaType IMAGE_PNG = register("image/png", "PNG image");
// [ifndef gwt] member
public static final MediaType IMAGE_SVG = register("image/svg+xml",
"Scalable Vector Graphics");
// [ifndef gwt] member
public static final MediaType IMAGE_TIFF = register("image/tiff",
"TIFF image");
// [ifndef gwt] member
public static final MediaType MESSAGE_ALL = register("message/*",
"All messages");
// [ifndef gwt] member
public static final MediaType MESSAGE_HTTP = register("message/http",
"HTTP message");
// [ifndef gwt] member
public static final MediaType MODEL_ALL = register("model/*", "All models");
// [ifndef gwt] member
public static final MediaType MODEL_VRML = register("model/vrml", "VRML");
// [ifndef gwt] member
public static final MediaType MULTIPART_ALL = register("multipart/*",
"All multipart data");
// [ifndef gwt] member
public static final MediaType MULTIPART_FORM_DATA = register(
"multipart/form-data", "Multipart form data");
public static final MediaType TEXT_ALL = register("text/*", "All texts");
// [ifndef gwt] member
public static final MediaType TEXT_CALENDAR = register("text/calendar",
"iCalendar event");
public static final MediaType TEXT_CSS = register("text/css",
"CSS stylesheet");
// [ifndef gwt] member
public static final MediaType TEXT_CSV = register("text/csv",
"Comma-separated Values");
// [ifndef gwt] member
public static final MediaType TEXT_DAT = register("text/x-fixed-field",
"Fixed-width Values");
public static final MediaType TEXT_HTML = register("text/html",
"HTML document");
// [ifndef gwt] member
public static final MediaType TEXT_J2ME_APP_DESCRIPTOR = register(
"text/vnd.sun.j2me.app-descriptor", "J2ME Application Descriptor");
public static final MediaType TEXT_JAVASCRIPT = register("text/javascript",
"Javascript document");
public static final MediaType TEXT_PLAIN = register("text/plain",
"Plain text");
// [ifndef gwt] member
public static final MediaType TEXT_RDF_N3 = register("text/n3",
"N3 serialized Resource Description Framework document");
// [ifndef gwt] member
public static final MediaType TEXT_RDF_NTRIPLES = register(
"text/n-triples",
"N-Triples serialized Resource Description Framework document");
// [ifndef gwt] member
public static final MediaType TEXT_TSV = register(
"text/tab-separated-values", "Tab-separated Values");
// [ifndef gwt] member
public static final MediaType TEXT_TURTLE = register("text/turtle",
"Plain text serialized Resource Description Framework document");
public static final MediaType TEXT_URI_LIST = register("text/uri-list",
"List of URIs");
// [ifndef gwt] member
public static final MediaType TEXT_VCARD = register("text/x-vcard", "vCard");
public static final MediaType TEXT_XML = register("text/xml", "XML text");
// [ifndef gwt] member
public static final MediaType TEXT_YAML = register("text/x-yaml",
"YAML document");
// [ifndef gwt] member
public static final MediaType VIDEO_ALL = register("video/*", "All videos");
// [ifndef gwt] member
public static final MediaType VIDEO_AVI = register("video/x-msvideo",
"AVI video");
// [ifndef gwt] member
public static final MediaType VIDEO_MP4 = register("video/mp4",
"MPEG-4 video");
// [ifndef gwt] member
public static final MediaType VIDEO_MPEG = register("video/mpeg",
"MPEG video");
// [ifndef gwt] member
public static final MediaType VIDEO_QUICKTIME = register("video/quicktime",
"Quicktime video");
// [ifndef gwt] member
public static final MediaType VIDEO_WMV = register("video/x-ms-wmv",
"Windows movie");
/**
* Returns the first of the most specific media type of the given array of
* {@link MediaType}s.
* <p>
* Examples:
* <ul>
* <li>"text/plain" is more specific than "text/*" or "image/*"</li>
* <li>"text/html" is same specific as "application/pdf" or "image/jpg"</li>
* <li>"text/*" is same specific than "application/*" or "image/*"</li>
* <li>"*<!---->/*" is the most unspecific MediaType</li>
* </ul>
*
* @param mediaTypes
* An array of media types.
* @return The most concrete MediaType.
* @throws IllegalArgumentException
* If the array is null or empty.
*/
public static MediaType getMostSpecific(MediaType... mediaTypes)
throws IllegalArgumentException {
if ((mediaTypes == null) || (mediaTypes.length == 0)) {
throw new IllegalArgumentException(
"You must give at least one MediaType");
}
if (mediaTypes.length == 1) {
return mediaTypes[0];
}
MediaType mostSpecific = mediaTypes[0];
for (int i = 1; i < mediaTypes.length; i++) {
MediaType mediaType = mediaTypes[i];
if (mediaType != null) {
if (mediaType.getMainType().equals("*")) {
continue;
}
if (mostSpecific.getMainType().equals("*")) {
mostSpecific = mediaType;
continue;
}
if (mostSpecific.getSubType().contains("*")) {
mostSpecific = mediaType;
continue;
}
}
}
return mostSpecific;
}
/**
* Returns the known media types map.
*
* @return the known media types map.
*/
private static Map<String, MediaType> getTypes() {
if (_types == null) {
_types = new HashMap<String, MediaType>();
}
return _types;
}
/**
* Normalizes the specified token.
*
* @param token
* Token to normalize.
* @return The normalized token.
* @throws IllegalArgumentException
* if <code>token</code> is not legal.
*/
private static String normalizeToken(String token) {
int length;
char c;
// Makes sure we're not dealing with a "*" token.
token = token.trim();
if ("".equals(token) || "*".equals(token))
return "*";
// Makes sure the token is RFC compliant.
length = token.length();
for (int i = 0; i < length; i++) {
c = token.charAt(i);
if (c <= 32 || c >= 127 || _TSPECIALS.indexOf(c) != -1)
throw new IllegalArgumentException("Illegal token: " + token);
}
return token;
}
/**
* Normalizes the specified media type.
*
* @param name
* The name of the type to normalize.
* @param parameters
* The parameters of the type to normalize.
* @return The normalized type.
*/
private static String normalizeType(String name,
Series<Parameter> parameters) {
int slashIndex;
int colonIndex;
String mainType;
String subType;
StringBuilder params = null;
// Ignore null names (backward compatibility).
if (name == null)
return null;
// Check presence of parameters
if ((colonIndex = name.indexOf(';')) != -1) {
params = new StringBuilder(name.substring(colonIndex));
name = name.substring(0, colonIndex);
}
// No main / sub separator, assumes name/*.
if ((slashIndex = name.indexOf('/')) == -1) {
mainType = normalizeToken(name);
subType = "*";
} else {
// Normalizes the main and sub types.
mainType = normalizeToken(name.substring(0, slashIndex));
subType = normalizeToken(name.substring(slashIndex + 1));
}
// Merge parameters taken from the name and the method argument.
if (parameters != null && !parameters.isEmpty()) {
try {
if (params == null) {
params = new StringBuilder();
}
HeaderWriter<Parameter> hw = new HeaderWriter<Parameter>() {
@Override
public HeaderWriter<Parameter> append(Parameter value) {
return appendExtension(value);
}
};
for (int i = 0; i < parameters.size(); i++) {
Parameter p = parameters.get(i);
hw.appendParameterSeparator();
hw.appendSpace();
hw.append(p);
}
params.append(hw.toString());
hw.close();
} catch (IOException e) {
Context.getCurrentLogger().log(Level.INFO,
"Unable to parse the media type parameter", e);
}
}
return (params == null) ? mainType + '/' + subType : mainType + '/'
+ subType + params.toString();
}
/**
* Register a media type as a known type that can later be retrieved using
* {@link #valueOf(String)}. If the type already exists, the existing type
* is returned, otherwise a new instance is created.
*
* @param name
* The name.
* @param description
* The description.
* @return The registered media type
*/
public static synchronized MediaType register(String name,
String description) {
if (!getTypes().containsKey(name)) {
final MediaType type = new MediaType(name, description);
getTypes().put(name, type);
}
return getTypes().get(name);
}
/**
* Returns the media type associated to a name. If an existing constant
* exists then it is returned, otherwise a new instance is created.
*
* @param name
* The name.
* @return The associated media type.
*/
public static MediaType valueOf(String name) {
MediaType result = null;
if ((name != null) && !name.equals("")) {
result = getTypes().get(name);
if (result == null) {
result = new MediaType(name);
}
}
return result;
}
/** The list of parameters. */
private volatile Series<Parameter> parameters;
/**
* Constructor.
*
* @param name
* The name.
*/
public MediaType(String name) {
this(name, null, "Media type or range of media types");
}
/**
* Constructor.
*
* @param name
* The name.
* @param parameters
* The list of parameters.
*/
public MediaType(String name, Series<Parameter> parameters) {
this(name, parameters, "Media type or range of media types");
}
/**
* Constructor.
*
* @param name
* The name.
* @param parameters
* The list of parameters.
* @param description
* The description.
*/
@SuppressWarnings("unchecked")
public MediaType(String name, Series<Parameter> parameters,
String description) {
super(normalizeType(name, parameters), description);
if (parameters != null) {
// [ifndef gwt] instruction
this.parameters = (Series<Parameter>) Series
.unmodifiableSeries(parameters);
// [ifdef gwt] instruction uncomment
// this.parameters =
// org.restlet.engine.util.ParameterSeries.unmodifiableSeries(parameters);
}
}
/**
* Constructor.
*
* @param name
* The name.
* @param description
* The description.
*/
public MediaType(String name, String description) {
this(name, null, description);
}
/** {@inheritDoc} */
@Override
public boolean equals(Object obj) {
return equals(obj, false);
}
/**
* Test the equality of two media types, with the possibility to ignore the
* parameters.
*
* @param obj
* The object to compare to.
* @param ignoreParameters
* Indicates if parameters should be ignored during comparison.
* @return True if both media types are equal.
*/
public boolean equals(Object obj, boolean ignoreParameters) {
boolean result = (obj == this);
// if obj == this no need to go further
if (!result) {
// if obj isn't a mediatype or is null don't evaluate further
if (obj instanceof MediaType) {
final MediaType that = (MediaType) obj;
if (getMainType().equals(that.getMainType())
&& getSubType().equals(that.getSubType())) {
result = ignoreParameters
|| getParameters().equals(that.getParameters());
}
}
}
return result;
}
/**
* Returns the main type.
*
* @return The main type.
*/
public String getMainType() {
String result = null;
if (getName() != null) {
int index = getName().indexOf('/');
// Some clients appear to use name types without subtypes
if (index == -1) {
index = getName().indexOf(';');
}
if (index == -1) {
result = getName();
} else {
result = getName().substring(0, index);
}
}
return result;
}
/**
* Returns the unmodifiable list of parameters corresponding to subtype
* modifiers. Creates a new instance if no one has been set.
*
* @return The list of parameters.
*/
@SuppressWarnings("unchecked")
public Series<Parameter> getParameters() {
// Lazy initialization with double-check.
Series<Parameter> p = this.parameters;
if (p == null) {
synchronized (this) {
p = this.parameters;
if (p == null) {
Series<Parameter> params = null;
if (getName() != null) {
int index = getName().indexOf(';');
if (index != -1) {
params = new Form(getName().substring(index + 1)
.trim(), ';');
}
}
if (params == null) {
// [ifndef gwt] instruction
params = new Series<Parameter>(Parameter.class);
// [ifdef gwt] instruction uncomment
// params = new
// org.restlet.engine.util.ParameterSeries();
}
// [ifndef gwt] instruction
this.parameters = p = (Series<Parameter>) Series
.unmodifiableSeries(params);
// [ifdef gwt] instruction uncomment
// this.parameters = p =
// org.restlet.engine.util.ParameterSeries.unmodifiableSeries(params);
}
}
}
return p;
}
/**
* {@inheritDoc}<br>
* In case the media type has parameters, this method returns the
* concatenation of the main type and the subtype. If the subtype is not
* equal to "*", it returns the concatenation of the main type and "*".
* Otherwise, it returns either the {@link #ALL} media type if it is already
* the {@link #ALL} media type, or null.
*/
@Override
public MediaType getParent() {
MediaType result = null;
if (getParameters().size() > 0) {
result = MediaType.valueOf(getMainType() + "/" + getSubType());
} else {
if (getSubType().equals("*")) {
result = equals(ALL) ? null : ALL;
} else {
result = MediaType.valueOf(getMainType() + "/*");
}
}
return result;
}
/**
* Returns the sub-type.
*
* @return The sub-type.
*/
public String getSubType() {
String result = null;
if (getName() != null) {
final int slash = getName().indexOf('/');
if (slash == -1) {
// No subtype found, assume that all subtypes are accepted
result = "*";
} else {
final int separator = getName().indexOf(';');
if (separator == -1) {
result = getName().substring(slash + 1);
} else {
result = getName().substring(slash + 1, separator);
}
}
}
return result;
}
/** {@inheritDoc} */
@Override
public int hashCode() {
return SystemUtils.hashCode(super.hashCode(), getParameters());
}
/**
* Indicates if a given media type is included in the current one @see
* {@link #includes(Metadata, boolean)}. It ignores the parameters.
*
* @param included
* The media type to test for inclusion.
* @return True if the given media type is included in the current one.
* @see #isCompatible(Metadata)
*/
@Override
public boolean includes(Metadata included) {
return includes(included, true);
}
/**
* Indicates if a given media type is included in the current one @see
* {@link #includes(Metadata, boolean)}. The test is true if both types are
* equal or if the given media type is within the range of the current one.
* For example, ALL includes all media types. Parameters are ignored for
* this comparison. A null media type is considered as included into the
* current one. It ignores the parameters.
* <p>
* Examples:
* <ul>
* <li>TEXT_ALL.includes(TEXT_PLAIN) -> true</li>
* <li>TEXT_PLAIN.includes(TEXT_ALL) -> false</li>
* </ul>
*
* @param included
* The media type to test for inclusion.
* @return True if the given media type is included in the current one.
* @see #isCompatible(Metadata)
*/
public boolean includes(Metadata included, boolean ignoreParameters) {
boolean result = equals(ALL) || equals(included);
if (!result && (included instanceof MediaType)) {
MediaType includedMediaType = (MediaType) included;
if (getMainType().equals(includedMediaType.getMainType())) {
// Both media types are different
if (getSubType().equals(includedMediaType.getSubType())) {
if (ignoreParameters) {
result = true;
} else {
// Check parameters:
// Media type A includes media type B if for each param
// name/value pair in A, B contains the same name/value.
result = true;
for (int i = 0; result && i < getParameters().size(); i++) {
Parameter param = getParameters().get(i);
Parameter includedParam = includedMediaType
.getParameters().getFirst(param.getName());
// If there was no param with the same name, or the
// param with the same name had a different value,
// then no match.
result = (includedParam != null && param.getValue()
.equals(includedParam.getValue()));
}
}
} else if (getSubType().equals("*")) {
result = true;
} else if (getSubType().startsWith("*+")
&& includedMediaType.getSubType().endsWith(
getSubType().substring(2))) {
result = true;
}
}
}
return result;
}
/**
* Checks if the current media type is concrete. A media type is concrete if
* neither the main type nor the sub-type are equal to "*".
*
* @return True if this media type is concrete.
*/
public boolean isConcrete() {
return !getName().contains("*");
}
}