| /**************************************************************** |
| * Licensed to the Apache Software Foundation (ASF) under one * |
| * or more contributor license agreements. See the NOTICE file * |
| * distributed with this work for additional information * |
| * regarding copyright ownership. The ASF licenses this file * |
| * to you under the Apache License, Version 2.0 (the * |
| * "License"); you may not use this file except in compliance * |
| * with the License. You may obtain a copy of the License at * |
| * * |
| * http://www.apache.org/licenses/LICENSE-2.0 * |
| * * |
| * Unless required by applicable law or agreed to in writing, * |
| * software distributed under the License is distributed on an * |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * |
| * KIND, either express or implied. See the License for the * |
| * specific language governing permissions and limitations * |
| * under the License. * |
| ****************************************************************/ |
| |
| package org.apache.james.mime4j.storage; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.nio.charset.Charset; |
| |
| import org.apache.james.mime4j.Charsets; |
| import org.apache.james.mime4j.codec.DecodeMonitor; |
| import org.apache.james.mime4j.dom.BinaryBody; |
| import org.apache.james.mime4j.dom.Disposable; |
| import org.apache.james.mime4j.dom.SingleBody; |
| import org.apache.james.mime4j.dom.TextBody; |
| import org.apache.james.mime4j.message.BodyFactory; |
| import org.apache.james.mime4j.util.CharsetUtil; |
| |
| /** |
| * Factory for creating message bodies. |
| */ |
| public class StorageBodyFactory implements BodyFactory { |
| |
| private static final Charset FALLBACK_CHARSET = Charsets.DEFAULT_CHARSET; |
| |
| private final StorageProvider storageProvider; |
| private final DecodeMonitor monitor; |
| |
| /** |
| * Creates a new <code>BodyFactory</code> instance that uses the default |
| * storage provider for creating message bodies from input streams. |
| */ |
| public StorageBodyFactory() { |
| this(null, null); |
| } |
| |
| /** |
| * Creates a new <code>BodyFactory</code> instance that uses the given |
| * storage provider for creating message bodies from input streams. |
| * |
| * @param storageProvider |
| * a storage provider or <code>null</code> to use the default |
| * one. |
| */ |
| public StorageBodyFactory( |
| final StorageProvider storageProvider, |
| final DecodeMonitor monitor) { |
| this.storageProvider = |
| storageProvider != null ? storageProvider : DefaultStorageProvider.getInstance(); |
| this.monitor = |
| monitor != null ? monitor : DecodeMonitor.SILENT; |
| } |
| |
| /** |
| * Returns the <code>StorageProvider</code> this <code>BodyFactory</code> |
| * uses to create message bodies from input streams. |
| * |
| * @return a <code>StorageProvider</code>. |
| */ |
| public StorageProvider getStorageProvider() { |
| return storageProvider; |
| } |
| |
| /** |
| * Creates a {@link BinaryBody} that holds the content of the given input |
| * stream. |
| * |
| * @param is |
| * input stream to create a message body from. |
| * @return a binary body. |
| * @throws IOException |
| * if an I/O error occurs. |
| */ |
| public BinaryBody binaryBody(InputStream is) throws IOException { |
| if (is == null) |
| throw new IllegalArgumentException(); |
| |
| Storage storage = storageProvider.store(is); |
| return new StorageBinaryBody(new MultiReferenceStorage(storage)); |
| } |
| |
| /** |
| * Creates a {@link BinaryBody} that holds the content of the given |
| * {@link Storage}. |
| * <p> |
| * Note that the caller must not invoke {@link Storage#delete() delete()} on |
| * the given <code>Storage</code> object after it has been passed to this |
| * method. Instead the message body created by this method takes care of |
| * deleting the storage when it gets disposed of (see |
| * {@link Disposable#dispose()}). |
| * |
| * @param storage |
| * storage to create a message body from. |
| * @return a binary body. |
| * @throws IOException |
| * if an I/O error occurs. |
| */ |
| public BinaryBody binaryBody(Storage storage) throws IOException { |
| if (storage == null) |
| throw new IllegalArgumentException(); |
| |
| return new StorageBinaryBody(new MultiReferenceStorage(storage)); |
| } |
| |
| /** |
| * Creates a {@link TextBody} that holds the content of the given input |
| * stream. |
| * <p> |
| * "us-ascii" is used to decode the byte content of the |
| * <code>Storage</code> into a character stream when calling |
| * {@link TextBody#getReader() getReader()} on the returned object. |
| * |
| * @param is |
| * input stream to create a message body from. |
| * @return a text body. |
| * @throws IOException |
| * if an I/O error occurs. |
| */ |
| public TextBody textBody(InputStream is) throws IOException { |
| if (is == null) |
| throw new IllegalArgumentException(); |
| |
| Storage storage = storageProvider.store(is); |
| return new StorageTextBody(new MultiReferenceStorage(storage), Charsets.DEFAULT_CHARSET); |
| } |
| |
| /** |
| * Creates a {@link TextBody} that holds the content of the given input |
| * stream. |
| * <p> |
| * The charset corresponding to the given MIME charset name is used to |
| * decode the byte content of the input stream into a character stream when |
| * calling {@link TextBody#getReader() getReader()} on the returned object. |
| * If the MIME charset has no corresponding Java charset or the Java charset |
| * cannot be used for decoding then "us-ascii" is used instead. |
| * |
| * @param is |
| * input stream to create a message body from. |
| * @param mimeCharset |
| * name of a MIME charset. |
| * @return a text body. |
| * @throws IOException |
| * if an I/O error occurs. |
| */ |
| public TextBody textBody(InputStream is, String mimeCharset) |
| throws IOException { |
| if (is == null) |
| throw new IllegalArgumentException(); |
| if (mimeCharset == null) |
| throw new IllegalArgumentException(); |
| |
| Storage storage = storageProvider.store(is); |
| Charset charset = toJavaCharset(mimeCharset, false, monitor); |
| return new StorageTextBody(new MultiReferenceStorage(storage), charset); |
| } |
| |
| /** |
| * Creates a {@link TextBody} that holds the content of the given |
| * {@link Storage}. |
| * <p> |
| * "us-ascii" is used to decode the byte content of the |
| * <code>Storage</code> into a character stream when calling |
| * {@link TextBody#getReader() getReader()} on the returned object. |
| * <p> |
| * Note that the caller must not invoke {@link Storage#delete() delete()} on |
| * the given <code>Storage</code> object after it has been passed to this |
| * method. Instead the message body created by this method takes care of |
| * deleting the storage when it gets disposed of (see |
| * {@link Disposable#dispose()}). |
| * |
| * @param storage |
| * storage to create a message body from. |
| * @return a text body. |
| * @throws IOException |
| * if an I/O error occurs. |
| */ |
| public TextBody textBody(Storage storage) throws IOException { |
| if (storage == null) |
| throw new IllegalArgumentException(); |
| |
| return new StorageTextBody(new MultiReferenceStorage(storage), Charsets.DEFAULT_CHARSET); |
| } |
| |
| /** |
| * Creates a {@link TextBody} that holds the content of the given |
| * {@link Storage}. |
| * <p> |
| * The charset corresponding to the given MIME charset name is used to |
| * decode the byte content of the <code>Storage</code> into a character |
| * stream when calling {@link TextBody#getReader() getReader()} on the |
| * returned object. If the MIME charset has no corresponding Java charset or |
| * the Java charset cannot be used for decoding then "us-ascii" is |
| * used instead. |
| * <p> |
| * Note that the caller must not invoke {@link Storage#delete() delete()} on |
| * the given <code>Storage</code> object after it has been passed to this |
| * method. Instead the message body created by this method takes care of |
| * deleting the storage when it gets disposed of (see |
| * {@link Disposable#dispose()}). |
| * |
| * @param storage |
| * storage to create a message body from. |
| * @param mimeCharset |
| * name of a MIME charset. |
| * @return a text body. |
| * @throws IOException |
| * if an I/O error occurs. |
| */ |
| public TextBody textBody(Storage storage, String mimeCharset) |
| throws IOException { |
| if (storage == null) |
| throw new IllegalArgumentException(); |
| if (mimeCharset == null) |
| throw new IllegalArgumentException(); |
| |
| Charset charset = toJavaCharset(mimeCharset, false, monitor); |
| return new StorageTextBody(new MultiReferenceStorage(storage), charset); |
| } |
| |
| /** |
| * Creates a {@link TextBody} that holds the content of the given string. |
| * <p> |
| * "us-ascii" is used to encode the characters of the string into |
| * a byte stream when calling |
| * {@link SingleBody#writeTo(java.io.OutputStream) writeTo(OutputStream)} on |
| * the returned object. |
| * |
| * @param text |
| * text to create a message body from. |
| * @return a text body. |
| */ |
| public TextBody textBody(String text) { |
| if (text == null) |
| throw new IllegalArgumentException(); |
| |
| return new StringTextBody(text, Charsets.DEFAULT_CHARSET); |
| } |
| |
| /** |
| * Creates a {@link TextBody} that holds the content of the given string. |
| * <p> |
| * The charset corresponding to the given MIME charset name is used to |
| * encode the characters of the string into a byte stream when calling |
| * {@link SingleBody#writeTo(java.io.OutputStream) writeTo(OutputStream)} on |
| * the returned object. If the MIME charset has no corresponding Java |
| * charset or the Java charset cannot be used for encoding then |
| * "us-ascii" is used instead. |
| * |
| * @param text |
| * text to create a message body from. |
| * @param mimeCharset |
| * name of a MIME charset. |
| * @return a text body. |
| */ |
| public TextBody textBody(String text, String mimeCharset) { |
| if (text == null) |
| throw new IllegalArgumentException(); |
| if (mimeCharset == null) |
| throw new IllegalArgumentException(); |
| |
| Charset charset = toJavaCharset(mimeCharset, true, monitor); |
| return new StringTextBody(text, charset); |
| } |
| |
| private static Charset toJavaCharset( |
| final String mimeCharset, |
| boolean forEncoding, |
| final DecodeMonitor monitor) { |
| Charset charset = CharsetUtil.lookup(mimeCharset); |
| if (charset == null) { |
| if (monitor.isListening()) { |
| monitor.warn( |
| "MIME charset '" + mimeCharset + "' has no " |
| + "corresponding Java charset", "Using " |
| + FALLBACK_CHARSET + " instead."); |
| } |
| return FALLBACK_CHARSET; |
| } |
| return charset; |
| } |
| |
| } |