001 /* MimeType.java -- A MIME type as defined in RFC2046 and RFC2047.
002 Copyright (C) 2004 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038 package javax.activation;
039
040 import gnu.java.lang.CPStringBuilder;
041
042 import java.io.Externalizable;
043 import java.io.IOException;
044 import java.io.ObjectInput;
045 import java.io.ObjectOutput;
046
047 /**
048 * A MIME content type, as defined in RFCs 2045 and 2046.
049 *
050 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
051 * @version 1.1
052 */
053 public class MimeType
054 implements Externalizable
055 {
056
057 static final String TSPECIALS = "()<>@,;:/[]?=\\\"";
058
059 private String primaryType;
060 private String subType;
061 private MimeTypeParameterList parameters;
062
063 /**
064 * Constructor for an <code>application/*</code> content type.
065 */
066 public MimeType()
067 {
068 primaryType = "application";
069 subType = "*";
070 parameters = new MimeTypeParameterList();
071 }
072
073 /**
074 * Constructor that parses a raw String.
075 * @param rawdata the MIME type string
076 */
077 public MimeType(String rawdata)
078 throws MimeTypeParseException
079 {
080 parse(rawdata);
081 }
082
083 /**
084 * Constructor for a new MIME type with the given primary and sub types
085 * and an empty parameter list.
086 * @param primary the primary type
087 * @param sub the subtype
088 */
089 public MimeType(String primary, String sub)
090 throws MimeTypeParseException
091 {
092 checkValidity(primary, "Primary type is invalid");
093 checkValidity(sub, "Sub type is invalid");
094 primaryType = primary.toLowerCase();
095 subType = sub.toLowerCase();
096 parameters = new MimeTypeParameterList();
097 }
098
099 /**
100 * Returns the primary type.
101 */
102 public String getPrimaryType()
103 {
104 return primaryType;
105 }
106
107 /**
108 * Sets the primary type.
109 * @param primary the new primary type
110 */
111 public void setPrimaryType(String primary)
112 throws MimeTypeParseException
113 {
114 checkValidity(primary, "Primary type is invalid");
115 primaryType = primary.toLowerCase();
116 }
117
118 /**
119 * Returns the subtype.
120 */
121 public String getSubType()
122 {
123 return subType;
124 }
125
126 /**
127 * Sets the subtype.
128 * @param sub the new subtype
129 */
130 public void setSubType(String sub)
131 throws MimeTypeParseException
132 {
133 checkValidity(sub, "Sub type is invalid");
134 subType = sub.toLowerCase();
135 }
136
137 /**
138 * Returns the MIME parameters.
139 */
140 public MimeTypeParameterList getParameters()
141 {
142 return parameters;
143 }
144
145 /**
146 * Returns the parameter value for the specified name.
147 * @param name the parameter name
148 */
149 public String getParameter(String name)
150 {
151 return parameters.get(name);
152 }
153
154 /**
155 * Sets the parameter value for the specified name.
156 * @param name the parameter name
157 * @param value the new value
158 */
159 public void setParameter(String name, String value)
160 {
161 parameters.set(name, value);
162 }
163
164 /**
165 * Removes the parameter value for the specified name.
166 * @param name the parameter name
167 */
168 public void removeParameter(String name)
169 {
170 parameters.remove(name);
171 }
172
173 /**
174 * Returns the complete string representation of this MIME type.
175 */
176 public String toString()
177 {
178 return new CPStringBuilder(primaryType)
179 .append('/')
180 .append(subType)
181 .append(parameters.toString())
182 .toString();
183 }
184
185 /**
186 * Returns the string representation of this MIME type without
187 * parameters.
188 */
189 public String getBaseType()
190 {
191 return new CPStringBuilder(primaryType)
192 .append('/')
193 .append(subType)
194 .toString();
195 }
196
197 /**
198 * Returns true if the primary and subtype of this MIME type are the
199 * same as in the given MIME type.
200 */
201 public boolean match(MimeType type)
202 {
203 String primary2 = type.getPrimaryType();
204 String sub2 = type.getSubType();
205 return primaryType.equals(primary2) && (subType.equals(sub2) ||
206 "*".equals(subType) ||
207 "*".equals(sub2));
208 }
209
210 /**
211 * Returns true if the primary and subtype of this MIME type are the
212 * same as in the given MIME type string.
213 */
214 public boolean match(String rawdata)
215 throws MimeTypeParseException
216 {
217 return match(new MimeType(rawdata));
218 }
219
220 public void writeExternal(ObjectOutput out)
221 throws IOException
222 {
223 out.writeUTF(toString());
224 out.flush();
225 }
226
227 public void readExternal(ObjectInput in)
228 throws IOException, ClassNotFoundException
229 {
230 try
231 {
232 parse(in.readUTF());
233 }
234 catch (MimeTypeParseException e)
235 {
236 throw new IOException(e.getMessage());
237 }
238 }
239
240 private void parse(String rawdata)
241 throws MimeTypeParseException
242 {
243 int si = rawdata.indexOf('/');
244 int pi = rawdata.indexOf(';');
245 if (si == -1)
246 {
247 throw new MimeTypeParseException("Unable to find a sub type.");
248 }
249 if (pi == -1)
250 {
251 primaryType = rawdata.substring(0, si).toLowerCase().trim();
252 subType = rawdata.substring(si + 1).toLowerCase().trim();
253 parameters = new MimeTypeParameterList();
254 }
255 else if (si < pi)
256 {
257 primaryType = rawdata.substring(0, si).toLowerCase().trim();
258 subType = rawdata.substring(si + 1, pi).toLowerCase().trim();
259 parameters = new MimeTypeParameterList(rawdata.substring(pi));
260 }
261 else
262 {
263 throw new MimeTypeParseException("Unable to find a sub type.");
264 }
265 checkValidity(primaryType, "Primary type is invalid");
266 checkValidity(subType, "Sub type is invalid");
267 }
268
269 static void checkValidity(String token, String message)
270 throws MimeTypeParseException
271 {
272 int len = token.length();
273 if (len == 0)
274 {
275 throw new MimeTypeParseException(message, token);
276 }
277 for (int i = 0; i < len; i++)
278 {
279 char c = token.charAt(i);
280 if (!isValidChar(c))
281 {
282 throw new MimeTypeParseException(message, token);
283 }
284 }
285 }
286
287 static boolean isValidChar(char c)
288 {
289 return c > ' ' && c <= '~' && TSPECIALS.indexOf(c) == -1;
290 }
291
292 }