source: contrib/MailArchiver/sources/vendor/mime4j/apache-mime4j-0.7-SNAPSHOT-20110327.010440-17/dom/src/main/java/org/apache/james/mime4j/message/MimeWriter.java @ 6785

Revision 6785, 8.8 KB checked in by rafaelraymundo, 12 years ago (diff)

Ticket #2946 - Liberado codigo do MailArchiver?. Documentação na subpasta DOCS.

Line 
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
20package org.apache.james.mime4j.message;
21
22import java.io.IOException;
23import java.io.OutputStream;
24
25import org.apache.james.mime4j.codec.CodecUtil;
26import org.apache.james.mime4j.dom.BinaryBody;
27import org.apache.james.mime4j.dom.Body;
28import org.apache.james.mime4j.dom.Entity;
29import org.apache.james.mime4j.dom.Header;
30import org.apache.james.mime4j.dom.Message;
31import org.apache.james.mime4j.dom.Multipart;
32import org.apache.james.mime4j.dom.SingleBody;
33import org.apache.james.mime4j.dom.field.ContentTypeField;
34import org.apache.james.mime4j.dom.field.Field;
35import org.apache.james.mime4j.dom.field.FieldName;
36import org.apache.james.mime4j.util.ByteArrayBuffer;
37import org.apache.james.mime4j.util.ByteSequence;
38import org.apache.james.mime4j.util.ContentUtil;
39import org.apache.james.mime4j.util.MimeUtil;
40
41/**
42 * Writes a message (or a part of a message) to an output stream.
43 * <p>
44 * This class cannot be instantiated; instead the static instance
45 * {@link #DEFAULT} implements the default strategy for writing a message.
46 * <p>
47 * This class may be subclassed to implement custom strategies for writing
48 * messages.
49 */
50public class MimeWriter {
51
52    private static final byte[] CRLF = { '\r', '\n' };
53    private static final byte[] DASHES = { '-', '-' };
54
55    /**
56     * The default message writer.
57     */
58    public static final MimeWriter DEFAULT = new MimeWriter();
59
60    /**
61     * Protected constructor prevents direct instantiation.
62     */
63    protected MimeWriter() {
64    }
65
66    /**
67     * Write the specified <code>Body</code> to the specified
68     * <code>OutputStream</code>.
69     *
70     * @param body
71     *            the <code>Body</code> to write.
72     * @param out
73     *            the OutputStream to write to.
74     * @throws IOException
75     *             if an I/O error occurs.
76     */
77    public void writeBody(Body body, OutputStream out) throws IOException {
78        if (body instanceof Message) {
79            writeEntity((Message) body, out);
80        } else if (body instanceof Multipart) {
81            writeMultipart((Multipart) body, out);
82        } else if (body instanceof SingleBody) {
83            ((SingleBody) body).writeTo(out);
84        } else
85            throw new IllegalArgumentException("Unsupported body class");
86    }
87
88    /**
89     * Write the specified <code>Entity</code> to the specified
90     * <code>OutputStream</code>.
91     *
92     * @param entity
93     *            the <code>Entity</code> to write.
94     * @param out
95     *            the OutputStream to write to.
96     * @throws IOException
97     *             if an I/O error occurs.
98     */
99    public void writeEntity(Entity entity, OutputStream out) throws IOException {
100        final Header header = entity.getHeader();
101        if (header == null)
102            throw new IllegalArgumentException("Missing header");
103
104        writeHeader(header, out);
105
106        final Body body = entity.getBody();
107        if (body == null)
108            throw new IllegalArgumentException("Missing body");
109
110        boolean binaryBody = body instanceof BinaryBody;
111        OutputStream encOut = encodeStream(out, entity
112                .getContentTransferEncoding(), binaryBody);
113
114        writeBody(body, encOut);
115
116        // close if wrapped (base64 or quoted-printable)
117        if (encOut != out)
118            encOut.close();
119    }
120
121    /**
122     * Write the specified <code>Message</code> to the specified
123     * <code>OutputStream</code>.
124     *
125     * @param entity
126     *            the <code>Message</code> to write.
127     * @param out
128     *            the OutputStream to write to.
129     * @throws IOException
130     *             if an I/O error occurs.
131     */
132    public void writeMessage(Message message, OutputStream out) throws IOException {
133        writeEntity(message, out);
134    }
135   
136    /**
137     * Write the specified <code>Multipart</code> to the specified
138     * <code>OutputStream</code>.
139     *
140     * @param multipart
141     *            the <code>Multipart</code> to write.
142     * @param out
143     *            the OutputStream to write to.
144     * @throws IOException
145     *             if an I/O error occurs.
146     */
147    public void writeMultipart(Multipart multipart, OutputStream out)
148            throws IOException {
149        ContentTypeField contentType = getContentType(multipart);
150
151        ByteSequence boundary = getBoundary(contentType);
152
153        ByteSequence preamble;
154        ByteSequence epilogue;
155        if (multipart instanceof MultipartImpl) {
156            preamble = ((MultipartImpl) multipart).getPreambleRaw();
157            epilogue = ((MultipartImpl) multipart).getEpilogueRaw();
158        } else {
159            preamble = multipart.getPreamble() != null ? ContentUtil.encode(multipart.getPreamble()) : null;
160            epilogue = multipart.getEpilogue() != null ? ContentUtil.encode(multipart.getEpilogue()) : null;
161        }
162        if (preamble != null) {
163            writeBytes(preamble, out);
164            out.write(CRLF);
165        }
166
167        for (Entity bodyPart : multipart.getBodyParts()) {
168            out.write(DASHES);
169            writeBytes(boundary, out);
170            out.write(CRLF);
171
172            writeEntity(bodyPart, out);
173            out.write(CRLF);
174        }
175
176        out.write(DASHES);
177        writeBytes(boundary, out);
178        out.write(DASHES);
179        if (epilogue != null) {
180            out.write(CRLF);
181            writeBytes(epilogue, out);
182        }
183    }
184
185    /**
186     * Write the specified <code>Header</code> to the specified
187     * <code>OutputStream</code>.
188     *
189     * @param header
190     *            the <code>Header</code> to write.
191     * @param out
192     *            the OutputStream to write to.
193     * @throws IOException
194     *             if an I/O error occurs.
195     */
196    public void writeHeader(Header header, OutputStream out) throws IOException {
197        for (Field field : header) {
198            field.writeTo(out);
199            out.write(CRLF);
200        }
201
202        out.write(CRLF);
203    }
204
205    protected OutputStream encodeStream(OutputStream out, String encoding,
206            boolean binaryBody) throws IOException {
207        if (MimeUtil.isBase64Encoding(encoding)) {
208            return CodecUtil.wrapBase64(out);
209        } else if (MimeUtil.isQuotedPrintableEncoded(encoding)) {
210            return CodecUtil.wrapQuotedPrintable(out, binaryBody);
211        } else {
212            return out;
213        }
214    }
215
216    private ContentTypeField getContentType(Multipart multipart) {
217        Entity parent = multipart.getParent();
218        if (parent == null)
219            throw new IllegalArgumentException(
220                    "Missing parent entity in multipart");
221
222        Header header = parent.getHeader();
223        if (header == null)
224            throw new IllegalArgumentException(
225                    "Missing header in parent entity");
226
227        ContentTypeField contentType = (ContentTypeField) header
228                .getField(FieldName.CONTENT_TYPE);
229        if (contentType == null)
230            throw new IllegalArgumentException(
231                    "Content-Type field not specified");
232
233        return contentType;
234    }
235
236    private ByteSequence getBoundary(ContentTypeField contentType) {
237        String boundary = contentType.getBoundary();
238        if (boundary == null)
239            throw new IllegalArgumentException(
240                    "Multipart boundary not specified");
241
242        return ContentUtil.encode(boundary);
243    }
244
245    private void writeBytes(ByteSequence byteSequence, OutputStream out)
246            throws IOException {
247        if (byteSequence instanceof ByteArrayBuffer) {
248            ByteArrayBuffer bab = (ByteArrayBuffer) byteSequence;
249            out.write(bab.buffer(), 0, bab.length());
250        } else {
251            out.write(byteSequence.toByteArray());
252        }
253    }
254
255}
Note: See TracBrowser for help on using the repository browser.