| /* |
| * The contents of this file are subject to the terms |
| * of the Common Development and Distribution License |
| * (the "License"). You may not use this file except |
| * in compliance with the License. |
| * |
| * You can obtain a copy of the license at |
| * http://www.opensource.org/licenses/cddl1.php |
| * See the License for the specific language governing |
| * permissions and limitations under the License. |
| */ |
| |
| /* |
| * MediaType.java |
| * |
| * Created on March 22, 2007, 2:35 PM |
| * |
| */ |
| |
| package javax.ws.rs.core; |
| |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Map; |
| import java.util.TreeMap; |
| import javax.ws.rs.ext.RuntimeDelegate; |
| import javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate; |
| |
| /** |
| * An abstraction for a media type. Instances are immutable. |
| * @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7">HTTP/1.1 section 3.7</a> |
| */ |
| public class MediaType { |
| |
| private String type; |
| private String subtype; |
| private Map<String, String> parameters; |
| |
| /** |
| * Empty immutable map used for all instances without parameters |
| */ |
| private static final Map<String, String> emptyMap = Collections.emptyMap(); |
| |
| private static final HeaderDelegate<MediaType> delegate = |
| RuntimeDelegate.getInstance().createHeaderDelegate(MediaType.class); |
| |
| /** The value of a type or subtype wildcard: "*" */ |
| public static final String MEDIA_TYPE_WILDCARD = "*"; |
| |
| // Common media type constants |
| /** "*/*" */ |
| public final static String WILDCARD = "*/*"; |
| /** "*/*" */ |
| public final static MediaType WILDCARD_TYPE = new MediaType(); |
| |
| /** "application/xml" */ |
| public final static String APPLICATION_XML = "application/xml"; |
| /** "application/xml" */ |
| public final static MediaType APPLICATION_XML_TYPE = new MediaType("application","xml"); |
| |
| /** "application/atom+xml" */ |
| public final static String APPLICATION_ATOM_XML = "application/atom+xml"; |
| /** "application/atom+xml" */ |
| public final static MediaType APPLICATION_ATOM_XML_TYPE = new MediaType("application","atom+xml"); |
| |
| /** "application/xhtml+xml" */ |
| public final static String APPLICATION_XHTML_XML = "application/xhtml+xml"; |
| /** "application/xhtml+xml" */ |
| public final static MediaType APPLICATION_XHTML_XML_TYPE = new MediaType("application","xhtml+xml"); |
| |
| /** "application/svg+xml" */ |
| public final static String APPLICATION_SVG_XML = "application/svg+xml"; |
| /** "application/svg+xml" */ |
| public final static MediaType APPLICATION_SVG_XML_TYPE = new MediaType("application","svg+xml"); |
| |
| /** "application/json" */ |
| public final static String APPLICATION_JSON = "application/json"; |
| /** "application/json" */ |
| public final static MediaType APPLICATION_JSON_TYPE = new MediaType("application","json"); |
| |
| /** "application/x-www-form-urlencoded" */ |
| public final static String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded"; |
| /** "application/x-www-form-urlencoded" */ |
| public final static MediaType APPLICATION_FORM_URLENCODED_TYPE = new MediaType("application","x-www-form-urlencoded"); |
| |
| /** "multipart/form-data" */ |
| public final static String MULTIPART_FORM_DATA = "multipart/form-data"; |
| /** "multipart/form-data" */ |
| public final static MediaType MULTIPART_FORM_DATA_TYPE = new MediaType("multipart","form-data"); |
| |
| /** "application/octet-stream" */ |
| public final static String APPLICATION_OCTET_STREAM = "application/octet-stream"; |
| /** "application/octet-stream" */ |
| public final static MediaType APPLICATION_OCTET_STREAM_TYPE = new MediaType("application","octet-stream"); |
| |
| /** "text/plain" */ |
| public final static String TEXT_PLAIN = "text/plain"; |
| /** "text/plain" */ |
| public final static MediaType TEXT_PLAIN_TYPE = new MediaType("text","plain"); |
| |
| /** "text/xml" */ |
| public final static String TEXT_XML = "text/xml"; |
| /** "text/xml" */ |
| public final static MediaType TEXT_XML_TYPE = new MediaType("text","xml"); |
| |
| /** "text/html" */ |
| public final static String TEXT_HTML = "text/html"; |
| /** "text/html" */ |
| public final static MediaType TEXT_HTML_TYPE = new MediaType("text","html"); |
| |
| /** |
| * Creates a new instance of MediaType by parsing the supplied string. |
| * @param type the media type string |
| * @return the newly created MediaType |
| * @throws IllegalArgumentException if the supplied string cannot be parsed |
| * or is null |
| */ |
| public static MediaType valueOf(String type) throws IllegalArgumentException { |
| return delegate.fromString(type); |
| } |
| |
| /** |
| * Creates a new instance of MediaType with the supplied type, subtype and |
| * parameters. |
| * @param type the primary type, null is equivalent to |
| * {@link #MEDIA_TYPE_WILDCARD}. |
| * @param subtype the subtype, null is equivalent to |
| * {@link #MEDIA_TYPE_WILDCARD}. |
| * @param parameters a map of media type parameters, null is the same as an |
| * empty map. |
| */ |
| public MediaType(String type, String subtype, Map<String, String> parameters) { |
| this.type = type==null ? MEDIA_TYPE_WILDCARD : type; |
| this.subtype = subtype==null ? MEDIA_TYPE_WILDCARD : subtype; |
| if (parameters==null) { |
| this.parameters = emptyMap; |
| } else { |
| Map<String, String> map = new TreeMap<String, String>(new Comparator<String>() { |
| public int compare(String o1, String o2) { |
| return o1.compareToIgnoreCase(o2); |
| } |
| }); |
| for (Map.Entry<String, String> e: parameters.entrySet()) { |
| map.put(e.getKey().toLowerCase(), e.getValue()); |
| } |
| this.parameters = Collections.unmodifiableMap(map); |
| } |
| } |
| |
| /** |
| * Creates a new instance of MediaType with the supplied type and subtype. |
| * @param type the primary type, null is equivalent to |
| * {@link #MEDIA_TYPE_WILDCARD} |
| * @param subtype the subtype, null is equivalent to |
| * {@link #MEDIA_TYPE_WILDCARD} |
| */ |
| public MediaType(String type, String subtype) { |
| this(type,subtype,emptyMap); |
| } |
| |
| /** |
| * Creates a new instance of MediaType, both type and subtype are wildcards. |
| * Consider using the constant {@link #WILDCARD_TYPE} instead. |
| */ |
| public MediaType() { |
| this(MEDIA_TYPE_WILDCARD, MEDIA_TYPE_WILDCARD); |
| } |
| |
| /** |
| * Getter for primary type. |
| * @return value of primary type. |
| */ |
| public String getType() { |
| return this.type; |
| } |
| |
| /** |
| * Checks if the primary type is a wildcard. |
| * @return true if the primary type is a wildcard |
| */ |
| public boolean isWildcardType() { |
| return this.getType().equals(MEDIA_TYPE_WILDCARD); |
| } |
| |
| /** |
| * Getter for subtype. |
| * @return value of subtype. |
| */ |
| public String getSubtype() { |
| return this.subtype; |
| } |
| |
| /** |
| * Checks if the subtype is a wildcard |
| * @return true if the subtype is a wildcard |
| */ |
| public boolean isWildcardSubtype() { |
| return this.getSubtype().equals(MEDIA_TYPE_WILDCARD); |
| } |
| |
| /** |
| * Getter for a read-only parameter map. Keys are case-insensitive. |
| * @return an immutable map of parameters. |
| */ |
| public Map<String, String> getParameters() { |
| return parameters; |
| } |
| |
| /** |
| * Check if this media type is compatible with another media type. E.g. |
| * image/* is compatible with image/jpeg, image/png, etc. Media type |
| * parameters are ignored. The function is commutative. |
| * @return true if the types are compatible, false otherwise. |
| * @param other the media type to compare with |
| */ |
| public boolean isCompatible(MediaType other) { |
| if (other == null) |
| return false; |
| if (type.equals(MEDIA_TYPE_WILDCARD) || other.type.equals(MEDIA_TYPE_WILDCARD)) |
| return true; |
| else if (type.equalsIgnoreCase(other.type) && (subtype.equals(MEDIA_TYPE_WILDCARD) || other.subtype.equals(MEDIA_TYPE_WILDCARD))) |
| return true; |
| else |
| return this.type.equalsIgnoreCase(other.type) |
| && this.subtype.equalsIgnoreCase(other.subtype); |
| } |
| |
| /** |
| * Compares obj to this media type to see if they are the same by comparing |
| * type, subtype and parameters. Note that the case-sensitivity of parameter |
| * values is dependent on the semantics of the parameter name, see |
| * {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7">HTTP/1.1</a>}. |
| * This method assumes that values are case-sensitive. |
| * @param obj the object to compare to |
| * @return true if the two media types are the same, false otherwise. |
| */ |
| @Override |
| public boolean equals(Object obj) { |
| if (obj == null) |
| return false; |
| if (!(obj instanceof MediaType)) |
| return false; |
| MediaType other = (MediaType)obj; |
| return (this.type.equalsIgnoreCase(other.type) |
| && this.subtype.equalsIgnoreCase(other.subtype) |
| && this.parameters.equals(other.parameters)); |
| } |
| |
| /** |
| * Generate a hashcode from the type, subtype and parameters. |
| * @return a hashcode |
| */ |
| @Override |
| public int hashCode() { |
| return (this.type.toLowerCase()+this.subtype.toLowerCase()).hashCode()+this.parameters.hashCode(); |
| } |
| |
| /** |
| * Convert the media type to a string suitable for use as the value of a |
| * corresponding HTTP header. |
| * @return a stringified media type |
| */ |
| @Override |
| public String toString() { |
| return delegate.toString(this); |
| } |
| } |