blob: 8f7cdca84c5a338ec560d5ff3d659ca6a2042f11 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.axiom.mime;
import java.text.ParseException;
/**
* Represents a media type as defined by <a href="http://tools.ietf.org/html/rfc2045">RFC 2045</a>
* and <a href="http://tools.ietf.org/html/rfc2046">RFC 2046</a>. It specifies a primary type (e.g.
* {@code text}) and a subtype (e.g. {@code xml}). Note that in RFC 2045, "media type" refers to
* what is called "primary type" here, while this class uses "media type" to refer to the
* combination of primary and subtype.
* <p>
* This class is immutable. It overrides {@link Object#equals(Object)} and {@link Object#hashCode()}
* to allow comparing media types as described by RFC 2045, i.e. in a case insensitive way.
*/
public final class MediaType {
/**
* The media type for {@code text/xml}.
*/
public static final MediaType TEXT_XML = new MediaType("text", "xml");
/**
* The media type for {@code application/xml}.
*/
public static final MediaType APPLICATION_XML = new MediaType("application", "xml");
/**
* The media type for {@code application/soap+xml}.
*/
public static final MediaType APPLICATION_SOAP_XML = new MediaType("application", "soap+xml");
/**
* The media type for {@code application/xop+xml}.
*/
public static final MediaType APPLICATION_XOP_XML = new MediaType("application", "xop+xml");
/**
* The media type for {@code multipart/related}.
*/
public static final MediaType MULTIPART_RELATED = new MediaType("multipart", "related");
/**
* The media type for {@code application/octet-stream}.
*/
public static final MediaType APPLICATION_OCTET_STREAM = new MediaType("application", "octet-stream");
/**
* The media type for {@code text/plain}.
*/
public static final MediaType TEXT_PLAIN = new MediaType("text", "plain");
private final String primaryType;
private final String subType;
/**
* Constructor.
*
* @param primaryType
* the primary type
* @param subType
* the subtype
*/
public MediaType(String primaryType, String subType) {
this.primaryType = primaryType;
this.subType = subType;
}
/**
* Constructor that parses a media type.
*
* @param type
* the media type to parse
* @throws ParseException
* if the value is invalid and could not be parsed
*/
public MediaType(String type) throws ParseException {
ContentTypeTokenizer tokenizer = new ContentTypeTokenizer(type);
primaryType = tokenizer.requireToken();
tokenizer.require('/');
subType = tokenizer.requireToken();
tokenizer.requireEndOfString();
}
/**
* Get the primary type.
*
* @return the primary type
*/
public String getPrimaryType() {
return primaryType;
}
/**
* Get the subtype.
*
* @return the subtype
*/
public String getSubType() {
return subType;
}
/**
* Check if this media type has the given primary type.
*
* @param type
* the primary type to check against
* @return whether the primary type matches
*/
public boolean hasPrimaryType(String type) {
return primaryType.equalsIgnoreCase(type);
}
/**
* Check if this media type has the given sub type.
*
* @param type
* the sub type to check against
* @return whether the sub type matches
*/
public boolean hasSubType(String type) {
return subType.equalsIgnoreCase(type);
}
/**
* Check if this media type describes XML content as defined in
* <a href="http://tools.ietf.org/html/rfc7303">RFC 7303</a>.
*
* @return whether the content expected for this media type is XML
*/
public boolean isXML() {
return equals(TEXT_XML)
|| hasPrimaryType("application") && (
hasSubType("xml")
|| subType.length() > 4 && subType.substring(subType.length() - 4).equalsIgnoreCase("+xml"));
}
@Override
public int hashCode() {
int hash = 0;
for (int i=0, l=primaryType.length(); i<l; i++) {
hash = 31*hash + Character.toLowerCase(primaryType.charAt(i));
}
hash *= 31;
for (int i=0, l=subType.length(); i<l; i++) {
hash = 31*hash + Character.toLowerCase(subType.charAt(i));
}
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MediaType) {
MediaType other = (MediaType)obj;
return primaryType.equalsIgnoreCase(other.primaryType) && subType.equalsIgnoreCase(other.subType);
} else {
return false;
}
}
@Override
public String toString() {
return primaryType + "/" + subType;
}
}