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 }