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 *
10
* http://www.apache.org/licenses/LICENSE-2.0 *
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
****************************************************************/
20
package org.apache.james.mime4j.message;
22
import java.io.IOException;
23
import java.io.InputStream;
24
import java.nio.charset.Charset;
26
import org.apache.commons.logging.Log;
27
import org.apache.commons.logging.LogFactory;
28
import org.apache.james.mime4j.storage.DefaultStorageProvider;
29
import org.apache.james.mime4j.storage.MultiReferenceStorage;
30
import org.apache.james.mime4j.storage.Storage;
31
import org.apache.james.mime4j.storage.StorageProvider;
32
import org.apache.james.mime4j.util.CharsetUtil;
35
* Factory for creating message bodies.
37
public class BodyFactory {
39
private static Log log = LogFactory.getLog(BodyFactory.class);
41
private static final Charset FALLBACK_CHARSET = CharsetUtil.DEFAULT_CHARSET;
43
private StorageProvider storageProvider;
46
* Creates a new <code>BodyFactory</code> instance that uses the default
47
* storage provider for creating message bodies from input streams.
49
public BodyFactory() {
50
this.storageProvider = DefaultStorageProvider.getInstance();
54
* Creates a new <code>BodyFactory</code> instance that uses the given
55
* storage provider for creating message bodies from input streams.
57
* @param storageProvider
58
* a storage provider or <code>null</code> to use the default
61
public BodyFactory(StorageProvider storageProvider) {
62
if (storageProvider == null)
63
storageProvider = DefaultStorageProvider.getInstance();
65
this.storageProvider = storageProvider;
69
* Returns the <code>StorageProvider</code> this <code>BodyFactory</code>
70
* uses to create message bodies from input streams.
72
* @return a <code>StorageProvider</code>.
74
public StorageProvider getStorageProvider() {
75
return storageProvider;
79
* Creates a {@link BinaryBody} that holds the content of the given input
83
* input stream to create a message body from.
84
* @return a binary body.
86
* if an I/O error occurs.
88
public BinaryBody binaryBody(InputStream is) throws IOException {
90
throw new IllegalArgumentException();
92
Storage storage = storageProvider.store(is);
93
return new StorageBinaryBody(new MultiReferenceStorage(storage));
97
* Creates a {@link BinaryBody} that holds the content of the given
100
* Note that the caller must not invoke {@link Storage#delete() delete()} on
101
* the given <code>Storage</code> object after it has been passed to this
102
* method. Instead the message body created by this method takes care of
103
* deleting the storage when it gets disposed of (see
104
* {@link Disposable#dispose()}).
107
* storage to create a message body from.
108
* @return a binary body.
109
* @throws IOException
110
* if an I/O error occurs.
112
public BinaryBody binaryBody(Storage storage) throws IOException {
114
throw new IllegalArgumentException();
116
return new StorageBinaryBody(new MultiReferenceStorage(storage));
120
* Creates a {@link TextBody} that holds the content of the given input
123
* "us-ascii" is used to decode the byte content of the
124
* <code>Storage</code> into a character stream when calling
125
* {@link TextBody#getReader() getReader()} on the returned object.
128
* input stream to create a message body from.
129
* @return a text body.
130
* @throws IOException
131
* if an I/O error occurs.
133
public TextBody textBody(InputStream is) throws IOException {
135
throw new IllegalArgumentException();
137
Storage storage = storageProvider.store(is);
138
return new StorageTextBody(new MultiReferenceStorage(storage),
139
CharsetUtil.DEFAULT_CHARSET);
143
* Creates a {@link TextBody} that holds the content of the given input
146
* The charset corresponding to the given MIME charset name is used to
147
* decode the byte content of the input stream into a character stream when
148
* calling {@link TextBody#getReader() getReader()} on the returned object.
149
* If the MIME charset has no corresponding Java charset or the Java charset
150
* cannot be used for decoding then "us-ascii" is used instead.
153
* input stream to create a message body from.
155
* name of a MIME charset.
156
* @return a text body.
157
* @throws IOException
158
* if an I/O error occurs.
160
public TextBody textBody(InputStream is, String mimeCharset)
163
throw new IllegalArgumentException();
164
if (mimeCharset == null)
165
throw new IllegalArgumentException();
167
Storage storage = storageProvider.store(is);
168
Charset charset = toJavaCharset(mimeCharset, false);
169
return new StorageTextBody(new MultiReferenceStorage(storage), charset);
173
* Creates a {@link TextBody} that holds the content of the given
176
* "us-ascii" is used to decode the byte content of the
177
* <code>Storage</code> into a character stream when calling
178
* {@link TextBody#getReader() getReader()} on the returned object.
180
* Note that the caller must not invoke {@link Storage#delete() delete()} on
181
* the given <code>Storage</code> object after it has been passed to this
182
* method. Instead the message body created by this method takes care of
183
* deleting the storage when it gets disposed of (see
184
* {@link Disposable#dispose()}).
187
* storage to create a message body from.
188
* @return a text body.
189
* @throws IOException
190
* if an I/O error occurs.
192
public TextBody textBody(Storage storage) throws IOException {
194
throw new IllegalArgumentException();
196
return new StorageTextBody(new MultiReferenceStorage(storage),
197
CharsetUtil.DEFAULT_CHARSET);
201
* Creates a {@link TextBody} that holds the content of the given
204
* The charset corresponding to the given MIME charset name is used to
205
* decode the byte content of the <code>Storage</code> into a character
206
* stream when calling {@link TextBody#getReader() getReader()} on the
207
* returned object. If the MIME charset has no corresponding Java charset or
208
* the Java charset cannot be used for decoding then "us-ascii" is
211
* Note that the caller must not invoke {@link Storage#delete() delete()} on
212
* the given <code>Storage</code> object after it has been passed to this
213
* method. Instead the message body created by this method takes care of
214
* deleting the storage when it gets disposed of (see
215
* {@link Disposable#dispose()}).
218
* storage to create a message body from.
220
* name of a MIME charset.
221
* @return a text body.
222
* @throws IOException
223
* if an I/O error occurs.
225
public TextBody textBody(Storage storage, String mimeCharset)
228
throw new IllegalArgumentException();
229
if (mimeCharset == null)
230
throw new IllegalArgumentException();
232
Charset charset = toJavaCharset(mimeCharset, false);
233
return new StorageTextBody(new MultiReferenceStorage(storage), charset);
237
* Creates a {@link TextBody} that holds the content of the given string.
239
* "us-ascii" is used to encode the characters of the string into
240
* a byte stream when calling
241
* {@link SingleBody#writeTo(java.io.OutputStream) writeTo(OutputStream)} on
242
* the returned object.
245
* text to create a message body from.
246
* @return a text body.
248
public TextBody textBody(String text) {
250
throw new IllegalArgumentException();
252
return new StringTextBody(text, CharsetUtil.DEFAULT_CHARSET);
256
* Creates a {@link TextBody} that holds the content of the given string.
258
* The charset corresponding to the given MIME charset name is used to
259
* encode the characters of the string into a byte stream when calling
260
* {@link SingleBody#writeTo(java.io.OutputStream) writeTo(OutputStream)} on
261
* the returned object. If the MIME charset has no corresponding Java
262
* charset or the Java charset cannot be used for encoding then
263
* "us-ascii" is used instead.
266
* text to create a message body from.
268
* name of a MIME charset.
269
* @return a text body.
271
public TextBody textBody(String text, String mimeCharset) {
273
throw new IllegalArgumentException();
274
if (mimeCharset == null)
275
throw new IllegalArgumentException();
277
Charset charset = toJavaCharset(mimeCharset, true);
278
return new StringTextBody(text, charset);
281
private static Charset toJavaCharset(String mimeCharset, boolean forEncoding) {
282
String charset = CharsetUtil.toJavaCharset(mimeCharset);
283
if (charset == null) {
284
if (log.isWarnEnabled())
285
log.warn("MIME charset '" + mimeCharset + "' has no "
286
+ "corresponding Java charset. Using "
287
+ FALLBACK_CHARSET + " instead.");
288
return FALLBACK_CHARSET;
291
if (forEncoding && !CharsetUtil.isEncodingSupported(charset)) {
292
if (log.isWarnEnabled())
293
log.warn("MIME charset '" + mimeCharset
294
+ "' does not support encoding. Using "
295
+ FALLBACK_CHARSET + " instead.");
296
return FALLBACK_CHARSET;
299
if (!forEncoding && !CharsetUtil.isDecodingSupported(charset)) {
300
if (log.isWarnEnabled())
301
log.warn("MIME charset '" + mimeCharset
302
+ "' does not support decoding. Using "
303
+ FALLBACK_CHARSET + " instead.");
304
return FALLBACK_CHARSET;
307
return Charset.forName(charset);