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]