KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > datatransfer > MimeType


1 /*
2  * @(#)MimeType.java 1.25 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.awt.datatransfer;
9
10 import java.io.Externalizable JavaDoc;
11 import java.io.ObjectOutput JavaDoc;
12 import java.io.ObjectInput JavaDoc;
13 import java.io.IOException JavaDoc;
14 import java.util.Enumeration JavaDoc;
15
16
17 /**
18  * A Multipurpose Internet Mail Extension (MIME) type, as defined
19  * in RFC 2045 and 2046.
20  *
21  * THIS IS *NOT* - REPEAT *NOT* - A PUBLIC CLASS! DataFlavor IS
22  * THE PUBLIC INTERFACE, AND THIS IS PROVIDED AS A ***PRIVATE***
23  * (THAT IS AS IN *NOT* PUBLIC) HELPER CLASS!
24  */

25 class MimeType implements Externalizable JavaDoc, Cloneable JavaDoc {
26
27     /*
28      * serialization support
29      */

30
31     static final long serialVersionUID = -6568722458793895906L;
32
33     /**
34      * Constructor for externalization; this constructor should not be
35      * called directly by an application, since the result will be an
36      * uninitialized, immutable <code>MimeType</code> object.
37      */

38     public MimeType() {
39     }
40     
41     /**
42      * Builds a <code>MimeType</code> from a <code>String</code>.
43      *
44      * @param rawdata text used to initialize the <code>MimeType</code>
45      * @throws NullPointerException if <code>rawdata</code> is null
46      */

47     public MimeType(String JavaDoc rawdata) throws MimeTypeParseException JavaDoc {
48         parse(rawdata);
49     }
50
51     /**
52      * Builds a <code>MimeType</code> with the given primary and sub
53      * type but has an empty parameter list.
54      *
55      * @param primary the primary type of this <code>MimeType</code>
56      * @param sub the subtype of this <code>MimeType</code>
57      * @throws NullPointerException if either <code>primary</code> or
58      * <code>sub</code> is null
59      */

60     public MimeType(String JavaDoc primary, String JavaDoc sub) throws MimeTypeParseException JavaDoc {
61     this(primary, sub, new MimeTypeParameterList JavaDoc());
62     }
63
64     /**
65      * Builds a <code>MimeType</code> with a pre-defined
66      * and valid (or empty) parameter list.
67      *
68      * @param primary the primary type of this <code>MimeType</code>
69      * @param sub the subtype of this <code>MimeType</code>
70      * @param mtpl the requested parameter list
71      * @throws NullPointerException if either <code>primary</code>,
72      * <code>sub</code> or <code>mtpl</code> is null
73      */

74     public MimeType(String JavaDoc primary, String JavaDoc sub, MimeTypeParameterList JavaDoc mtpl) throws
75 MimeTypeParseException JavaDoc {
76         // check to see if primary is valid
77
if(isValidToken(primary)) {
78             primaryType = primary.toLowerCase();
79         } else {
80             throw new MimeTypeParseException JavaDoc("Primary type is invalid.");
81         }
82         
83         // check to see if sub is valid
84
if(isValidToken(sub)) {
85             subType = sub.toLowerCase();
86         } else {
87             throw new MimeTypeParseException JavaDoc("Sub type is invalid.");
88         }
89         
90     parameters = (MimeTypeParameterList JavaDoc)mtpl.clone();
91     }
92
93     public int hashCode() {
94
95     // We sum up the hash codes for all of the strings. This
96
// way, the order of the strings is irrelevant
97
int code = 0;
98     code += primaryType.hashCode();
99     code += subType.hashCode();
100     code += parameters.hashCode();
101     return code;
102     } // hashCode()
103

104     /**
105      * <code>MimeType</code>s are equal if their primary types,
106      * subtypes, and parameters are all equal. No default values
107      * are taken into account.
108      * @param thatObject the object to be evaluated as a
109      * <code>MimeType</code>
110      * @return <code>true</code> if <code>thatObject</code> is
111      * a <code>MimeType</code>; otherwise returns <code>false</code>
112      */

113     public boolean equals(Object JavaDoc thatObject) {
114     if (!(thatObject instanceof MimeType JavaDoc)) {
115         return false;
116     }
117     MimeType JavaDoc that = (MimeType JavaDoc)thatObject;
118     boolean isIt =
119         ((this.primaryType.equals(that.primaryType)) &&
120          (this.subType.equals(that.subType)) &&
121          (this.parameters.equals(that.parameters)));
122     return isIt;
123     } // equals()
124

125     /**
126      * A routine for parsing the MIME type out of a String.
127      *
128      * @throws NullPointerException if <code>rawdata</code> is null
129      */

130     private void parse(String JavaDoc rawdata) throws MimeTypeParseException JavaDoc {
131         int slashIndex = rawdata.indexOf('/');
132         int semIndex = rawdata.indexOf(';');
133         if((slashIndex < 0) && (semIndex < 0)) {
134             // neither character is present, so treat it
135
// as an error
136
throw new MimeTypeParseException JavaDoc("Unable to find a sub type.");
137         } else if((slashIndex < 0) && (semIndex >= 0)) {
138             // we have a ';' (and therefore a parameter list),
139
// but no '/' indicating a sub type is present
140
throw new MimeTypeParseException JavaDoc("Unable to find a sub type.");
141         } else if((slashIndex >= 0) && (semIndex < 0)) {
142             // we have a primary and sub type but no parameter list
143
primaryType = rawdata.substring(0,
144 slashIndex).trim().toLowerCase();
145             subType = rawdata.substring(slashIndex +
146 1).trim().toLowerCase();
147             parameters = new MimeTypeParameterList JavaDoc();
148         } else if (slashIndex < semIndex) {
149             // we have all three items in the proper sequence
150
primaryType = rawdata.substring(0,
151 slashIndex).trim().toLowerCase();
152             subType = rawdata.substring(slashIndex + 1,
153 semIndex).trim().toLowerCase();
154             parameters = new
155 MimeTypeParameterList JavaDoc(rawdata.substring(semIndex));
156         } else {
157             // we have a ';' lexically before a '/' which means we have a primary type
158
// & a parameter list but no sub type
159
throw new MimeTypeParseException JavaDoc("Unable to find a sub type.");
160         }
161         
162         // now validate the primary and sub types
163

164         // check to see if primary is valid
165
if(!isValidToken(primaryType)) {
166             throw new MimeTypeParseException JavaDoc("Primary type is invalid.");
167         }
168         
169         // check to see if sub is valid
170
if(!isValidToken(subType)) {
171             throw new MimeTypeParseException JavaDoc("Sub type is invalid.");
172         }
173     }
174
175     /**
176      * Retrieve the primary type of this object.
177      */

178     public String JavaDoc getPrimaryType() {
179         return primaryType;
180     }
181
182     /**
183      * Retrieve the sub type of this object.
184      */

185     public String JavaDoc getSubType() {
186         return subType;
187     }
188
189     /**
190      * Retrieve a copy of this object's parameter list.
191      */

192     public MimeTypeParameterList JavaDoc getParameters() {
193     return (MimeTypeParameterList JavaDoc)parameters.clone();
194     }
195
196     /**
197      * Retrieve the value associated with the given name, or null if there
198      * is no current association.
199      */

200     public String JavaDoc getParameter(String JavaDoc name) {
201         return parameters.get(name);
202     }
203
204     /**
205      * Set the value to be associated with the given name, replacing
206      * any previous association.
207      *
208      * @throw IllegalArgumentException if parameter or value is illegal
209      */

210     public void setParameter(String JavaDoc name, String JavaDoc value) {
211         parameters.set(name, value);
212     }
213
214     /**
215      * Remove any value associated with the given name.
216      *
217      * @throw IllegalArgumentExcpetion if parameter may not be deleted
218      */

219     public void removeParameter(String JavaDoc name) {
220         parameters.remove(name);
221     }
222
223     /**
224      * Return the String representation of this object.
225      */

226     public String JavaDoc toString() {
227         return getBaseType() + parameters.toString();
228     }
229
230     /**
231      * Return a String representation of this object
232      * without the parameter list.
233      */

234     public String JavaDoc getBaseType() {
235         return primaryType + "/" + subType;
236     }
237     
238     /**
239      * Returns <code>true</code> if the primary type and the
240      * subtype of this object are the same as the specified
241      * <code>type</code>; otherwise returns <code>false</code>.
242      *
243      * @param type the type to compare to <code>this</code>'s type
244      * @return <code>true</code> if the primary type and the
245      * subtype of this object are the same as the
246      * specified <code>type</code>; otherwise returns
247      * <code>false</code>
248      */

249     public boolean match(MimeType JavaDoc type) {
250     if (type == null)
251             return false;
252         return primaryType.equals(type.getPrimaryType())
253                     && (subType.equals("*")
254                             || type.getSubType().equals("*")
255                             || (subType.equals(type.getSubType())));
256     }
257     
258     /**
259      * Returns <code>true</code> if the primary type and the
260      * subtype of this object are the same as the content type
261      * described in <code>rawdata</code>; otherwise returns
262      * <code>false</code>.
263      *
264      * @param rawdata the raw data to be examined
265      * @return <code>true</code> if the primary type and the
266      * subtype of this object are the same as the content type
267      * described in <code>rawdata</code>; otherwise returns
268      * <code>false</code>; if <code>rawdata</code> is
269      * <code>null</code>, returns <code>false</code>
270      */

271     public boolean match(String JavaDoc rawdata) throws MimeTypeParseException JavaDoc {
272         if (rawdata == null)
273             return false;
274         return match(new MimeType JavaDoc(rawdata));
275     }
276     
277     /**
278      * The object implements the writeExternal method to save its contents
279      * by calling the methods of DataOutput for its primitive values or
280      * calling the writeObject method of ObjectOutput for objects, strings
281      * and arrays.
282      * @exception IOException Includes any I/O exceptions that may occur
283      */

284     public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc {
285         String JavaDoc s = toString(); // contains ASCII chars only
286
// one-to-one correspondence between ASCII char and byte in UTF string
287
if (s.length() <= 65535) { // 65535 is max length of UTF string
288
out.writeUTF(s);
289         } else {
290             out.writeByte(0);
291             out.writeByte(0);
292             out.writeInt(s.length());
293             out.write(s.getBytes());
294         }
295     }
296
297     /**
298      * The object implements the readExternal method to restore its
299      * contents by calling the methods of DataInput for primitive
300      * types and readObject for objects, strings and arrays. The
301      * readExternal method must read the values in the same sequence
302      * and with the same types as were written by writeExternal.
303      * @exception ClassNotFoundException If the class for an object being
304      * restored cannot be found.
305      */

306     public void readExternal(ObjectInput JavaDoc in) throws IOException JavaDoc,
307 ClassNotFoundException JavaDoc {
308         String JavaDoc s = in.readUTF();
309         if (s == null || s.length() == 0) { // long mime type
310
byte[] ba = new byte[in.readInt()];
311             in.readFully(ba);
312             s = new String JavaDoc(ba);
313         }
314         try {
315             parse(s);
316         } catch(MimeTypeParseException JavaDoc e) {
317             throw new IOException JavaDoc(e.toString());
318         }
319     }
320
321     /**
322      * Returns a clone of this object.
323      * @return a clone of this object
324      */

325
326     public Object JavaDoc clone() {
327     MimeType JavaDoc newObj = null;
328     try {
329         newObj = (MimeType JavaDoc)super.clone();
330     } catch (CloneNotSupportedException JavaDoc cannotHappen) {
331     }
332     newObj.parameters = (MimeTypeParameterList JavaDoc)parameters.clone();
333     return newObj;
334     }
335
336     private String JavaDoc primaryType;
337     private String JavaDoc subType;
338     private MimeTypeParameterList JavaDoc parameters;
339     
340     // below here be scary parsing related things
341

342     /**
343      * Determines whether or not a given character belongs to a legal token.
344      */

345     private static boolean isTokenChar(char c) {
346         return ((c > 040) && (c < 0177)) && (TSPECIALS.indexOf(c) < 0);
347     }
348     
349     /**
350      * Determines whether or not a given string is a legal token.
351      *
352      * @throws NullPointerException if <code>s</code> is null
353      */

354     private boolean isValidToken(String JavaDoc s) {
355         int len = s.length();
356         if(len > 0) {
357             for (int i = 0; i < len; ++i) {
358                 char c = s.charAt(i);
359                 if (!isTokenChar(c)) {
360                     return false;
361                 }
362             }
363             return true;
364         } else {
365             return false;
366         }
367     }
368
369     /**
370      * A string that holds all the special chars.
371      */

372
373     private static final String JavaDoc TSPECIALS = "()<>@,;:\\\"/[]?=";
374     
375 } // class MimeType
376
Popular Tags