001/* MimeType.java -- A MIME type as defined in RFC2046 and RFC2047. 002 Copyright (C) 2004 Free Software Foundation, Inc. 003 004This file is part of GNU Classpath. 005 006GNU Classpath is free software; you can redistribute it and/or modify 007it under the terms of the GNU General Public License as published by 008the Free Software Foundation; either version 2, or (at your option) 009any later version. 010 011GNU Classpath is distributed in the hope that it will be useful, but 012WITHOUT ANY WARRANTY; without even the implied warranty of 013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014General Public License for more details. 015 016You should have received a copy of the GNU General Public License 017along with GNU Classpath; see the file COPYING. If not, write to the 018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 01902110-1301 USA. 020 021Linking this library statically or dynamically with other modules is 022making a combined work based on this library. Thus, the terms and 023conditions of the GNU General Public License cover the whole 024combination. 025 026As a special exception, the copyright holders of this library give you 027permission to link this library with independent modules to produce an 028executable, regardless of the license terms of these independent 029modules, and to copy and distribute the resulting executable under 030terms of your choice, provided that you also meet, for each linked 031independent module, the terms and conditions of the license of that 032module. An independent module is a module which is not derived from 033or based on this library. If you modify this library, you may extend 034this exception to your version of the library, but you are not 035obligated to do so. If you do not wish to do so, delete this 036exception statement from your version. */ 037 038package javax.activation; 039 040import gnu.java.lang.CPStringBuilder; 041 042import java.io.Externalizable; 043import java.io.IOException; 044import java.io.ObjectInput; 045import 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 */ 053public 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} 293