Author: bago
Date: Sun May 14 08:10:45 2006
New Revision: 406350

URL: http://svn.apache.org/viewcvs?rev=406350&view=rev
Log:
Core mimemessage handling changes to remove random NPE: merged r404773-r404802 
to 2.3 branch (JAMES-474)

Modified:
    
james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageCopyOnWriteProxy.java
    
james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageUtil.java
    
james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageWrapper.java
    
james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageCopyOnWriteProxyTest.java
    
james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageTest.java
    
james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageWrapperTest.java

Modified: 
james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageCopyOnWriteProxy.java
URL: 
http://svn.apache.org/viewcvs/james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageCopyOnWriteProxy.java?rev=406350&r1=406349&r2=406350&view=diff
==============================================================================
--- 
james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageCopyOnWriteProxy.java
 (original)
+++ 
james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageCopyOnWriteProxy.java
 Sun May 14 08:10:45 2006
@@ -18,6 +18,7 @@
 package org.apache.james.core;
 
 import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.container.ContainerUtil;
 
 import javax.activation.DataHandler;
 import javax.mail.Address;
@@ -46,8 +47,10 @@
 
     /**
      * 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 ReferenceCounter {
+    protected static class MessageReferenceTracker {
 
         /**
          * reference counter
@@ -55,24 +58,12 @@
         private int referenceCount = 1;
 
         /**
-         * @param original
-         *            MimeMessageWrapper
-         * @throws MessagingException
+         * The mime message in memory
          */
-        public ReferenceCounter() throws MessagingException {
-            this(0);
-        }
+        private MimeMessage wrapped = null;
 
-        /**
-         * @param original
-         *            MimeMessage to wrap
-         * @param writable
-         *            if true we can alter the message itself, otherwise copy 
on
-         *            write it.
-         * @throws MessagingException
-         */
-        public ReferenceCounter(int startCounter) throws MessagingException {
-            referenceCount = startCounter;
+        public MessageReferenceTracker(MimeMessage ref) {
+            wrapped = ref;
         }
 
         protected synchronized void incrementReferenceCount() {
@@ -81,15 +72,23 @@
 
         protected synchronized void decrementReferenceCount() {
             referenceCount--;
+            if (referenceCount<=0) {
+                ContainerUtil.dispose(wrapped);
+                wrapped = null;
+        }
         }
 
         protected synchronized int getReferenceCount() {
             return referenceCount;
         }
 
+        public MimeMessage getWrapped() {
+            return wrapped;
     }
 
-    protected ReferenceCounter refCount;
+    }
+
+    protected MessageReferenceTracker refCount;
 
     /**
      * @param original
@@ -123,12 +122,10 @@
             throws MessagingException {
         super(Session.getDefaultInstance(System.getProperties(), null));
 
-        this.wrapped = original;
-        if (wrapped instanceof MimeMessageCopyOnWriteProxy) {
-            refCount = ((MimeMessageCopyOnWriteProxy) wrapped).refCount;
-            wrapped = ((MimeMessageCopyOnWriteProxy) 
wrapped).getWrappedMessage();
+        if (original instanceof MimeMessageCopyOnWriteProxy) {
+            refCount = ((MimeMessageCopyOnWriteProxy) original).refCount;
         } else {
-            refCount = new ReferenceCounter();
+            refCount = new MessageReferenceTracker(original);
         }
         
         if (!writeable) {
@@ -138,31 +135,43 @@
 
     /**
      * Check the number of references over the MimeMessage and clone it if
-     * needed.
+     * needed before returning the reference
      * 
      * @throws MessagingException
      *             exception
      */
-    protected void checkCopyOnWrite() throws MessagingException {
+    protected MimeMessage getWrappedMessageForWriting() throws 
MessagingException {
         synchronized (refCount) {
             if (refCount.getReferenceCount() > 1) {
                 refCount.decrementReferenceCount();
-                refCount = new ReferenceCounter(1);
-                wrapped = new MimeMessageWrapper(wrapped);
+                refCount = new MessageReferenceTracker(new 
MimeMessageWrapper(refCount.getWrapped()));
             }
         }
+        return refCount.getWrapped();
+    }
+
+    /**
+     * @return
+     */
+    public MimeMessage getWrappedMessage() {
+        return refCount.getWrapped();
     }
 
     /**
-     * The mime message in memory
+     * @see org.apache.avalon.framework.activity.Disposable#dispose()
      */
-    protected MimeMessage wrapped = null;
+    public synchronized void dispose() {
+        if (refCount != null) {
+            refCount.decrementReferenceCount();
+            refCount = null;
+        }
+    }
 
     /**
      * Rewritten for optimization purposes
      */
     public void writeTo(OutputStream os) throws IOException, 
MessagingException {
-        wrapped.writeTo(os);
+        getWrappedMessage().writeTo(os);
     }
 
     /**
@@ -170,7 +179,7 @@
      */
     public void writeTo(OutputStream os, String[] ignoreList)
             throws IOException, MessagingException {
-        wrapped.writeTo(os, ignoreList);
+        getWrappedMessage().writeTo(os, ignoreList);
     }
 
     /**
@@ -181,7 +190,7 @@
      * @see javax.mail.Message#getFrom()
      */
     public Address[] getFrom() throws MessagingException {
-        return wrapped.getFrom();
+        return getWrappedMessage().getFrom();
     }
 
     /**
@@ -189,154 +198,154 @@
      */
     public Address[] getRecipients(Message.RecipientType type)
             throws MessagingException {
-        return wrapped.getRecipients(type);
+        return getWrappedMessage().getRecipients(type);
     }
 
     /**
      * @see javax.mail.Message#getAllRecipients()
      */
     public Address[] getAllRecipients() throws MessagingException {
-        return wrapped.getAllRecipients();
+        return getWrappedMessage().getAllRecipients();
     }
 
     /**
      * @see javax.mail.Message#getReplyTo()
      */
     public Address[] getReplyTo() throws MessagingException {
-        return wrapped.getReplyTo();
+        return getWrappedMessage().getReplyTo();
     }
 
     /**
      * @see javax.mail.Message#getSubject()
      */
     public String getSubject() throws MessagingException {
-        return wrapped.getSubject();
+        return getWrappedMessage().getSubject();
     }
 
     /**
      * @see javax.mail.Message#getSentDate()
      */
     public Date getSentDate() throws MessagingException {
-        return wrapped.getSentDate();
+        return getWrappedMessage().getSentDate();
     }
 
     /**
      * @see javax.mail.Message#getReceivedDate()
      */
     public Date getReceivedDate() throws MessagingException {
-        return wrapped.getReceivedDate();
+        return getWrappedMessage().getReceivedDate();
     }
 
     /**
      * @see javax.mail.Part#getSize()
      */
     public int getSize() throws MessagingException {
-        return wrapped.getSize();
+        return getWrappedMessage().getSize();
     }
 
     /**
      * @see javax.mail.Part#getLineCount()
      */
     public int getLineCount() throws MessagingException {
-        return wrapped.getLineCount();
+        return getWrappedMessage().getLineCount();
     }
 
     /**
      * @see javax.mail.Part#getContentType()
      */
     public String getContentType() throws MessagingException {
-        return wrapped.getContentType();
+        return getWrappedMessage().getContentType();
     }
 
     /**
      * @see javax.mail.Part#isMimeType(java.lang.String)
      */
     public boolean isMimeType(String mimeType) throws MessagingException {
-        return wrapped.isMimeType(mimeType);
+        return getWrappedMessage().isMimeType(mimeType);
     }
 
     /**
      * @see javax.mail.Part#getDisposition()
      */
     public String getDisposition() throws MessagingException {
-        return wrapped.getDisposition();
+        return getWrappedMessage().getDisposition();
     }
 
     /**
      * @see javax.mail.internet.MimePart#getEncoding()
      */
     public String getEncoding() throws MessagingException {
-        return wrapped.getEncoding();
+        return getWrappedMessage().getEncoding();
     }
 
     /**
      * @see javax.mail.internet.MimePart#getContentID()
      */
     public String getContentID() throws MessagingException {
-        return wrapped.getContentID();
+        return getWrappedMessage().getContentID();
     }
 
     /**
      * @see javax.mail.internet.MimePart#getContentMD5()
      */
     public String getContentMD5() throws MessagingException {
-        return wrapped.getContentMD5();
+        return getWrappedMessage().getContentMD5();
     }
 
     /**
      * @see javax.mail.Part#getDescription()
      */
     public String getDescription() throws MessagingException {
-        return wrapped.getDescription();
+        return getWrappedMessage().getDescription();
     }
 
     /**
      * @see javax.mail.internet.MimePart#getContentLanguage()
      */
     public String[] getContentLanguage() throws MessagingException {
-        return wrapped.getContentLanguage();
+        return getWrappedMessage().getContentLanguage();
     }
 
     /**
      * @see javax.mail.internet.MimeMessage#getMessageID()
      */
     public String getMessageID() throws MessagingException {
-        return wrapped.getMessageID();
+        return getWrappedMessage().getMessageID();
     }
 
     /**
      * @see javax.mail.Part#getFileName()
      */
     public String getFileName() throws MessagingException {
-        return wrapped.getFileName();
+        return getWrappedMessage().getFileName();
     }
 
     /**
      * @see javax.mail.Part#getInputStream()
      */
     public InputStream getInputStream() throws IOException, MessagingException 
{
-        return wrapped.getInputStream();
+        return getWrappedMessage().getInputStream();
     }
 
     /**
      * @see javax.mail.Part#getDataHandler()
      */
     public DataHandler getDataHandler() throws MessagingException {
-        return wrapped.getDataHandler();
+        return getWrappedMessage().getDataHandler();
     }
 
     /**
      * @see javax.mail.Part#getContent()
      */
     public Object getContent() throws IOException, MessagingException {
-        return wrapped.getContent();
+        return getWrappedMessage().getContent();
     }
 
     /**
      * @see javax.mail.Part#getHeader(java.lang.String)
      */
     public String[] getHeader(String name) throws MessagingException {
-        return wrapped.getHeader(name);
+        return getWrappedMessage().getHeader(name);
     }
 
     /**
@@ -344,14 +353,14 @@
      */
     public String getHeader(String name, String delimiter)
             throws MessagingException {
-        return wrapped.getHeader(name, delimiter);
+        return getWrappedMessage().getHeader(name, delimiter);
     }
 
     /**
      * @see javax.mail.Part#getAllHeaders()
      */
     public Enumeration getAllHeaders() throws MessagingException {
-        return wrapped.getAllHeaders();
+        return getWrappedMessage().getAllHeaders();
     }
 
     /**
@@ -359,7 +368,7 @@
      */
     public Enumeration getMatchingHeaders(String[] names)
             throws MessagingException {
-        return wrapped.getMatchingHeaders(names);
+        return getWrappedMessage().getMatchingHeaders(names);
     }
 
     /**
@@ -367,14 +376,14 @@
      */
     public Enumeration getNonMatchingHeaders(String[] names)
             throws MessagingException {
-        return wrapped.getNonMatchingHeaders(names);
+        return getWrappedMessage().getNonMatchingHeaders(names);
     }
 
     /**
      * @see javax.mail.internet.MimePart#getAllHeaderLines()
      */
     public Enumeration getAllHeaderLines() throws MessagingException {
-        return wrapped.getAllHeaderLines();
+        return getWrappedMessage().getAllHeaderLines();
     }
 
     /**
@@ -382,7 +391,7 @@
      */
     public Enumeration getMatchingHeaderLines(String[] names)
             throws MessagingException {
-        return wrapped.getMatchingHeaderLines(names);
+        return getWrappedMessage().getMatchingHeaderLines(names);
     }
 
     /**
@@ -390,84 +399,84 @@
      */
     public Enumeration getNonMatchingHeaderLines(String[] names)
             throws MessagingException {
-        return wrapped.getNonMatchingHeaderLines(names);
+        return getWrappedMessage().getNonMatchingHeaderLines(names);
     }
 
     /**
      * @see javax.mail.Message#getFlags()
      */
     public Flags getFlags() throws MessagingException {
-        return wrapped.getFlags();
+        return getWrappedMessage().getFlags();
     }
 
     /**
      * @see javax.mail.Message#isSet(javax.mail.Flags.Flag)
      */
     public boolean isSet(Flags.Flag flag) throws MessagingException {
-        return wrapped.isSet(flag);
+        return getWrappedMessage().isSet(flag);
     }
 
     /**
      * @see javax.mail.internet.MimeMessage#getSender()
      */
     public Address getSender() throws MessagingException {
-        return wrapped.getSender();
+        return getWrappedMessage().getSender();
     }
 
     /**
      * @see javax.mail.Message#match(javax.mail.search.SearchTerm)
      */
     public boolean match(SearchTerm arg0) throws MessagingException {
-        return wrapped.match(arg0);
+        return getWrappedMessage().match(arg0);
     }
 
     /**
      * @see javax.mail.internet.MimeMessage#getRawInputStream()
      */
     public InputStream getRawInputStream() throws MessagingException {
-        return wrapped.getRawInputStream();
+        return getWrappedMessage().getRawInputStream();
     }
 
     /**
      * @see javax.mail.Message#getFolder()
      */
     public Folder getFolder() {
-        return wrapped.getFolder();
+        return getWrappedMessage().getFolder();
     }
 
     /**
      * @see javax.mail.Message#getMessageNumber()
      */
     public int getMessageNumber() {
-        return wrapped.getMessageNumber();
+        return getWrappedMessage().getMessageNumber();
     }
 
     /**
      * @see javax.mail.Message#isExpunged()
      */
     public boolean isExpunged() {
-        return wrapped.isExpunged();
+        return getWrappedMessage().isExpunged();
     }
 
     /**
      * @see java.lang.Object#equals(java.lang.Object)
      */
     public boolean equals(Object arg0) {
-        return wrapped.equals(arg0);
+        return getWrappedMessage().equals(arg0);
     }
 
     /**
      * @see java.lang.Object#hashCode()
      */
     public int hashCode() {
-        return wrapped.hashCode();
+        return getWrappedMessage().hashCode();
     }
 
     /**
      * @see java.lang.Object#toString()
      */
     public String toString() {
-        return wrapped.toString();
+        return getWrappedMessage().toString();
     }
 
     /*
@@ -478,24 +487,21 @@
      * @see javax.mail.Message#setFrom(javax.mail.Address)
      */
     public void setFrom(Address address) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setFrom(address);
+        getWrappedMessageForWriting().setFrom(address);
     }
 
     /**
      * @see javax.mail.Message#setFrom()
      */
     public void setFrom() throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setFrom();
+        getWrappedMessageForWriting().setFrom();
     }
 
     /**
      * @see javax.mail.Message#addFrom(javax.mail.Address[])
      */
     public void addFrom(Address[] addresses) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.addFrom(addresses);
+        getWrappedMessageForWriting().addFrom(addresses);
     }
 
     /**
@@ -503,8 +509,7 @@
      */
     public void setRecipients(Message.RecipientType type, Address[] addresses)
             throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setRecipients(type, addresses);
+        getWrappedMessageForWriting().setRecipients(type, addresses);
     }
 
     /**
@@ -512,24 +517,21 @@
      */
     public void addRecipients(Message.RecipientType type, Address[] addresses)
             throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.addRecipients(type, addresses);
+        getWrappedMessageForWriting().addRecipients(type, addresses);
     }
 
     /**
      * @see javax.mail.Message#setReplyTo(javax.mail.Address[])
      */
     public void setReplyTo(Address[] addresses) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setReplyTo(addresses);
+        getWrappedMessageForWriting().setReplyTo(addresses);
     }
 
     /**
      * @see javax.mail.Message#setSubject(java.lang.String)
      */
     public void setSubject(String subject) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setSubject(subject);
+        getWrappedMessageForWriting().setSubject(subject);
     }
 
     /**
@@ -537,48 +539,42 @@
      */
     public void setSubject(String subject, String charset)
             throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setSubject(subject, charset);
+        getWrappedMessageForWriting().setSubject(subject, charset);
     }
 
     /**
      * @see javax.mail.Message#setSentDate(java.util.Date)
      */
     public void setSentDate(Date d) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setSentDate(d);
+        getWrappedMessageForWriting().setSentDate(d);
     }
 
     /**
      * @see javax.mail.Part#setDisposition(java.lang.String)
      */
     public void setDisposition(String disposition) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setDisposition(disposition);
+        getWrappedMessageForWriting().setDisposition(disposition);
     }
 
     /**
      * @see javax.mail.internet.MimeMessage#setContentID(java.lang.String)
      */
     public void setContentID(String cid) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setContentID(cid);
+        getWrappedMessageForWriting().setContentID(cid);
     }
 
     /**
      * @see javax.mail.internet.MimePart#setContentMD5(java.lang.String)
      */
     public void setContentMD5(String md5) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setContentMD5(md5);
+        getWrappedMessageForWriting().setContentMD5(md5);
     }
 
     /**
      * @see javax.mail.Part#setDescription(java.lang.String)
      */
     public void setDescription(String description) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setDescription(description);
+        getWrappedMessageForWriting().setDescription(description);
     }
 
     /**
@@ -586,8 +582,7 @@
      */
     public void setDescription(String description, String charset)
             throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setDescription(description, charset);
+        getWrappedMessageForWriting().setDescription(description, charset);
     }
 
     /**
@@ -595,109 +590,99 @@
      */
     public void setContentLanguage(String[] languages)
             throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setContentLanguage(languages);
+        getWrappedMessageForWriting().setContentLanguage(languages);
     }
 
     /**
      * @see javax.mail.Part#setFileName(java.lang.String)
      */
     public void setFileName(String filename) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setFileName(filename);
+        getWrappedMessageForWriting().setFileName(filename);
     }
 
     /**
      * @see javax.mail.Part#setDataHandler(javax.activation.DataHandler)
      */
     public void setDataHandler(DataHandler dh) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setDataHandler(dh);
+        getWrappedMessageForWriting().setDataHandler(dh);
     }
 
     /**
      * @see javax.mail.Part#setContent(java.lang.Object, java.lang.String)
      */
     public void setContent(Object o, String type) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setContent(o, type);
+        getWrappedMessageForWriting().setContent(o, type);
     }
 
     /**
      * @see javax.mail.Part#setText(java.lang.String)
      */
     public void setText(String text) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setText(text);
+        getWrappedMessageForWriting().setText(text);
     }
 
     /**
      * @see javax.mail.internet.MimePart#setText(java.lang.String, 
java.lang.String)
      */
     public void setText(String text, String charset) throws MessagingException 
{
-        checkCopyOnWrite();
-        wrapped.setText(text, charset);
+        getWrappedMessageForWriting().setText(text, charset);
     }
 
     /**
      * @see javax.mail.Part#setContent(javax.mail.Multipart)
      */
     public void setContent(Multipart mp) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setContent(mp);
+        getWrappedMessageForWriting().setContent(mp);
     }
 
+    /**
+     * This does not need a writable message
+     * @see javax.mail.Message#reply(boolean)
+     */
     public Message reply(boolean replyToAll) throws MessagingException {
-        checkCopyOnWrite();
-        return wrapped.reply(replyToAll);
+        return getWrappedMessage().reply(replyToAll);
     }
 
     /**
      * @see javax.mail.Part#setHeader(java.lang.String, java.lang.String)
      */
     public void setHeader(String name, String value) throws MessagingException 
{
-        checkCopyOnWrite();
-        wrapped.setHeader(name, value);
+        getWrappedMessageForWriting().setHeader(name, value);
     }
 
     /**
      * @see javax.mail.Part#addHeader(java.lang.String, java.lang.String)
      */
     public void addHeader(String name, String value) throws MessagingException 
{
-        checkCopyOnWrite();
-        wrapped.addHeader(name, value);
+        getWrappedMessageForWriting().addHeader(name, value);
     }
 
     /**
      * @see javax.mail.Part#removeHeader(java.lang.String)
      */
     public void removeHeader(String name) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.removeHeader(name);
+        getWrappedMessageForWriting().removeHeader(name);
     }
 
     /**
      * @see javax.mail.internet.MimePart#addHeaderLine(java.lang.String)
      */
     public void addHeaderLine(String line) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.addHeaderLine(line);
+        getWrappedMessageForWriting().addHeaderLine(line);
     }
 
     /**
      * @see javax.mail.Message#setFlags(javax.mail.Flags, boolean)
      */
     public void setFlags(Flags flag, boolean set) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setFlags(flag, set);
+        getWrappedMessageForWriting().setFlags(flag, set);
     }
 
     /**
      * @see javax.mail.Message#saveChanges()
      */
     public void saveChanges() throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.saveChanges();
+        getWrappedMessageForWriting().saveChanges();
     }
 
     /*
@@ -709,8 +694,7 @@
      */
     public void addRecipients(Message.RecipientType type, String addresses)
             throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.addRecipients(type, addresses);
+        getWrappedMessageForWriting().addRecipients(type, addresses);
     }
 
     /**
@@ -718,16 +702,14 @@
      */
     public void setRecipients(Message.RecipientType type, String addresses)
             throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setRecipients(type, addresses);
+        getWrappedMessageForWriting().setRecipients(type, addresses);
     }
 
     /**
      * @see javax.mail.internet.MimeMessage#setSender(javax.mail.Address)
      */
     public void setSender(Address arg0) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setSender(arg0);
+        getWrappedMessageForWriting().setSender(arg0);
     }
 
     /**
@@ -735,31 +717,14 @@
      */
     public void addRecipient(RecipientType arg0, Address arg1)
             throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.addRecipient(arg0, arg1);
+        getWrappedMessageForWriting().addRecipient(arg0, arg1);
     }
 
     /**
      * @see javax.mail.Message#setFlag(javax.mail.Flags.Flag, boolean)
      */
     public void setFlag(Flag arg0, boolean arg1) throws MessagingException {
-        checkCopyOnWrite();
-        wrapped.setFlag(arg0, arg1);
-    }
-
-    /**
-     * @see org.apache.avalon.framework.activity.Disposable#dispose()
-     */
-    public synchronized void dispose() {
-        if (wrapped != null) {
-            refCount.decrementReferenceCount();
-            if (refCount.getReferenceCount()<=0) {
-                if (wrapped instanceof Disposable) {
-                    ((Disposable) wrapped).dispose();
-                }
-            }
-            wrapped = null;
-        }
+        getWrappedMessageForWriting().setFlag(arg0, arg1);
     }
 
     /**
@@ -775,14 +740,8 @@
      * @throws MessagingException 
      */
     public long getMessageSize() throws MessagingException {
-        return MimeMessageUtil.getMessageSize(wrapped);
-    }
-
-    /**
-     * @return
-     */
-    public MimeMessage getWrappedMessage() {
-        return wrapped;
+        return MimeMessageUtil.getMessageSize(getWrappedMessage());
     }
 
 }
+

Modified: 
james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageUtil.java
URL: 
http://svn.apache.org/viewcvs/james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageUtil.java?rev=406350&r1=406349&r2=406350&view=diff
==============================================================================
--- 
james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageUtil.java 
(original)
+++ 
james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageUtil.java 
Sun May 14 08:10:45 2006
@@ -65,6 +65,19 @@
                 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, UnsupportedDataTypeException {
         if(message.getMessageID() == null) {
             message.saveChanges();
         }
@@ -167,6 +180,18 @@
     private static void writeHeadersTo(MimeMessage message, OutputStream 
headerOs, String[] ignoreList) throws MessagingException {
         //Write the headers (minus ignored ones)
         Enumeration headers = message.getNonMatchingHeaderLines(ignoreList);
+        writeHeadersTo(headers, headerOs);
+    }
+
+    /**
+     * Write the message headers to the given outputstream
+     * 
+     * @param message
+     * @param headerOs
+     * @param ignoreList
+     * @throws MessagingException
+     */
+    public static void writeHeadersTo(Enumeration headers, OutputStream 
headerOs) throws MessagingException {
         PrintWriter hos = new InternetPrintWriter(new BufferedWriter(new 
OutputStreamWriter(headerOs), 512), true);
         while (headers.hasMoreElements()) {
             hos.println((String)headers.nextElement());

Modified: 
james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageWrapper.java
URL: 
http://svn.apache.org/viewcvs/james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageWrapper.java?rev=406350&r1=406349&r2=406350&view=diff
==============================================================================
--- 
james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageWrapper.java
 (original)
+++ 
james/server/branches/v2.3/src/java/org/apache/james/core/MimeMessageWrapper.java
 Sun May 14 08:10:45 2006
@@ -36,6 +36,7 @@
 import java.util.Enumeration;
 
 import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.container.ContainerUtil;
 import org.apache.james.util.InternetPrintWriter;
 import org.apache.james.util.io.IOUtil;
 import org.apache.mailet.RFC2822Headers;
@@ -118,7 +119,8 @@
             // this probably speed up things
             if (((MimeMessageWrapper) original).headers != null) {
                 ByteArrayOutputStream temp = new ByteArrayOutputStream();
-                ((MailHeaders) ((MimeMessageWrapper) 
original).headers).writeTo(temp);
+                InternetHeaders ih = ((MimeMessageWrapper) original).headers;
+                MimeMessageUtil.writeHeadersTo(ih.getAllHeaderLines(),temp);
                 headers = createInternetHeaders(new 
ByteArrayInputStream(temp.toByteArray()));
                 headersModified = ((MimeMessageWrapper) 
original).headersModified;
             }
@@ -193,19 +195,22 @@
         if (messageParsed) {
             //Another thread has already loaded this message
             return;
-        }
-        sourceIn = null;
-        try {
-            sourceIn = source.getInputStream();
-
-            parse(sourceIn);
-            // TODO is it ok?
-            saved = true;
-            
-        } catch (IOException ioe) {
-            IOUtil.shutdownStream(sourceIn);
+        } else if (source != null) {
             sourceIn = null;
-            throw new MessagingException("Unable to parse stream: " + 
ioe.getMessage(), ioe);
+            try {
+                sourceIn = source.getInputStream();
+    
+                parse(sourceIn);
+                // TODO is it ok?
+                saved = true;
+                
+            } catch (IOException ioe) {
+                IOUtil.shutdownStream(sourceIn);
+                sourceIn = null;
+                throw new MessagingException("Unable to parse stream: " + 
ioe.getMessage(), ioe);
+            }
+        } else {
+            throw new MessagingException("loadHeaders called for an unparsed 
message with no source");
         }
     }
 
@@ -222,7 +227,7 @@
      * Rewritten for optimization purposes
      */
     public synchronized void writeTo(OutputStream os) throws IOException, 
MessagingException {
-        if (!isModified()) {
+        if (source != null && !isModified()) {
             // We do not want to instantiate the message... just read from 
source
             // and write to this outputstream
             InputStream in = source.getInputStream();
@@ -251,7 +256,7 @@
     }
 
     public synchronized void writeTo(OutputStream headerOs, OutputStream 
bodyOs, String[] ignoreList) throws IOException, MessagingException {
-        if (!isModified()) {
+        if (source != null && !isModified()) {
             //We do not want to instantiate the message... just read from 
source
             //  and write to this outputstream
 
@@ -271,7 +276,7 @@
                 IOUtil.shutdownStream(in);
             }
         } else {
-            MimeMessageUtil.writeTo(this, headerOs, bodyOs, ignoreList);
+            MimeMessageUtil.writeToInternal(this, headerOs, bodyOs, 
ignoreList);
         }
     }
 
@@ -328,7 +333,7 @@
      * Returns size of message, ie headers and content
      */
     public long getMessageSize() throws MessagingException {
-        if (!isModified()) {
+        if (source != null && !isModified()) {
             try {
                 return source.getMessageSize();
             } catch (IOException ioe) {
@@ -449,8 +454,8 @@
         if (sourceIn != null) {
             IOUtil.shutdownStream(sourceIn);
         }
-        if (source instanceof Disposable) {
-            ((Disposable)source).dispose();
+        if (source != null) {
+            ContainerUtil.dispose(source);
         }
     }
 

Modified: 
james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageCopyOnWriteProxyTest.java
URL: 
http://svn.apache.org/viewcvs/james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageCopyOnWriteProxyTest.java?rev=406350&r1=406349&r2=406350&view=diff
==============================================================================
--- 
james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageCopyOnWriteProxyTest.java
 (original)
+++ 
james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageCopyOnWriteProxyTest.java
 Sun May 14 08:10:45 2006
@@ -20,21 +20,19 @@
 import org.apache.mailet.Mail;
 import org.apache.mailet.MailAddress;
 
-import javax.mail.util.SharedByteArrayInputStream;
-
 import javax.mail.MessagingException;
+import javax.mail.Session;
 import javax.mail.internet.MimeMessage;
+import javax.mail.util.SharedByteArrayInputStream;
 
-import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Properties;
 
 public class MimeMessageCopyOnWriteProxyTest extends MimeMessageFromStreamTest 
{
 
-    MimeMessageCopyOnWriteProxy mw = null;
     String content = "Subject: foo\r\nContent-Transfer-Encoding2: plain";
     String sep = "\r\n\r\n";
     String body = "bar\r\n.\r\n";
-    MailImpl mail;
 
     protected MimeMessage getMessageFromSources(String sources) throws 
Exception {
         MimeMessageInputStreamSource mmis = null;
@@ -46,20 +44,11 @@
 //        return new MimeMessage(Session.getDefaultInstance(new 
Properties()),new ByteArrayInputStream(sources.getBytes()));
     }
 
-    protected void setUp() throws Exception {
-        mw = (MimeMessageCopyOnWriteProxy) 
getMessageFromSources(content+sep+body);
-    }
-
-
-    protected void tearDown() throws Exception {
-        ContainerUtil.dispose(mw);
-    }
-
-    
-    public void testMessageCloning1() throws MessagingException, IOException {
+    public void testMessageCloning1() throws Exception {
         ArrayList r = new ArrayList();
         r.add(new MailAddress("[EMAIL PROTECTED]"));
-        mail = new MailImpl("test",new MailAddress("[email protected]"),r,mw);
+        MimeMessageCopyOnWriteProxy messageFromSources = 
(MimeMessageCopyOnWriteProxy) getMessageFromSources(content+sep+body);
+        MailImpl mail = new MailImpl("test",new 
MailAddress("[email protected]"),r,messageFromSources);
         MailImpl m2 = (MailImpl) mail.duplicate();
         System.out.println("mail: "+getReferences(mail.getMessage())+" m2: 
"+getReferences(m2.getMessage()));
         assertNotSame(m2,mail);
@@ -74,13 +63,17 @@
         // test it is different after a write operation!
         mail.getMessage().setSubject("new Subject");
         assertTrue(!isSameMimeMessage(m2.getMessage(),mail.getMessage()));
+        ContainerUtil.dispose(mail);
+        ContainerUtil.dispose(m2);
+        ContainerUtil.dispose(messageFromSources);
     }
 
     
-    public void testMessageCloning2() throws MessagingException, IOException {
+    public void testMessageCloning2() throws Exception {
         ArrayList r = new ArrayList();
         r.add(new MailAddress("[EMAIL PROTECTED]"));
-        mail = new MailImpl("test",new MailAddress("[email protected]"),r,mw);
+        MimeMessageCopyOnWriteProxy messageFromSources = 
(MimeMessageCopyOnWriteProxy) getMessageFromSources(content+sep+body);
+        MailImpl mail = new MailImpl("test",new 
MailAddress("[email protected]"),r,messageFromSources);
         MailImpl m2 = (MailImpl) mail.duplicate();
         System.out.println("mail: "+getReferences(mail.getMessage())+" m2: 
"+getReferences(m2.getMessage()));
         assertNotSame(m2,mail);
@@ -114,12 +107,19 @@
         m2clone.getMessage().setSubject("new Subject 2");
         m2clone.getMessage().setText("new Body 3");
         assertTrue(isSameMimeMessage(m2clone.getMessage(),mm));
+        ContainerUtil.dispose(mail);
+        ContainerUtil.dispose(messageFromSources);
     }
     
-    public void testMessageAvoidCloning() throws MessagingException, 
IOException {
+    /**
+     * If I create a new MimeMessageCopyOnWriteProxy from another 
MimeMessageCopyOnWriteProxy,
+     * I remove references to the first and I change the second, then it 
should not clone
+     */
+    public void testMessageAvoidCloning() throws Exception {
         ArrayList r = new ArrayList();
         r.add(new MailAddress("[EMAIL PROTECTED]"));
-        mail = new MailImpl("test",new MailAddress("[email protected]"),r,mw);
+        MimeMessageCopyOnWriteProxy messageFromSources = 
(MimeMessageCopyOnWriteProxy) getMessageFromSources(content+sep+body);
+        MailImpl mail = new MailImpl("test",new 
MailAddress("[email protected]"),r,messageFromSources);
         // cloning the message
         Mail mailClone = mail.duplicate();
         
assertTrue(isSameMimeMessage(mailClone.getMessage(),mail.getMessage()));
@@ -127,6 +127,10 @@
         assertNotSame(mail.getMessage(),mailClone.getMessage());
         // dispose mail and check that the clone has still a valid message and 
it is the same!
         ((MailImpl) mail).dispose();
+        ContainerUtil.dispose(messageFromSources);
+        // need to add a gc and a wait, because the original mimemessage 
should be finalized before the test.
+        System.gc();
+        Thread.sleep(1000);
         // dumb test
         
assertTrue(isSameMimeMessage(mailClone.getMessage(),mailClone.getMessage()));
         // change the message that should be not referenced by mail that has
@@ -134,13 +138,41 @@
         mailClone.getMessage().setSubject("new Subject 2");
         mailClone.getMessage().setText("new Body 3");
         assertTrue(isSameMimeMessage(mailClone.getMessage(),mm));
+        ContainerUtil.dispose(mailClone);
+        ContainerUtil.dispose(mm);
+    }
+
+    
+    /**
+     * If I create a new MimeMessageCopyOnWriteProxy from a MimeMessage and I 
change the new 
+     * message, the original should be unaltered and the proxy should clone 
the message.
+     */
+    public void testMessageCloning3() throws Exception {
+        ArrayList r = new ArrayList();
+        r.add(new MailAddress("[EMAIL PROTECTED]"));
+        MimeMessage m = new MimeMessage(Session.getDefaultInstance(new 
Properties(null)));
+        m.setText("CIPS");
+        MailImpl mail = new MailImpl("test",new 
MailAddress("[email protected]"),r,m);
+        assertTrue(isSameMimeMessage(m,mail.getMessage()));
+        // change the message that should be not referenced by mail that has
+        // been disposed, so it should not clone it!
+        System.gc();
+        Thread.sleep(100);
+        mail.getMessage().setSubject("new Subject 2");
+        mail.getMessage().setText("new Body 3");
+        System.gc();
+        Thread.sleep(100);
+        assertFalse(isSameMimeMessage(m,mail.getMessage()));
+        ContainerUtil.dispose(mail);
+        ContainerUtil.dispose(m);
     }
 
     
-    public void testMessageDisposing() throws MessagingException, IOException {
+    public void testMessageDisposing() throws Exception {
         ArrayList r = new ArrayList();
         r.add(new MailAddress("[EMAIL PROTECTED]"));
-        mail = new MailImpl("test",new MailAddress("[email protected]"),r,mw);
+        MimeMessageCopyOnWriteProxy messageFromSources = 
(MimeMessageCopyOnWriteProxy) getMessageFromSources(content+sep+body);
+        MailImpl mail = new MailImpl("test",new 
MailAddress("[email protected]"),r,messageFromSources);
         // cloning the message
         MailImpl mailClone = (MailImpl) mail.duplicate();
         mail.dispose();
@@ -152,6 +184,55 @@
         
         assertNull(mailClone.getMessage());
         assertNull(mail.getMessage());
+        ContainerUtil.dispose(mail);
+        ContainerUtil.dispose(messageFromSources);
+    }
+    
+    public void testNPE1() throws MessagingException, InterruptedException {
+        ArrayList recipients = new ArrayList();
+        recipients.add(new MailAddress("[EMAIL PROTECTED]"));
+        MimeMessageCopyOnWriteProxy mw = new MimeMessageCopyOnWriteProxy(
+                new MimeMessageInputStreamSource(
+                        "test",
+                        new SharedByteArrayInputStream(
+                                ("Return-path: [EMAIL PROTECTED]"+
+                                 "Content-Transfer-Encoding: plain\r\n"+
+                                 "Subject: test\r\n\r\n"+
+                                 "Body Text\r\n").getBytes())));
+        
+        MimeMessageCopyOnWriteProxy mw2 = new MimeMessageCopyOnWriteProxy(mw);
+        ContainerUtil.dispose(mw2);
+        mw2 = null;
+        System.gc();
+        Thread.sleep(1000);
+        // the NPE was inside this call
+        mw.getMessageSize();
+        ContainerUtil.dispose(mw);
+    }
+
+    
+    /**
+     * This test throw a NullPointerException when the original message was 
created by
+     * a MimeMessageInputStreamSource.
+     */
+    public void testMessageCloningViaCoW3() throws Exception {
+        MimeMessage mmorig = getSimpleMessage();
+        
+        MimeMessage mm = new MimeMessageCopyOnWriteProxy(mmorig);
+        
+        ContainerUtil.dispose(mmorig);
+        mmorig = null;
+        System.gc();
+        Thread.sleep(200);
+
+        try {
+            mm.writeTo(System.out);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail("Exception while writing the message to output");
+        }
+        
+        ContainerUtil.dispose(mmorig);
     }
 
     private static String getReferences(MimeMessage m) {

Modified: 
james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageTest.java
URL: 
http://svn.apache.org/viewcvs/james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageTest.java?rev=406350&r1=406349&r2=406350&view=diff
==============================================================================
--- 
james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageTest.java 
(original)
+++ 
james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageTest.java 
Sun May 14 08:10:45 2006
@@ -315,18 +315,46 @@
         MimeMessage mmorig = getSimpleMessage();
         
         MimeMessage mm = new MimeMessageCopyOnWriteProxy(mmorig);
-        
+
         MimeMessage mm2 = new MimeMessageCopyOnWriteProxy(mm);
         
         mm2.setHeader("Subject", "Modified");
         ContainerUtil.dispose(mm2);
+        System.gc();
+        Thread.sleep(200);
         //((Disposable)mail_dup.getMessage()).dispose();
         
         mm.setHeader("Subject", "Modified");
         
+        ContainerUtil.dispose(mm);
         ContainerUtil.dispose(mmorig);
+    }
+    
+    /**
+     * This test throw a NullPointerException when the original message was 
created by
+     * a MimeMessageInputStreamSource.
+     */
+    public void testMessageCloningViaCoW2() throws Exception {
+        MimeMessage mmorig = getSimpleMessage();
+        
+        MimeMessage mm = new MimeMessageCopyOnWriteProxy(mmorig);
+        
+        MimeMessage mm2 = new MimeMessageCopyOnWriteProxy(mm);
+        
         ContainerUtil.dispose(mm);
+        mm = null;
+        System.gc();
+        Thread.sleep(200);
+
+        try {
+            mm2.writeTo(System.out);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail("Exception while writing the message to output");
+        }
         
+        ContainerUtil.dispose(mm2);
+        ContainerUtil.dispose(mmorig);
     }
     
 }

Modified: 
james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageWrapperTest.java
URL: 
http://svn.apache.org/viewcvs/james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageWrapperTest.java?rev=406350&r1=406349&r2=406350&view=diff
==============================================================================
--- 
james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageWrapperTest.java
 (original)
+++ 
james/server/branches/v2.3/src/test/org/apache/james/core/MimeMessageWrapperTest.java
 Sun May 14 08:10:45 2006
@@ -147,6 +147,19 @@
         }
     }
 
+    /**
+     * See JAMES-474
+     * MimeMessageWrapper(MimeMessage) should clone the original message.
+     */
+    public void testMessageCloned() throws MessagingException, IOException, 
InterruptedException {
+        MimeMessageWrapper mmw = new MimeMessageWrapper(mw);
+        ContainerUtil.dispose(mw);
+        mw = null;
+        System.gc();
+        Thread.sleep(200);
+        mmw.writeTo(System.out);
+    }
+
     /*
      * Class under test for String getSubject()
      */



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to