Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (C) 2011 The Guava Authors
   *
   * Licensed 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 com.google.common.net;
 
 import static com.google.common.base.CharMatcher.ASCII;
 import static com.google.common.base.CharMatcher.JAVA_ISO_CONTROL;
 import static com.google.common.base.Charsets.UTF_8;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 
 
 import java.util.Map;
 
 import  javax.annotation.Nullable;
 import  javax.annotation.concurrent.Immutable;

Represents an Internet Media Type (also known as a MIME Type or Content Type). This class also supports the concept of media ranges defined by HTTP/1.1. As such, the * character is treated as a wildcard and is used to represent any acceptable type or subtype value. A media type may not have wildcard type with a declared subtype. The * character has no special meaning as part of a parameter. All values for type, subtype, parameter attributes or parameter values must be valid according to RFCs 2045 and 2046.

All portions of the media type that are case-insensitive (type, subtype, parameter attributes) are normalized to lowercase. The value of the charset parameter is normalized to lowercase, but all others are left as-is.

Note that this specifically does not represent the value of the MIME Content-Type header and as such has no support for header-specific considerations such as line folding and comments.

For media types that take a charset the predefined constants default to UTF-8 and have a "_UTF_8" suffix. To get a version without a character set, use withoutParameters.

Author(s):
Gregory Kick
Since:
12.0
 
 @Immutable
 public final class MediaType {
   private static final String CHARSET_ATTRIBUTE = "charset";
   private static final ImmutableListMultimap<StringStringUTF_8_CONSTANT_PARAMETERS =
       ImmutableListMultimap.of(, Ascii.toLowerCase(.name()));

  
Matcher for type, subtype and attributes.
 
   private static final CharMatcher TOKEN_MATCHER = .and(.negate())
       .and(CharMatcher.isNot(' '))
       .and(CharMatcher.noneOf("()<>@,;:\\\"/[]?="));
   private static final CharMatcher QUOTED_TEXT_MATCHER = 
       .and(CharMatcher.noneOf("\"\\\r"));
   /*
    * This matches the same characters as linear-white-space from RFC 822, but we make no effort to
    * enforce any particular rules with regards to line folding as stated in the class docs.
    */
   private static final CharMatcher LINEAR_WHITE_SPACE = CharMatcher.anyOf(" \t\r\n");
 
  // TODO(gak): make these public?
  private static final String APPLICATION_TYPE = "application";
  private static final String AUDIO_TYPE = "audio";
  private static final String IMAGE_TYPE = "image";
  private static final String TEXT_TYPE = "text";
  private static final String VIDEO_TYPE = "video";
  private static final String WILDCARD = "*";
  /*
   * The following constants are grouped by their type and ordered alphabetically by the constant
   * name within that type. The constant name should be a sensible identifier that is closest to the
   * "common name" of the media.  This is often, but not necessarily the same as the subtype.
   *
   * Be sure to declare all constants with the type and subtype in all lowercase.
   *
   * When adding constants, be sure to add an entry into the KNOWN_TYPES map. For types that
   * take a charset (e.g. all text/* types), default to UTF-8 and suffix with "_UTF_8".
   */
  public static final MediaType ANY_TYPE = createConstant();
  public static final MediaType ANY_TEXT_TYPE = createConstant();
  public static final MediaType ANY_IMAGE_TYPE = createConstant();
  public static final MediaType ANY_AUDIO_TYPE = createConstant();
  public static final MediaType ANY_VIDEO_TYPE = createConstant();
  /* text types */
  public static final MediaType CACHE_MANIFEST_UTF_8 =
      createConstantUtf8("cache-manifest");
  public static final MediaType CSS_UTF_8 = createConstantUtf8("css");
  public static final MediaType CSV_UTF_8 = createConstantUtf8("csv");
  public static final MediaType HTML_UTF_8 = createConstantUtf8("html");
  public static final MediaType I_CALENDAR_UTF_8 = createConstantUtf8("calendar");
  public static final MediaType PLAIN_TEXT_UTF_8 = createConstantUtf8("plain");
  
RFC 4329 declares application/javascript to be the correct media type for JavaScript, but this may be necessary in certain situations for compatibility.
  public static final MediaType TEXT_JAVASCRIPT_UTF_8 = createConstantUtf8("javascript");
  public static final MediaType VCARD_UTF_8 = createConstantUtf8("vcard");
  public static final MediaType WML_UTF_8 = createConstantUtf8("vnd.wap.wml");
  public static final MediaType XML_UTF_8 = createConstantUtf8("xml");
  /* image types */
  public static final MediaType BMP = createConstant("bmp");
  public static final MediaType GIF = createConstant("gif");
  public static final MediaType ICO = createConstant("vnd.microsoft.icon");
  public static final MediaType JPEG = createConstant("jpeg");
  public static final MediaType PNG = createConstant("png");
  public static final MediaType SVG_UTF_8 = createConstantUtf8("svg+xml");
  public static final MediaType TIFF = createConstant("tiff");
  public static final MediaType WEBP = createConstant("webp");
  /* audio types */
  public static final MediaType MP4_AUDIO = createConstant("mp4");
  public static final MediaType MPEG_AUDIO = createConstant("mpeg");
  public static final MediaType OGG_AUDIO = createConstant("ogg");
  public static final MediaType WEBM_AUDIO = createConstant("webm");
  /* video types */
  public static final MediaType MP4_VIDEO = createConstant("mp4");
  public static final MediaType MPEG_VIDEO = createConstant("mpeg");
  public static final MediaType OGG_VIDEO = createConstant("ogg");
  public static final MediaType QUICKTIME = createConstant("quicktime");
  public static final MediaType WEBM_VIDEO = createConstant("webm");
  public static final MediaType WMV = createConstant("x-ms-wmv");
  /* application types */
  public static final MediaType ATOM_UTF_8 = createConstantUtf8("atom+xml");
  public static final MediaType BZIP2 = createConstant("x-bzip2");
  public static final MediaType FORM_DATA = createConstant(,
      "x-www-form-urlencoded");
  public static final MediaType GZIP = createConstant("x-gzip");
   
RFC 4329 declares this to be the correct media type for JavaScript, but text/javascript may be necessary in certain situations for compatibility.
  public static final MediaType JAVASCRIPT_UTF_8 =
      createConstantUtf8("javascript");
  public static final MediaType JSON_UTF_8 = createConstantUtf8("json");
  public static final MediaType KML = createConstant("vnd.google-earth.kml+xml");
  public static final MediaType KMZ = createConstant("vnd.google-earth.kmz");
  public static final MediaType MBOX = createConstant("mbox");
  public static final MediaType MICROSOFT_EXCEL = createConstant("vnd.ms-excel");
  public static final MediaType MICROSOFT_POWERPOINT =
      createConstant("vnd.ms-powerpoint");
  public static final MediaType MICROSOFT_WORD = createConstant("msword");
  public static final MediaType OCTET_STREAM = createConstant("octet-stream");
  public static final MediaType OGG_CONTAINER = createConstant("ogg");
      "vnd.openxmlformats-officedocument.wordprocessingml.document");
      "vnd.openxmlformats-officedocument.presentationml.presentation");
  public static final MediaType OOXML_SHEET =
      createConstant("vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  public static final MediaType OPENDOCUMENT_GRAPHICS =
      createConstant("vnd.oasis.opendocument.graphics");
  public static final MediaType OPENDOCUMENT_PRESENTATION =
      createConstant("vnd.oasis.opendocument.presentation");
  public static final MediaType OPENDOCUMENT_SPREADSHEET =
      createConstant("vnd.oasis.opendocument.spreadsheet");
  public static final MediaType OPENDOCUMENT_TEXT =
      createConstant("vnd.oasis.opendocument.text");
  public static final MediaType PDF = createConstant("pdf");
  public static final MediaType POSTSCRIPT = createConstant("postscript");
  public static final MediaType RTF_UTF_8 = createConstantUtf8("rtf");
      "x-shockwave-flash");
  public static final MediaType SKETCHUP = createConstant("vnd.sketchup.skp");
  public static final MediaType TAR = createConstant("x-tar");
  public static final MediaType XHTML_UTF_8 = createConstantUtf8("xhtml+xml");
  public static final MediaType ZIP = createConstant("zip");
  private static final ImmutableMap<MediaTypeMediaTypeKNOWN_TYPES =
          .put()
          .put()
          .put()
          .put()
          .put()
          /* text types */
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          /* image types */
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          /* audio types */
          .put()
          .put()
          .put()
          .put()
          /* video types */
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          /* application types */
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .put()
          .build();
  private final String type;
  private final String subtype;
  private MediaType(String typeString subtype,
      ImmutableListMultimap<StringStringparameters) {
    this. = type;
    this. = subtype;
    this. = parameters;
  }
  private static MediaType createConstant(String typeString subtype) {
    return new MediaType(typesubtype, ImmutableListMultimap.<StringString>of());
  }
  private static MediaType createConstantUtf8(String typeString subtype) {
    return new MediaType(typesubtype);
  }

  
Returns the top-level media type. For example, "text" in "text/plain".
  public String type() {
    return ;
  }

  
Returns the media subtype. For example, "plain" in "text/plain".
  public String subtype() {
    return ;
  }

  
Returns a multimap containing the parameters of this media type.
    return ;
  }
    return Maps.transformValues(.asMap(),
        new Function<Collection<String>, ImmutableMultiset<String>>() {
          @Override public ImmutableMultiset<Stringapply(Collection<Stringinput) {
            return ImmutableMultiset.copyOf(input);
          }
        });
  }

  
Returns an optional charset for the value of the charset parameter if it is specified.

Throws:
IllegalStateException if multiple charset values have been set for this media type
IllegalCharsetNameException if a charset value is present, but illegal
UnsupportedCharsetException if a charset value is present, but no support is available in this instance of the Java virtual machine
  public Optional<Charsetcharset() {
    ImmutableSet<StringcharsetValues = ImmutableSet.copyOf(.get());
    switch (charsetValues.size()) {
      case 0:
        return Optional.absent();
      case 1:
        return Optional.of(Charset.forName(Iterables.getOnlyElement(charsetValues)));
      default:
        throw new IllegalStateException("Multiple charset values defined: " + charsetValues);
    }
  }

  
Returns a new instance with the same type and subtype as this instance, but without any parameters.
    return .isEmpty() ? this : create();
  }

  
Replaces all parameters with the given parameters.

Throws:
IllegalArgumentException if any parameter or value is invalid
  public MediaType withParameters(Multimap<StringStringparameters) {
    return create(parameters);
  }

  
Replaces all parameters with the given attribute with a single parameter with the given value. If multiple parameters with the same attributes are necessary use withParameters. Prefer withCharset for setting the charset parameter when using a Charset object.

Throws:
IllegalArgumentException if either attribute or value is invalid
  public MediaType withParameter(String attributeString value) {
    checkNotNull(attribute);
    checkNotNull(value);
    String normalizedAttribute = normalizeToken(attribute);
    ImmutableListMultimap.Builder<StringStringbuilder = ImmutableListMultimap.builder();
    for (Entry<StringStringentry : .entries()) {
      String key = entry.getKey();
      if (!normalizedAttribute.equals(key)) {
        builder.put(keyentry.getValue());
      }
    }
    builder.put(normalizedAttributenormalizeParameterValue(normalizedAttributevalue));
    MediaType mediaType = new MediaType(builder.build());
    // Return one of the constants if the media type is a known type.
    return Objects.firstNonNull(.get(mediaType), mediaType);
  }

  
Returns a new instance with the same type and subtype as this instance, with the charset parameter set to the name of the given charset. Only one charset parameter will be present on the new instance regardless of the number set on this one.

If a charset must be specified that is not supported on this JVM (and thus is not representable as a Charset instance, use withParameter.

  public MediaType withCharset(Charset charset) {
    checkNotNull(charset);
    return withParameter(charset.name());
  }

  
Returns true if either the type or subtype is the wildcard.
  public boolean hasWildcard() {
    return .equals() || .equals();
  }

  
Returns true if this instance falls within the range (as defined by the HTTP Accept header) given by the argument according to three criteria:
  1. The type of the argument is the wildcard or equal to the type of this instance.
  2. The subtype of the argument is the wildcard or equal to the subtype of this instance.
  3. All of the parameters present in the argument are present in this instance.
For example:
   PLAIN_TEXT_UTF_8.is(PLAIN_TEXT_UTF_8) // true
   PLAIN_TEXT_UTF_8.is(HTML_UTF_8) // false
   PLAIN_TEXT_UTF_8.is(ANY_TYPE) // true
   PLAIN_TEXT_UTF_8.is(ANY_TEXT_TYPE) // true
   PLAIN_TEXT_UTF_8.is(ANY_IMAGE_TYPE) // false
   PLAIN_TEXT_UTF_8.is(ANY_TEXT_TYPE.withCharset(UTF_8)) // true
   PLAIN_TEXT_UTF_8.withoutParameters().is(ANY_TEXT_TYPE.withCharset(UTF_8)) // false
   PLAIN_TEXT_UTF_8.is(ANY_TEXT_TYPE.withCharset(UTF_16)) // false

Note that while it is possible to have the same parameter declared multiple times within a media type this method does not consider the number of occurrences of a parameter. For example, "text/plain; charset=UTF-8" satisfies "text/plain; charset=UTF-8; charset=UTF-8".

  public boolean is(MediaType mediaTypeRange) {
    return (mediaTypeRange.type.equals() || mediaTypeRange.type.equals(this.))
        && (mediaTypeRange.subtype.equals() || mediaTypeRange.subtype.equals(this.))
        && this..entries().containsAll(mediaTypeRange.parameters.entries());
  }

  
Creates a new media type with the given type and subtype.

Throws:
IllegalArgumentException if type or subtype is invalid or if a wildcard is used for the type, but not the subtype.
  public static MediaType create(String typeString subtype) {
    return create(typesubtype, ImmutableListMultimap.<StringString>of());
  }

  
Creates a media type with the "application" type and the given subtype.

Throws:
IllegalArgumentException if subtype is invalid
  static MediaType createApplicationType(String subtype) {
    return create(subtype);
  }

  
Creates a media type with the "audio" type and the given subtype.

Throws:
IllegalArgumentException if subtype is invalid
  static MediaType createAudioType(String subtype) {
    return create(subtype);
  }

  
Creates a media type with the "image" type and the given subtype.

Throws:
IllegalArgumentException if subtype is invalid
  static MediaType createImageType(String subtype) {
    return create(subtype);
  }

  
Creates a media type with the "text" type and the given subtype.

Throws:
IllegalArgumentException if subtype is invalid
  static MediaType createTextType(String subtype) {
    return create(subtype);
  }

  
Creates a media type with the "video" type and the given subtype.

Throws:
IllegalArgumentException if subtype is invalid
  static MediaType createVideoType(String subtype) {
    return create(subtype);
  }
  private static MediaType create(String typeString subtype,
      Multimap<StringStringparameters) {
    checkNotNull(type);
    checkNotNull(subtype);
    checkNotNull(parameters);
    String normalizedType = normalizeToken(type);
    String normalizedSubtype = normalizeToken(subtype);
    checkArgument(!.equals(normalizedType) || .equals(normalizedSubtype),
        "A wildcard type cannot be used with a non-wildcard subtype");
    ImmutableListMultimap.Builder<StringStringbuilder = ImmutableListMultimap.builder();
    for (Entry<StringStringentry : parameters.entries()) {
      String attribute = normalizeToken(entry.getKey());
      builder.put(attributenormalizeParameterValue(attributeentry.getValue()));
    }
    MediaType mediaType = new MediaType(normalizedTypenormalizedSubtypebuilder.build());
    // Return one of the constants if the media type is a known type.
    return Objects.firstNonNull(.get(mediaType), mediaType);
  }
  private static String normalizeToken(String token) {
    return Ascii.toLowerCase(token);
  }
  private static String normalizeParameterValue(String attributeString value) {
    return .equals(attribute) ? Ascii.toLowerCase(value) : value;
  }

  
Parses a media type from its string representation.

Throws:
IllegalArgumentException if the input is not parsable
  public static MediaType parse(String input) {
    checkNotNull(input);
    Tokenizer tokenizer = new Tokenizer(input);
    try {
      String type = tokenizer.consumeToken();
      tokenizer.consumeCharacter('/');
      String subtype = tokenizer.consumeToken();
      ImmutableListMultimap.Builder<StringStringparameters = ImmutableListMultimap.builder();
      while (tokenizer.hasMore()) {
        tokenizer.consumeCharacter(';');
        tokenizer.consumeTokenIfPresent();
        String attribute = tokenizer.consumeToken();
        tokenizer.consumeCharacter('=');
        final String value;
        if ('"' == tokenizer.previewChar()) {
          tokenizer.consumeCharacter('"');
          StringBuilder valueBuilder = new StringBuilder();
          while ('"' != tokenizer.previewChar()) {
            if ('\\' == tokenizer.previewChar()) {
              tokenizer.consumeCharacter('\\');
              valueBuilder.append(tokenizer.consumeCharacter());
            } else {
              valueBuilder.append(tokenizer.consumeToken());
            }
          }
          value = valueBuilder.toString();
          tokenizer.consumeCharacter('"');
        } else {
          value = tokenizer.consumeToken();
        }
        parameters.put(attributevalue);
      }
      return create(typesubtypeparameters.build());
    } catch (IllegalStateException e) {
      throw new IllegalArgumentException(e);
    }
  }
  private static final class Tokenizer {
    final String input;
    int position = 0;
    Tokenizer(String input) {
      this. = input;
    }
      checkState(hasMore());
      int startPosition = ;
       = matcher.negate().indexIn(startPosition);
      return hasMore() ? .substring(startPosition) : .substring(startPosition);
    }
    String consumeToken(CharMatcher matcher) {
      int startPosition = ;
      String token = consumeTokenIfPresent(matcher);
      checkState( != startPosition);
      return token;
    }
    char consumeCharacter(CharMatcher matcher) {
      checkState(hasMore());
      char c = previewChar();
      checkState(matcher.matches(c));
      ++;
      return c;
    }
    char consumeCharacter(char c) {
      checkState(hasMore());
      checkState(previewChar() == c);
      ++;
      return c;
    }
    char previewChar() {
      checkState(hasMore());
      return .charAt();
    }
    boolean hasMore() {
      return ( >= 0) && ( < .length());
    }
  }
  @Override public boolean equals(@Nullable Object obj) {
    if (obj == this) {
      return true;
    } else if (obj instanceof MediaType) {
      MediaType that = (MediaTypeobj;
      return this..equals(that.type)
          && this..equals(that.subtype)
          // compare parameters regardless of order
          && this.parametersAsMap().equals(that.parametersAsMap());
    } else {
      return false;
    }
  }
  @Override public int hashCode() {
    return Objects.hashCode(parametersAsMap());
  }
  private static final MapJoiner PARAMETER_JOINER = Joiner.on("; ").withKeyValueSeparator("=");

  
Returns the string representation of this media type in the format described in RFC 2045.
  @Override public String toString() {
    StringBuilder builder = new StringBuilder().append().append('/').append();
    if (!.isEmpty()) {
      builder.append("; ");
      Multimap<StringStringquotedParameters = Multimaps.transformValues(,
          new Function<StringString>() {
            @Override public String apply(String value) {
              return .matchesAllOf(value) ? value : escapeAndQuote(value);
            }
          });
      .appendTo(builderquotedParameters.entries());
    }
    return builder.toString();
  }
  private static String escapeAndQuote(String value) {
    StringBuilder escaped = new StringBuilder(value.length() + 16).append('"');
    for (char ch : value.toCharArray()) {
      if (ch == '\r' || ch == '\\' || ch == '"') {
        escaped.append('\\');
      }
      escaped.append(ch);
    }
    return escaped.append('"').toString();
  }
New to GrepCode? Check out our FAQ X