This patch should illustrate how I think copying a message could be done. It
is only a sketch - there is no JavaDoc and no unit tests. But at least we
have something more concrete to talk about. A few lines of code might say
more than a thousand words..

Here are some details: the public classes Message, Multipart, Entity and
BodyPart all have a public copy constructor. The interface Body has a method
getCopy() that is used by the copy constructors.

Please let me know what you think of this.

Markus
Index: src/test/java/org/apache/james/mime4j/message/MultipartFormTest.java
===================================================================
--- src/test/java/org/apache/james/mime4j/message/MultipartFormTest.java	(revision 700849)
+++ src/test/java/org/apache/james/mime4j/message/MultipartFormTest.java	(working copy)
@@ -111,6 +111,10 @@
             this(text, null);
         }
         
+        public Body getCopy() {
+            return new StringPart(text, charset);
+        }
+        
         public Reader getReader() throws IOException {
             return new StringReader(this.text);
         }
Index: src/main/java/org/apache/james/mime4j/message/Entity.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/Entity.java	(revision 700849)
+++ src/main/java/org/apache/james/mime4j/message/Entity.java	(working copy)
@@ -41,6 +41,19 @@
     private Body body = null;
     private Entity parent = null;
 
+    protected Entity() {
+    }
+
+    protected Entity(Entity other) {
+        parent = null;
+        if (other.header != null)
+            header = new Header(other.header);
+        if (other.body != null) {
+            body = other.body.getCopy();
+            body.setParent(this);
+        }
+    }
+
     /**
      * Gets the parent entity of this entity.
      * Returns <code>null</code> if this is the root entity.
Index: src/main/java/org/apache/james/mime4j/message/Multipart.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/Multipart.java	(revision 700849)
+++ src/main/java/org/apache/james/mime4j/message/Multipart.java	(working copy)
@@ -59,6 +59,25 @@
         this.subType = subType;
     }
 
+    public Multipart(Multipart other) {
+        preamble = other.preamble;
+        epilogue = other.epilogue;
+        parent = null;
+        subType = other.subType;
+        
+        bodyParts = new LinkedList();
+        for (Iterator iter = other.bodyParts.iterator(); iter.hasNext();) {
+            BodyPart otherBodyPart = (BodyPart) iter.next();
+            BodyPart copy = new BodyPart(otherBodyPart);
+            bodyParts.add(copy);
+            copy.setParent(parent);
+        }
+    }
+    
+    public Body getCopy() {
+        return new Multipart(this);
+    }
+    
     /**
      * Gets the multipart sub-type. E.g. <code>alternative</code> (the default)
      * or <code>parallel</code>. See RFC 2045 for common sub-types and their
Index: src/main/java/org/apache/james/mime4j/message/BodyPart.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/BodyPart.java	(revision 700849)
+++ src/main/java/org/apache/james/mime4j/message/BodyPart.java	(working copy)
@@ -29,4 +29,11 @@
  */
 public class BodyPart extends Entity {
 
+    public BodyPart() {
+    }
+
+    public BodyPart(BodyPart other) {
+        super(other);
+    }
+
 }
Index: src/main/java/org/apache/james/mime4j/message/Message.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/Message.java	(revision 700849)
+++ src/main/java/org/apache/james/mime4j/message/Message.java	(working copy)
@@ -72,7 +72,15 @@
     public Message(InputStream is) throws IOException {
         this(is, null);
     }
-    
+
+    public Message(Message other) {
+        super(other);
+    }
+
+    public Body getCopy() {
+        return new Message(this);
+    }
+
     /**
      * Gets the <code>Subject</code> field.
      * 
Index: src/main/java/org/apache/james/mime4j/message/Header.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/Header.java	(revision 700849)
+++ src/main/java/org/apache/james/mime4j/message/Header.java	(working copy)
@@ -30,6 +30,8 @@
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.field.ContentTypeField;
@@ -57,6 +59,17 @@
     public Header() {
     }
 
+    public Header(Header other) {
+        fields = new LinkedList(other.fields);
+        fieldMap = new HashMap();
+        for (Iterator iter = other.fieldMap.entrySet().iterator(); iter.hasNext();) {
+            Map.Entry entry = (Entry) iter.next();
+            String name = (String) entry.getKey();
+            List fields = (List) entry.getValue();
+            fieldMap.put(name, fields);
+        }
+    }
+    
     /**
      * Creates a new <code>Header</code> from the specified stream.
      * 
Index: src/main/java/org/apache/james/mime4j/message/TempFileBinaryBody.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/TempFileBinaryBody.java	(revision 700849)
+++ src/main/java/org/apache/james/mime4j/message/TempFileBinaryBody.java	(working copy)
@@ -37,8 +37,8 @@
  */
 class TempFileBinaryBody extends AbstractBody implements BinaryBody {
     
-    private Entity parent = null;
     private TempFile tempFile = null;
+    private ReferenceCounter refCounter = new ReferenceCounter();
 
     /**
      * Use the given InputStream to build the TemporyFileBinaryBody
@@ -55,22 +55,18 @@
         CodecUtil.copy(is, out);
         out.close();
     }
+
+    public TempFileBinaryBody(TempFileBinaryBody other) {
+        tempFile = other.tempFile;
+        refCounter = other.refCounter;
+        refCounter.increment();
+    }    
     
-    /**
-     * @see org.apache.james.mime4j.message.AbstractBody#getParent()
-     */
-    public Entity getParent() {
-        return parent;
+    public Body getCopy() {
+        return new TempFileBinaryBody(this);
     }
-    
+
     /**
-     * @see org.apache.james.mime4j.message.AbstractBody#setParent(org.apache.james.mime4j.message.Entity)
-     */
-    public void setParent(Entity parent) {
-        this.parent = parent;
-    }
-    
-    /**
      * @see org.apache.james.mime4j.message.BinaryBody#getInputStream()
      */
     public InputStream getInputStream() throws IOException {
@@ -91,6 +87,7 @@
      * @see org.apache.james.mime4j.message.Disposable#dispose()
      */
     public void dispose() {
-        tempFile.delete();
+        if (refCounter.decrement())
+            tempFile.delete();
     }
 }
Index: src/main/java/org/apache/james/mime4j/message/TempFileTextBody.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/TempFileTextBody.java	(revision 700849)
+++ src/main/java/org/apache/james/mime4j/message/TempFileTextBody.java	(working copy)
@@ -46,6 +46,7 @@
     
     private String mimeCharset = null;
     private TempFile tempFile = null;
+    private ReferenceCounter refCounter = new ReferenceCounter();
 
     public TempFileTextBody(final InputStream is, final String mimeCharset) throws IOException {
         
@@ -58,6 +59,17 @@
         out.close();
     }
     
+    public TempFileTextBody(TempFileTextBody other) {
+        mimeCharset = other.mimeCharset;
+        tempFile = other.tempFile;
+        refCounter = other.refCounter;
+        refCounter.increment();
+    }
+    
+    public Body getCopy() {
+        return new TempFileTextBody(this);
+    }
+    
     /**
      * @see org.apache.james.mime4j.message.TextBody#getReader()
      */
@@ -114,6 +126,7 @@
      * @see org.apache.james.mime4j.message.Disposable#dispose()
      */
     public void dispose() {
-        tempFile.delete();
+        if (refCounter.decrement())
+            tempFile.delete();
     }
 }
Index: src/main/java/org/apache/james/mime4j/message/Body.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/Body.java	(revision 700849)
+++ src/main/java/org/apache/james/mime4j/message/Body.java	(working copy)
@@ -33,6 +33,8 @@
  */
 public interface Body extends Disposable {
 
+    Body getCopy();
+    
     /**
      * Gets the parent of this body.
      * 
Index: src/main/java/org/apache/james/mime4j/message/ReferenceCounter.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/ReferenceCounter.java	(revision 0)
+++ src/main/java/org/apache/james/mime4j/message/ReferenceCounter.java	(revision 0)
@@ -0,0 +1,13 @@
+package org.apache.james.mime4j.message;
+
+class ReferenceCounter {
+    int counter = 1;
+
+    public void increment() {
+        ++counter;
+    }
+
+    public boolean decrement() {
+        return --counter == 0;
+    }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to