KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > ristretto > message > MimeHeader


1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Mozilla Public License Version
5  * 1.1 (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11  * for the specific language governing rights and limitations under the
12  * License.
13  *
14  * The Original Code is Ristretto Mail API.
15  *
16  * The Initial Developers of the Original Code are
17  * Timo Stich and Frederik Dietz.
18  * Portions created by the Initial Developers are Copyright (C) 2004
19  * All Rights Reserved.
20  *
21  * Contributor(s):
22  *
23  * Alternatively, the contents of this file may be used under the terms of
24  * either the GNU General Public License Version 2 or later (the "GPL"), or
25  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26  * in which case the provisions of the GPL or the LGPL are applicable instead
27  * of those above. If you wish to allow use of your version of this file only
28  * under the terms of either the GPL or the LGPL, and not to allow others to
29  * use your version of this file under the terms of the MPL, indicate your
30  * decision by deleting the provisions above and replace them with the notice
31  * and other provisions required by the GPL or the LGPL. If you do not delete
32  * the provisions above, a recipient may use your version of this file under
33  * the terms of any one of the MPL, the GPL or the LGPL.
34  *
35  * ***** END LICENSE BLOCK ***** */

36 package org.columba.ristretto.message;
37
38 import java.io.InputStream JavaDoc;
39 import java.nio.charset.Charset JavaDoc;
40 import java.nio.charset.IllegalCharsetNameException JavaDoc;
41 import java.nio.charset.UnsupportedCharsetException JavaDoc;
42 import java.util.regex.Matcher JavaDoc;
43 import java.util.regex.Pattern JavaDoc;
44
45 import org.columba.ristretto.coder.EncodedWord;
46 import org.columba.ristretto.io.Streamable;
47 import org.columba.ristretto.parser.MimeTypeParser;
48 import org.columba.ristretto.parser.ParserException;
49
50 /**
51  * Wrapper around a {@link Header} to convieniently access Mime-Specific header fields.
52  *
53  * @author Timo Stich <tstich@users.sourceforge.net>
54  */

55 public class MimeHeader implements Streamable {
56     
57     /**
58      * Transfer encoding.
59      */

60     public final static int PLAIN = 0; //default
61
/**
62      * Transfer encoding.
63      */

64     public final static int QUOTED_PRINTABLE = 1;
65     /**
66      * Transfer encoding.
67      */

68     public final static int BASE64 = 2;
69     
70     private Header header;
71
72     /**
73      * Constructs a MimeHeader with a new instanciated {@link Header}.
74      * <p>
75      * Sets the {@link MimeType} to "text/plain".
76      *
77      */

78     public MimeHeader() {
79         this(new Header());
80         setMimeType(new MimeType("text","plain"));
81     }
82
83     /**
84      * Constructs a MimeHeader from a {@link Header}
85      *
86      * @param header
87      */

88     public MimeHeader( Header header ) {
89         this.header = header;
90     }
91     
92     /**
93      * Constructs a MimeHeader with a new instanciated {@link Header}.
94      * <p>
95      *
96      * @param type type of the mime-part (e.g. text)
97      * @param subtype subtype of the mime-part (e.g. plain)
98      */

99     public MimeHeader( String JavaDoc type, String JavaDoc subtype ) {
100         this.header = new Header();
101         setMimeType( new MimeType(type, subtype));
102     }
103     
104     /**
105      * Gets the {@link MimeType} of the mime-part.
106      * <p>
107      * Intern the {@link MimeTypeParser} is used to parse the headerfield
108      * "Content-Type" to retrieve the mimetype.
109      *
110      * @return {@link MimeType} of the mime-part
111      */

112     public MimeType getMimeType() {
113         try {
114             return MimeTypeParser.parse( header.get("Content-Type") );
115         } catch (ParserException e) {
116             return new MimeType();
117         }
118     }
119     
120     /**
121      * Gets the mimetype of the mime-part (e.g. text)
122      *
123      * @return mimetype of the mime-part
124      *
125      * @deprecated Use {@link #getMimeType()} instead
126      */

127     public String JavaDoc getContentType() {
128         return getMimeType().getType();
129     }
130
131     /**
132      * Gets the mimesubtype of the mime-part (e.g. plain)
133      *
134      * @return mimesubtype of the mime-part
135      *
136      * @deprecated Use {@link #getMimeType()} instead
137      */

138     public String JavaDoc getContentSubtype() {
139         return getMimeType().getSubtype();
140     }
141
142     /**
143      * Gets the content-disposition of the mime-part.
144      * This can be either "attachment" of "inline". MailClients
145      * may use this information to either display this mime-part
146      * inside the message-body or as a separate attachment
147      * <p>
148      * See RFC2183
149      *
150      * @return content disposition of the mime-part
151      */

152     public String JavaDoc getContentDisposition() {
153         return this.header.get("Content-Disposition");
154     }
155     
156     /**
157      * Gets a content parameter of the mime-part.
158      * This parameter is specified in the "Content-Type" headerfield
159      * e.g. the boundary of a multipart or the charset of a text part
160      * <p>
161      * See RFC2045
162      *
163      * @param key the parameter name (e.g. boundary)
164      * @return the value of the parameter or null if not found
165      */

166     public String JavaDoc getContentParameter(String JavaDoc key) {
167         return getParameter(header.get("Content-Type"), key);
168     }
169
170     /**
171      * Gets the content transfer encoding of the mime-part.
172      * This may be either base64 or quoted-printable.
173      * <p>
174      * See RFC2045 for more information about the encodings.
175      *
176      * @return the content transfer encoding
177      */

178     public int getContentTransferEncoding() {
179         String JavaDoc value = header.get("Content-Transfer-Encoding");
180         if( value != null ) {
181             if( value.equalsIgnoreCase("quoted-printable") ) return QUOTED_PRINTABLE;
182             if( value.equalsIgnoreCase("base64") ) return BASE64;
183         }
184         
185         return PLAIN;
186     }
187
188     /**
189      * Gets the content id of the mime-part.
190      * Content IDs are used to reference to e.g. images that
191      * are attached to the message inside a html message body.
192      * <p>
193      * See RFC2393.
194      *
195      * @return content id of the mime-part
196      */

197     public String JavaDoc getContentID() {
198         String JavaDoc result = header.get("Content-ID");
199         if( result == null ) {
200             return header.get("Content-Id");
201         }
202         return result;
203     }
204
205     /**
206      * Gets the content description of the mime-part.
207      * <p>
208      * See RFC2045
209      *
210      * @return the content description
211      */

212     public String JavaDoc getContentDescription() {
213         return header.get("Content-Description");
214     }
215
216     /**
217      * Gets a parameter of the content disposition of the mime-part.
218      * This might be e.g. a filename.
219      * <p>
220      * See RFC2183
221      *
222      * @param key
223      * @return the disposition parameter
224      */

225     public String JavaDoc getDispositionParameter(String JavaDoc key) {
226         return getParameter(header.get("Content-Disposition"), key);
227     }
228
229     protected String JavaDoc getParameter(String JavaDoc headerLine, String JavaDoc key) {
230         if( headerLine == null) return null;
231         Pattern JavaDoc parameterPattern = Pattern.compile(key + "\\s*=\\s*((\"([^\"]+)\")|([^\r\n\\s;]+))", Pattern.CASE_INSENSITIVE);
232         Matcher JavaDoc matcher = parameterPattern.matcher( headerLine );
233         if( matcher.find() ) {
234             if( matcher.group(3) != null ) {
235                 return matcher.group(3);
236             } else {
237                 return matcher.group(4);
238             }
239         }
240         return null;
241     }
242     
243     protected String JavaDoc appendParameter(String JavaDoc headerLine, String JavaDoc key, String JavaDoc value) {
244         StringBuffer JavaDoc result = new StringBuffer JavaDoc(headerLine);
245         result.ensureCapacity(headerLine.length() + 2 + key.length() + 1 + value.length());
246         result.append("; ");
247         result.append(key);
248         result.append('=');
249         result.append(value);
250         return result.toString();
251     }
252
253     /**
254      * Gets the filename of the mime-part.
255      * Use this method to check both places a filename may
256      * be specified:
257      * <ul>
258      * <li> as the content-type parameter name
259      * <li> as the content-disposition parameter filename
260      * </ul>
261      *
262      *
263      * @return filename of the mime-part
264      */

265     public String JavaDoc getFileName() {
266         String JavaDoc result = null;
267
268         result = getContentParameter("name");
269         if (result != null)
270             return EncodedWord.decode(result).toString();
271
272         result = getDispositionParameter("filename");
273         if (result != null)
274             return EncodedWord.decode(result).toString();
275
276         return result;
277     }
278
279     /**
280      * @see java.lang.Object#toString()
281      */

282     public String JavaDoc toString() {
283         return header.toString();
284     }
285
286     /**
287      * Adds a content parameter to the mime-part.
288      * This parameter is specified in the "Content-Type" headerfield
289      * e.g. the boundary of a multipart or the charset of a text part
290      * <p>
291      * Note: Make sure that you called {@link #setMimeType(MimeType)} <b>before</b>
292      * you call this method, because it will erase all previously added parameters
293      * <p>
294      * See RFC2045
295      *
296      * @param key the parameter name (e.g. boundary)
297      * @param value the value of the parameter
298      */

299     public void putContentParameter(String JavaDoc key, String JavaDoc value) {
300         header.set("Content-Type", appendParameter(header.get("Content-Type") , key, "\"" + value + "\""));
301     }
302
303     /**
304      * Adds a parameter to the content disposition of the mime-part.
305      * This might be e.g. a filename.
306      * <p>
307      * Note: Make sure that you called {@link #setContentDisposition(String)} <b>before</b>
308      * you call this method, because it will erase all previously added parameters
309      * <p>
310      * <p>
311      * See RFC2183
312
313      * @param key
314      * @param value
315      */

316     public void putDispositionParameter(String JavaDoc key, String JavaDoc value) {
317         header.set("Content-Disposition", appendParameter(header.get("Content-Disposition") , key, "\"" + value + "\"" ));
318     }
319     
320     /**
321      * Sets the mime-type of the mime-part.
322      * For text parts of the message this is something like text/plain
323      * or text/html, while an image might be of type image/jpeg.
324      * <p>
325      * See RFC2046 for more mime-types
326      *
327      * @param type {@link MimeType} of the mime-part
328      */

329     public void setMimeType( MimeType type ) {
330         header.set("Content-Type", type.toString());
331     }
332     
333     /**
334      * Sets the content description of the mime-part.
335      * <p>
336      * Note: Make sure that you called this method <b>before</b>
337      * you call {@link #putContentParameter(String,String)}, because it will erase all previously added parameters
338      * <p>
339      * See RFC2045
340      *
341      * @param description of the mime-part
342      */

343     public void setContentDescription( String JavaDoc description ) {
344         header.set("Content-Description", description );
345     }
346     
347     /**
348      * Sets the content-disposition of the mime-part.
349      * This can be either "attachment" of "inline". MailClients
350      * may use this information to either display this mime-part
351      * inside the message-body or as a separate attachment
352      * <p>
353      * Note: Make sure that you called this method <b>before</b>
354      * you call {@link #putDispositionParameter(String,String)}, because it will erase all previously added parameters
355      * <p>
356      * See RFC2183
357      *
358      * @param disposition of the message
359      */

360     public void setContentDisposition( String JavaDoc disposition ) {
361         header.set("Content-Disposition", disposition );
362     }
363
364     /**
365      * Sets the content id of the mime-part.
366      * Content IDs are used to reference to e.g. images that
367      * are attached to the message inside a html message body.
368      * <p>
369      * See RFC2393.
370      *
371      * @param id of the mime-part
372      */

373     public void setContentID( String JavaDoc id) {
374         header.set("Content-ID", id);
375     }
376     
377     /**
378      * Sets the content transfer encoding of the mime-part.
379      * This may be either base64 or quoted-printable.
380      * <p>
381      * See RFC2045 for more information about the encodings.
382      *
383      * @param encoding of the mime-part
384      */

385     public void setContentTransferEncoding(String JavaDoc encoding) {
386         header.set("Content-Transfer-Encoding", encoding);
387     }
388     
389     /**
390      * @return the number of defined Headers.
391      */

392     public int count() {
393         return header.count();
394     }
395
396     /**
397      * Get the Header for the specified key.
398      *
399      * @param key
400      * @return the Header
401      */

402     public String JavaDoc get(String JavaDoc key) {
403         return header.get(key);
404     }
405
406     /**
407      * Set the header with the specified value.
408      *
409      * @param key
410      * @param value
411      */

412     public void set(String JavaDoc key, Object JavaDoc value) {
413         header.set(key, value);
414     }
415     
416     /**
417      * Gets the charset this mime-part is encoded in.
418      * If no charset parameter is found or the charset is not
419      * supported by the VM the default charset of the system
420      * is returned.
421      *
422      * @return {@link Charset} of the mime-part
423      */

424     public Charset JavaDoc getCharset() {
425         String JavaDoc charsetField = getContentParameter("charset");
426
427         if( charsetField != null ) {
428             try {
429                 return Charset.forName( charsetField );
430             } catch ( IllegalCharsetNameException JavaDoc e ) {
431                 return Charset.forName( System.getProperty("file.encoding"));
432             } catch ( UnsupportedCharsetException JavaDoc e ) {
433                 return Charset.forName( System.getProperty("file.encoding"));
434             }
435         } else {
436             return Charset.forName( System.getProperty("file.encoding"));
437         }
438     }
439
440     /**
441      * @return the Header
442      */

443     public Header getHeader() {
444         return header;
445     }
446
447     /**
448      * Set the Header.
449      *
450      * @param header
451      */

452     public void setHeader(Header header) {
453         this.header = header;
454     }
455
456     /**
457      * @see org.columba.ristretto.io.Streamable#getInputStream()
458      */

459     public InputStream JavaDoc getInputStream() {
460         return header.getInputStream();
461     }
462
463 }
464
Popular Tags