• 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      */
85     @Override
writeTo(OutputStream out)86     public void writeTo(OutputStream out) throws IOException {
87         getHeader().writeTo(out);
88 
89         Body body = getBody();
90         if (body instanceof Multipart) {
91             Multipart mp = (Multipart) body;
92             mp.writeTo(out);
93         } else {
94             body.writeTo(out);
95         }
96     }
97 
98 
99     private class MessageBuilder implements ContentHandler {
100         private Stack<Object> stack = new Stack<Object>();
101 
MessageBuilder()102         public MessageBuilder() {
103         }
104 
expect(Class c)105         private void expect(Class c) {
106             if (!c.isInstance(stack.peek())) {
107                 throw new IllegalStateException("Internal stack error: "
108                         + "Expected '" + c.getName() + "' found '"
109                         + stack.peek().getClass().getName() + "'");
110             }
111         }
112 
113         /**
114          * @see org.apache.james.mime4j.ContentHandler#startMessage()
115          */
startMessage()116         public void startMessage() {
117             if (stack.isEmpty()) {
118                 stack.push(Message.this);
119             } else {
120                 expect(Entity.class);
121                 Message m = new Message();
122                 ((Entity) stack.peek()).setBody(m);
123                 stack.push(m);
124             }
125         }
126 
127         /**
128          * @see org.apache.james.mime4j.ContentHandler#endMessage()
129          */
endMessage()130         public void endMessage() {
131             expect(Message.class);
132             stack.pop();
133         }
134 
135         /**
136          * @see org.apache.james.mime4j.ContentHandler#startHeader()
137          */
startHeader()138         public void startHeader() {
139             stack.push(new Header());
140         }
141 
142         /**
143          * @see org.apache.james.mime4j.ContentHandler#field(java.lang.String)
144          */
field(String fieldData)145         public void field(String fieldData) {
146             expect(Header.class);
147             ((Header) stack.peek()).addField(Field.parse(fieldData));
148         }
149 
150         /**
151          * @see org.apache.james.mime4j.ContentHandler#endHeader()
152          */
endHeader()153         public void endHeader() {
154             expect(Header.class);
155             Header h = (Header) stack.pop();
156             expect(Entity.class);
157             ((Entity) stack.peek()).setHeader(h);
158         }
159 
160         /**
161          * @see org.apache.james.mime4j.ContentHandler#startMultipart(org.apache.james.mime4j.BodyDescriptor)
162          */
startMultipart(BodyDescriptor bd)163         public void startMultipart(BodyDescriptor bd) {
164             expect(Entity.class);
165 
166             Entity e = (Entity) stack.peek();
167             Multipart multiPart = new Multipart();
168             e.setBody(multiPart);
169             stack.push(multiPart);
170         }
171 
172         /**
173          * @see org.apache.james.mime4j.ContentHandler#body(org.apache.james.mime4j.BodyDescriptor, java.io.InputStream)
174          */
body(BodyDescriptor bd, InputStream is)175         public void body(BodyDescriptor bd, InputStream is) throws IOException {
176             expect(Entity.class);
177 
178             String enc = bd.getTransferEncoding();
179             if ("base64".equals(enc)) {
180                 is = new Base64InputStream(is);
181             } else if ("quoted-printable".equals(enc)) {
182                 is = new QuotedPrintableInputStream(is);
183             }
184 
185             Body body = null;
186             if (bd.getMimeType().startsWith("text/")) {
187                 body = new MemoryTextBody(is, bd.getCharset());
188             } else {
189                 body = new MemoryBinaryBody(is);
190             }
191 
192             ((Entity) stack.peek()).setBody(body);
193         }
194 
195         /**
196          * @see org.apache.james.mime4j.ContentHandler#endMultipart()
197          */
endMultipart()198         public void endMultipart() {
199             stack.pop();
200         }
201 
202         /**
203          * @see org.apache.james.mime4j.ContentHandler#startBodyPart()
204          */
startBodyPart()205         public void startBodyPart() {
206             expect(Multipart.class);
207 
208             BodyPart bodyPart = new BodyPart();
209             ((Multipart) stack.peek()).addBodyPart(bodyPart);
210             stack.push(bodyPart);
211         }
212 
213         /**
214          * @see org.apache.james.mime4j.ContentHandler#endBodyPart()
215          */
endBodyPart()216         public void endBodyPart() {
217             expect(BodyPart.class);
218             stack.pop();
219         }
220 
221         /**
222          * @see org.apache.james.mime4j.ContentHandler#epilogue(java.io.InputStream)
223          */
epilogue(InputStream is)224         public void epilogue(InputStream is) throws IOException {
225             expect(Multipart.class);
226             StringBuffer sb = new StringBuffer();
227             int b;
228             while ((b = is.read()) != -1) {
229                 sb.append((char) b);
230             }
231             ((Multipart) stack.peek()).setEpilogue(sb.toString());
232         }
233 
234         /**
235          * @see org.apache.james.mime4j.ContentHandler#preamble(java.io.InputStream)
236          */
preamble(InputStream is)237         public void preamble(InputStream is) throws IOException {
238             expect(Multipart.class);
239             StringBuffer sb = new StringBuffer();
240             int b;
241             while ((b = is.read()) != -1) {
242                 sb.append((char) b);
243             }
244             ((Multipart) stack.peek()).setPreamble(sb.toString());
245         }
246 
247         /**
248          * TODO: Implement me
249          *
250          * @see org.apache.james.mime4j.ContentHandler#raw(java.io.InputStream)
251          */
raw(InputStream is)252         public void raw(InputStream is) throws IOException {
253             throw new UnsupportedOperationException("Not supported");
254         }
255 
256     }
257 }
258