1. /*
  2. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  3. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  4. */
  5. package javax.mail.internet;
  6. import javax.mail.*;
  7. import java.util.*;
  8. import java.io.*;
  9. /**
  10. * This class represents a MIME ContentType value. It provides
  11. * methods to parse a ContentType string into individual components
  12. * and to generate a MIME style ContentType string.
  13. *
  14. * @version 1.6, 00/09/20
  15. * @author John Mani
  16. */
  17. public class ContentType {
  18. private String primaryType; // primary type
  19. private String subType; // subtype
  20. private ParameterList list; // parameter list
  21. /**
  22. * No-arg Constructor.
  23. */
  24. public ContentType() { }
  25. /**
  26. * Constructor.
  27. *
  28. * @param primaryType primary type
  29. * @param subType subType
  30. * @param list ParameterList
  31. */
  32. public ContentType(String primaryType, String subType,
  33. ParameterList list) {
  34. this.primaryType = primaryType;
  35. this.subType = subType;
  36. this.list = list;
  37. }
  38. /**
  39. * Constructor that takes a Content-Type string. The String
  40. * is parsed into its constituents: primaryType, subType
  41. * and parameters. A ParseException is thrown if the parse fails.
  42. *
  43. * @param s the Content-Type string.
  44. * @exception ParseException if the parse fails.
  45. */
  46. public ContentType(String s) throws ParseException {
  47. HeaderTokenizer h = new HeaderTokenizer(s, HeaderTokenizer.MIME);
  48. HeaderTokenizer.Token tk;
  49. // First "type" ..
  50. tk = h.next();
  51. if (tk.getType() != HeaderTokenizer.Token.ATOM)
  52. throw new ParseException();
  53. primaryType = tk.getValue();
  54. // The '/' separator ..
  55. tk = h.next();
  56. if ((char)tk.getType() != '/')
  57. throw new ParseException();
  58. // Then "subType" ..
  59. tk = h.next();
  60. if (tk.getType() != HeaderTokenizer.Token.ATOM)
  61. throw new ParseException();
  62. subType = tk.getValue();
  63. // Finally parameters ..
  64. String rem = h.getRemainder();
  65. if (rem != null)
  66. list = new ParameterList(rem);
  67. }
  68. /**
  69. * Return the primary type.
  70. * @return the primary type
  71. */
  72. public String getPrimaryType() {
  73. return primaryType;
  74. }
  75. /**
  76. * Return the subType.
  77. * @return the subType
  78. */
  79. public String getSubType() {
  80. return subType;
  81. }
  82. /**
  83. * Return the MIME type string, without the parameters.
  84. * The returned value is basically the concatenation of
  85. * the primaryType, the '/' character and the secondaryType.
  86. *
  87. * @return the type
  88. */
  89. public String getBaseType() {
  90. return primaryType + '/' + subType;
  91. }
  92. /**
  93. * Return the specified parameter value. Returns <code>null</code>
  94. * if this parameter is absent.
  95. * @return parameter value
  96. */
  97. public String getParameter(String name) {
  98. if (list == null)
  99. return null;
  100. return list.get(name);
  101. }
  102. /**
  103. * Return a ParameterList object that holds all the available
  104. * parameters. Returns null if no parameters are available.
  105. *
  106. * @return ParameterList
  107. */
  108. public ParameterList getParameterList() {
  109. return list;
  110. }
  111. /**
  112. * Set the primary type. Overrides existing primary type.
  113. * @param primaryType primary type
  114. */
  115. public void setPrimaryType(String primaryType) {
  116. this.primaryType = primaryType;
  117. }
  118. /**
  119. * Set the subType. Overrides existing subType
  120. * @param type subType
  121. */
  122. public void setSubType(String subType) {
  123. this.subType = subType;
  124. }
  125. /**
  126. * Set the specified parameter. If this parameter already exists,
  127. * it is replaced by this new value.
  128. *
  129. * @param name parameter name
  130. * @param value parameter value
  131. */
  132. public void setParameter(String name, String value) {
  133. if (list == null)
  134. list = new ParameterList();
  135. list.set(name, value);
  136. }
  137. /**
  138. * Set a new ParameterList.
  139. * @param list ParameterList
  140. */
  141. public void setParameterList(ParameterList list) {
  142. this.list = list;
  143. }
  144. /**
  145. * Retrieve a RFC2045 style string representation of
  146. * this Content-Type. Returns <code>null</code> if
  147. * the conversion failed.
  148. *
  149. * @return RFC2045 style string
  150. */
  151. public String toString() {
  152. if (primaryType == null || subType == null) // need both
  153. return null;
  154. StringBuffer sb = new StringBuffer();
  155. sb.append(primaryType).append('/').append(subType);
  156. if (list != null)
  157. // append the parameter list
  158. // use the length of the string buffer + the length of
  159. // the header name formatted as follows "Content-Type: "
  160. sb.append(list.toString(sb.length() + 14));
  161. return sb.toString();
  162. }
  163. /**
  164. * Match with the specified ContentType object. This method
  165. * compares <strong>only the <code>primaryType</code> and
  166. * <code>subType</code> </strong>. The parameters of both operands
  167. * are ignored. <p>
  168. *
  169. * For example, this method will return <code>true</code> when
  170. * comparing the ContentTypes for <strong>"text/plain"</strong>
  171. * and <strong>"text/plain; charset=foobar"</strong>.
  172. *
  173. * If the <code>subType</code> of either operand is the special
  174. * character '*', then the subtype is ignored during the match.
  175. * For example, this method will return <code>true</code> when
  176. * comparing the ContentTypes for <strong>"text/plain"</strong>
  177. * and <strong>"text/*" </strong>
  178. *
  179. * @param ContentType to compare this against
  180. */
  181. public boolean match(ContentType cType) {
  182. // Match primaryType
  183. if (!primaryType.equalsIgnoreCase(cType.getPrimaryType()))
  184. return false;
  185. String sType = cType.getSubType();
  186. // If either one of the subTypes is wildcarded, return true
  187. if ((subType.charAt(0) == '*') || (sType.charAt(0) == '*'))
  188. return true;
  189. // Match subType
  190. if (!subType.equalsIgnoreCase(sType))
  191. return false;
  192. return true;
  193. }
  194. /**
  195. * Match with the specified content-type string. This method
  196. * compares <strong>only the <code>primaryType</code> and
  197. * <code>subType</code> </strong>.
  198. * The parameters of both operands are ignored. <p>
  199. *
  200. * For example, this method will return <code>true</code> when
  201. * comparing the ContentType for <strong>"text/plain"</strong>
  202. * with <strong>"text/plain; charset=foobar"</strong>.
  203. *
  204. * If the <code>subType</code> of either operand is the special
  205. * character '*', then the subtype is ignored during the match.
  206. * For example, this method will return <code>true</code> when
  207. * comparing the ContentType for <strong>"text/plain"</strong>
  208. * with <strong>"text/*" </strong>
  209. */
  210. public boolean match(String s) {
  211. try {
  212. return match(new ContentType(s));
  213. } catch (ParseException pex) {
  214. return false;
  215. }
  216. }
  217. }