1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.james.mime4j.message;
21
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.util.Stack;
25
26 import org.apache.james.mime4j.MimeException;
27 import org.apache.james.mime4j.codec.Base64InputStream;
28 import org.apache.james.mime4j.codec.QuotedPrintableInputStream;
29 import org.apache.james.mime4j.descriptor.BodyDescriptor;
30 import org.apache.james.mime4j.field.AbstractField;
31 import org.apache.james.mime4j.parser.ContentHandler;
32 import org.apache.james.mime4j.parser.Field;
33 import org.apache.james.mime4j.parser.MimeStreamParser;
34 import org.apache.james.mime4j.storage.StorageProvider;
35 import org.apache.james.mime4j.util.ByteArrayBuffer;
36 import org.apache.james.mime4j.util.ByteSequence;
37 import org.apache.james.mime4j.util.MimeUtil;
38
39
40
41
42
43 public class MessageBuilder implements ContentHandler {
44
45 private final Entity entity;
46 private final BodyFactory bodyFactory;
47 private Stack<Object> stack = new Stack<Object>();
48
49 public MessageBuilder(Entity entity) {
50 this.entity = entity;
51 this.bodyFactory = new BodyFactory();
52 }
53
54 public MessageBuilder(Entity entity, StorageProvider storageProvider) {
55 this.entity = entity;
56 this.bodyFactory = new BodyFactory(storageProvider);
57 }
58
59 private void expect(Class<?> c) {
60 if (!c.isInstance(stack.peek())) {
61 throw new IllegalStateException("Internal stack error: "
62 + "Expected '" + c.getName() + "' found '"
63 + stack.peek().getClass().getName() + "'");
64 }
65 }
66
67
68
69
70 public void startMessage() throws MimeException {
71 if (stack.isEmpty()) {
72 stack.push(this.entity);
73 } else {
74 expect(Entity.class);
75 Message m = new Message();
76 ((Entity) stack.peek()).setBody(m);
77 stack.push(m);
78 }
79 }
80
81
82
83
84 public void endMessage() throws MimeException {
85 expect(Message.class);
86 stack.pop();
87 }
88
89
90
91
92 public void startHeader() throws MimeException {
93 stack.push(new Header());
94 }
95
96
97
98
99 public void field(Field field) throws MimeException {
100 expect(Header.class);
101 Field parsedField = AbstractField.parse(field.getRaw());
102 ((Header) stack.peek()).addField(parsedField);
103 }
104
105
106
107
108 public void endHeader() throws MimeException {
109 expect(Header.class);
110 Header h = (Header) stack.pop();
111 expect(Entity.class);
112 ((Entity) stack.peek()).setHeader(h);
113 }
114
115
116
117
118 public void startMultipart(final BodyDescriptor bd) throws MimeException {
119 expect(Entity.class);
120
121 final Entity e = (Entity) stack.peek();
122 final String subType = bd.getSubType();
123 final Multipart multiPart = new Multipart(subType);
124 e.setBody(multiPart);
125 stack.push(multiPart);
126 }
127
128
129
130
131 public void body(BodyDescriptor bd, final InputStream is) throws MimeException, IOException {
132 expect(Entity.class);
133
134 final String enc = bd.getTransferEncoding();
135
136 final Body body;
137
138 final InputStream decodedStream;
139 if (MimeUtil.ENC_BASE64.equals(enc)) {
140 decodedStream = new Base64InputStream(is);
141 } else if (MimeUtil.ENC_QUOTED_PRINTABLE.equals(enc)) {
142 decodedStream = new QuotedPrintableInputStream(is);
143 } else {
144 decodedStream = is;
145 }
146
147 if (bd.getMimeType().startsWith("text/")) {
148 body = bodyFactory.textBody(decodedStream, bd.getCharset());
149 } else {
150 body = bodyFactory.binaryBody(decodedStream);
151 }
152
153 Entity entity = ((Entity) stack.peek());
154 entity.setBody(body);
155 }
156
157
158
159
160 public void endMultipart() throws MimeException {
161 stack.pop();
162 }
163
164
165
166
167 public void startBodyPart() throws MimeException {
168 expect(Multipart.class);
169
170 BodyPart bodyPart = new BodyPart();
171 ((Multipart) stack.peek()).addBodyPart(bodyPart);
172 stack.push(bodyPart);
173 }
174
175
176
177
178 public void endBodyPart() throws MimeException {
179 expect(BodyPart.class);
180 stack.pop();
181 }
182
183
184
185
186 public void epilogue(InputStream is) throws MimeException, IOException {
187 expect(Multipart.class);
188 ByteSequence bytes = loadStream(is);
189 ((Multipart) stack.peek()).setEpilogueRaw(bytes);
190 }
191
192
193
194
195 public void preamble(InputStream is) throws MimeException, IOException {
196 expect(Multipart.class);
197 ByteSequence bytes = loadStream(is);
198 ((Multipart) stack.peek()).setPreambleRaw(bytes);
199 }
200
201
202
203
204
205 public void raw(InputStream is) throws MimeException, IOException {
206 throw new UnsupportedOperationException("Not supported");
207 }
208
209 private static ByteSequence loadStream(InputStream in) throws IOException {
210 ByteArrayBuffer bab = new ByteArrayBuffer(64);
211
212 int b;
213 while ((b = in.read()) != -1) {
214 bab.append(b);
215 }
216
217 return bab;
218 }
219
220 }