james-server-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From b...@apache.org
Subject svn commit: r385090 - in /james/server/trunk/src: java/org/apache/james/core/ java/org/apache/james/mailrepository/filepair/ java/org/apache/james/transport/mailets/ test/org/apache/james/core/
Date Sat, 11 Mar 2006 15:19:34 GMT
Author: bago
Date: Sat Mar 11 07:19:33 2006
New Revision: 385090

URL: http://svn.apache.org/viewcvs?rev=385090&view=rev
Log:
Removed wrapping from MimeMessageWrapper: now it is a simple MimeMessage extension (thanks to latest javamail providing much more protected methods than earlier releases)
Updated a few file/stream handling objects to use SharedFileInputStream so that javamail will not load the full message in memory when cloning the message. (Related to JAMES-134)
Added a bunch of tests to check consistency of the various MimeMessage implementation/constructors.
(Sorry, no "streaming support" for db repositories in this commit: still working on it)

Added:
    james/server/trunk/src/test/org/apache/james/core/MimeMessageFromMimeMessageTest.java
    james/server/trunk/src/test/org/apache/james/core/MimeMessageFromSharedStreamTest.java
    james/server/trunk/src/test/org/apache/james/core/MimeMessageFromStreamTest.java
    james/server/trunk/src/test/org/apache/james/core/MimeMessageTest.java
    james/server/trunk/src/test/org/apache/james/core/MimeMessageUtilTest.java
Modified:
    james/server/trunk/src/java/org/apache/james/core/MimeMessageCopyOnWriteProxy.java
    james/server/trunk/src/java/org/apache/james/core/MimeMessageInputStreamSource.java
    james/server/trunk/src/java/org/apache/james/core/MimeMessageUtil.java
    james/server/trunk/src/java/org/apache/james/core/MimeMessageWrapper.java
    james/server/trunk/src/java/org/apache/james/mailrepository/filepair/AbstractFileRepository.java
    james/server/trunk/src/java/org/apache/james/mailrepository/filepair/File_Persistent_Stream_Repository.java
    james/server/trunk/src/java/org/apache/james/transport/mailets/AbstractRedirect.java
    james/server/trunk/src/java/org/apache/james/transport/mailets/AddHeader.java
    james/server/trunk/src/test/org/apache/james/core/MimeMessageCopyOnWriteProxyTest.java
    james/server/trunk/src/test/org/apache/james/core/MimeMessageWrapperTest.java

Modified: james/server/trunk/src/java/org/apache/james/core/MimeMessageCopyOnWriteProxy.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/core/MimeMessageCopyOnWriteProxy.java?rev=385090&r1=385089&r2=385090&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/core/MimeMessageCopyOnWriteProxy.java (original)
+++ james/server/trunk/src/java/org/apache/james/core/MimeMessageCopyOnWriteProxy.java Sat Mar 11 07:19:33 2006
@@ -89,7 +89,7 @@
 
     }
 
-    ReferenceCounter refCount;
+    protected ReferenceCounter refCount;
 
     /**
      * @param original
@@ -756,15 +756,6 @@
     public void setFlag(Flag arg0, boolean arg1) throws MessagingException {
         checkCopyOnWrite();
         wrapped.setFlag(arg0, arg1);
-    }
-
-    /**
-     * @see javax.mail.Message#setRecipient(javax.mail.Message.RecipientType, javax.mail.Address)
-     */
-    public void setRecipient(RecipientType arg0, Address arg1)
-            throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setRecipient(arg0, arg1);
     }
 
     /**

Modified: james/server/trunk/src/java/org/apache/james/core/MimeMessageInputStreamSource.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/core/MimeMessageInputStreamSource.java?rev=385090&r1=385089&r2=385090&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/core/MimeMessageInputStreamSource.java (original)
+++ james/server/trunk/src/java/org/apache/james/core/MimeMessageInputStreamSource.java Sat Mar 11 07:19:33 2006
@@ -19,10 +19,8 @@
 
 import javax.mail.MessagingException;
 
-import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -30,6 +28,8 @@
 
 import org.apache.avalon.framework.activity.Disposable;
 
+import com.sun.mail.util.SharedFileInputStream;
+
 /**
  * Takes an input stream and creates a repeatable input stream source
  * for a MimeMessageWrapper.  It does this by completely reading the
@@ -116,7 +116,7 @@
      * @return a <code>BufferedInputStream</code> containing the data
      */
     public synchronized InputStream getInputStream() throws IOException {
-        return new BufferedInputStream(new FileInputStream(file));
+        return new SharedFileInputStream(file.getAbsolutePath());
     }
 
     /**

Modified: james/server/trunk/src/java/org/apache/james/core/MimeMessageUtil.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/core/MimeMessageUtil.java?rev=385090&r1=385089&r2=385090&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/core/MimeMessageUtil.java (original)
+++ james/server/trunk/src/java/org/apache/james/core/MimeMessageUtil.java Sat Mar 11 07:19:33 2006
@@ -25,6 +25,8 @@
 import javax.mail.internet.MimeUtility;
 
 import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -51,38 +53,29 @@
      * different output streams, with an ignore list
      */
     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;
-            MimeMessage m = wr.getWrappedMessage();
-            if (m instanceof MimeMessageWrapper) {
-                MimeMessageWrapper wrapper = (MimeMessageWrapper)m;
+            testMessage = wr.getWrappedMessage();
+        }
+        if (testMessage instanceof MimeMessageWrapper) {
+            MimeMessageWrapper wrapper = (MimeMessageWrapper)testMessage;
+            if (!wrapper.isModified()) {
                 wrapper.writeTo(headerOs, bodyOs, ignoreList);
                 return;
             }
-        } else if (message instanceof MimeMessageWrapper) {
-            MimeMessageWrapper wrapper = (MimeMessageWrapper)message;
-            wrapper.writeTo(headerOs, bodyOs, ignoreList);
-            return;
         }
         if(message.getMessageID() == null) {
             message.saveChanges();
         }
 
-        //Write the headers (minus ignored ones)
-        Enumeration headers = message.getNonMatchingHeaderLines(ignoreList);
-        PrintWriter hos = new InternetPrintWriter(new BufferedWriter(new OutputStreamWriter(headerOs), 512), true);
-        while (headers.hasMoreElements()) {
-            hos.println((String)headers.nextElement());
-        }
-        // Print header/data separator
-        hos.println();
-        hos.flush();
+        writeHeadersTo(message, headerOs, ignoreList);
 
         // Write the body to the output stream
-        writeMessageTo(message, bodyOs);
+        writeMessageBodyTo(message, bodyOs);
     }
 
-    public static void writeMessageTo(MimeMessage message, OutputStream bodyOs) throws IOException, UnsupportedDataTypeException, MessagingException {
+    public static void writeMessageBodyTo(MimeMessage message, OutputStream bodyOs) throws IOException, UnsupportedDataTypeException, MessagingException {
         OutputStream bos;
         InputStream bis;
 
@@ -160,6 +153,39 @@
             out.write(block, 0, read);
         }
         out.flush();
+    }
+
+
+    /**
+     * Write the message headers to the given outputstream
+     * 
+     * @param message
+     * @param headerOs
+     * @param ignoreList
+     * @throws MessagingException
+     */
+    private static void writeHeadersTo(MimeMessage message, OutputStream headerOs, String[] ignoreList) throws MessagingException {
+        //Write the headers (minus ignored ones)
+        Enumeration headers = message.getNonMatchingHeaderLines(ignoreList);
+        PrintWriter hos = new InternetPrintWriter(new BufferedWriter(new OutputStreamWriter(headerOs), 512), true);
+        while (headers.hasMoreElements()) {
+            hos.println((String)headers.nextElement());
+        }
+        // Print header/data separator
+        hos.println();
+        hos.flush();
+    }
+    
+    /**
+     * @param message
+     * @param ignoreList
+     * @return
+     * @throws MessagingException
+     */
+    public static InputStream getHeadersInputStream(MimeMessage message, String[] ignoreList) throws MessagingException {
+        ByteArrayOutputStream bo = new ByteArrayOutputStream();
+        writeHeadersTo(message,bo,ignoreList);
+        return new ByteArrayInputStream(bo.toByteArray());
     }
 
 

Modified: james/server/trunk/src/java/org/apache/james/core/MimeMessageWrapper.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/core/MimeMessageWrapper.java?rev=385090&r1=385089&r2=385090&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/core/MimeMessageWrapper.java (original)
+++ james/server/trunk/src/java/org/apache/james/core/MimeMessageWrapper.java Sat Mar 11 07:19:33 2006
@@ -18,43 +18,29 @@
 package org.apache.james.core;
 
 import javax.activation.DataHandler;
-import javax.mail.Address;
-import javax.mail.Flags;
-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.InternetAddress;
 import javax.mail.internet.InternetHeaders;
 import javax.mail.internet.MimeMessage;
-import javax.mail.internet.MimeUtility;
-import javax.mail.internet.NewsAddress;
-import javax.mail.search.SearchTerm;
 
-import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.io.IOException;
 import java.io.LineNumberReader;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
-import java.io.SequenceInputStream;
-import java.io.StringReader;
-import java.io.UnsupportedEncodingException;
-import java.text.ParseException;
-import java.util.Date;
 import java.util.Enumeration;
 
+import org.apache.avalon.framework.activity.Disposable;
 import org.apache.james.util.InternetPrintWriter;
 import org.apache.james.util.io.IOUtil;
 import org.apache.mailet.RFC2822Headers;
-import org.apache.mailet.dates.RFC822DateFormat;
 
-import org.apache.avalon.framework.activity.Disposable;
+import com.sun.mail.util.SharedByteArrayInputStream;
 
 /**
  * This object wraps a MimeMessage, only loading the underlying MimeMessage
@@ -68,33 +54,90 @@
     /**
      * Can provide an input stream to the data
      */
-    MimeMessageSource source = null;
+    protected MimeMessageSource source = null;
+    
     /**
-     * The Internet headers in memory
+     * This is false until we parse the message 
      */
-    MailHeaders headers = null;
+    protected boolean messageParsed = false;
+    
     /**
-     * The mime message in memory
+     * This is false until we parse the message 
      */
-    MimeMessage message = null;
+    protected boolean headersModified = false;
+    
     /**
-     * Record whether a change was made to this message
+     * This is false until we parse the message 
      */
-    boolean modified = false;
+    protected boolean bodyModified = false;
+
+    
     /**
-     * How to format a mail date
+     * A constructor that instantiates a MimeMessageWrapper based on
+     * a MimeMessageSource
+     *
+     * @param source the MimeMessageSource
+     * @throws MessagingException 
      */
-    RFC822DateFormat mailDateFormat = new RFC822DateFormat();
+    public MimeMessageWrapper(Session session, MimeMessageSource source) throws MessagingException {
+        super(session);
+        this.headers = null;
+        this.modified = false;
+        this.headersModified = false;
+        this.bodyModified = false;
+        this.source = source;
+    }
 
     /**
      * A constructor that instantiates a MimeMessageWrapper based on
      * a MimeMessageSource
      *
      * @param source the MimeMessageSource
+     * @throws MessagingException 
+     * @throws MessagingException 
      */
-    public MimeMessageWrapper(MimeMessageSource source) {
-        super(Session.getDefaultInstance(System.getProperties(), null));
-        this.source = source;
+    public MimeMessageWrapper(MimeMessageSource source) throws MessagingException {
+        this(Session.getDefaultInstance(System.getProperties()),source);
+    }
+    
+    public MimeMessageWrapper(MimeMessage original) throws MessagingException {
+        super(Session.getDefaultInstance(System.getProperties()));
+        flags = original.getFlags();
+        
+        // if the original is an unmodified MimeMessageWrapped we clone the headers and
+        // take its source.
+        if (original instanceof MimeMessageWrapper && !((MimeMessageWrapper) original).bodyModified) {
+            source = ((MimeMessageWrapper) original).source;
+            // this probably speed up things
+            if (((MimeMessageWrapper) original).headers != null) {
+                ByteArrayOutputStream temp = new ByteArrayOutputStream();
+                ((MailHeaders) ((MimeMessageWrapper) original).headers).writeTo(temp);
+                headers = createInternetHeaders(new ByteArrayInputStream(temp.toByteArray()));
+                headersModified = ((MimeMessageWrapper) original).headersModified;
+            }
+        }
+        
+        if (source == null) {
+            ByteArrayOutputStream bos;
+            int size = original.getSize();
+            if (size > 0)
+                bos = new ByteArrayOutputStream(size);
+            else
+                bos = new ByteArrayOutputStream();
+            try {
+                original.writeTo(bos);
+                bos.close();
+                SharedByteArrayInputStream bis =
+                        new SharedByteArrayInputStream(bos.toByteArray());
+                parse(bis);
+                bis.close();
+                saved = true;
+            } catch (IOException ex) {
+                // should never happen, but just in case...
+                throw new MessagingException("IOException while copying message",
+                                ex);
+            }
+        }
     }
     
     /**
@@ -106,34 +149,13 @@
         return source.getSourceId();
     }
 
-    private synchronized MailHeaders loadHeaders(InputStream is) throws MessagingException {
-
-        /* InternetHeaders can be a bit awkward to work with due to
-         * its own internal handling of header order.  This hack may
-         * not always be necessary, but for now we are trying to
-         * ensure that there is a Return-Path header, even if just a
-         * placeholder, so that later, e.g., in LocalDelivery, when we
-         * call setHeader, it will remove any other Return-Path
-         * headers, and ensure that ours is on the top. addHeader
-         * handles header order, but not setHeader. This may change in
-         * future JavaMail.  But if there are other Return-Path header
-         * values, let's drop our placeholder. */
-
-        headers = new MailHeaders(new ByteArrayInputStream((RFC2822Headers.RETURN_PATH + ": placeholder").getBytes()));
-        headers.setHeader(RFC2822Headers.RETURN_PATH, null);
-        headers.load(is);
-        String[] returnPathHeaders = headers.getHeader(RFC2822Headers.RETURN_PATH);
-        if (returnPathHeaders.length > 1) headers.setHeader(RFC2822Headers.RETURN_PATH, returnPathHeaders[1]);
-        return headers;
-    }
-
     /**
      * Load the message headers from the internal source.
      *
      * @throws MessagingException if an error is encountered while
      *                            loading the headers
      */
-    private synchronized void loadHeaders() throws MessagingException {
+    protected synchronized void loadHeaders() throws MessagingException {
         if (headers != null) {
             //Another thread has already loaded these headers
             return;
@@ -141,7 +163,7 @@
         try {
             InputStream in = source.getInputStream();
             try {
-                headers = loadHeaders(in);
+                headers = createInternetHeaders(in);
             } finally {
                 IOUtil.shutdownStream(in);
             }
@@ -156,21 +178,18 @@
      * @throws MessagingException if an error is encountered while
      *                            loading the message
      */
-    private synchronized void loadMessage() throws MessagingException {
-        if (message != null) {
+    protected synchronized void loadMessage() throws MessagingException {
+        if (messageParsed) {
             //Another thread has already loaded this message
             return;
         }
         InputStream in = null;
         try {
             in = source.getInputStream();
-            headers = loadHeaders(in);
 
-            ByteArrayInputStream headersIn
-                    = new ByteArrayInputStream(headers.toByteArray());
-            in = new SequenceInputStream(headersIn, in);
-
-            message = new MimeMessage(session, in);
+            parse(in);
+            // TODO is it ok?
+            saved = true;
             
         } catch (IOException ioe) {
             throw new MessagingException("Unable to parse stream: " + ioe.getMessage(), ioe);
@@ -180,52 +199,19 @@
     }
 
     /**
-     * Internal implementation to get InternetAddress headers
-     */
-    private Address[] getAddressHeader(String name) throws MessagingException {
-        String addr = getHeader(name, ",");
-        if (addr == null) {
-            return null;
-        } else {
-            return InternetAddress.parse(addr);
-        }
-    }
-
-
-    /**
-     * Internal implementation to find headers
-     */
-    private String getHeaderName(Message.RecipientType recipienttype) throws MessagingException {
-        String s;
-        if (recipienttype == Message.RecipientType.TO) {
-            s = RFC2822Headers.TO;
-        } else if (recipienttype == Message.RecipientType.CC) {
-            s = RFC2822Headers.CC;
-        } else if (recipienttype == Message.RecipientType.BCC) {
-            s = RFC2822Headers.BCC;
-        } else if (recipienttype == RecipientType.NEWSGROUPS) {
-            s = "Newsgroups";
-        } else {
-            throw new MessagingException("Invalid Recipient Type");
-        }
-        return s;
-    }
-
-
-    /**
      * Get whether the message has been modified.
      *
      * @return whether the message has been modified
      */
     public boolean isModified() {
-        return modified;
+        return headersModified || bodyModified || modified;
     }
 
     /**
      * Rewritten for optimization purposes
      */
     public void writeTo(OutputStream os) throws IOException, MessagingException {
-        if (message == null || !isModified()) {
+        if (!isModified()) {
             // We do not want to instantiate the message... just read from source
             // and write to this outputstream
             InputStream in = source.getInputStream();
@@ -254,7 +240,7 @@
     }
 
     public void writeTo(OutputStream headerOs, OutputStream bodyOs, String[] ignoreList) throws IOException, MessagingException {
-        if (message == null || !isModified()) {
+        if (!isModified()) {
             //We do not want to instantiate the message... just read from source
             //  and write to this outputstream
 
@@ -274,140 +260,20 @@
                 IOUtil.shutdownStream(in);
             }
         } else {
-            MimeMessageUtil.writeTo(message, headerOs, bodyOs, ignoreList);
-        }
-    }
-
-    /**
-     * Various reader methods
-     */
-    public Address[] getFrom() throws MessagingException {
-        if (headers == null) {
-            loadHeaders();
-        }
-        Address from[] = getAddressHeader(RFC2822Headers.FROM);
-        if(from == null) {
-            from = getAddressHeader(RFC2822Headers.SENDER);
-        }
-        return from;
-    }
-
-    public Address[] getRecipients(Message.RecipientType type) throws MessagingException {
-        if (headers == null) {
-            loadHeaders();
-        }
-        if (type == RecipientType.NEWSGROUPS) {
-            String s = headers.getHeader("Newsgroups", ",");
-            if(s == null) {
-                return null;
-            } else {
-                return NewsAddress.parse(s);
-            }
-        } else {
-            return getAddressHeader(getHeaderName(type));
-        }
-    }
-
-    public Address[] getAllRecipients() throws MessagingException {
-        if (headers == null) {
-            loadHeaders();
-        }
-        Address toAddresses[] = getRecipients(RecipientType.TO);
-        Address ccAddresses[] = getRecipients(RecipientType.CC);
-        Address bccAddresses[] = getRecipients(RecipientType.BCC);
-        Address newsAddresses[] = getRecipients(RecipientType.NEWSGROUPS);
-        if(ccAddresses == null && bccAddresses == null && newsAddresses == null) {
-            return toAddresses;
-        }
-        int i = (toAddresses == null ? 0 : toAddresses.length)
-                + (ccAddresses == null ? 0 : ccAddresses.length)
-                + (bccAddresses == null ? 0 : bccAddresses.length)
-                + (newsAddresses == null ? 0 : newsAddresses.length);
-        Address allAddresses[] = new Address[i];
-        int j = 0;
-        if (toAddresses != null) {
-            System.arraycopy(toAddresses, 0, allAddresses, j, toAddresses.length);
-            j += toAddresses.length;
-        }
-        if(ccAddresses != null) {
-            System.arraycopy(ccAddresses, 0, allAddresses, j, ccAddresses.length);
-            j += ccAddresses.length;
-        }
-        if(bccAddresses != null) {
-            System.arraycopy(bccAddresses, 0, allAddresses, j, bccAddresses.length);
-            j += bccAddresses.length;
-        }
-        if(newsAddresses != null) {
-            System.arraycopy(newsAddresses, 0, allAddresses, j, newsAddresses.length);
-            j += newsAddresses.length;
-        }
-        return allAddresses;
-    }
-
-    public Address[] getReplyTo() throws MessagingException {
-        if (headers == null) {
-            loadHeaders();
-        }
-        Address replyTo[] = getAddressHeader(RFC2822Headers.REPLY_TO);
-        if(replyTo == null) {
-            replyTo = getFrom();
-        }
-        return replyTo;
-    }
-
-    public String getSubject() throws MessagingException {
-        if (headers == null) {
-            loadHeaders();
-        }
-        String subject = getHeader(RFC2822Headers.SUBJECT, null);
-        if (subject == null) {
-            return null;
-        }
-        try {
-            return MimeUtility.decodeText(unfold(subject));
-        } catch(UnsupportedEncodingException _ex) {
-            return subject;
-        }
-    }
-
-    public Date getSentDate() throws MessagingException {
-        if (headers == null) {
-            loadHeaders();
-        }
-        String header = getHeader(RFC2822Headers.DATE, null);
-        if(header != null) {
-            try {
-                return mailDateFormat.parse(header);
-            } catch(ParseException _ex) {
-                return null;
-            }
-        } else {
-            return null;
+            MimeMessageUtil.writeTo(this, headerOs, bodyOs, ignoreList);
         }
     }
 
     /**
-     * We do not attempt to define the received date, although in theory this is the last
-     * most date in the Received: headers.  For now we return null, which means we are
-     * not implementing it.
-     */
-    public Date getReceivedDate() throws MessagingException {
-        if (headers == null) {
-            loadHeaders();
-        }
-        return null;
-    }
-
-    /**
      * This is the MimeMessage implementation - this should return ONLY the
      * body, not the entire message (should not count headers).  Will have
      * to parse the message.
      */
     public int getSize() throws MessagingException {
-        if (message == null) {
+        if (!messageParsed) {
             loadMessage();
         }
-        return message.getSize();
+        return super.getSize();
     }
 
     /**
@@ -454,108 +320,13 @@
             throw new MessagingException("Error retrieving message size", ioe);
         }
     }
-
-    public String getContentType() throws MessagingException {
-        if (headers == null) {
-            loadHeaders();
-        }
-        String value = getHeader(RFC2822Headers.CONTENT_TYPE, null);
-        if (value == null) {
-            return "text/plain";
-        } else {
-            return value;
-        }
-    }
-
-    public boolean isMimeType(String mimeType) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        return message.isMimeType(mimeType);
-    }
-
-    public String getDisposition() throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        return message.getDisposition();
-    }
-
-    public String getEncoding() throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        return message.getEncoding();
-    }
-
-    public String getContentID() throws MessagingException {
-        if (headers == null) {
-            loadHeaders();
-        }
-        return getHeader("Content-Id", null);
-    }
-
-    public String getContentMD5() throws MessagingException {
-        if (headers == null) {
-            loadHeaders();
-        }
-        return getHeader("Content-MD5", null);
-    }
-
-    public String getDescription() throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        return message.getDescription();
-    }
-
-    public String[] getContentLanguage() throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        return message.getContentLanguage();
-    }
-
-    public String getMessageID() throws MessagingException {
-        if (headers == null) {
-            loadHeaders();
-        }
-        return getHeader(RFC2822Headers.MESSAGE_ID, null);
-    }
-
-    public String getFileName() throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        return message.getFileName();
-    }
-
-    public InputStream getInputStream() throws IOException, MessagingException {
-        if (message == null) {
-            //This is incorrect... supposed to return a decoded inputstream of
-            //  the message body
-            //return source.getInputStream();
-            loadMessage();
-            return message.getInputStream();
-        } else {
-            return message.getInputStream();
-        }
-    }
-
-    public DataHandler getDataHandler() throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        return message.getDataHandler();
-    }
-
-    public Object getContent() throws IOException, MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        return message.getContent();
-    }
-
+    
+    
+    /**
+     * We override all the "headers" access methods to be sure that we
+     * loaded the headers 
+     */
+    
     public String[] getHeader(String name) throws MessagingException {
         if (headers == null) {
             loadHeaders();
@@ -612,398 +383,115 @@
         return headers.getNonMatchingHeaderLines(names);
     }
 
-    public Flags getFlags() throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        return message.getFlags();
-    }
-
-    public boolean isSet(Flags.Flag flag) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        return message.isSet(flag);
-    }
-
-
-    /**
-     * Writes content only, ie not headers, to the specified OutputStream.
-     *
-     * @param outs the OutputStream to which the content is written
-     */
-    public void writeContentTo(OutputStream outs)
-            throws java.io.IOException, MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        InputStream in = getContentStream();
-        try {
-            MimeMessageUtil.copyStream(in, outs);
-        } finally {
-            IOUtil.shutdownStream(in);
-        }
-    }
-
-    /*
-     * Various writer methods
-     */
 
-    public void setFrom(Address address) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setFrom(address);
-    }
-
-    public void setFrom() throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setFrom();
-    }
-
-    public void addFrom(Address[] addresses) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.addFrom(addresses);
-    }
-
-    public void setRecipients(Message.RecipientType type, Address[] addresses) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setRecipients(type, addresses);
-    }
-
-    public void addRecipients(Message.RecipientType type, Address[] addresses) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.addRecipients(type, addresses);
-    }
-
-    public void setReplyTo(Address[] addresses) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setReplyTo(addresses);
-    }
-
-    public void setSubject(String subject) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        headers.setHeader(RFC2822Headers.SUBJECT, subject);
-        message.setSubject(subject);
-    }
-
-    public void setSubject(String subject, String charset) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        // is this correct?
-        try {
-            headers.setHeader(RFC2822Headers.SUBJECT, new String(subject.getBytes(charset)));
-        }
-        catch (java.io.UnsupportedEncodingException _) { /* TODO */ }
-        message.setSubject(subject, charset);
-    }
-
-    public void setSentDate(Date d) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        headers.setHeader(RFC2822Headers.DATE, mailDateFormat.format(d));
-        message.setSentDate(d);
-    }
-
-    public void setDisposition(String disposition) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setDisposition(disposition);
-    }
-
-    public void setContentID(String cid) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setContentID(cid);
-    }
-
-    public void setContentMD5(String md5) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setContentMD5(md5);
-    }
-
-    public void setDescription(String description) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setDescription(description);
-    }
-
-    public void setDescription(String description, String charset) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setDescription(description, charset);
-    }
-
-    public void setContentLanguage(String[] languages) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setContentLanguage(languages);
-    }
-
-    public void setFileName(String filename) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setFileName(filename);
-    }
-
-    public void setDataHandler(DataHandler dh) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setDataHandler(dh);
-    }
-
-    public void setContent(Object o, String type) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setContent(o, type);
-    }
-
-    public void setText(String text) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setText(text);
-    }
-
-    public void setText(String text, String charset) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setText(text, charset);
-    }
-
-    public void setContent(Multipart mp) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setContent(mp);
-    }
-
-    public Message reply(boolean replyToAll) throws MessagingException {
-        if (message == null) {
-            loadMessage();
+    private void checkModifyHeaders() throws MessagingException {
+        if (headers == null) {
+            loadHeaders();
         }
         modified = true;
-        return message.reply(replyToAll);
+        headersModified = true;
     }
 
     public void setHeader(String name, String value) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        headers.setHeader(name, value);
-        message.setHeader(name, value);
+        checkModifyHeaders();
+        super.setHeader(name, value);
     }
 
     public void addHeader(String name, String value) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        headers.addHeader(name, value);
-        message.addHeader(name, value);
+        checkModifyHeaders();
+        super.addHeader(name, value);
     }
 
     public void removeHeader(String name) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        headers.removeHeader(name);
-        message.removeHeader(name);
+        checkModifyHeaders();
+        super.removeHeader(name);
     }
 
     public void addHeaderLine(String line) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        headers.addHeaderLine(line);
-        message.addHeaderLine(line);
-    }
-
-    public void setFlags(Flags flag, boolean set) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setFlags(flag, set);
+        checkModifyHeaders();
+        super.addHeaderLine(line);
     }
 
-    public void saveChanges() throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.saveChanges();
-    }
 
-    /*
-     * Since JavaMail 1.2
+    /**
+     * The message is changed when working with headers and when altering the content.
+     * Every method that alter the content will fallback to this one.
+     * 
+     * @see javax.mail.Part#setDataHandler(javax.activation.DataHandler)
      */
-    public InputStream getRawInputStream() throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        return message.getRawInputStream();
-    }
-
-    public void addRecipients(Message.RecipientType type, String addresses) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
+    public synchronized void setDataHandler(DataHandler arg0) throws MessagingException {
         modified = true;
-        message.addRecipients(type, addresses);
+        bodyModified = true;
+        super.setDataHandler(arg0);
     }
 
-    public void setRecipients(Message.RecipientType type, String addresses) throws MessagingException {
-        if (message == null) {
-            loadMessage();
+    /**
+     * @see org.apache.avalon.framework.activity.Disposable#dispose()
+     */
+    public void dispose() {
+        if (source instanceof Disposable) {
+            ((Disposable)source).dispose();
         }
-        modified = true;
-        message.setRecipients(type, addresses);
     }
 
-    /*
-     * Since JavaMail 1.3
+    /**
+     * TODO fixme
+     * @see javax.mail.internet.MimeMessage#parse(java.io.InputStream)
      */
-    public Address getSender() throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        return message.getSender();
+    protected void parse(InputStream is) throws MessagingException {
+        // the super implementation calls
+        // headers = createInternetHeaders(is);
+        super.parse(is);
+        messageParsed = true;
     }
 
-    public void setSender(Address arg0) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setSender(arg0);
-    }
+    /**
+     * If we already parsed the headers then we simply return the updated ones.
+     * Otherwise we parse
+     * 
+     * @see javax.mail.internet.MimeMessage#createInternetHeaders(java.io.InputStream)
+     */
+    protected InternetHeaders createInternetHeaders(InputStream is) throws MessagingException {
 
-    public void addRecipient(RecipientType arg0, Address arg1) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.addRecipient(arg0,arg1);
-    }
+        // Keep this: skip the headers from the stream
+        // we could put that code in the else and simple write an "header" skipping
+        // reader for the others.
 
-    public boolean match(SearchTerm arg0) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        return message.match(arg0);
-    }
+        
+        /* InternetHeaders can be a bit awkward to work with due to
+         * its own internal handling of header order.  This hack may
+         * not always be necessary, but for now we are trying to
+         * ensure that there is a Return-Path header, even if just a
+         * placeholder, so that later, e.g., in LocalDelivery, when we
+         * call setHeader, it will remove any other Return-Path
+         * headers, and ensure that ours is on the top. addHeader
+         * handles header order, but not setHeader. This may change in
+         * future JavaMail.  But if there are other Return-Path header
+         * values, let's drop our placeholder. */
 
-    public void setFlag(Flag arg0, boolean arg1) throws MessagingException {
-        if (message == null) {
-            loadMessage();
+        MailHeaders newHeaders = new MailHeaders(new ByteArrayInputStream((RFC2822Headers.RETURN_PATH + ": placeholder").getBytes()));
+        newHeaders.setHeader(RFC2822Headers.RETURN_PATH, null);
+        newHeaders.load(is);
+        String[] returnPathHeaders = newHeaders.getHeader(RFC2822Headers.RETURN_PATH);
+        if (returnPathHeaders.length > 1) newHeaders.setHeader(RFC2822Headers.RETURN_PATH, returnPathHeaders[1]);
+        
+        if (headers != null) {
+            return headers;
+        } else {
+            return newHeaders;
         }
-        modified = true;
-        message.setFlag(arg0,arg1);
     }
 
-    public void setRecipient(RecipientType arg0, Address arg1) throws MessagingException {
-        if (message == null) {
-            loadMessage();
-        }
-        modified = true;
-        message.setRecipient(arg0,arg1);
-    }
-    
     /**
-     * @see org.apache.avalon.framework.activity.Disposable#dispose()
+     * @see javax.mail.internet.MimeMessage#getContentStream()
      */
-    public void dispose() {
-        if (source instanceof Disposable) {
-            ((Disposable)source).dispose();
+    protected InputStream getContentStream() throws MessagingException {
+        if (!messageParsed) {
+            loadMessage();
         }
+        return super.getContentStream();
     }
 
-    /**
-     * To be optimized.
-     * Starting from Javamail 1.3.3/1.4.0 we could use the unfold code 
-     * from the javamail.MimeMessage
-     * 
-     * @param s
-     * @return
-     */
-    static String unfold(String message) {
-        if (message == null) return null;
-
-        BufferedReader read = new BufferedReader(new StringReader(message));
-        StringBuffer result = new StringBuffer();
-        boolean unfolded = false;
-        String line;
-        boolean firstLine = true;
-        try {
-            while ((line = read.readLine())!= null && !line.equals("")) {
-              if (line.startsWith("\t") || line.startsWith(" ")) {
-                  result.append(" "+line.trim());
-                  unfolded = true;
-              } else {
-                  if (firstLine) {
-                    firstLine = false;
-                  } else {
-                    result.append("\r\n");
-                  }
-                  result.append(line);
-              }
-            }
-        } catch (IOException e) {
-            // This should never happen as we read from a String.
-          unfolded = false;
-        }
-        if (unfolded) {
-            return result.toString();
-        } else return message;
-    }
-
+    
+    
 }

Modified: james/server/trunk/src/java/org/apache/james/mailrepository/filepair/AbstractFileRepository.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/mailrepository/filepair/AbstractFileRepository.java?rev=385090&r1=385089&r2=385090&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/mailrepository/filepair/AbstractFileRepository.java (original)
+++ james/server/trunk/src/java/org/apache/james/mailrepository/filepair/AbstractFileRepository.java Sat Mar 11 07:19:33 2006
@@ -18,7 +18,6 @@
 package org.apache.james.mailrepository.filepair;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.FilenameFilter;
 import java.io.IOException;
@@ -40,6 +39,8 @@
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.avalon.framework.service.Serviceable;
 
+import com.sun.mail.util.SharedFileInputStream;
+
 /**
  * This an abstract class implementing functionality for creating a file-store.
  *
@@ -257,7 +258,7 @@
     protected InputStream getInputStream( final String key )
         throws IOException
     {
-        return new FileInputStream( getFile( key ) );
+        return new SharedFileInputStream( encode( key ) );
     }
 
     protected OutputStream getOutputStream( final String key )

Modified: james/server/trunk/src/java/org/apache/james/mailrepository/filepair/File_Persistent_Stream_Repository.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/mailrepository/filepair/File_Persistent_Stream_Repository.java?rev=385090&r1=385089&r2=385090&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/mailrepository/filepair/File_Persistent_Stream_Repository.java (original)
+++ james/server/trunk/src/java/org/apache/james/mailrepository/filepair/File_Persistent_Stream_Repository.java Sat Mar 11 07:19:33 2006
@@ -23,9 +23,9 @@
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
+
 import org.apache.avalon.cornerstone.services.store.StreamRepository;
 import org.apache.james.util.io.IOUtil;
-import org.apache.james.util.io.ResettableFileInputStream;
 
 /**
  * Implementation of a StreamRepository to a File.
@@ -52,8 +52,7 @@
     {
         try
         {
-            final ResettableFileInputStream stream =
-                new ResettableFileInputStream( getFile( key ) );
+            InputStream stream = getInputStream( key );
 
             final Object o = m_inputs.get( key );
             if( null == o )

Modified: james/server/trunk/src/java/org/apache/james/transport/mailets/AbstractRedirect.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/transport/mailets/AbstractRedirect.java?rev=385090&r1=385089&r2=385090&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/transport/mailets/AbstractRedirect.java (original)
+++ james/server/trunk/src/java/org/apache/james/transport/mailets/AbstractRedirect.java Sat Mar 11 07:19:33 2006
@@ -1177,7 +1177,7 @@
      */
     private String getMessageBody(MimeMessage message) throws Exception {
         java.io.ByteArrayOutputStream bodyOs = new java.io.ByteArrayOutputStream();
-        MimeMessageUtil.writeMessageTo(message,bodyOs);
+        MimeMessageUtil.writeMessageBodyTo(message,bodyOs);
         return bodyOs.toString();
     }
 

Modified: james/server/trunk/src/java/org/apache/james/transport/mailets/AddHeader.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/transport/mailets/AddHeader.java?rev=385090&r1=385089&r2=385090&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/transport/mailets/AddHeader.java (original)
+++ james/server/trunk/src/java/org/apache/james/transport/mailets/AddHeader.java Sat Mar 11 07:19:33 2006
@@ -19,7 +19,6 @@
 
 import javax.mail.internet.MimeMessage ;
 
-import org.apache.james.core.MailImpl ;
 import org.apache.mailet.GenericMailet ;
 import org.apache.mailet.Mail ;
 

Modified: james/server/trunk/src/test/org/apache/james/core/MimeMessageCopyOnWriteProxyTest.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/test/org/apache/james/core/MimeMessageCopyOnWriteProxyTest.java?rev=385090&r1=385089&r2=385090&view=diff
==============================================================================
--- james/server/trunk/src/test/org/apache/james/core/MimeMessageCopyOnWriteProxyTest.java (original)
+++ james/server/trunk/src/test/org/apache/james/core/MimeMessageCopyOnWriteProxyTest.java Sat Mar 11 07:19:33 2006
@@ -19,16 +19,15 @@
 import org.apache.mailet.Mail;
 import org.apache.mailet.MailAddress;
 
+import com.sun.mail.util.SharedByteArrayInputStream;
+
 import javax.mail.MessagingException;
 import javax.mail.internet.MimeMessage;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 
-import junit.framework.TestCase;
-
-public class MimeMessageCopyOnWriteProxyTest extends TestCase {
+public class MimeMessageCopyOnWriteProxyTest extends MimeMessageFromStreamTest {
 
     MimeMessageWrapper mw = null;
     String content = "Subject: foo\r\nContent-Transfer-Encoding2: plain";
@@ -36,16 +35,20 @@
     String body = "bar\r\n.\r\n";
     MailImpl mail;
 
-    public MimeMessageCopyOnWriteProxyTest(String arg0) throws MessagingException {
-        super(arg0);
-
+    protected MimeMessage getMessageFromSources(String sources) throws Exception {
         MimeMessageInputStreamSource mmis = null;
         try {
-            mmis = new MimeMessageInputStreamSource("test", new ByteArrayInputStream((content+sep+body).getBytes()));
+            mmis = new MimeMessageInputStreamSource("test", new SharedByteArrayInputStream(sources.getBytes()));
         } catch (MessagingException e) {
         }
-        mw = new MimeMessageWrapper(mmis);
+        return new MimeMessageWrapper(mmis);
+//        return new MimeMessage(Session.getDefaultInstance(new Properties()),new ByteArrayInputStream(sources.getBytes()));
+    }
+
+    protected void setUp() throws Exception {
+        mw = (MimeMessageWrapper) getMessageFromSources(content+sep+body);
     }
+
     
     public void testMessageCloning1() throws MessagingException, IOException {
         ArrayList r = new ArrayList();
@@ -171,14 +174,6 @@
     private static boolean isSameMimeMessage(MimeMessage first, MimeMessage second) {
         return getWrappedMessage(first) == getWrappedMessage(second);
         
-    }
-
-    protected void setUp() throws Exception {
-        super.setUp();
-    }
-
-    protected void tearDown() throws Exception {
-        super.tearDown();
     }
 
 }

Added: james/server/trunk/src/test/org/apache/james/core/MimeMessageFromMimeMessageTest.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/test/org/apache/james/core/MimeMessageFromMimeMessageTest.java?rev=385090&view=auto
==============================================================================
--- james/server/trunk/src/test/org/apache/james/core/MimeMessageFromMimeMessageTest.java (added)
+++ james/server/trunk/src/test/org/apache/james/core/MimeMessageFromMimeMessageTest.java Sat Mar 11 07:19:33 2006
@@ -0,0 +1,27 @@
+/***********************************************************************
+ * Copyright (c) 1999-2006 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.mail.internet.MimeMessage;
+
+public class MimeMessageFromMimeMessageTest extends MimeMessageFromStreamTest {
+    
+    protected MimeMessage getMessageFromSources(String sources) throws Exception {
+        return new MimeMessage(super.getMessageFromSources(sources));
+    }
+
+}

Added: james/server/trunk/src/test/org/apache/james/core/MimeMessageFromSharedStreamTest.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/test/org/apache/james/core/MimeMessageFromSharedStreamTest.java?rev=385090&view=auto
==============================================================================
--- james/server/trunk/src/test/org/apache/james/core/MimeMessageFromSharedStreamTest.java (added)
+++ james/server/trunk/src/test/org/apache/james/core/MimeMessageFromSharedStreamTest.java Sat Mar 11 07:19:33 2006
@@ -0,0 +1,31 @@
+/***********************************************************************
+ * Copyright (c) 1999-2006 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.mail.Session;
+import javax.mail.internet.MimeMessage;
+
+import java.io.ByteArrayInputStream;
+import java.util.Properties;
+
+public class MimeMessageFromSharedStreamTest extends MimeMessageFromStreamTest {
+    
+    protected MimeMessage getMessageFromSources(String sources) throws Exception {
+        return new MimeMessage(Session.getDefaultInstance(new Properties()),new ByteArrayInputStream(sources.getBytes()));
+    }
+
+}

Added: james/server/trunk/src/test/org/apache/james/core/MimeMessageFromStreamTest.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/test/org/apache/james/core/MimeMessageFromStreamTest.java?rev=385090&view=auto
==============================================================================
--- james/server/trunk/src/test/org/apache/james/core/MimeMessageFromStreamTest.java (added)
+++ james/server/trunk/src/test/org/apache/james/core/MimeMessageFromStreamTest.java Sat Mar 11 07:19:33 2006
@@ -0,0 +1,44 @@
+/***********************************************************************
+ * Copyright (c) 1999-2006 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.mail.Session;
+import javax.mail.internet.MimeMessage;
+
+import java.io.ByteArrayInputStream;
+import java.util.Properties;
+
+public class MimeMessageFromStreamTest extends MimeMessageTest {
+    
+    protected MimeMessage getMessageFromSources(String sources) throws Exception {
+        return new MimeMessage(Session.getDefaultInstance(new Properties()),new ByteArrayInputStream(sources.getBytes()));
+    }
+
+    protected MimeMessage getMultipartMessage() throws Exception {
+        return getMessageFromSources(getMultipartMessageSource());
+    }
+
+    protected MimeMessage getSimpleMessage() throws Exception {
+        return getMessageFromSources(getSimpleMessageCleanedSource());
+    }
+
+    protected MimeMessage getMissingEncodingAddHeaderMessage() throws Exception {
+        return getMessageFromSources(getMissingEncodingAddHeaderSource());
+    }
+
+
+}

Added: james/server/trunk/src/test/org/apache/james/core/MimeMessageTest.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/test/org/apache/james/core/MimeMessageTest.java?rev=385090&view=auto
==============================================================================
--- james/server/trunk/src/test/org/apache/james/core/MimeMessageTest.java (added)
+++ james/server/trunk/src/test/org/apache/james/core/MimeMessageTest.java Sat Mar 11 07:19:33 2006
@@ -0,0 +1,262 @@
+/***********************************************************************
+ * Copyright (c) 1999-2006 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed 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 org.apache.mailet.RFC2822Headers;
+
+import javax.mail.BodyPart;
+import javax.mail.Session;
+import javax.mail.internet.InternetHeaders;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+/**
+ * Test the subject folding issue.
+ */
+public class MimeMessageTest extends TestCase {
+
+    protected MimeMessage getSimpleMessage() throws Exception {
+        MimeMessage mmCreated = new MimeMessage(Session.getDefaultInstance(new Properties()));
+        mmCreated.setSubject("test");
+        mmCreated.setText("test body");
+        mmCreated.saveChanges();
+        return mmCreated;
+    }
+    
+    protected String getSimpleMessageCleanedSource() throws Exception {
+        return "Subject: test\r\n"
+            +"MIME-Version: 1.0\r\n"
+            +"Content-Type: text/plain; charset=us-ascii\r\n"
+            +"Content-Transfer-Encoding: 7bit\r\n"
+            +"\r\n"
+            +"test body";
+    }
+    
+    /*
+     * Class under test for String getSubject()
+     */
+    public void testSimpleMessage() throws Exception {
+        assertEquals(getSimpleMessageCleanedSource(), getCleanedMessageSource(getSimpleMessage()));
+    }
+
+    
+    protected MimeMessage getMultipartMessage() throws Exception {
+        MimeMessage mmCreated = new MimeMessage(Session.getDefaultInstance(new Properties()));
+        mmCreated.setSubject("test");
+        MimeMultipart mm = new MimeMultipart("alternative");
+        mm.addBodyPart(new MimeBodyPart(new InternetHeaders(new ByteArrayInputStream("X-header: test1\r\n".getBytes())),"first part òàù".getBytes()));
+        mm.addBodyPart(new MimeBodyPart(new InternetHeaders(new ByteArrayInputStream("X-header: test2\r\n".getBytes())),"second part èè".getBytes()));
+        mmCreated.setContent(mm);
+        mmCreated.saveChanges();
+        return mmCreated;
+    }
+    
+    protected String getMultipartMessageSource() {
+        return "Subject: test\r\n"
+            +"MIME-Version: 1.0\r\n"
+            +"Content-Type: multipart/alternative; \r\n" 
+            +"\tboundary=\"----=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\"\r\n"
+            +"\r\n"
+            +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n"
+            +"X-header: test1\r\n"
+            +"Content-Transfer-Encoding: quoted-printable\r\n"
+            +"Content-Type: text/plain; charset=Cp1252\r\n"
+            +"\r\n"
+            +"first part òàù\r\n"
+            +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n"
+            +"X-header: test2\r\n"
+            +"Content-Transfer-Encoding: quoted-printable\r\n"
+            +"Content-Type: text/plain; charset=Cp1252\r\n"
+            +"\r\n"
+            +"second part =E8=E8\r\n"
+            +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX--\r\n";
+    }
+    
+    protected String getMultipartMessageExpected1() {
+        return "Subject: test\r\n"
+            +"MIME-Version: 1.0\r\n"
+            +"Content-Type: multipart/alternative; \r\n" 
+            +"\tboundary=\"----=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\"\r\n"
+            +"\r\n"
+            +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n"
+            +"X-header: test1\r\n"
+            +"Content-Transfer-Encoding: quoted-printable\r\n"
+            +"Content-Type: text/plain; charset=Cp1252\r\n"
+            +"\r\n"
+            +"test=E8\r\n"
+            +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n"
+            +"X-header: test2\r\n"
+            +"Content-Transfer-Encoding: quoted-printable\r\n"
+            +"Content-Type: text/plain; charset=Cp1252\r\n"
+            +"\r\n"
+            +"second part =E8=E8\r\n"
+            +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX--\r\n";
+    }
+    
+    protected String getMultipartMessageExpected2() {
+        return "Subject: test\r\n"
+            +"MIME-Version: 1.0\r\n"
+            +"Content-Type: multipart/alternative; \r\n" 
+            +"\tboundary=\"----=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\"\r\n"
+            +"\r\n"
+            +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n"
+            +"X-header: test1\r\n"
+            +"Content-Transfer-Encoding: quoted-printable\r\n"
+            +"Content-Type: text/plain; charset=Cp1252\r\n"
+            +"\r\n"
+            +"test=E8\r\n"
+            +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n"
+            +"X-header: test2\r\n"
+            +"Content-Transfer-Encoding: quoted-printable\r\n"
+            +"Content-Type: text/plain; charset=Cp1252\r\n"
+            +"\r\n"
+            +"second part =E8=E8\r\n"
+            +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n"
+            +"Subject: test3\r\n"
+            +"Content-Transfer-Encoding: 7bit\r\n"
+            +"Content-Type: text/plain; charset=us-ascii\r\n"
+            +"\r\n"
+            +"second part\r\n"
+            +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX--\r\n";
+    }
+    
+    protected String getMultipartMessageExpected3() {
+        return "Subject: test\r\n"
+            +"MIME-Version: 1.0\r\n"
+            +"Content-Type: binary/octet-stream\r\n"
+            +"Content-Transfer-Encoding: 8bit\r\n"
+            +"\r\n"
+            +"mynewcoòàùntent?à!";
+    }
+    
+    /*
+     * Class under test for String getSubject()
+     */
+    public void testMultipartMessageChanges() throws Exception {
+
+        MimeMessage mm = getMultipartMessage();
+        
+//        ByteArrayOutputStream out = new ByteArrayOutputStream();
+//        mmCreated.writeTo(out,new String[] {"Message-ID"});
+//        String messageSource = out.toString();
+//        System.out.println(messageSource);
+        
+        
+        MimeMultipart content1 = (MimeMultipart) mm.getContent();
+        BodyPart b1 = content1.getBodyPart(0);
+        b1.setText("testè");
+        mm.setContent(content1,mm.getContentType());
+        mm.saveChanges();
+
+        assertEquals(getMultipartMessageExpected1(),getCleanedMessageSource(mm));
+
+        MimeMultipart content2 = (MimeMultipart) mm.getContent();
+        content2.addBodyPart(new MimeBodyPart(new InternetHeaders(new ByteArrayInputStream("Subject: test3\r\n".getBytes())),"second part".getBytes()));
+        mm.setContent(content2,mm.getContentType());
+        mm.saveChanges();
+
+        assertEquals(getMultipartMessageExpected2(),getCleanedMessageSource(mm));
+
+        mm.setContent("mynewcoòàùntent€à!","text/plain");
+        mm.setHeader(RFC2822Headers.CONTENT_TYPE,"binary/octet-stream");
+        mm.setHeader("Content-Transfer-Encoding","8bit");
+        mm.saveChanges();
+        
+        assertEquals(getMultipartMessageExpected3(),getCleanedMessageSource(mm));
+        
+    }
+
+    protected MimeMessage getMissingEncodingAddHeaderMessage() throws Exception {
+        MimeMessage m = new MimeMessage(Session.getDefaultInstance(new Properties()));
+        m.setText("Testà\r\n");
+        m.setSubject("test");
+        m.saveChanges();
+        return m;
+    }
+    
+
+    protected String getMissingEncodingAddHeaderSource() {
+        return "Subject: test\r\n"+
+                "\r\n"+
+                "Testà\r\n";
+    }
+    
+    protected String getMissingEncodingAddHeaderExpected() {
+        return "Subject: test\r\n"
+            +"MIME-Version: 1.0\r\n"
+            +"Content-Type: text/plain; charset=Cp1252\r\n"
+            +"Content-Transfer-Encoding: quoted-printable\r\n"
+            +"\r\n"
+            +"Test=E0\r\n";
+    }
+    
+
+    public void testMissingEncodingAddHeader() throws Exception {
+        MimeMessage mm = getMissingEncodingAddHeaderMessage();
+        mm.setHeader("Content-Transfer-Encoding", "quoted-printable");
+        mm.saveChanges();
+
+        assertEquals(getMissingEncodingAddHeaderExpected(),getCleanedMessageSource(mm));
+}
+    
+
+    protected String getCleanedMessageSource(MimeMessage mm) throws Exception {
+        ByteArrayOutputStream out2;
+        out2 = new ByteArrayOutputStream();
+        mm.writeTo(out2,new String[] {"Message-ID"});
+
+        String res = out2.toString();
+
+        // we put a "Return-Path: null" placeholder in MimeMessageWrapper.
+        // if noone write it, we should consider it equals.
+        if (res.startsWith("Return-Path: null")) res = res.substring(19);
+        
+        int p = res.indexOf("\r\n\r\n");
+        if (p > 0) {
+            String head = res.substring(0,p);
+            String[] str = head.split("\r\n");
+            Arrays.sort(str);
+            StringBuffer outputHead = new StringBuffer();
+            for (int i = str.length-1; i >= 0; i--) {
+                outputHead.append(str[i]);
+                outputHead.append("\r\n");
+            }
+            outputHead.append(res.substring(p+2));
+            res = outputHead.toString();
+        }
+        
+        res = res.replaceAll("----=_Part_\\d_\\d+\\.\\d+","----=_Part_\\0_XXXXXXXXXXX.XXXXXXXXXXX");
+        return res;
+    }
+    
+    protected void debugMessage(MimeMessage mm) throws Exception {
+        System.out.println("-------------------");
+        System.out.println(getCleanedMessageSource(mm));
+        System.out.println("-------------------");
+    }
+    
+    
+    
+}

Added: james/server/trunk/src/test/org/apache/james/core/MimeMessageUtilTest.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/test/org/apache/james/core/MimeMessageUtilTest.java?rev=385090&view=auto
==============================================================================
--- james/server/trunk/src/test/org/apache/james/core/MimeMessageUtilTest.java (added)
+++ james/server/trunk/src/test/org/apache/james/core/MimeMessageUtilTest.java Sat Mar 11 07:19:33 2006
@@ -0,0 +1,66 @@
+/***********************************************************************
+ * Copyright (c) 2006 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.internet.MimeMessage;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+public class MimeMessageUtilTest extends TestCase {
+
+    public void testWriteMimeMessageMultipartWithMessageID() throws MessagingException, IOException {
+        String message = "Received: from localhost.localdomain ([127.0.0.1])\r\n"+
+        "          by athlon14 (JAMES SMTP Server 2.3-dev) with SMTP ID 694\r\n"+
+        "          for <test_int1@athlon14.bf.loc>;\r\n"+
+        "          Sat, 18 Feb 2006 19:30:53 +0100 (CET)\r\n"+
+        "Subject: ext2int\r\n"+
+        "X-James-Postage: This is a test mail sent by James Postage\r\n"+
+        "Mime-Version: 1.0\r\n"+
+        "Content-Type: multipart/alternative; boundary=\"XyoYyxCQIfmZ5Sxofid6XQVZt5Z09XtTnqBF4Z45XSA=\"\r\n"+
+        "Date: Sat, 18 Feb 2006 19:30:53 +0100 (CET)\r\n"+
+        "From: test_ext2@another.bf.loc\r\n"+
+        "\r\n"+
+        "\r\n"+
+        "--XyoYyxCQIfmZ5Sxofid6XQVZt5Z09XtTnqBF4Z45XSA=\r\n"+
+        "Content-Type: text/plain\r\n"+
+        "\r\n"+
+        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r\n"+
+        "--XyoYyxCQIfmZ5Sxofid6XQVZt5Z09XtTnqBF4Z45XSA=\r\n"+
+        "Content-Type: application/octet-stream\r\n"+
+        "\r\n"+
+        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r\n"+
+        "--XyoYyxCQIfmZ5Sxofid6XQVZt5Z09XtTnqBF4Z45XSA=--\r\n";
+        
+        ;
+
+        MimeMessage mimeMessage = new MimeMessage(Session.getDefaultInstance(new Properties()),new ByteArrayInputStream(message.getBytes()));
+        mimeMessage.getSize();
+        ByteArrayOutputStream headerOut = new ByteArrayOutputStream();
+        ByteArrayOutputStream bodyOut = new ByteArrayOutputStream();
+        MimeMessageUtil.writeTo(mimeMessage, headerOut, bodyOut);
+    }
+
+}

Modified: james/server/trunk/src/test/org/apache/james/core/MimeMessageWrapperTest.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/test/org/apache/james/core/MimeMessageWrapperTest.java?rev=385090&r1=385089&r2=385090&view=diff
==============================================================================
--- james/server/trunk/src/test/org/apache/james/core/MimeMessageWrapperTest.java (original)
+++ james/server/trunk/src/test/org/apache/james/core/MimeMessageWrapperTest.java Sat Mar 11 07:19:33 2006
@@ -19,33 +19,127 @@
 import com.sun.mail.util.SharedByteArrayInputStream;
 
 import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
 
 import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.InputStreamReader;
 
-import junit.framework.TestCase;
-
 /**
  * Test the subject folding issue.
  */
-public class MimeMessageWrapperTest extends TestCase {
+public class MimeMessageWrapperTest extends MimeMessageFromStreamTest {
+
+    private final class TestableMimeMessageWrapper extends MimeMessageWrapper {
+        
+        boolean messageLoadable = true;
+        boolean headersLoadable = true;
+        
+        private TestableMimeMessageWrapper(MimeMessageSource source) throws MessagingException {
+            super(source);
+        }
+
+        public boolean messageParsed() {
+            return messageParsed;
+        }
+
+        public MailHeaders getInnerHeaders() {
+            return (MailHeaders) headers;
+        }
+
+        public boolean isHeadersLoadable() {
+            return headersLoadable;
+        }
+
+        public void setHeadersLoadable(boolean headersLoadable) {
+            this.headersLoadable = headersLoadable;
+        }
+
+        public boolean isMessageLoadable() {
+            return messageLoadable;
+        }
+
+        public void setMessageLoadable(boolean messageLoadable) {
+            this.messageLoadable = messageLoadable;
+        }
+
+        protected synchronized void loadHeaders() throws MessagingException {
+            if (headersLoadable) {
+                super.loadHeaders();
+            } else {
+                throw new IllegalStateException("headersLoadable disabled");
+            }
+        }
+
+        protected synchronized MailHeaders loadHeaders(InputStream is) throws MessagingException {
+            if (headersLoadable) {
+                return (MailHeaders) super.createInternetHeaders(is);
+            } else {
+                throw new IllegalStateException("headersLoadable disabled");
+            }
+        }
+
+        protected synchronized void loadMessage() throws MessagingException {
+            if (messageLoadable) {
+                super.loadMessage();
+            } else {
+                throw new IllegalStateException("messageLoadable disabled");
+            }
+        }
+        
+        
+        
+    }
 
-    MimeMessageWrapper mw = null;
+    TestableMimeMessageWrapper mw = null;
     String content = "Subject: foo\r\nContent-Transfer-Encoding2: plain";
     String sep = "\r\n\r\n";
-    String body = "bar\r\n.\r\n";
-
-    public MimeMessageWrapperTest(String arg0) {
-        super(arg0);
+    String body = "bar\r\n";
 
+    protected MimeMessage getMessageFromSources(String sources) throws Exception {
         MimeMessageInputStreamSource mmis = null;
         try {
-            mmis = new MimeMessageInputStreamSource("test", new SharedByteArrayInputStream((content+sep+body).getBytes()));
+            mmis = new MimeMessageInputStreamSource("test", new SharedByteArrayInputStream(sources.getBytes()));
         } catch (MessagingException e) {
         }
-        mw = new MimeMessageWrapper(mmis);
+        return new TestableMimeMessageWrapper(mmis);
+    }
+
+    protected void setUp() throws Exception {
+        mw = (TestableMimeMessageWrapper) getMessageFromSources(content+sep+body);
+    }
+
+    
+    public void testDeferredMessageLoading() throws MessagingException, IOException {
+        assertEquals("foo",mw.getSubject());
+        assertFalse(mw.messageParsed());
+        assertEquals("bar\r\n",mw.getContent());
+        assertTrue(mw.messageParsed());
+        assertFalse(mw.isModified());
+    }
+
+    public void testDeferredMessageLoadingWhileWriting() throws MessagingException, IOException {
+        mw.setMessageLoadable(false);
+        assertEquals("foo",mw.getSubject());
+        assertFalse(mw.isModified());
+        mw.setSubject("newSubject");
+        assertEquals("newSubject",mw.getSubject());
+        assertFalse(mw.messageParsed());
+        assertTrue(mw.isModified());
+        mw.setMessageLoadable(true);
+        
+    }
+
+    public void testDeferredHeaderLoading() throws MessagingException, IOException {
+        mw.setHeadersLoadable(false);
+        try {
+            assertEquals("foo",mw.getSubject());
+            fail("subject should not be loadable here, headers loading is disabled");
+        } catch (IllegalStateException e) {
+            
+        }
     }
 
     /*
@@ -77,10 +171,16 @@
     public void testAddHeaderAndSave() {
         try {
             mw.addHeader("X-Test", "X-Value");
+            
+            assertEquals("X-Value", mw.getHeader("X-Test")[0]);
+            
             mw.saveChanges();
 
             ByteArrayOutputStream rawMessage = new ByteArrayOutputStream();
             mw.writeTo(rawMessage);
+            
+            assertEquals("X-Value", mw.getHeader("X-Test")[0]);
+
             String res = rawMessage.toString();
             
             boolean found = res.indexOf("X-Test: X-Value") > 0;



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


Mime
View raw message