Index: src/test/java/org/apache/james/mime4j/message/MessageTest.java
===================================================================
--- src/test/java/org/apache/james/mime4j/message/MessageTest.java	(revision 702746)
+++ src/test/java/org/apache/james/mime4j/message/MessageTest.java	(working copy)
@@ -26,11 +26,13 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
+import java.util.ArrayList;
 import java.util.List;
 
 import junit.framework.TestCase;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.james.mime4j.ExampleMail;
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.field.Field;
 import org.apache.james.mime4j.util.MessageUtils;
@@ -188,7 +190,8 @@
         assertFalse(body1.disposed);
         assertFalse(body2.disposed);
 
-        m.dispose();
+        BodyWalker walker = new BodyWalker(new DisposingBodyVisitor());
+        walker.walk(m);
 
         assertTrue(body1.disposed);
         assertTrue(body2.disposed);
@@ -198,7 +201,8 @@
             throws Exception {
         byte[] inputByte = getRawMessageAsByteArray();
         Message m = new Message(new ByteArrayInputStream(inputByte));
-        m.dispose();
+        BodyWalker walker = new BodyWalker(new DisposingBodyVisitor());
+        walker.walk(m);
 
         try {
             m.writeTo(new ByteArrayOutputStream(), MessageUtils.LENIENT);
@@ -226,7 +230,7 @@
         return complete.toString().getBytes();
     }
 
-    private static final class DummyBody extends AbstractBody {
+    private static final class DummyBody extends AbstractBody implements Disposable {
 
         public boolean disposed = false;
 
@@ -241,4 +245,55 @@
 
     }
 
+    static class SimpleBodyVisitor implements BodyVisitor {
+
+        private final List visitedBodies;
+        
+        public SimpleBodyVisitor() {
+            super();
+            this.visitedBodies = new ArrayList();
+        }
+        
+        public void visit(Body body) {
+            this.visitedBodies.add(body.getClass().getName());
+        }
+        
+        public List getVisitedBodies() {
+            return this.visitedBodies;
+        }
+        
+    }
+    
+    public void testSimpleMailVisitor() throws Exception {
+        ByteArrayInputStream in = new ByteArrayInputStream(ExampleMail.RFC822_SIMPLE_BYTES);
+        Message message = new Message(in);
+
+        SimpleBodyVisitor visitor = new SimpleBodyVisitor();
+        BodyWalker walker = new BodyWalker(visitor);
+        walker.walk(message);
+
+        List visitedBodies = visitor.getVisitedBodies();
+        assertEquals(2, visitedBodies.size());
+        assertEquals("org.apache.james.mime4j.message.Message", visitedBodies.get(0));
+        assertEquals("org.apache.james.mime4j.message.TempFileTextBody", visitedBodies.get(1));
+    }
+    
+    public void testMultipartMailVisitor() throws Exception {
+        ByteArrayInputStream in = new ByteArrayInputStream(ExampleMail.MULTIPART_WITH_BINARY_ATTACHMENTS_BYTES);
+        Message message = new Message(in);
+
+        SimpleBodyVisitor visitor = new SimpleBodyVisitor();
+        BodyWalker walker = new BodyWalker(visitor);
+        walker.walk(message);
+
+        List visitedBodies = visitor.getVisitedBodies();
+        assertEquals(6, visitedBodies.size());
+        assertEquals("org.apache.james.mime4j.message.Message", visitedBodies.get(0));
+        assertEquals("org.apache.james.mime4j.message.Multipart", visitedBodies.get(1));
+        assertEquals("org.apache.james.mime4j.message.TempFileTextBody", visitedBodies.get(2));
+        assertEquals("org.apache.james.mime4j.message.TempFileBinaryBody", visitedBodies.get(3));
+        assertEquals("org.apache.james.mime4j.message.TempFileBinaryBody", visitedBodies.get(4));
+        assertEquals("org.apache.james.mime4j.message.TempFileTextBody", visitedBodies.get(5));
+    }
+    
 }
Index: src/main/java/org/apache/james/mime4j/message/BodyWalker.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/BodyWalker.java	(revision 0)
+++ src/main/java/org/apache/james/mime4j/message/BodyWalker.java	(revision 0)
@@ -0,0 +1,49 @@
+package org.apache.james.mime4j.message;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class BodyWalker {
+
+    private final BodyVisitor visitor;
+    
+    public BodyWalker(final BodyVisitor visitor) {
+        super();
+        this.visitor = visitor;
+    }
+    
+    public void walk(final Message message) {
+        traverseMessage(message);
+    }
+
+    private void traverseMessage(final Message message) {
+        visitBody(message);
+        traverseBody(message.getBody());
+    }
+
+    private void traverseMultipart(final Multipart multipart) {
+        visitBody(multipart);
+        List bodyParts = multipart.getBodyParts();
+        for (Iterator it = bodyParts.iterator(); it.hasNext(); ) {
+            BodyPart bodyPart = (BodyPart) it.next();
+            traverseBody(bodyPart.getBody());
+        }
+    }
+    
+    private void traverseBody(final Body body) {
+        if (body instanceof Message) {
+            traverseMessage((Message) body);
+        } else if (body instanceof Multipart) {
+            traverseMultipart((Multipart) body);
+        } else {
+            visitBody(body);
+        }
+    }
+
+    private void visitBody(final Body body) {
+        if (body != null) {
+            this.visitor.visit(body);
+        }
+    }
+    
+}

Property changes on: src/main/java/org/apache/james/mime4j/message/BodyWalker.java
___________________________________________________________________
Added: svn:mergeinfo

Index: src/main/java/org/apache/james/mime4j/message/Entity.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/Entity.java	(revision 702746)
+++ src/main/java/org/apache/james/mime4j/message/Entity.java	(working copy)
@@ -36,11 +36,11 @@
  * 
  * @version $Id: Entity.java,v 1.3 2004/10/02 12:41:11 ntherning Exp $
  */
-public abstract class Entity implements Disposable {
+public abstract class Entity {
+
     private Header header = null;
     private Body body = null;
     private Entity parent = null;
-    private boolean disposed = false;
 
     /**
      * Gets the parent entity of this entity.
@@ -59,9 +59,6 @@
      *        this will be the root entity.
      */
     public void setParent(Entity parent) {
-        if (disposed)
-            throw new IllegalStateException("Entity has been disposed");
-
         this.parent = parent;
     }
     
@@ -80,9 +77,6 @@
      * @param header the header.
      */
     public void setHeader(Header header) {
-        if (disposed)
-            throw new IllegalStateException("Entity has been disposed");
-
         this.header = header;
     }
     
@@ -101,9 +95,6 @@
      * @param body the body.
      */
     public void setBody(Body body) {
-        if (disposed)
-            throw new IllegalStateException("Entity has been disposed");
-
         this.body = body;
         body.setParent(this);
     }
@@ -183,15 +174,10 @@
      * @throws IOException 
      */
     public void writeTo(OutputStream out, int mode) throws IOException, MimeException {
-        if (disposed)
-            throw new IllegalStateException("Entity has been disposed");
-
         getHeader().writeTo(out, mode);
-        
         out.flush();
         
         final Body body = getBody();
-
         OutputStream encOut;
         if (MimeUtil.ENC_BASE64.equals(getContentTransferEncoding())) {
             encOut = CodecUtil.wrapBase64(out);
@@ -208,39 +194,4 @@
         if (encOut != out) encOut.close();
     }
 
-    /**
-     * Disposes the body of this entity. Note that the dispose call does not get
-     * forwarded to the parent entity of this Entity.
-     * 
-     * Subclasses that need to free resources should override this method and
-     * invoke super.dispose().
-     * 
-     * @see org.apache.james.mime4j.message.Disposable#dispose()
-     */
-    public void dispose() {
-        if (disposed)
-            return;
-
-        try {
-            if (body != null)
-                body.dispose();
-        } finally {
-            disposed = true;
-
-            header = null;
-            body = null;
-            parent = null;
-        }
-    }
-
-    /**
-     * Ensures that the <code>dispose</code> method of this entity is called
-     * when there are no more references to it.
-     *
-     * Leave them out ATM (https://issues.apache.org/jira/browse/MIME4J-72?focusedCommentId=12636007#action_12636007)
-    protected void finalize() throws Throwable {
-        dispose();
-    }
-     */
-
 }
Index: src/main/java/org/apache/james/mime4j/message/BodyVisitor.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/BodyVisitor.java	(revision 0)
+++ src/main/java/org/apache/james/mime4j/message/BodyVisitor.java	(revision 0)
@@ -0,0 +1,36 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mime4j.message;
+
+/**
+ * Visitor interface for {@link Body} objects contained in a MIME body.
+ * 
+ * @version $Id$
+ */
+public interface BodyVisitor {
+
+    /**
+     * Visits the {@link Body}
+     * 
+     * @param body
+     */
+    void visit(Body body);
+    
+}

Property changes on: src/main/java/org/apache/james/mime4j/message/BodyVisitor.java
___________________________________________________________________
Added: svn:mergeinfo

Index: src/main/java/org/apache/james/mime4j/message/AbstractBody.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/AbstractBody.java	(revision 702746)
+++ src/main/java/org/apache/james/mime4j/message/AbstractBody.java	(working copy)
@@ -28,8 +28,8 @@
  * @version $Id: AbstractBody.java,v 1.2 2004/10/02 12:41:11 ntherning Exp $
  */
 public abstract class AbstractBody implements Body {
+
     private Entity parent = null;
-    protected boolean disposed = false;
     
     /**
      * @see org.apache.james.mime4j.message.Body#getParent()
@@ -42,39 +42,7 @@
      * @see org.apache.james.mime4j.message.Body#setParent(org.apache.james.mime4j.message.Entity)
      */
     public void setParent(Entity parent) {
-        if (disposed)
-            throw new IllegalStateException("AbstractBody has been disposed");
-
         this.parent = parent;
     }
 
-    /**
-     * Subclasses should override this method if they have allocated resources
-     * that need to be freed explicitly (e.g. cannot be simply reclaimed by the
-     * garbage collector). Subclasses that override this method should invoke
-     * super.dispose().
-     * 
-     * The default implementation marks this AbstractBody as disposed.
-     * 
-     * @see org.apache.james.mime4j.message.Disposable#dispose()
-     */
-    public void dispose() {
-        if (disposed)
-            return;
-
-        disposed = true;
-
-        parent = null;
-    }
-
-    /**
-     * Ensures that the <code>dispose</code> method of this abstract body is
-     * called when there are no more references to it.
-     *
-     * Leave them out ATM (https://issues.apache.org/jira/browse/MIME4J-72?focusedCommentId=12636007#action_12636007)
-    protected void finalize() throws Throwable {
-        dispose();
-    }
-     */
-
 }
Index: src/main/java/org/apache/james/mime4j/message/Multipart.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/Multipart.java	(revision 702746)
+++ src/main/java/org/apache/james/mime4j/message/Multipart.java	(working copy)
@@ -51,7 +51,6 @@
     private List bodyParts = new LinkedList();
     private Entity parent = null;
     private String subType;
-    private boolean disposed = false;
 
     /**
      * Creates a new empty <code>Multipart</code> instance.
@@ -79,9 +78,6 @@
      * @param subType the sub-type.
      */
     public void setSubType(String subType) {
-        if (disposed)
-            throw new IllegalStateException("Multipart has been disposed");
-
         this.subType = subType;
     }
     
@@ -96,9 +92,6 @@
      * @see org.apache.james.mime4j.message.Body#setParent(org.apache.james.mime4j.message.Entity)
      */
     public void setParent(Entity parent) {
-        if (disposed)
-            throw new IllegalStateException("Multipart has been disposed");
-
         this.parent = parent;
         for (Iterator it = bodyParts.iterator(); it.hasNext();) {
             ((BodyPart) it.next()).setParent(parent);
@@ -120,9 +113,6 @@
      * @param epilogue the epilogue.
      */
     public void setEpilogue(String epilogue) {
-        if (disposed)
-            throw new IllegalStateException("Multipart has been disposed");
-
         this.epilogue = epilogue;
     }
     
@@ -141,9 +131,6 @@
      * @param bodyParts the new list of <code>BodyPart</code> objects.
      */
     public void setBodyParts(List bodyParts) {
-        if (disposed)
-            throw new IllegalStateException("Multipart has been disposed");
-
         this.bodyParts = bodyParts;
         for (Iterator it = bodyParts.iterator(); it.hasNext();) {
             ((BodyPart) it.next()).setParent(parent);
@@ -156,9 +143,6 @@
      * @param bodyPart the body part.
      */
     public void addBodyPart(BodyPart bodyPart) {
-        if (disposed)
-            throw new IllegalStateException("Multipart has been disposed");
-
         bodyParts.add(bodyPart);
         bodyPart.setParent(parent);
     }
@@ -178,9 +162,6 @@
      * @param preamble the preamble.
      */
     public void setPreamble(String preamble) {
-        if (disposed)
-            throw new IllegalStateException("Multipart has been disposed");
-
         this.preamble = preamble;
     }
 
@@ -194,9 +175,6 @@
      * @throws MimeException if case of a MIME protocol violation
      */
     public void writeTo(final OutputStream out, int mode) throws IOException, MimeException {
-        if (disposed)
-            throw new IllegalStateException("Multipart has been disposed");
-
         Entity e = getParent();
         
         ContentTypeField cField = (ContentTypeField) e.getHeader().getField(
@@ -244,38 +222,4 @@
         writer.flush();
     }
 
-    /**
-     * Disposes the BodyParts of this Multipart. Note that the dispose call does
-     * not get forwarded to the parent entity of this Multipart.
-     * 
-     * @see org.apache.james.mime4j.message.Disposable#dispose()
-     */
-    public void dispose() {
-        if (disposed)
-            return;
-
-        try {
-            for (Iterator it = bodyParts.iterator(); it.hasNext();) {
-                ((BodyPart) it.next()).dispose();
-            }
-        } finally {
-            disposed = true;
-
-            preamble = null;
-            epilogue = null;
-            bodyParts = null;
-            parent = null;
-            subType = null;
-        }
-    }
-
-    /**
-     * Ensures that the <code>dispose</code> method of this multipart is
-     * called when there are no more references to it.
-     *
-     * Leave them out ATM (https://issues.apache.org/jira/browse/MIME4J-72?focusedCommentId=12636007#action_12636007)
-    protected void finalize() throws Throwable {
-        dispose();
-    }
-     */
 }
Index: src/main/java/org/apache/james/mime4j/message/TempFileBinaryBody.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/TempFileBinaryBody.java	(revision 702746)
+++ src/main/java/org/apache/james/mime4j/message/TempFileBinaryBody.java	(working copy)
@@ -35,9 +35,10 @@
  * 
  * @version $Id: TempFileBinaryBody.java,v 1.2 2004/10/02 12:41:11 ntherning Exp $
  */
-class TempFileBinaryBody extends AbstractBody implements BinaryBody {
+class TempFileBinaryBody extends AbstractBody implements BinaryBody, Disposable {
     
     private TempFile tempFile = null;
+    private boolean disposed;
 
     /**
      * Use the given InputStream to build the TemporyFileBinaryBody
@@ -79,12 +80,14 @@
      * @see org.apache.james.mime4j.message.Disposable#dispose()
      */
     public void dispose() {
+        if (disposed) {
+            return;
+        }
+        disposed = true;
         try {
             tempFile.delete();
         } finally {
             tempFile = null;
-
-            super.dispose();
         }
     }
 }
Index: src/main/java/org/apache/james/mime4j/message/TempFileTextBody.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/TempFileTextBody.java	(revision 702746)
+++ src/main/java/org/apache/james/mime4j/message/TempFileTextBody.java	(working copy)
@@ -41,11 +41,12 @@
  * 
  * @version $Id: TempFileTextBody.java,v 1.3 2004/10/25 07:26:46 ntherning Exp $
  */
-class TempFileTextBody extends AbstractBody implements TextBody {
+class TempFileTextBody extends AbstractBody implements TextBody, Disposable {
     private static Log log = LogFactory.getLog(TempFileTextBody.class);
     
     private String mimeCharset = null;
     private TempFile tempFile = null;
+    private boolean disposed;
 
     public TempFileTextBody(final InputStream is, final String mimeCharset) throws IOException {
         
@@ -117,13 +118,15 @@
      * @see org.apache.james.mime4j.message.Disposable#dispose()
      */
     public void dispose() {
+        if (disposed) {
+            return;
+        }
+        disposed = true;
         try {
             tempFile.delete();
         } finally {
             mimeCharset = null;
             tempFile = null;
-
-            super.dispose();
         }
     }
 }
Index: src/main/java/org/apache/james/mime4j/message/Body.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/Body.java	(revision 702746)
+++ src/main/java/org/apache/james/mime4j/message/Body.java	(working copy)
@@ -31,7 +31,7 @@
  * 
  * @version $Id: Body.java,v 1.4 2004/10/04 15:36:43 ntherning Exp $
  */
-public interface Body extends Disposable {
+public interface Body {
 
     /**
      * Gets the parent of this body.
Index: src/main/java/org/apache/james/mime4j/message/DisposingBodyVisitor.java
===================================================================
--- src/main/java/org/apache/james/mime4j/message/DisposingBodyVisitor.java	(revision 0)
+++ src/main/java/org/apache/james/mime4j/message/DisposingBodyVisitor.java	(revision 0)
@@ -0,0 +1,36 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mime4j.message;
+
+/**
+ * Visitor implementation that disposes of {@link Disposable}
+ * body objects.
+ * 
+ * @version $Id$
+ */
+public class DisposingBodyVisitor implements BodyVisitor {
+
+    public void visit(Body body) {
+        if (body instanceof Disposable) {
+            ((Disposable) body).dispose();
+        }
+    }
+    
+}

Property changes on: src/main/java/org/apache/james/mime4j/message/DisposingBodyVisitor.java
___________________________________________________________________
Added: svn:mergeinfo

