http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/MailImpl.java
----------------------------------------------------------------------
diff --git 
a/server/container/core/src/main/java/org/apache/james/core/MailImpl.java 
b/server/container/core/src/main/java/org/apache/james/core/MailImpl.java
deleted file mode 100644
index c7ecd83..0000000
--- a/server/container/core/src/main/java/org/apache/james/core/MailImpl.java
+++ /dev/null
@@ -1,691 +0,0 @@
-/****************************************************************
- * 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.core;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.OptionalDataException;
-import java.io.OutputStream;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.UUID;
-
-import javax.mail.MessagingException;
-import javax.mail.internet.MimeMessage;
-import javax.mail.internet.ParseException;
-
-import org.apache.james.lifecycle.api.Disposable;
-import org.apache.james.lifecycle.api.LifecycleUtil;
-import org.apache.mailet.Mail;
-import org.apache.mailet.MailAddress;
-import org.apache.mailet.PerRecipientHeaders;
-import org.apache.mailet.PerRecipientHeaders.Header;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * <p>
- * Wraps a MimeMessage adding routing information (from SMTP) and some simple
- * API enhancements.
- * </p>
- * <p>
- * From James version > 2.2.0a8 "mail attributes" have been added. Backward and
- * forward compatibility is supported:
- * <ul>
- * <li>messages stored in file repositories <i>without</i> attributes by James
- * version <= 2.2.0a8 will be processed by later versions as having an empty
- * attributes hashmap;</li>
- * <li>messages stored in file repositories <i>with</i> attributes by James
- * version > 2.2.0a8 will be processed by previous versions, ignoring the
- * attributes.</li>
- * </ul>
- * </p>
- */
-public class MailImpl implements Disposable, Mail {
-
-    private static final Logger LOGGER = 
LoggerFactory.getLogger(MailImpl.class);
-
-    /**
-     * We hardcode the serialVersionUID so that from James 1.2 on, MailImpl 
will
-     * be deserializable (so your mail doesn't get lost)
-     */
-    public static final long serialVersionUID = -4289663364703986260L;
-    /**
-     * The error message, if any, associated with this mail.
-     */
-    private String errorMessage;
-    /**
-     * The state of this mail, which determines how it is processed.
-     */
-    private String state;
-    /**
-     * The MimeMessage that holds the mail data.
-     */
-    private MimeMessage message;
-    /**
-     * The sender of this mail.
-     */
-    private MailAddress sender;
-    /**
-     * The collection of recipients to whom this mail was sent.
-     */
-    private Collection<MailAddress> recipients;
-    /**
-     * The identifier for this mail message
-     */
-    private String name;
-    /**
-     * The remote host from which this mail was sent.
-     */
-    private String remoteHost = "localhost";
-    /**
-     * The remote address from which this mail was sent.
-     */
-    private String remoteAddr = "127.0.0.1";
-    /**
-     * The last time this message was updated.
-     */
-    private Date lastUpdated = new Date();
-    /**
-     * Attributes added to this MailImpl instance
-     */
-    private Map<String, Object> attributes;
-    /**
-     * Specific headers for some recipients
-     * These headers will be added at delivery time
-     */
-    private PerRecipientHeaders perRecipientSpecificHeaders;
-
-    /**
-     * A constructor that creates a new, uninitialized MailImpl
-     */
-    public MailImpl() {
-        setState(Mail.DEFAULT);
-        attributes = new HashMap<>();
-        perRecipientSpecificHeaders = new PerRecipientHeaders();
-    }
-
-    /**
-     * A constructor that creates a MailImpl with the specified name, sender,
-     * and recipients.
-     *
-     * @param name       the name of the MailImpl
-     * @param sender     the sender for this MailImpl
-     * @param recipients the collection of recipients of this MailImpl
-     */
-    public MailImpl(String name, MailAddress sender, Collection<MailAddress> 
recipients) {
-        this();
-        this.name = name;
-        this.sender = sender;
-        this.recipients = null;
-
-        // Copy the recipient list
-        if (recipients != null) {
-            this.recipients = new ArrayList<>();
-            this.recipients.addAll(recipients);
-        }
-    }
-
-    /**
-     * Create a copy of the input mail and assign it a new name
-     *
-     * @param mail original mail
-     * @throws MessagingException when the message is not clonable
-     */
-    public MailImpl(Mail mail) throws MessagingException {
-        this(mail, newName(mail));
-    }
-
-    /**
-     * @param mail
-     * @param newName
-     * @throws MessagingException
-     */
-    @SuppressWarnings("unchecked")
-    public MailImpl(Mail mail, String newName) throws MessagingException {
-        this(newName, mail.getSender(), mail.getRecipients(), 
mail.getMessage());
-        setRemoteHost(mail.getRemoteHost());
-        setRemoteAddr(mail.getRemoteAddr());
-        setLastUpdated(mail.getLastUpdated());
-        try {
-            if (mail instanceof MailImpl) {
-                setAttributesRaw((HashMap<String, Object>) 
cloneSerializableObject(((MailImpl) mail).getAttributesRaw()));
-            } else {
-                HashMap<String, Object> attribs = new HashMap<>();
-                for (Iterator<String> i = mail.getAttributeNames(); 
i.hasNext(); ) {
-                    String hashKey = i.next();
-                    attribs.put(hashKey, 
cloneSerializableObject(mail.getAttribute(hashKey)));
-                }
-                setAttributesRaw(attribs);
-            }
-        } catch (IOException | ClassNotFoundException e) {
-            LOGGER.error("Error while deserializing attributes", e);
-            setAttributesRaw(new HashMap<>());
-        }
-    }
-
-    /**
-     * A constructor that creates a MailImpl with the specified name, sender,
-     * recipients, and message data.
-     *
-     * @param name       the name of the MailImpl
-     * @param sender     the sender for this MailImpl
-     * @param recipients the collection of recipients of this MailImpl
-     * @param messageIn  a stream containing the message source
-     */
-    public MailImpl(String name, MailAddress sender, Collection<MailAddress> 
recipients, InputStream messageIn) throws MessagingException {
-        this(name, sender, recipients);
-        MimeMessageSource source = new MimeMessageInputStreamSource(name, 
messageIn);
-        // if MimeMessageCopyOnWriteProxy throws an error in the constructor we
-        // have to manually care disposing our source.
-        try {
-            this.setMessage(new MimeMessageCopyOnWriteProxy(source));
-        } catch (MessagingException e) {
-            LifecycleUtil.dispose(source);
-            throw e;
-        }
-    }
-
-    /**
-     * A constructor that creates a MailImpl with the specified name, sender,
-     * recipients, and MimeMessage.
-     *
-     * @param name       the name of the MailImpl
-     * @param sender     the sender for this MailImpl
-     * @param recipients the collection of recipients of this MailImpl
-     * @param message    the MimeMessage associated with this MailImpl
-     */
-    public MailImpl(String name, MailAddress sender, Collection<MailAddress> 
recipients, MimeMessage message) {
-        this(name, sender, recipients);
-        this.setMessage(new MimeMessageCopyOnWriteProxy(message));
-    }
-
-    /**
-     * Duplicate the MailImpl.
-     *
-     * @return a MailImpl that is a duplicate of this one
-     */
-    public Mail duplicate() {
-        return duplicate(name);
-    }
-
-    /**
-     * Duplicate the MailImpl, replacing the mail name with the one passed in 
as
-     * an argument.
-     *
-     * @param newName the name for the duplicated mail
-     * @return a MailImpl that is a duplicate of this one with a different name
-     */
-    public Mail duplicate(String newName) {
-        try {
-            return new MailImpl(this, newName);
-        } catch (MessagingException me) {
-            // Ignored. Return null in the case of an error.
-        }
-        return null;
-    }
-
-    /**
-     * Get the error message associated with this MailImpl.
-     *
-     * @return the error message associated with this MailImpl
-     */
-    @Override
-    public String getErrorMessage() {
-        return errorMessage;
-    }
-
-    /**
-     * Get the MimeMessage associated with this MailImpl.
-     *
-     * @return the MimeMessage associated with this MailImpl
-     */
-    @Override
-    public MimeMessage getMessage() throws MessagingException {
-        return message;
-    }
-
-    /**
-     * Set the name of this MailImpl.
-     *
-     * @param name the name of this MailImpl
-     */
-    @Override
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    /**
-     * Get the name of this MailImpl.
-     *
-     * @return the name of this MailImpl
-     */
-    @Override
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Get the recipients of this MailImpl.
-     *
-     * @return the recipients of this MailImpl
-     */
-    @Override
-    public Collection<MailAddress> getRecipients() {
-        return recipients;
-    }
-
-    /**
-     * Get the sender of this MailImpl.
-     *
-     * @return the sender of this MailImpl
-     */
-    @Override
-    public MailAddress getSender() {
-        return sender;
-    }
-
-    /**
-     * Get the state of this MailImpl.
-     *
-     * @return the state of this MailImpl
-     */
-    @Override
-    public String getState() {
-        return state;
-    }
-
-    /**
-     * Get the remote host associated with this MailImpl.
-     *
-     * @return the remote host associated with this MailImpl
-     */
-    @Override
-    public String getRemoteHost() {
-        return remoteHost;
-    }
-
-    /**
-     * Get the remote address associated with this MailImpl.
-     *
-     * @return the remote address associated with this MailImpl
-     */
-    @Override
-    public String getRemoteAddr() {
-        return remoteAddr;
-    }
-
-    /**
-     * Get the last updated time for this MailImpl.
-     *
-     * @return the last updated time for this MailImpl
-     */
-    @Override
-    public Date getLastUpdated() {
-        return lastUpdated;
-    }
-
-    /**
-     * <p>
-     * Return the size of the message including its headers.
-     * MimeMessage.getSize() method only returns the size of the message body.
-     * </p>
-     * <p/>
-     * <p>
-     * Note: this size is not guaranteed to be accurate - see Sun's
-     * documentation of MimeMessage.getSize().
-     * </p>
-     *
-     * @return approximate size of full message including headers.
-     * @throws MessagingException if a problem occurs while computing the 
message size
-     */
-    @Override
-    public long getMessageSize() throws MessagingException {
-        return MimeMessageUtil.getMessageSize(message);
-    }
-
-    /**
-     * Set the error message associated with this MailImpl.
-     *
-     * @param msg the new error message associated with this MailImpl
-     */
-    @Override
-    public void setErrorMessage(String msg) {
-        this.errorMessage = msg;
-    }
-
-    /**
-     * Set the MimeMessage associated with this MailImpl.
-     *
-     * @param message the new MimeMessage associated with this MailImpl
-     */
-    @Override
-    public void setMessage(MimeMessage message) {
-
-        // TODO: We should use the MimeMessageCopyOnWriteProxy
-        // everytime we set the MimeMessage. We should
-        // investigate if we should wrap it here
-
-        if (this.message != message) {
-            // If a setMessage is called on a Mail that already have a message
-            // (discouraged) we have to make sure that the message we remove is
-            // correctly unreferenced and disposed, otherwise it will keep 
locks
-            if (this.message != null) {
-                LifecycleUtil.dispose(this.message);
-            }
-            this.message = message;
-        }
-    }
-
-    /**
-     * Set the recipients for this MailImpl.
-     *
-     * @param recipients the recipients for this MailImpl
-     */
-    @Override
-    public void setRecipients(Collection<MailAddress> recipients) {
-        this.recipients = recipients;
-    }
-
-    /**
-     * Set the sender of this MailImpl.
-     *
-     * @param sender the sender of this MailImpl
-     */
-    public void setSender(MailAddress sender) {
-        this.sender = sender;
-    }
-
-    /**
-     * Set the state of this MailImpl.
-     *
-     * @param state the state of this MailImpl
-     */
-    public void setState(String state) {
-        this.state = state;
-    }
-
-    /**
-     * Set the remote address associated with this MailImpl.
-     *
-     * @param remoteHost the new remote host associated with this MailImpl
-     */
-    public void setRemoteHost(String remoteHost) {
-        this.remoteHost = remoteHost;
-    }
-
-    /**
-     * Set the remote address associated with this MailImpl.
-     *
-     * @param remoteAddr the new remote address associated with this MailImpl
-     */
-    public void setRemoteAddr(String remoteAddr) {
-        this.remoteAddr = remoteAddr;
-    }
-
-    /**
-     * Set the date this mail was last updated.
-     *
-     * @param lastUpdated the date the mail was last updated
-     */
-    public void setLastUpdated(Date lastUpdated) {
-        // Make a defensive copy to ensure that the date
-        // doesn't get changed external to the class
-        if (lastUpdated != null) {
-            lastUpdated = new Date(lastUpdated.getTime());
-        }
-        this.lastUpdated = lastUpdated;
-    }
-
-    /**
-     * Writes the message out to an OutputStream.
-     *
-     * @param out the OutputStream to which to write the content
-     * @throws MessagingException if the MimeMessage is not set for this 
MailImpl
-     * @throws IOException        if an error occurs while reading or writing 
from the stream
-     */
-    public void writeMessageTo(OutputStream out) throws IOException, 
MessagingException {
-        if (message != null) {
-            message.writeTo(out);
-        } else {
-            throw new MessagingException("No message set for this MailImpl.");
-        }
-    }
-
-    // Serializable Methods
-    // TODO: These need some work. Currently very tightly coupled to
-    // the internal representation.
-
-    /**
-     * Read the MailImpl from an <code>ObjectInputStream</code>.
-     *
-     * @param in the ObjectInputStream from which the object is read
-     * @throws IOException            if an error occurs while reading from 
the stream
-     * @throws ClassNotFoundException ?
-     * @throws ClassCastException     if the serialized objects are not of the 
appropriate type
-     */
-    @SuppressWarnings("unchecked")
-    private void readObject(java.io.ObjectInputStream in) throws IOException, 
ClassNotFoundException {
-        try {
-            Object obj = in.readObject();
-            if (obj == null) {
-                sender = null;
-            } else if (obj instanceof String) {
-                sender = new MailAddress((String) obj);
-            } else if (obj instanceof MailAddress) {
-                sender = (MailAddress) obj;
-            }
-        } catch (ParseException pe) {
-            throw new IOException("Error parsing sender address: " + 
pe.getMessage());
-        }
-        recipients = (Collection<MailAddress>) in.readObject();
-        state = (String) in.readObject();
-        errorMessage = (String) in.readObject();
-        name = (String) in.readObject();
-        remoteHost = (String) in.readObject();
-        remoteAddr = (String) in.readObject();
-        setLastUpdated((Date) in.readObject());
-        // the following is under try/catch to be backwards compatible
-        // with messages created with James version <= 2.2.0a8
-        try {
-            attributes = (HashMap<String, Object>) in.readObject();
-        } catch (OptionalDataException ode) {
-            if (ode.eof) {
-                attributes = new HashMap<>();
-            } else {
-                throw ode;
-            }
-        }
-    }
-
-    /**
-     * Write the MailImpl to an <code>ObjectOutputStream</code>.
-     *
-     * @param out the ObjectOutputStream to which the object is written
-     * @throws IOException if an error occurs while writing to the stream
-     */
-    private void writeObject(java.io.ObjectOutputStream out) throws 
IOException {
-        out.writeObject(sender);
-        out.writeObject(recipients);
-        out.writeObject(state);
-        out.writeObject(errorMessage);
-        out.writeObject(name);
-        out.writeObject(remoteHost);
-        out.writeObject(remoteAddr);
-        out.writeObject(lastUpdated);
-        out.writeObject(attributes);
-    }
-
-    @Override
-    public void dispose() {
-        LifecycleUtil.dispose(message);
-        message = null;
-    }
-
-    /**
-     * <p>
-     * This method is necessary, when Mail repositories needs to deal 
explicitly
-     * with storing Mail attributes as a Serializable
-     * </p>
-     * <p>
-     * <strong>Note</strong>: This method is not exposed in the Mail interface,
-     * it is for internal use by James only.
-     * </p>
-     *
-     * @return Serializable of the entire attributes collection
-     * @since 2.2.0
-     */
-    public Map<String, Object> getAttributesRaw() {
-        return attributes;
-    }
-
-    /**
-     * <p>
-     * This method is necessary, when Mail repositories needs to deal 
explicitly
-     * with retriving Mail attributes as a Serializable
-     * </p>
-     * <p>
-     * <strong>Note</strong>: This method is not exposed in the Mail interface,
-     * it is for internal use by James only.
-     * </p>
-     *
-     * @param attr Serializable of the entire attributes collection
-     * @since 2.2.0
-     */
-    public void setAttributesRaw(HashMap<String, Object> attr) {
-        this.attributes = (attr == null) ? new HashMap<>() : attr;
-    }
-
-    @Override
-    public Serializable getAttribute(String key) {
-        return (Serializable) attributes.get(key);
-    }
-
-    @Override
-    public Serializable setAttribute(String key, Serializable object) {
-        return (Serializable) attributes.put(key, object);
-    }
-
-    @Override
-    public Serializable removeAttribute(String key) {
-        return (Serializable) attributes.remove(key);
-    }
-
-    @Override
-    public void removeAllAttributes() {
-        attributes.clear();
-    }
-
-    @Override
-    public Iterator<String> getAttributeNames() {
-        return attributes.keySet().iterator();
-    }
-
-    @Override
-    public boolean hasAttributes() {
-        return !attributes.isEmpty();
-    }
-
-    /**
-     * This methods provide cloning for serializable objects. Mail Attributes
-     * are Serializable but not Clonable so we need a deep copy
-     *
-     * @param o Object to be cloned
-     * @return the cloned Object
-     * @throws IOException
-     * @throws ClassNotFoundException
-     */
-    private static Object cloneSerializableObject(Object o) throws 
IOException, ClassNotFoundException {
-        ByteArrayOutputStream b = new ByteArrayOutputStream();
-        ObjectOutputStream out = new ObjectOutputStream(b);
-        out.writeObject(o);
-        out.flush();
-        out.close();
-        ByteArrayInputStream bi = new ByteArrayInputStream(b.toByteArray());
-        ObjectInputStream in = new ObjectInputStream(bi);
-        return in.readObject();
-    }
-
-    private static final java.util.Random random = new java.util.Random(); // 
Used
-    // to
-    // generate
-    // new
-    // mail
-    // names
-
-    /**
-     * Create a unique new primary key name for the given MailObject.
-     *
-     * @param mail the mail to use as the basis for the new mail name
-     * @return a new name
-     */
-    public static String newName(Mail mail) throws MessagingException {
-        String oldName = mail.getName();
-
-        // Checking if the original mail name is too long, perhaps because of a
-        // loop caused by a configuration error.
-        // it could cause a "null pointer exception" in AvalonMailRepository
-        // much
-        // harder to understand.
-        if (oldName.length() > 76) {
-            int count = 0;
-            int index = 0;
-            while ((index = oldName.indexOf('!', index + 1)) >= 0) {
-                count++;
-            }
-            // It looks like a configuration loop. It's better to stop.
-            if (count > 7) {
-                throw new MessagingException("Unable to create a new message 
name: too long." + " Possible loop in config.xml.");
-            } else {
-                oldName = oldName.substring(0, 76);
-            }
-        }
-
-        return oldName + "-!" + random.nextInt(1048576);
-    }
-
-    /**
-     * Generate a new identifier/name for a mail being processed by this 
server.
-     *
-     * @return the new identifier
-     */
-    public static String getId() {
-        return "Mail" + System.currentTimeMillis() + "-" + UUID.randomUUID();
-    }
-
-    @Override
-    public PerRecipientHeaders getPerRecipientSpecificHeaders() {
-        return perRecipientSpecificHeaders;
-    }
-
-    @Override
-    public void addSpecificHeaderForRecipient(Header header, MailAddress 
recipient) {
-        perRecipientSpecificHeaders.addHeaderForRecipient(header, recipient);
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/MimeMessageCopyOnWriteProxy.java
----------------------------------------------------------------------
diff --git 
a/server/container/core/src/main/java/org/apache/james/core/MimeMessageCopyOnWriteProxy.java
 
b/server/container/core/src/main/java/org/apache/james/core/MimeMessageCopyOnWriteProxy.java
deleted file mode 100644
index f75d7dd..0000000
--- 
a/server/container/core/src/main/java/org/apache/james/core/MimeMessageCopyOnWriteProxy.java
+++ /dev/null
@@ -1,561 +0,0 @@
-/****************************************************************
- * 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.core;
-
-import javax.activation.DataHandler;
-import javax.mail.Address;
-import javax.mail.Flags;
-import javax.mail.Folder;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.mail.Multipart;
-import javax.mail.Session;
-import javax.mail.Flags.Flag;
-import javax.mail.internet.MimeMessage;
-import javax.mail.search.SearchTerm;
-
-import org.apache.james.lifecycle.api.Disposable;
-import org.apache.james.lifecycle.api.LifecycleUtil;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Date;
-import java.util.Enumeration;
-
-/**
- * This object wraps a "possibly shared" MimeMessage tracking copies and
- * automatically cloning it (if shared) when a write operation is invoked.
- */
-public class MimeMessageCopyOnWriteProxy extends MimeMessage implements 
Disposable {
-
-    /**
-     * Used internally to track the reference count It is important that this 
is
-     * static otherwise it will keep a reference to the parent object.
-     */
-    protected static class MessageReferenceTracker {
-
-        /**
-         * reference counter
-         */
-        private int referenceCount = 1;
-
-        /**
-         * The mime message in memory
-         */
-        private MimeMessage wrapped = null;
-
-        public MessageReferenceTracker(MimeMessage ref) {
-            wrapped = ref;
-        }
-
-        protected synchronized void incrementReferenceCount() {
-            referenceCount++;
-        }
-
-        protected synchronized void decrementReferenceCount() {
-            referenceCount--;
-            if (referenceCount <= 0) {
-                LifecycleUtil.dispose(wrapped);
-                wrapped = null;
-            }
-        }
-
-        protected synchronized int getReferenceCount() {
-            return referenceCount;
-        }
-
-        public synchronized MimeMessage getWrapped() {
-            return wrapped;
-        }
-
-    }
-
-    protected MessageReferenceTracker refCount;
-
-    public MimeMessageCopyOnWriteProxy(MimeMessage original) {
-        this(original, false);
-    }
-
-    public MimeMessageCopyOnWriteProxy(MimeMessageSource original) throws 
MessagingException {
-        this(new MimeMessageWrapper(original), true);
-    }
-
-    /**
-     * Private constructor providing an external reference counter.
-     */
-    private MimeMessageCopyOnWriteProxy(MimeMessage original, boolean 
writeable) {
-        super(Session.getDefaultInstance(System.getProperties(), null));
-
-        if (original instanceof MimeMessageCopyOnWriteProxy) {
-            refCount = ((MimeMessageCopyOnWriteProxy) original).refCount;
-        } else {
-            refCount = new MessageReferenceTracker(original);
-        }
-
-        if (!writeable) {
-            refCount.incrementReferenceCount();
-        }
-    }
-
-    /**
-     * Check the number of references over the MimeMessage and clone it if
-     * needed before returning the reference
-     * 
-     * @throws MessagingException
-     *             exception
-     */
-    protected synchronized MimeMessage getWrappedMessageForWriting() throws 
MessagingException {
-        if (refCount.getReferenceCount() > 1) {
-            refCount.decrementReferenceCount();
-            refCount = new MessageReferenceTracker(new 
MimeMessageWrapper(refCount.getWrapped()));
-        }
-        return refCount.getWrapped();
-    }
-
-    /**
-     * Return wrapped mimeMessage
-     * 
-     * @return wrapped return the wrapped mimeMessage
-     */
-    public synchronized MimeMessage getWrappedMessage() {
-        return refCount.getWrapped();
-    }
-
-    @Override
-    public synchronized void dispose() {
-        if (refCount != null) {
-            refCount.decrementReferenceCount();
-            refCount = null;
-        }
-    }
-
-    @Override
-    public void writeTo(OutputStream os) throws IOException, 
MessagingException {
-        getWrappedMessage().writeTo(os);
-    }
-
-    /**
-     * Rewritten for optimization purposes
-     */
-    @Override
-    public void writeTo(OutputStream os, String[] ignoreList) throws 
IOException, MessagingException {
-        getWrappedMessage().writeTo(os, ignoreList);
-    }
-
-    /*
-     * Various reader methods
-     */
-
-    @Override
-    public Address[] getFrom() throws MessagingException {
-        return getWrappedMessage().getFrom();
-    }
-
-    @Override
-    public Address[] getRecipients(Message.RecipientType type) throws 
MessagingException {
-        return getWrappedMessage().getRecipients(type);
-    }
-
-    @Override
-    public Address[] getAllRecipients() throws MessagingException {
-        return getWrappedMessage().getAllRecipients();
-    }
-
-    @Override
-    public Address[] getReplyTo() throws MessagingException {
-        return getWrappedMessage().getReplyTo();
-    }
-
-    @Override
-    public String getSubject() throws MessagingException {
-        return getWrappedMessage().getSubject();
-    }
-
-    @Override
-    public Date getSentDate() throws MessagingException {
-        return getWrappedMessage().getSentDate();
-    }
-
-    @Override
-    public Date getReceivedDate() throws MessagingException {
-        return getWrappedMessage().getReceivedDate();
-    }
-
-    @Override
-    public int getSize() throws MessagingException {
-        return getWrappedMessage().getSize();
-    }
-
-    @Override
-    public int getLineCount() throws MessagingException {
-        return getWrappedMessage().getLineCount();
-    }
-
-    @Override
-    public String getContentType() throws MessagingException {
-        return getWrappedMessage().getContentType();
-    }
-
-    @Override
-    public boolean isMimeType(String mimeType) throws MessagingException {
-        return getWrappedMessage().isMimeType(mimeType);
-    }
-
-    @Override
-    public String getDisposition() throws MessagingException {
-        return getWrappedMessage().getDisposition();
-    }
-
-    @Override
-    public String getEncoding() throws MessagingException {
-        return getWrappedMessage().getEncoding();
-    }
-
-    @Override
-    public String getContentID() throws MessagingException {
-        return getWrappedMessage().getContentID();
-    }
-
-    @Override
-    public String getContentMD5() throws MessagingException {
-        return getWrappedMessage().getContentMD5();
-    }
-
-    @Override
-    public String getDescription() throws MessagingException {
-        return getWrappedMessage().getDescription();
-    }
-
-    @Override
-    public String[] getContentLanguage() throws MessagingException {
-        return getWrappedMessage().getContentLanguage();
-    }
-
-    @Override
-    public String getMessageID() throws MessagingException {
-        return getWrappedMessage().getMessageID();
-    }
-
-    @Override
-    public String getFileName() throws MessagingException {
-        return getWrappedMessage().getFileName();
-    }
-
-    @Override
-    public InputStream getInputStream() throws IOException, MessagingException 
{
-        return getWrappedMessage().getInputStream();
-    }
-
-    @Override
-    public DataHandler getDataHandler() throws MessagingException {
-        return getWrappedMessage().getDataHandler();
-    }
-
-    @Override
-    public Object getContent() throws IOException, MessagingException {
-        return getWrappedMessage().getContent();
-    }
-
-    @Override
-    public String[] getHeader(String name) throws MessagingException {
-        return getWrappedMessage().getHeader(name);
-    }
-
-    @Override
-    public String getHeader(String name, String delimiter) throws 
MessagingException {
-        return getWrappedMessage().getHeader(name, delimiter);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public Enumeration<String> getAllHeaders() throws MessagingException {
-        return getWrappedMessage().getAllHeaders();
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public Enumeration<String> getMatchingHeaders(String[] names) throws 
MessagingException {
-        return getWrappedMessage().getMatchingHeaders(names);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public Enumeration<String> getNonMatchingHeaders(String[] names) throws 
MessagingException {
-        return getWrappedMessage().getNonMatchingHeaders(names);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public Enumeration<String> getAllHeaderLines() throws MessagingException {
-        return getWrappedMessage().getAllHeaderLines();
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public Enumeration<String> getMatchingHeaderLines(String[] names) throws 
MessagingException {
-        return getWrappedMessage().getMatchingHeaderLines(names);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public Enumeration<String> getNonMatchingHeaderLines(String[] names) 
throws MessagingException {
-        return getWrappedMessage().getNonMatchingHeaderLines(names);
-    }
-
-    @Override
-    public Flags getFlags() throws MessagingException {
-        return getWrappedMessage().getFlags();
-    }
-
-    @Override
-    public boolean isSet(Flags.Flag flag) throws MessagingException {
-        return getWrappedMessage().isSet(flag);
-    }
-
-    @Override
-    public Address getSender() throws MessagingException {
-        return getWrappedMessage().getSender();
-    }
-
-    @Override
-    public boolean match(SearchTerm arg0) throws MessagingException {
-        return getWrappedMessage().match(arg0);
-    }
-
-    @Override
-    public InputStream getRawInputStream() throws MessagingException {
-        return getWrappedMessage().getRawInputStream();
-    }
-
-    @Override
-    public Folder getFolder() {
-        return getWrappedMessage().getFolder();
-    }
-
-    @Override
-    public int getMessageNumber() {
-        return getWrappedMessage().getMessageNumber();
-    }
-
-    @Override
-    public boolean isExpunged() {
-        return getWrappedMessage().isExpunged();
-    }
-
-    @Override
-    public boolean equals(Object arg0) {
-        return getWrappedMessage().equals(arg0);
-    }
-
-    @Override
-    public int hashCode() {
-        return getWrappedMessage().hashCode();
-    }
-
-    @Override
-    public String toString() {
-        return getWrappedMessage().toString();
-    }
-
-    @Override
-    public void setFrom(Address address) throws MessagingException {
-        getWrappedMessageForWriting().setFrom(address);
-    }
-
-    @Override
-    public void setFrom() throws MessagingException {
-        getWrappedMessageForWriting().setFrom();
-    }
-
-    @Override
-    public void addFrom(Address[] addresses) throws MessagingException {
-        getWrappedMessageForWriting().addFrom(addresses);
-    }
-
-    @Override
-    public void setRecipients(Message.RecipientType type, Address[] addresses) 
throws MessagingException {
-        getWrappedMessageForWriting().setRecipients(type, addresses);
-    }
-
-    @Override
-    public void addRecipients(Message.RecipientType type, Address[] addresses) 
throws MessagingException {
-        getWrappedMessageForWriting().addRecipients(type, addresses);
-    }
-
-    @Override
-    public void setReplyTo(Address[] addresses) throws MessagingException {
-        getWrappedMessageForWriting().setReplyTo(addresses);
-    }
-
-    @Override
-    public void setSubject(String subject) throws MessagingException {
-        getWrappedMessageForWriting().setSubject(subject);
-    }
-
-    @Override
-    public void setSubject(String subject, String charset) throws 
MessagingException {
-        getWrappedMessageForWriting().setSubject(subject, charset);
-    }
-
-    @Override
-    public void setSentDate(Date d) throws MessagingException {
-        getWrappedMessageForWriting().setSentDate(d);
-    }
-
-    @Override
-    public void setDisposition(String disposition) throws MessagingException {
-        getWrappedMessageForWriting().setDisposition(disposition);
-    }
-
-    @Override
-    public void setContentID(String cid) throws MessagingException {
-        getWrappedMessageForWriting().setContentID(cid);
-    }
-
-    @Override
-    public void setContentMD5(String md5) throws MessagingException {
-        getWrappedMessageForWriting().setContentMD5(md5);
-    }
-
-    @Override
-    public void setDescription(String description) throws MessagingException {
-        getWrappedMessageForWriting().setDescription(description);
-    }
-
-    @Override
-    public void setDescription(String description, String charset) throws 
MessagingException {
-        getWrappedMessageForWriting().setDescription(description, charset);
-    }
-
-    @Override
-    public void setContentLanguage(String[] languages) throws 
MessagingException {
-        getWrappedMessageForWriting().setContentLanguage(languages);
-    }
-
-    @Override
-    public void setFileName(String filename) throws MessagingException {
-        getWrappedMessageForWriting().setFileName(filename);
-    }
-
-    @Override
-    public void setDataHandler(DataHandler dh) throws MessagingException {
-        getWrappedMessageForWriting().setDataHandler(dh);
-    }
-
-    @Override
-    public void setContent(Object o, String type) throws MessagingException {
-        getWrappedMessageForWriting().setContent(o, type);
-    }
-
-    @Override
-    public void setText(String text) throws MessagingException {
-        getWrappedMessageForWriting().setText(text);
-    }
-
-    @Override
-    public void setText(String text, String charset) throws MessagingException 
{
-        getWrappedMessageForWriting().setText(text, charset);
-    }
-
-    @Override
-    public void setContent(Multipart mp) throws MessagingException {
-        getWrappedMessageForWriting().setContent(mp);
-    }
-
-    /**
-     * This does not need a writable message
-     */
-    @Override
-    public Message reply(boolean replyToAll) throws MessagingException {
-        return getWrappedMessage().reply(replyToAll);
-    }
-
-    @Override
-    public void setHeader(String name, String value) throws MessagingException 
{
-        getWrappedMessageForWriting().setHeader(name, value);
-    }
-
-    @Override
-    public void addHeader(String name, String value) throws MessagingException 
{
-        getWrappedMessageForWriting().addHeader(name, value);
-    }
-
-    @Override
-    public void removeHeader(String name) throws MessagingException {
-        getWrappedMessageForWriting().removeHeader(name);
-    }
-
-    @Override
-    public void addHeaderLine(String line) throws MessagingException {
-        getWrappedMessageForWriting().addHeaderLine(line);
-    }
-
-    @Override
-    public void setFlags(Flags flag, boolean set) throws MessagingException {
-        getWrappedMessageForWriting().setFlags(flag, set);
-    }
-
-    @Override
-    public void saveChanges() throws MessagingException {
-        getWrappedMessageForWriting().saveChanges();
-    }
-
-    /*
-     * Since JavaMail 1.2
-     */
-
-    @Override
-    public void addRecipients(Message.RecipientType type, String addresses) 
throws MessagingException {
-        getWrappedMessageForWriting().addRecipients(type, addresses);
-    }
-
-    @Override
-    public void setRecipients(Message.RecipientType type, String addresses) 
throws MessagingException {
-        getWrappedMessageForWriting().setRecipients(type, addresses);
-    }
-
-    @Override
-    public void setSender(Address arg0) throws MessagingException {
-        getWrappedMessageForWriting().setSender(arg0);
-    }
-
-    public void addRecipient(RecipientType arg0, Address arg1) throws 
MessagingException {
-        getWrappedMessageForWriting().addRecipient(arg0, arg1);
-    }
-
-    @Override
-    public void setFlag(Flag arg0, boolean arg1) throws MessagingException {
-        getWrappedMessageForWriting().setFlag(arg0, arg1);
-    }
-
-    public long getMessageSize() throws MessagingException {
-        return MimeMessageUtil.getMessageSize(getWrappedMessage());
-    }
-
-    /**
-     * Since javamail 1.4
-     */
-    @Override
-    public void setText(String text, String charset, String subtype) throws 
MessagingException {
-        getWrappedMessage().setText(text, charset, subtype);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/MimeMessageInputStream.java
----------------------------------------------------------------------
diff --git 
a/server/container/core/src/main/java/org/apache/james/core/MimeMessageInputStream.java
 
b/server/container/core/src/main/java/org/apache/james/core/MimeMessageInputStream.java
deleted file mode 100644
index f4ea3a7..0000000
--- 
a/server/container/core/src/main/java/org/apache/james/core/MimeMessageInputStream.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/****************************************************************
- * 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.core;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.mail.MessagingException;
-import javax.mail.internet.MimeMessage;
-
-/**
- * Provide an {@link InputStream} over an {@link MimeMessage}
- */
-public class MimeMessageInputStream extends InputStream {
-    private final InputStream in;
-
-    /**
-     * Provide an {@link InputStream} over a {@link MimeMessage}.
-     * 
-     * @param message
-     *            the message to wrap
-     * @param tryCast
-     *            try to cast the {@link MimeMessage} to
-     *            {@link MimeMessageCopyOnWriteProxy} /
-     *            {@link MimeMessageWrapper} to do some optimized processing if
-     *            possible
-     * @throws MessagingException
-     */
-    public MimeMessageInputStream(MimeMessage message, boolean tryCast) throws 
MessagingException {
-        MimeMessage m = message;
-
-        // check if we need to use the wrapped message
-        if (tryCast && m instanceof MimeMessageCopyOnWriteProxy) {
-            m = ((MimeMessageCopyOnWriteProxy) m).getWrappedMessage();
-        }
-
-        // check if we can use optimized operations
-        if (tryCast && m instanceof MimeMessageWrapper) {
-            in = ((MimeMessageWrapper) m).getMessageInputStream();
-        } else {
-
-            ByteArrayOutputStream out = new ByteArrayOutputStream();
-            try {
-                message.writeTo(out);
-                in = new ByteArrayInputStream(out.toByteArray());
-            } catch (IOException e1) {
-                throw new MessagingException("Unable to read message " + 
message, e1);
-            }
-
-        }
-
-    }
-
-    /**
-     * Use true as tryCast parameter
-     * 
-     * {@link #MimeMessageInputStream(MimeMessage, boolean)}
-     */
-    public MimeMessageInputStream(MimeMessage message) throws 
MessagingException {
-        this(message, true);
-    }
-
-    @Override
-    public int read() throws IOException {
-        return in.read();
-    }
-
-    @Override
-    public void close() throws IOException {
-        in.close();
-    }
-
-    @Override
-    public int available() throws IOException {
-        return in.available();
-    }
-
-    @Override
-    public void mark(int readlimit) {
-        in.mark(readlimit);
-    }
-
-    @Override
-    public boolean markSupported() {
-        return in.markSupported();
-    }
-
-    @Override
-    public int read(byte[] b, int off, int len) throws IOException {
-        return in.read(b, off, len);
-    }
-
-    @Override
-    public int read(byte[] b) throws IOException {
-        return in.read(b);
-    }
-
-    @Override
-    public void reset() throws IOException {
-        in.reset();
-    }
-
-    @Override
-    public long skip(long n) throws IOException {
-        return in.skip(n);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/MimeMessageInputStreamSource.java
----------------------------------------------------------------------
diff --git 
a/server/container/core/src/main/java/org/apache/james/core/MimeMessageInputStreamSource.java
 
b/server/container/core/src/main/java/org/apache/james/core/MimeMessageInputStreamSource.java
deleted file mode 100644
index 46d1afd..0000000
--- 
a/server/container/core/src/main/java/org/apache/james/core/MimeMessageInputStreamSource.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/****************************************************************
- * 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.core;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.mail.MessagingException;
-import javax.mail.util.SharedByteArrayInputStream;
-import javax.mail.util.SharedFileInputStream;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.output.DeferredFileOutputStream;
-import org.apache.james.lifecycle.api.Disposable;
-
-/**
- * Takes an input stream and creates a repeatable input stream source for a
- * MimeMessageWrapper. It does this by completely reading the input stream and
- * saving that to data to an {@link DeferredFileOutputStream} with its 
threshold set to 100kb
- */
-public class MimeMessageInputStreamSource extends MimeMessageSource implements 
Disposable {
-
-    private final List<InputStream> streams = new ArrayList<>();
-
-    /**
-     * A temporary file used to hold the message stream
-     */
-    private DeferredFileOutputStream out;
-
-    /**
-     * The full path of the temporary file
-     */
-    private final String sourceId;
-
-    /**
-     * 100kb threshold for the stream.
-     */
-    private final static int THRESHOLD = 1024 * 100;
-
-    /**
-     * Temporary directory to use
-     */
-    private final static File TMPDIR = new 
File(System.getProperty("java.io.tmpdir"));
-
-    /**
-     * Construct a new MimeMessageInputStreamSource from an
-     * <code>InputStream</code> that contains the bytes of a MimeMessage.
-     *
-     * @param key the prefix for the name of the temp file
-     * @param in  the stream containing the MimeMessage
-     * @throws MessagingException if an error occurs while trying to store the 
stream
-     */
-    public MimeMessageInputStreamSource(String key, InputStream in) throws 
MessagingException {
-        super();
-        // We want to immediately read this into a temporary file
-        // Create a temp file and channel the input stream into it
-        try {
-            out = new DeferredFileOutputStream(THRESHOLD, "mimemessage-" + 
key, ".m64", TMPDIR);
-            IOUtils.copy(in, out);
-            sourceId = key;
-        } catch (IOException ioe) {
-            File file = out.getFile();
-            if (file != null) {
-                FileUtils.deleteQuietly(file);
-            }
-            throw new MessagingException("Unable to retrieve the data: " + 
ioe.getMessage(), ioe);
-        } finally {
-            try {
-                if (out != null) {
-                    out.close();
-                }
-            } catch (IOException ioe) {
-                // Ignored - logging unavailable to log this non-fatal error.
-            }
-
-            try {
-                if (in != null) {
-                    in.close();
-                }
-            } catch (IOException ioe) {
-                // Ignored - logging unavailable to log this non-fatal error.
-            }
-
-        }
-    }
-
-    public MimeMessageInputStreamSource(String key) {
-        super();
-        out = new DeferredFileOutputStream(THRESHOLD, key, ".m64", TMPDIR);
-        sourceId = key;
-    }
-
-    /**
-     * Returns the unique identifier of this input stream source
-     *
-     * @return the unique identifier for this MimeMessageInputStreamSource
-     */
-    public String getSourceId() {
-        return sourceId;
-    }
-
-    /**
-     * Get an input stream to retrieve the data stored in the temporary file
-     *
-     * @return a <code>BufferedInputStream</code> containing the data
-     */
-    public synchronized InputStream getInputStream() throws IOException {
-        InputStream in;
-        if (out.isInMemory()) {
-            in = new SharedByteArrayInputStream(out.getData());
-        } else {
-            in = new SharedFileInputStream(out.getFile());
-        }
-        streams.add(in);
-        return in;
-    }
-
-    /**
-     * Get the size of the temp file
-     *
-     * @return the size of the temp file
-     * @throws IOException if an error is encoutered while computing the size 
of the
-     *                     message
-     */
-    @Override
-    public long getMessageSize() throws IOException {
-        return out.getByteCount();
-    }
-
-    public OutputStream getWritableOutputStream() {
-        return out;
-    }
-
-    @Override
-    public void dispose() {
-        // explicit close all streams
-        for (InputStream stream : streams) {
-            IOUtils.closeQuietly(stream);
-        }
-
-        if (out != null) {
-            IOUtils.closeQuietly(out);
-            File file = out.getFile();
-            if (file != null) {
-                FileUtils.deleteQuietly(file);
-                file = null;
-            }
-            out = null;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/MimeMessageSource.java
----------------------------------------------------------------------
diff --git 
a/server/container/core/src/main/java/org/apache/james/core/MimeMessageSource.java
 
b/server/container/core/src/main/java/org/apache/james/core/MimeMessageSource.java
deleted file mode 100644
index 57e1e23..0000000
--- 
a/server/container/core/src/main/java/org/apache/james/core/MimeMessageSource.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/****************************************************************
- * 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.core;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * This defines a reusable datasource that can supply an input stream with
- * MimeMessage data. This allows a MimeMessageWrapper or other classes to grab
- * the underlying data.
- * 
- * @see MimeMessageWrapper
- */
-public abstract class MimeMessageSource {
-
-    /**
-     * Returns a unique String ID that represents the location from where this
-     * file is loaded. This will be used to identify where the data is,
-     * primarily to avoid situations where this data would get overwritten.
-     * 
-     * @return the String ID
-     */
-    public abstract String getSourceId();
-
-    /**
-     * Get an input stream to retrieve the data stored in the datasource
-     * 
-     * @return a <code>InputStream</code> containing the data
-     * 
-     * @throws IOException
-     *             if an error occurs while generating the InputStream
-     */
-    public abstract InputStream getInputStream() throws IOException;
-
-    /**
-     * Return the size of all the data. Default implementation... others can
-     * override to do this much faster
-     * 
-     * @return the size of the data represented by this source
-     * @throws IOException
-     *             if an error is encountered while computing the message size
-     */
-    public long getMessageSize() throws IOException {
-        int size = 0;
-        InputStream in = null;
-        try {
-            in = getInputStream();
-            int read;
-            byte[] data = new byte[1024];
-            while ((read = in.read(data)) > 0) {
-                size += read;
-            }
-        } finally {
-            try {
-                if (in != null) {
-                    in.close();
-                }
-            } catch (IOException ioe) {
-                // Exception ignored because logging is
-                // unavailable
-            }
-        }
-        return size;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/MimeMessageUtil.java
----------------------------------------------------------------------
diff --git 
a/server/container/core/src/main/java/org/apache/james/core/MimeMessageUtil.java
 
b/server/container/core/src/main/java/org/apache/james/core/MimeMessageUtil.java
deleted file mode 100644
index 5ee7a49..0000000
--- 
a/server/container/core/src/main/java/org/apache/james/core/MimeMessageUtil.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/****************************************************************
- * 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.core;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Enumeration;
-
-import javax.activation.UnsupportedDataTypeException;
-import javax.mail.MessagingException;
-import javax.mail.internet.MimeMessage;
-import javax.mail.internet.MimeUtility;
-
-import org.apache.commons.io.IOUtils;
-
-/**
- * Utility class to provide optimized write methods for the various MimeMessage
- * implementations.
- */
-public class MimeMessageUtil {
-
-    /**
-     * Convenience method to take any MimeMessage and write the headers and 
body
-     * to two different output streams
-     * 
-     * @param message
-     *            the MimeMessage reading from
-     * @param headerOs
-     *            the OutputStream writting the headers to
-     * @param bodyOs
-     *            the OutputStream writting the body to
-     * @throws IOException
-     *             get thrown if an IO Error detected while writing to the
-     *             streams
-     * @throws MessagingException
-     *             get thrown if an error detected while reading the message
-     */
-    public static void writeTo(MimeMessage message, OutputStream headerOs, 
OutputStream bodyOs) throws IOException, MessagingException {
-        writeTo(message, headerOs, bodyOs, null);
-    }
-
-    /**
-     * Convenience method to take any MimeMessage and write the headers and 
body
-     * to two different output streams, with an ignore list
-     * 
-     * @param message
-     *            the MimeMessage reading from
-     * @param headerOs
-     *            the OutputStream writting the headers to
-     * @param bodyOs
-     *            the OutputStream writting the body to
-     * @param ignoreList
-     *            the String[] which contains headers which should be ignored
-     * @throws IOException
-     *             get thrown if an IO Error detected while writing to the
-     *             streams
-     * @throws MessagingException
-     *             get thrown if an error detected while reading the message
-     */
-    public static void writeTo(MimeMessage message, OutputStream headerOs, 
OutputStream bodyOs, String[] ignoreList) throws IOException, 
MessagingException {
-        MimeMessage testMessage = message;
-        if (message instanceof MimeMessageCopyOnWriteProxy) {
-            MimeMessageCopyOnWriteProxy wr = (MimeMessageCopyOnWriteProxy) 
message;
-            testMessage = wr.getWrappedMessage();
-        }
-        if (testMessage instanceof MimeMessageWrapper) {
-            MimeMessageWrapper wrapper = (MimeMessageWrapper) testMessage;
-            if (!wrapper.isModified()) {
-                wrapper.writeTo(headerOs, bodyOs, ignoreList);
-                return;
-            }
-        }
-        writeToInternal(message, headerOs, bodyOs, ignoreList);
-    }
-
-    /**
-     * 
-     * @param message
-     * @param headerOs
-     * @param bodyOs
-     * @param ignoreList
-     * @throws MessagingException
-     * @throws IOException
-     * @throws UnsupportedDataTypeException
-     */
-    public static void writeToInternal(MimeMessage message, OutputStream 
headerOs, OutputStream bodyOs, String[] ignoreList) throws MessagingException, 
IOException {
-        if (message.getMessageID() == null) {
-            message.saveChanges();
-        }
-
-        writeHeadersTo(message, headerOs, ignoreList);
-
-        // Write the body to the output stream
-        writeMessageBodyTo(message, bodyOs);
-    }
-
-    /**
-     * Write message body of given mimeessage to the given outputStream
-     * 
-     * @param message
-     *            the MimeMessage used as input
-     * @param bodyOs
-     *            the OutputStream to write the message body to
-     * @throws IOException
-     * @throws UnsupportedDataTypeException
-     * @throws MessagingException
-     */
-    public static void writeMessageBodyTo(MimeMessage message, OutputStream 
bodyOs) throws IOException, MessagingException {
-        OutputStream bos;
-        InputStream bis;
-
-        try {
-            // Get the message as a stream. This will encode
-            // objects as necessary, and we have some input from
-            // decoding an re-encoding the stream. I'd prefer the
-            // raw stream, but see
-            bos = MimeUtility.encode(bodyOs, message.getEncoding());
-            bis = message.getInputStream();
-        } catch (UnsupportedDataTypeException | MessagingException udte) {
-            /*
-             * If we get an UnsupportedDataTypeException try using the raw 
input
-             * stream as a "best attempt" at rendering a message.
-             * 
-             * WARNING: JavaMail v1.3 getRawInputStream() returns INVALID
-             * (unchanged) content for a changed message. getInputStream() 
works
-             * properly, but in this case has failed due to a missing
-             * DataHandler.
-             * 
-             * MimeMessage.getRawInputStream() may throw a "no content"
-             * MessagingException. In JavaMail v1.3, when you initially create 
a
-             * message using MimeMessage APIs, there is no raw content
-             * available. getInputStream() works, but getRawInputStream() 
throws
-             * an exception. If we catch that exception, throw the UDTE. It
-             * should mean that someone has locally constructed a message part
-             * for which JavaMail doesn't have a DataHandler.
-             */
-
-            try {
-                bis = message.getRawInputStream();
-                bos = bodyOs;
-            } catch (javax.mail.MessagingException ignored) {
-                throw udte;
-            }
-        }
-
-        try {
-            IOUtils.copy(bis, bos);
-        } finally {
-            IOUtils.closeQuietly(bis);
-        }
-    }
-
-    /**
-     * Write the message headers to the given outputstream
-     * 
-     * @param message
-     *            the MimeMessage to read from
-     * @param headerOs
-     *            the OutputStream to which the headers get written
-     * @param ignoreList
-     *            the String[] which holds headers which should be ignored
-     * @throws MessagingException
-     */
-    private static void writeHeadersTo(MimeMessage message, OutputStream 
headerOs, String[] ignoreList) throws MessagingException {
-        // Write the headers (minus ignored ones)
-        @SuppressWarnings("unchecked")
-        Enumeration<String> headers = 
message.getNonMatchingHeaderLines(ignoreList);
-        writeHeadersTo(headers, headerOs);
-    }
-
-    /**
-     * Write the message headers to the given outputstream
-     * 
-     * @param headers
-     *            the Enumeration which holds the headers
-     * @param headerOs
-     *            the OutputStream to which the headers get written
-     * @throws MessagingException
-     */
-    public static void writeHeadersTo(Enumeration<String> headers, 
OutputStream headerOs) throws MessagingException {
-        try {
-            IOUtils.copy(new InternetHeadersInputStream(headers), headerOs);
-        } catch (IOException e) {
-            throw new MessagingException("Unable to write headers to stream", 
e);
-        }
-    }
-
-    /**
-     * Get an InputStream which holds all headers of the given MimeMessage
-     * 
-     * @param message
-     *            the MimeMessage used as source
-     * @param ignoreList
-     *            the String[] which holds headers which should be ignored
-     * @return stream the InputStream which holds the headers
-     * @throws MessagingException
-     */
-    @SuppressWarnings("unchecked")
-    public static InputStream getHeadersInputStream(MimeMessage message, 
String[] ignoreList) throws MessagingException {
-        return new 
InternetHeadersInputStream(message.getNonMatchingHeaderLines(ignoreList));
-    }
-
-    /**
-     * Slow method to calculate the exact size of a message!
-     */
-    private static final class SizeCalculatorOutputStream extends OutputStream 
{
-        long size = 0;
-
-        public void write(int arg0) throws IOException {
-            size++;
-        }
-
-        public long getSize() {
-            return size;
-        }
-
-        public void write(byte[] arg0, int arg1, int arg2) throws IOException {
-            size += arg2;
-        }
-
-        public void write(byte[] arg0) throws IOException {
-            size += arg0.length;
-        }
-    }
-
-    /**
-     * Return the full site of an mimeMessage
-     * 
-     * @return size of full message including headers
-     * @throws MessagingException
-     *             if a problem occours while computing the message size
-     */
-    public static long getMessageSize(MimeMessage message) throws 
MessagingException {
-        // If we have a MimeMessageWrapper, then we can ask it for just the
-        // message size and skip calculating it
-        long size = -1;
-
-        if (message instanceof MimeMessageWrapper) {
-            MimeMessageWrapper wrapper = (MimeMessageWrapper) message;
-            size = wrapper.getMessageSize();
-        } else if (message instanceof MimeMessageCopyOnWriteProxy) {
-            MimeMessageCopyOnWriteProxy wrapper = 
(MimeMessageCopyOnWriteProxy) message;
-            size = wrapper.getMessageSize();
-        }
-
-        if (size == -1) {
-            size = calculateMessageSize(message);
-        }
-
-        return size;
-    }
-
-    /**
-     * Calculate the size of the give mimeMessage
-     * 
-     * @param message
-     *            the MimeMessage
-     * @return size the calculated size
-     * @throws MessagingException
-     *             if a problem occours while calculate the message size
-     */
-    public static long calculateMessageSize(MimeMessage message) throws 
MessagingException {
-        long size;
-        // SK: Should probably eventually store this as a locally
-        // maintained value (so we don't have to load and reparse
-        // messages each time).
-        size = message.getSize();
-        if (size != -1) {
-            Enumeration<?> e = message.getAllHeaderLines();
-            if (e.hasMoreElements()) {
-                size += 2;
-            }
-            while (e.hasMoreElements()) {
-                // add 2 bytes for the CRLF
-                size += ((String) e.nextElement()).length() + 2;
-            }
-        }
-
-        if (size == -1) {
-            SizeCalculatorOutputStream out = new SizeCalculatorOutputStream();
-            try {
-                message.writeTo(out);
-            } catch (IOException e) {
-                // should never happen as SizeCalculator does not actually 
throw
-                // IOExceptions.
-                throw new MessagingException("IOException wrapped by 
getMessageSize", e);
-            }
-            size = out.getSize();
-        }
-        return size;
-    }
-
-}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org

Reply via email to