KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)MimeTypeParameterList.java 1.15 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.util.Enumeration JavaDoc;
11 import java.util.Hashtable JavaDoc;
12 import java.util.Iterator JavaDoc;
13 import java.util.Map JavaDoc;
14 import java.util.Set JavaDoc;
15
16
17 /**
18  * An object that encapsualtes the parameter list of a MimeType
19  * as defined in RFC 2045 and 2046.
20  *
21  * @version 1.15, 12/19/03
22  * @author jeff.dunn@eng.sun.com
23  */

24 class MimeTypeParameterList implements Cloneable JavaDoc {
25
26     /**
27      * Default constructor.
28      */

29     public MimeTypeParameterList() {
30         parameters = new Hashtable JavaDoc();
31     }
32
33     public MimeTypeParameterList(String JavaDoc rawdata)
34     throws MimeTypeParseException JavaDoc
35     {
36         parameters = new Hashtable JavaDoc();
37         
38         // now parse rawdata
39
parse(rawdata);
40     }
41     
42     public int hashCode() {
43         int code = Integer.MAX_VALUE/45; // "random" value for empty lists
44
String JavaDoc paramName = null;
45         Enumeration JavaDoc enum_ = this.getNames();
46
47         while (enum_.hasMoreElements()) {
48             paramName = (String JavaDoc)enum_.nextElement();
49             code += paramName.hashCode();
50             code += this.get(paramName).hashCode();
51         }
52
53         return code;
54     } // hashCode()
55

56     /**
57      * Two parameter lists are considered equal if they have exactly
58      * the same set of parameter names and associated values. The
59      * order of the parameters is not considered.
60      */

61     public boolean equals(Object JavaDoc thatObject) {
62     //System.out.println("MimeTypeParameterList.equals("+this+","+thatObject+")");
63
if (!(thatObject instanceof MimeTypeParameterList JavaDoc)) {
64         return false;
65     }
66     MimeTypeParameterList JavaDoc that = (MimeTypeParameterList JavaDoc)thatObject;
67     if (this.size() != that.size()) {
68         return false;
69     }
70     String JavaDoc name = null;
71     String JavaDoc thisValue = null;
72     String JavaDoc thatValue = null;
73     Set JavaDoc entries = parameters.entrySet();
74     Iterator JavaDoc iterator = entries.iterator();
75     Map.Entry JavaDoc entry = null;
76     while (iterator.hasNext()) {
77         entry = (Map.Entry JavaDoc)iterator.next();
78         name = (String JavaDoc)entry.getKey();
79         thisValue = (String JavaDoc)entry.getValue();
80         thatValue = (String JavaDoc)that.parameters.get(name);
81         if ((thisValue == null) || (thatValue == null)) {
82         // both null -> equal, only one null -> not equal
83
if (thisValue != thatValue) {
84             return false;
85         }
86         } else if (!thisValue.equals(thatValue)) {
87             return false;
88         }
89     } // while iterator
90

91     return true;
92     } // equals()
93

94     /**
95      * A routine for parsing the parameter list out of a String.
96      */

97     protected void parse(String JavaDoc rawdata) throws MimeTypeParseException JavaDoc {
98         int length = rawdata.length();
99         if(length > 0) {
100             int currentIndex = skipWhiteSpace(rawdata, 0);
101             int lastIndex = 0;
102             
103             if(currentIndex < length) {
104                 char currentChar = rawdata.charAt(currentIndex);
105                 while ((currentIndex < length) && (currentChar == ';')) {
106                     String JavaDoc name;
107                     String JavaDoc value;
108                     boolean foundit;
109                     
110                     // eat the ';'
111
++currentIndex;
112                     
113                     // now parse the parameter name
114

115                     // skip whitespace
116
currentIndex = skipWhiteSpace(rawdata, currentIndex);
117                     
118                     if(currentIndex < length) {
119                         // find the end of the token char run
120
lastIndex = currentIndex;
121                         currentChar = rawdata.charAt(currentIndex);
122                         while((currentIndex < length) && isTokenChar(currentChar)) {
123                             ++currentIndex;
124                             currentChar = rawdata.charAt(currentIndex);
125                         }
126                         name = rawdata.substring(lastIndex, currentIndex).toLowerCase();
127                         
128                         // now parse the '=' that separates the name from the value
129

130                         // skip whitespace
131
currentIndex = skipWhiteSpace(rawdata, currentIndex);
132                         
133                         if((currentIndex < length) && (rawdata.charAt(currentIndex) == '=')) {
134                             // eat it and parse the parameter value
135
++currentIndex;
136                             
137                             // skip whitespace
138
currentIndex = skipWhiteSpace(rawdata, currentIndex);
139                             
140                             if(currentIndex < length) {
141                                 // now find out whether or not we have a quoted value
142
currentChar = rawdata.charAt(currentIndex);
143                                 if(currentChar == '"') {
144                                     // yup it's quoted so eat it and capture the quoted string
145
++currentIndex;
146                                     lastIndex = currentIndex;
147                                     
148                                     if(currentIndex < length) {
149                                         // find the next unescqped quote
150
foundit = false;
151                                         while((currentIndex < length) && !foundit) {
152                                             currentChar = rawdata.charAt(currentIndex);
153                                             if(currentChar == '\\') {
154                                                 // found an escape sequence so pass this and the next character
155
currentIndex += 2;
156                                             } else if(currentChar == '"') {
157                                                 // foundit!
158
foundit = true;
159                                             } else {
160                                                 ++currentIndex;
161                                             }
162                                         }
163                                         if(currentChar == '"') {
164                                             value = unquote(rawdata.substring(lastIndex, currentIndex));
165                                             // eat the quote
166
++currentIndex;
167                                         } else {
168                                             throw new MimeTypeParseException JavaDoc("Encountered unterminated quoted parameter value.");
169                                         }
170                                     } else {
171                                         throw new MimeTypeParseException JavaDoc("Encountered unterminated quoted parameter value.");
172                                     }
173                                 } else if(isTokenChar(currentChar)) {
174                                     // nope it's an ordinary token so it ends with a non-token char
175
lastIndex = currentIndex;
176                                     foundit = false;
177                                     while((currentIndex < length) && !foundit) {
178                                         currentChar = rawdata.charAt(currentIndex);
179                                         
180                                         if(isTokenChar(currentChar)) {
181                                             ++currentIndex;
182                                         } else {
183                                             foundit = true;
184                                         }
185                                     }
186                                     value = rawdata.substring(lastIndex, currentIndex);
187                                 } else {
188                                     // it ain't a value
189
throw new MimeTypeParseException JavaDoc("Unexpected character encountered at index " + currentIndex);
190                                 }
191                                 
192                                 // now put the data into the hashtable
193
parameters.put(name, value);
194                             } else {
195                                 throw new MimeTypeParseException JavaDoc("Couldn't find a value for parameter named " + name);
196                             }
197                         } else {
198                             throw new MimeTypeParseException JavaDoc("Couldn't find the '=' that separates a parameter name from its value.");
199                         }
200                     } else {
201                         throw new MimeTypeParseException JavaDoc("Couldn't find parameter name");
202                     }
203                     
204                     // setup the next iteration
205
currentIndex = skipWhiteSpace(rawdata, currentIndex);
206                     if(currentIndex < length) {
207                         currentChar = rawdata.charAt(currentIndex);
208                     }
209                 }
210                 if(currentIndex < length) {
211                     throw new MimeTypeParseException JavaDoc("More characters encountered in input than expected.");
212                 }
213             }
214         }
215     }
216
217     /**
218      * return the number of name-value pairs in this list.
219      */

220     public int size() {
221         return parameters.size();
222     }
223
224     /**
225      * Determine whether or not this list is empty.
226      */

227     public boolean isEmpty() {
228         return parameters.isEmpty();
229     }
230
231     /**
232      * Retrieve the value associated with the given name, or null if there
233      * is no current association.
234      */

235     public String JavaDoc get(String JavaDoc name) {
236         return (String JavaDoc)parameters.get(name.trim().toLowerCase());
237     }
238
239     /**
240      * Set the value to be associated with the given name, replacing
241      * any previous association.
242      */

243     public void set(String JavaDoc name, String JavaDoc value) {
244         parameters.put(name.trim().toLowerCase(), value);
245     }
246
247     /**
248      * Remove any value associated with the given name.
249      */

250     public void remove(String JavaDoc name) {
251         parameters.remove(name.trim().toLowerCase());
252     }
253
254     /**
255      * Retrieve an enumeration of all the names in this list.
256      */

257     public Enumeration JavaDoc getNames() {
258         return parameters.keys();
259     }
260
261     public String JavaDoc toString() {
262         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
263         buffer.ensureCapacity(parameters.size() * 16); // heuristic: 8 characters per field
264

265         Enumeration JavaDoc keys = parameters.keys();
266         while(keys.hasMoreElements())
267         {
268             buffer.append("; ");
269             
270             String JavaDoc key = (String JavaDoc)keys.nextElement();
271             buffer.append(key);
272             buffer.append('=');
273                buffer.append(quote((String JavaDoc)parameters.get(key)));
274         }
275         
276         return buffer.toString();
277     }
278
279     /**
280      * @return a clone of this object
281      */

282
283      public Object JavaDoc clone() {
284      MimeTypeParameterList JavaDoc newObj = null;
285      try {
286          newObj = (MimeTypeParameterList JavaDoc)super.clone();
287      } catch (CloneNotSupportedException JavaDoc cannotHappen) {
288      }
289      newObj.parameters = (Hashtable JavaDoc)parameters.clone();
290      return newObj;
291      }
292
293     private Hashtable JavaDoc parameters;
294     
295     // below here be scary parsing related things
296

297     /**
298      * Determine whether or not a given character belongs to a legal token.
299      */

300     private static boolean isTokenChar(char c) {
301         return ((c > 040) && (c < 0177)) && (TSPECIALS.indexOf(c) < 0);
302     }
303
304     /**
305      * return the index of the first non white space character in
306      * rawdata at or after index i.
307      */

308     private static int skipWhiteSpace(String JavaDoc rawdata, int i) {
309         int length = rawdata.length();
310         if (i < length) {
311             char c = rawdata.charAt(i);
312             while ((i < length) && Character.isWhitespace(c)) {
313                 ++i;
314                 c = rawdata.charAt(i);
315             }
316         }
317         
318         return i;
319     }
320     
321     /**
322      * A routine that knows how and when to quote and escape the given value.
323      */

324     private static String JavaDoc quote(String JavaDoc value) {
325         boolean needsQuotes = false;
326         
327         // check to see if we actually have to quote this thing
328
int length = value.length();
329         for(int i = 0; (i < length) && !needsQuotes; ++i) {
330             needsQuotes = !isTokenChar(value.charAt(i));
331         }
332         
333         if(needsQuotes) {
334             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
335             buffer.ensureCapacity((int)(length * 1.5));
336             
337             // add the initial quote
338
buffer.append('"');
339             
340             // add the properly escaped text
341
for(int i = 0; i < length; ++i) {
342                 char c = value.charAt(i);
343                 if((c == '\\') || (c == '"')) {
344                     buffer.append('\\');
345                 }
346                 buffer.append(c);
347             }
348             
349             // add the closing quote
350
buffer.append('"');
351             
352             return buffer.toString();
353         }
354         else
355         {
356             return value;
357         }
358     }
359     
360     /**
361      * A routine that knows how to strip the quotes and escape sequences from the given value.
362      */

363     private static String JavaDoc unquote(String JavaDoc value) {
364         int valueLength = value.length();
365         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
366         buffer.ensureCapacity(valueLength);
367         
368         boolean escaped = false;
369         for(int i = 0; i < valueLength; ++i) {
370             char currentChar = value.charAt(i);
371             if(!escaped && (currentChar != '\\')) {
372                 buffer.append(currentChar);
373             } else if(escaped) {
374                 buffer.append(currentChar);
375                 escaped = false;
376             } else {
377                 escaped = true;
378             }
379         }
380         
381         return buffer.toString();
382     }
383     
384     /**
385      * A string that holds all the special chars.
386      */

387     private static final String JavaDoc TSPECIALS = "()<>@,;:\\\"/[]?=";
388
389 }
390
Popular Tags