• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one   *
3  * or more contributor license agreements.  See the NOTICE file *
4  * distributed with this work for additional information        *
5  * regarding copyright ownership.  The ASF licenses this file   *
6  * to you under the Apache License, Version 2.0 (the            *
7  * "License"); you may not use this file except in compliance   *
8  * with the License.  You may obtain a copy of the License at   *
9  *                                                              *
10  *   http://www.apache.org/licenses/LICENSE-2.0                 *
11  *                                                              *
12  * Unless required by applicable law or agreed to in writing,   *
13  * software distributed under the License is distributed on an  *
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15  * KIND, either express or implied.  See the License for the    *
16  * specific language governing permissions and limitations      *
17  * under the License.                                           *
18  ****************************************************************/
19 
20 package org.apache.james.mime4j.message;
21 
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.util.Stack;
26 
27 import org.apache.james.mime4j.BodyDescriptor;
28 import org.apache.james.mime4j.ContentHandler;
29 import org.apache.james.mime4j.MimeStreamParser;
30 import org.apache.james.mime4j.decoder.Base64InputStream;
31 import org.apache.james.mime4j.decoder.QuotedPrintableInputStream;
32 import org.apache.james.mime4j.field.Field;
33 import org.apache.james.mime4j.field.UnstructuredField;
34 
35 
36 /**
37  * Represents a MIME message. The following code parses a stream into a
38  * <code>Message</code> object.
39  *
40  * <pre>
41  *      Message msg = new Message(new BufferedInputStream(
42  *                                      new FileInputStream("mime.msg")));
43  * </pre>
44  *
45  *
46  *
47  * @version $Id: Message.java,v 1.3 2004/10/02 12:41:11 ntherning Exp $
48  */
49 public class Message extends Entity implements Body {
50 
51     /**
52      * Creates a new empty <code>Message</code>.
53      */
Message()54     public Message() {
55     }
56 
57     /**
58      * Parses the specified MIME message stream into a <code>Message</code>
59      * instance.
60      *
61      * @param is the stream to parse.
62      * @throws IOException on I/O errors.
63      */
Message(InputStream is)64     public Message(InputStream is) throws IOException {
65         MimeStreamParser parser = new MimeStreamParser();
66         parser.setContentHandler(new MessageBuilder());
67         parser.parse(is);
68     }
69 
70 
71     /**
72      * Gets the <code>Subject</code> field.
73      *
74      * @return the <code>Subject</code> field or <code>null</code> if it
75      *         doesn't exist.
76      */
getSubject()77     public UnstructuredField getSubject() {
78         return (UnstructuredField) getHeader().getField(Field.SUBJECT);
79     }
80 
81     /**
82      *
83      * @see org.apache.james.mime4j.message.Entity#writeTo(java.io.OutputStream)
84      */
writeTo(OutputStream out)85     public void writeTo(OutputStream out) throws IOException {
86         getHeader().writeTo(out);
87 
88         Body body = getBody();
89         if (body instanceof Multipart) {
90             Multipart mp = (Multipart) body;
91             mp.writeTo(out);
92         } else {
93             body.writeTo(out);
94         }
95     }
96 
97 
98     private class MessageBuilder implements ContentHandler {
99         private Stack stack = new Stack();
100 
MessageBuilder()101         public MessageBuilder() {
102         }
103 
expect(Class c)104         private void expect(Class c) {
105             if (!c.isInstance(stack.peek())) {
106                 throw new IllegalStateException("Internal stack error: "
107                         + "Expected '" + c.getName() + "' found '"
108                         + stack.peek().getClass().getName() + "'");
109             }
110         }
111 
112         /**
113          * @see org.apache.james.mime4j.ContentHandler#startMessage()
114          */
startMessage()115         public void startMessage() {
116             if (stack.isEmpty()) {
117                 stack.push(Message.this);
118             } else {
119                 expect(Entity.class);
120                 Message m = new Message();
121                 ((Entity) stack.peek()).setBody(m);
122                 stack.push(m);
123             }
124         }
125 
126         /**
127          * @see org.apache.james.mime4j.ContentHandler#endMessage()
128          */
endMessage()129         public void endMessage() {
130             expect(Message.class);
131             stack.pop();
132         }
133 
134         /**
135          * @see org.apache.james.mime4j.ContentHandler#startHeader()
136          */
startHeader()137         public void startHeader() {
138             stack.push(new Header());
139         }
140 
141         /**
142          * @see org.apache.james.mime4j.ContentHandler#field(java.lang.String)
143          */
field(String fieldData)144         public void field(String fieldData) {
145             expect(Header.class);
146             ((Header) stack.peek()).addField(Field.parse(fieldData));
147         }
148 
149         /**
150          * @see org.apache.james.mime4j.ContentHandler#endHeader()
151          */
endHeader()152         public void endHeader() {
153             expect(Header.class);
154             Header h = (Header) stack.pop();
155             expect(Entity.class);
156             ((Entity) stack.peek()).setHeader(h);
157         }
158 
159         /**
160          * @see org.apache.james.mime4j.ContentHandler#startMultipart(org.apache.james.mime4j.BodyDescriptor)
161          */
startMultipart(BodyDescriptor bd)162         public void startMultipart(BodyDescriptor bd) {
163             expect(Entity.class);
164 
165             Entity e = (Entity) stack.peek();
166             Multipart multiPart = new Multipart();
167             e.setBody(multiPart);
168             stack.push(multiPart);
169         }
170 
171         /**
172          * @see org.apache.james.mime4j.ContentHandler#body(org.apache.james.mime4j.BodyDescriptor, java.io.InputStream)
173          */
body(BodyDescriptor bd, InputStream is)174         public void body(BodyDescriptor bd, InputStream is) throws IOException {
175             expect(Entity.class);
176 
177             String enc = bd.getTransferEncoding();
178             if ("base64".equals(enc)) {
179                 is = new Base64InputStream(is);
180             } else if ("quoted-printable".equals(enc)) {
181                 is = new QuotedPrintableInputStream(is);
182             }
183 
184             Body body = null;
185             if (bd.getMimeType().startsWith("text/")) {
186                 body = new MemoryTextBody(is, bd.getCharset());
187             } else {
188                 body = new MemoryBinaryBody(is);
189             }
190 
191             ((Entity) stack.peek()).setBody(body);
192         }
193 
194         /**
195          * @see org.apache.james.mime4j.ContentHandler#endMultipart()
196          */
endMultipart()197         public void endMultipart() {
198             stack.pop();
199         }
200 
201         /**
202          * @see org.apache.james.mime4j.ContentHandler#startBodyPart()
203          */
startBodyPart()204         public void startBodyPart() {
205             expect(Multipart.class);
206 
207             BodyPart bodyPart = new BodyPart();
208             ((Multipart) stack.peek()).addBodyPart(bodyPart);
209             stack.push(bodyPart);
210         }
211 
212         /**
213          * @see org.apache.james.mime4j.ContentHandler#endBodyPart()
214          */
endBodyPart()215         public void endBodyPart() {
216             expect(BodyPart.class);
217             stack.pop();
218         }
219 
220         /**
221          * @see org.apache.james.mime4j.ContentHandler#epilogue(java.io.InputStream)
222          */
epilogue(InputStream is)223         public void epilogue(InputStream is) throws IOException {
224             expect(Multipart.class);
225             StringBuffer sb = new StringBuffer();
226             int b;
227             while ((b = is.read()) != -1) {
228                 sb.append((char) b);
229             }
230             ((Multipart) stack.peek()).setEpilogue(sb.toString());
231         }
232 
233         /**
234          * @see org.apache.james.mime4j.ContentHandler#preamble(java.io.InputStream)
235          */
preamble(InputStream is)236         public void preamble(InputStream is) throws IOException {
237             expect(Multipart.class);
238             StringBuffer sb = new StringBuffer();
239             int b;
240             while ((b = is.read()) != -1) {
241                 sb.append((char) b);
242             }
243             ((Multipart) stack.peek()).setPreamble(sb.toString());
244         }
245 
246         /**
247          * TODO: Implement me
248          *
249          * @see org.apache.james.mime4j.ContentHandler#raw(java.io.InputStream)
250          */
raw(InputStream is)251         public void raw(InputStream is) throws IOException {
252             throw new UnsupportedOperationException("Not supported");
253         }
254 
255     }
256 }
257