KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lutris > mime > MimeHeader


1
2 /*
3  * Enhydra Java Application Server Project
4  *
5  * The contents of this file are subject to the Enhydra Public License
6  * Version 1.1 (the "License"); you may not use this file except in
7  * compliance with the License. You may obtain a copy of the License on
8  * the Enhydra web site ( http://www.enhydra.org/ ).
9  *
10  * Software distributed under the License is distributed on an "AS IS"
11  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
12  * the License for the specific terms governing rights and limitations
13  * under the License.
14  *
15  * The Initial Developer of the Enhydra Application Server is Lutris
16  * Technologies, Inc. The Enhydra Application Server and portions created
17  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
18  * All Rights Reserved.
19  *
20  * Contributor(s):
21  *
22  * $Id: MimeHeader.java,v 1.2 2005/03/24 10:51:25 slobodan Exp $
23  */

24
25
26
27
28 package com.lutris.mime;
29 import java.io.IOException JavaDoc;
30 import java.io.PushbackReader JavaDoc;
31 import java.io.StringReader JavaDoc;
32 import java.util.Enumeration JavaDoc;
33 import java.util.Hashtable JavaDoc;
34
35 /**
36  * Represents a generic parsed Mime header. Specific header types, such
37  * as <code>Content-Type</code> are represented by classes derived from
38  * this header. The constructor for this class parses only parameters
39  * according to the rules specified in RFC2045 Section 5.1 Page 11.
40  * It is left to derived classes to parse type-specifiec information
41  * such as the Mime type (<code>Content-Type</code>) or content disposition
42  * (<code>Content-Disposition</code>).
43  */

44 public class MimeHeader {
45     /**
46      * Contains the parsed parameters for this hash table.
47      */

48     private Hashtable JavaDoc myParams;
49     
50     /**
51      * Contains the type-independent value (if any) for the header.
52      */

53     private String JavaDoc myValue;
54     
55     /**
56      * Contains the Mime header type value, defined as the characters
57      * before the first colon (':') character.
58      */

59     private String JavaDoc myHeaderType;
60     
61     /**
62      * The raw, unparsed header line passed to the constructor.
63      */

64     private String JavaDoc rawHeaderLine;
65     
66     /**
67      * Constructs a generic <code>MimeHeader</code> object and initializes
68      * its internal parameter list.
69      */

70     public
71     MimeHeader(String JavaDoc headerLine)
72     {
73     myParams = new Hashtable JavaDoc();
74     rawHeaderLine = headerLine;
75     int pos = headerLine.indexOf(':');
76     if (pos < 0) {
77         myHeaderType = null;
78     } else {
79         myHeaderType = headerLine.substring(0, pos).trim().toLowerCase();
80         headerLine = headerLine.substring(pos+1);
81     }
82     pos = headerLine.indexOf(';');
83     if (pos < 0) {
84         // Handle potential comment.
85
pos = headerLine.indexOf('(');
86         if (pos < 0) {
87         myValue = headerLine.trim();
88         } else {
89         myValue = headerLine.substring(0, pos).trim();
90         }
91     } else {
92         myValue = headerLine.substring(0, pos).trim();
93     }
94     }
95     
96     /**
97      * Used by derived classes to put a parameter into the internal
98      * parameter value holder.
99      *
100      * @param name The name of the parameter value to add.
101      * @param value The value to add.
102      */

103     protected
104     void putParameter(String JavaDoc name, String JavaDoc value)
105     {
106     name = name.toLowerCase();
107     String JavaDoc[] oldvals = (String JavaDoc[]) myParams.get(name);
108     int num = oldvals == null ? 0 : oldvals.length;
109     String JavaDoc[] newvals = new String JavaDoc[num+1];
110     for (int i=0; i < num; i++) {
111         newvals[i] = oldvals[i];
112         oldvals[i] = null;
113     }
114     newvals[num] = value;
115     oldvals = null;
116     myParams.put(name, newvals);
117     }
118     
119     /**
120      * Returns the "value" of this header. This is defined to be the
121      * trimmed substring between the first colon (':') character and
122      * the first semicolon (';') character. For example, observe the
123      * following header line:
124      * <PRE>
125      * Content-Type: multipart/form-data; boundary="000572A9AD4"
126      * </PRE>
127      * The <b>value</b> of this header is <i>multipart/form-data</i>,
128      * the <b>header type</b> is <i>Content-Type</i>, and the first
129      * <b>parameter</b> is named <i>boundary</i> and has the value
130      * <i>00572A9AD4</i>.
131      *
132      * @return The <b>value</b> of this Mime header.
133      */

134     public
135     String JavaDoc getValue()
136     {
137     return myValue;
138     }
139     
140     /**
141      * Returns the <b>header type</b> of this header. This is defined to
142      * be the substring from the first character up to first colon (':')
143      * character. For example, observe the following header line:
144      * <PRE>
145      * Content-Type: multipart/form-data; boundary="000572A9AD4"
146      * </PRE>
147      * The <b>value</b> of this header is <i>multipart/form-data</i>,
148      * the <b>header type</b> is <i>Content-Type</i>, and the first
149      * <b>parameter</b> is named <i>boundary</i> and has the value
150      * <i>00572A9AD4</i>.
151      *
152      * @return The <b>header type</b> of this Mime header.
153      */

154     public
155     String JavaDoc getHeaderType()
156     {
157     return myHeaderType;
158     }
159     
160     /**
161      * Returns the string passed to the constructor without any parsing.
162      *
163      * @returns The unparsed Mime header line in its entirety.
164      */

165     public
166     String JavaDoc getRawHeaderLine()
167     {
168     return rawHeaderLine;
169     }
170
171     /**
172      * Returns a single <code>String</code> value representing the
173      * last occurence of the <b>parameter</b> named by <code>name</code>.
174      * For example, observe the following header line:
175      * <PRE>
176      * Content-Type: multipart/form-data; boundary="000572A9AD4"
177      * </PRE>
178      * The <b>value</b> of this header is <i>multipart/form-data</i>,
179      * the <b>header type</b> is <i>Content-Type</i>, and the first
180      * <b>parameter</b> is named <i>boundary</i> and has the value
181      * <i>00572A9AD4</i>.
182      *
183      * @param name The name of the <b>parameter</b> to return.
184      * @return The value of the last occurence of the named
185      * <b>parameter</b> or <code>null</code> if not found.
186      */

187     public
188     String JavaDoc getParameter(String JavaDoc name)
189     {
190     name = name.toLowerCase();
191     String JavaDoc[] vals = (String JavaDoc[]) myParams.get(name);
192     if (vals == null) return null;
193     if (vals.length < 1) return null;
194     return vals[vals.length - 1];
195     }
196     
197     /**
198      * Returns an array of <code>String</code> containing all occurences
199      * of values named by <code>name</code>.
200      * For example, observe the following header line:
201      * <PRE>
202      * Content-Type: multipart/form-data; boundary="000572A9AD4"
203      * </PRE>
204      * The <b>value</b> of this header is <i>multipart/form-data</i>,
205      * the <b>header type</b> is <i>Content-Type</i>, and the first
206      * <b>parameter</b> is named <i>boundary</i> and has the value
207      * <i>00572A9AD4</i>.
208      *
209      * @param name The name of the <b>parameter</b> to return.
210      * @return Array containing all values for the named
211      * <b>parameter</b> or <code>null</code> if not found.
212      */

213     public String JavaDoc[] getParameters(String JavaDoc name)
214     {
215     name = name.toLowerCase();
216     String JavaDoc[] vals = (String JavaDoc[]) myParams.get(name);
217     if (vals == null) return null;
218     if (vals.length < 1) return null;
219     return vals;
220     }
221     
222     /**
223      * Returns an enumeration of all of the parameter names parsed from
224      * the current Mime header.
225      *
226      * @return An enumeration of the names of all parameters parsed from
227      * the Mime header.
228      */

229     public Enumeration JavaDoc getParameterNames()
230     {
231     return myParams.keys();
232     }
233     
234     private static
235     void skipComment(PushbackReader JavaDoc input)
236     throws IOException JavaDoc
237     {
238     int ch;
239     while ((ch = input.read()) >= 0) if (ch == ')') return;
240     }
241     
242     private final
243     String JavaDoc parseToken(PushbackReader JavaDoc input, boolean trim)
244     throws IOException JavaDoc
245     {
246     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
247     int ch;
248     if (trim) {
249         while ((ch = input.read()) >= 0) if ((ch > ' ') && (ch < 0xff)) {
250         input.unread(ch);
251         if (ch == '(') {
252             skipComment(input);
253         }
254         else
255             break;
256         }
257     }
258         while ((ch = input.read()) >= 0) {
259         switch (ch) {
260         case '=': case ';':
261             input.unread(ch);
262             return buf.toString();
263         case '(':
264             skipComment(input);
265             break;
266         default:
267             if ((ch > ' ') && (ch < 0xff))
268             buf.append((char)ch);
269             else {
270             input.unread(ch);
271             return buf.toString();
272             }
273             break;
274         }
275     }
276     return buf.toString();
277     }
278     
279     private final
280     String JavaDoc parseQuotedString(PushbackReader JavaDoc input)
281     throws IOException JavaDoc
282     {
283     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
284     int ch;
285         while ((ch = input.read()) >= 0) {
286         switch (ch) {
287         case '"':
288             return buf.toString();
289             
290         case '\\':
291             if ((ch = input.read()) >= 0) {
292                 if ((ch!='\\')&&(ch!='"')) {
293                     buf.append('\\');
294                 }
295                 buf.append((char)ch);
296             } else {
297                 buf.append('\\');
298             return buf.toString();
299             }
300             break;
301             
302         default:
303             buf.append((char)ch);
304             break;
305         }
306     }
307     return buf.toString();
308     }
309     
310     /**
311      * Parses the a given string into <i>key=parameter</i> pairs in
312      * accordance with RFC2045 Section 5.1 Page 11. Quoted strings
313      * are parsed in accordance with the RFC822 definition of the
314      * "<code>quoted-string</code>" grammatic construct. According
315      * to RFC822, quoted strings are strings, enclosed in double-quote
316      * marks, which contain any character except LF or double-quote.
317      * The backslash character is used to literally quote the following
318      * character. Octal or hex code backquoting is not supported.
319      */

320     protected
321     void parseParameters(String JavaDoc headerLine)
322     {
323     try {
324         StringReader JavaDoc reader = new StringReader JavaDoc(headerLine);
325         PushbackReader JavaDoc input = new PushbackReader JavaDoc(reader);
326         int ch;
327         String JavaDoc key, value;
328         while (true) {
329             key = parseToken(input, true);
330         ch = input.read();
331         if (ch < 0) break;
332         switch (ch) {
333             case '=':
334             switch (ch = input.read()) {
335                 case '"':
336                 value = parseQuotedString(input);
337                 if (key.length() > 0) {
338                     putParameter(key, value);
339                 }
340                 break;
341                 default:
342                 input.unread(ch);
343                 value = parseToken(input, false);
344                 if (key.length() > 0) {
345                     putParameter(key, value);
346                 }
347                 break;
348             }
349             while (((ch = input.read()) >= 0) && (ch != ';')) {
350                 if (ch == '(') {
351                 skipComment(input);
352                 }
353             }
354             break;
355             case ';':
356             // Not a key=value pair.
357
break;
358             default:
359             // Garbled input.
360
return;
361         } // outer switch
362
} // outer while
363
return;
364     }
365     catch (IOException JavaDoc e) {
366         return;
367     }
368     }
369 }
370
371
Popular Tags