You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2010/04/06 10:48:03 UTC

svn commit: r931050 - in /james/imap/trunk: api/src/main/java/org/apache/james/imap/api/ bin/ decode/src/main/java/org/apache/james/imap/decode/parser/ deployment/src/test/java/org/apache/james/imap/functional/jpa/ jcr/src/main/java/org/apache/james/im...

Author: norman
Date: Tue Apr  6 08:48:02 2010
New Revision: 931050

URL: http://svn.apache.org/viewvc?rev=931050&view=rev
Log:
use InputStream as source for append messages to mailbox. Still not 100% complete, because it still read all data into memory atm. (IMAP-127)

Added:
    james/imap/trunk/bin/
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/AbstractJPAMessage.java
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/openjpa/
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/openjpa/JPAStreamingMessage.java
Modified:
    james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapMessageFactory.java
    james/imap/trunk/decode/src/main/java/org/apache/james/imap/decode/parser/AppendCommandParser.java
    james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java
    james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailbox.java
    james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMailboxMembership.java
    james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMessage.java
    james/imap/trunk/jpa/pom.xml
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMailboxMembership.java
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMessage.java
    james/imap/trunk/mailbox/src/main/java/org/apache/james/imap/mailbox/Mailbox.java
    james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java
    james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/AppendRequest.java
    james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/BaseImap4Rev1MessageFactory.java
    james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AppendProcessor.java
    james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java
    james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/model/AbstractDocument.java
    james/imap/trunk/torque/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailbox.java

Modified: james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapMessageFactory.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapMessageFactory.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapMessageFactory.java (original)
+++ james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapMessageFactory.java Tue Apr  6 08:48:02 2010
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.james.imap.api;
 
+import java.io.InputStream;
 import java.util.Date;
 
 import javax.mail.Flags;
@@ -53,7 +54,7 @@ public interface ImapMessageFactory {
 
     public ImapMessage createAppendMessage(ImapCommand command,
             String mailboxName, Flags flags, Date datetime,
-            byte[] message, String tag);
+            InputStream message, String tag);
 
     public ImapMessage createAuthenticateMessage(final ImapCommand command,
             final String authType, final String tag);

Modified: james/imap/trunk/decode/src/main/java/org/apache/james/imap/decode/parser/AppendCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/decode/src/main/java/org/apache/james/imap/decode/parser/AppendCommandParser.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/decode/src/main/java/org/apache/james/imap/decode/parser/AppendCommandParser.java (original)
+++ james/imap/trunk/decode/src/main/java/org/apache/james/imap/decode/parser/AppendCommandParser.java Tue Apr  6 08:48:02 2010
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import java.io.ByteArrayInputStream;
 import java.util.Date;
 
 import javax.mail.Flags;
@@ -81,8 +82,9 @@ class AppendCommandParser extends Abstra
         final byte[] message = consumeLiteral(request);
         endLine(request);
         final ImapMessageFactory factory = getMessageFactory();
+        //TODO: FIX ME
         final ImapMessage result = factory.createAppendMessage(command,
-                mailboxName, flags, datetime, message, tag);
+                mailboxName, flags, datetime, new ByteArrayInputStream(message), tag);
         return result;
     }
 }

Modified: james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java (original)
+++ james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java Tue Apr  6 08:48:02 2010
@@ -57,6 +57,7 @@ public class JPAHostSystem extends ImapH
         properties.put("openjpa.MetaDataFactory", "jpa(Types=org.apache.james.imap.jpa.mail.model.JPAHeader;" +
                 "org.apache.james.imap.jpa.mail.model.JPAMailbox;" +
                 "org.apache.james.imap.jpa.mail.model.JPAMailboxMembership;" +
+                "org.apache.james.imap.jpa.mail.model.AbstractJPAMessage;" +
                 "org.apache.james.imap.jpa.mail.model.JPAMessage;" +
                 "org.apache.james.imap.jpa.mail.model.JPAProperty;" +
                 "org.apache.james.imap.jpa.user.model.JPASubscription)");

Modified: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailbox.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailbox.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailbox.java (original)
+++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailbox.java Tue Apr  6 08:48:02 2010
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.james.imap.jcr;
 
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -90,7 +91,7 @@ public class JCRMailbox extends StoreMai
     }
 
     @Override
-    protected MailboxMembership<String> createMessage(Date internalDate, long uid, int size, int bodyStartOctet, byte[] document, Flags flags, List<Header> headers, PropertyBuilder propertyBuilder) {
+    protected MailboxMembership<String> createMessage(Date internalDate, long uid, int size, int bodyStartOctet, InputStream document, Flags flags, List<Header> headers, PropertyBuilder propertyBuilder) {
         final List<JCRHeader> jcrHeaders = new ArrayList<JCRHeader>(headers.size());
         for (Header header: headers) {
             jcrHeaders.add((JCRHeader) header);

Modified: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMailboxMembership.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMailboxMembership.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMailboxMembership.java (original)
+++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMailboxMembership.java Tue Apr  6 08:48:02 2010
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.james.imap.jcr.mail.model;
 
+import java.io.InputStream;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
@@ -72,7 +73,7 @@ public class JCRMailboxMembership extend
 	private Node node;
 
 	public JCRMailboxMembership(String mailboxUUID, long uid,
-			Date internalDate, int size, Flags flags, byte[] content,
+			Date internalDate, int size, Flags flags, InputStream content,
 			int bodyStartOctet, final List<JCRHeader> headers,
 			final PropertyBuilder propertyBuilder, Log logger) {
 		super();
@@ -80,7 +81,7 @@ public class JCRMailboxMembership extend
 		this.uid = uid;
 		this.internalDate = internalDate;
 		this.size = size;
-		this.message = new JCRMessage(content, bodyStartOctet, headers,
+		this.message = new JCRMessage(content, size, bodyStartOctet, headers,
 				propertyBuilder, logger);
 		this.logger = logger;
 		setFlags(flags);

Modified: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMessage.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMessage.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMessage.java (original)
+++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMessage.java Tue Apr  6 08:48:02 2010
@@ -18,9 +18,6 @@
  ****************************************************************/
 package org.apache.james.imap.jcr.mail.model;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
@@ -49,7 +46,7 @@ public class JCRMessage extends Abstract
 
     private Node node;
     private final Log logger;
-    private byte[] content;
+    private InputStream content;
     private List<JCRHeader> headers;
     private long fullContentOctets;
     private String mediaType;
@@ -74,11 +71,12 @@ public class JCRMessage extends Abstract
         this.node = node;
     }
     
-    public JCRMessage(byte[] content, final int bodyStartOctet, final List<JCRHeader> headers, final PropertyBuilder propertyBuilder, Log logger) {
+    public JCRMessage(InputStream content, final long contentOctets, final int bodyStartOctet, final List<JCRHeader> headers, final PropertyBuilder propertyBuilder, Log logger) {
         super();
         this.logger = logger;
         this.content = content;
-        this.fullContentOctets = content.length;
+        this.fullContentOctets = contentOctets;
+       
         this.bodyStartOctet = bodyStartOctet;
         this.headers = new ArrayList<JCRHeader>(headers);
         this.textualLineCount = propertyBuilder.getTextualLineCount();
@@ -102,13 +100,9 @@ public class JCRMessage extends Abstract
     public JCRMessage(JCRMessage message, Log logger) {
         this.logger = logger;
         ByteBuffer buf = message.getFullContent().duplicate();
-        int a = 0;
-        this.content = new byte[buf.capacity()];
-        while(buf.hasRemaining()) {
-            content[a] = buf.get();
-            a++;
-        }
-        this.fullContentOctets = content.length;
+        this.content = new ByteBufferInputStream(buf);
+       
+        this.fullContentOctets = message.getFullContentOctets();
         this.bodyStartOctet = (int) (message.getFullContentOctets() - message.getBodyOctets());
         this.headers = new ArrayList<JCRHeader>();
         
@@ -138,23 +132,13 @@ public class JCRMessage extends Abstract
             try {
                 //TODO: Maybe we should cache this somehow...
                 InputStream contentStream = node.getNode(JcrConstants.JCR_CONTENT).getProperty(JcrConstants.JCR_DATA).getStream();
-                ByteArrayOutputStream out = new ByteArrayOutputStream();
- 
-                    byte[] buf = new byte[1024];
-                    int i = 0;
-                    while ((i = contentStream.read(buf)) != -1) {
-                        out.write(buf, 0, i);
-                    }
-
-                return ByteBuffer.wrap(out.toByteArray());
+                return getContentAsByteBuffer(contentStream);
             } catch (RepositoryException e) {
                 logger.error("Unable to retrieve property " + JcrConstants.JCR_CONTENT, e);
-            } catch (IOException e) {
-                logger.error("Unable to retrieve property " + JcrConstants.JCR_CONTENT, e);
             }
             return null;
         }
-        return ByteBuffer.wrap(content);
+        return getContentAsByteBuffer(content);
     }
 
     /*
@@ -301,7 +285,7 @@ public class JCRMessage extends Abstract
         } else {
             contentNode = node.getNode(JcrConstants.JCR_CONTENT);
         }
-        contentNode.setProperty(JcrConstants.JCR_DATA, new ByteArrayInputStream(getFullContent().array()));
+        contentNode.setProperty(JcrConstants.JCR_DATA, new ByteBufferInputStream(getFullContent()));
         contentNode.setProperty(JcrConstants.JCR_MIMETYPE, getMediaType());
 
         node.setProperty(FULL_CONTENT_OCTETS_PROPERTY, getFullContentOctets());

Modified: james/imap/trunk/jpa/pom.xml
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/pom.xml?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/jpa/pom.xml (original)
+++ james/imap/trunk/jpa/pom.xml Tue Apr  6 08:48:02 2010
@@ -102,7 +102,7 @@
             </property>   
             <property>
               <name>metaDataFactory</name>
-              <value>jpa(Types=org.apache.james.imap.jpa.mail.model.JPAHeader;org.apache.james.imap.jpa.mail.model.JPAMailbox;org.apache.james.imap.jpa.mail.model.JPAMailboxMembership;org.apache.james.imap.jpa.mail.model.JPAMessage;org.apache.james.imap.jpa.mail.model.JPAProperty;org.apache.james.imap.jpa.user.model.JPASubscription)</value>
+              <value>jpa(Types=org.apache.james.imap.jpa.mail.model.JPAHeader;org.apache.james.imap.jpa.mail.model.JPAMailbox;org.apache.james.imap.jpa.mail.model.JPAMailboxMembership;org.apache.james.imap.jpa.mail.model.AbstractJPAMessage;org.apache.james.imap.jpa.mail.model.JPAMessage;org.apache.james.imap.jpa.mail.model.openjpa.JPAStreamingMessage;org.apache.james.imap.jpa.mail.model.JPAProperty;org.apache.james.imap.jpa.user.model.JPASubscription)</value>
             </property>           
           </toolProperties>
         </configuration>

Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java (original)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java Tue Apr  6 08:48:02 2010
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.james.imap.jpa;
 
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -80,7 +81,7 @@ public abstract class JPAMailbox extends
     }
     
     @Override
-    protected MailboxMembership<Long> createMessage(Date internalDate, final long uid, final int size, int bodyStartOctet, final byte[] document, 
+    protected MailboxMembership<Long> createMessage(Date internalDate, final long uid, final int size, int bodyStartOctet, final InputStream document, 
             final Flags flags, final List<Header> headers, PropertyBuilder propertyBuilder) {
         final List<JPAHeader> jpaHeaders = new ArrayList<JPAHeader>(headers.size());
         for (Header header: headers) {

Added: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/AbstractJPAMessage.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/AbstractJPAMessage.java?rev=931050&view=auto
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/AbstractJPAMessage.java (added)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/AbstractJPAMessage.java Tue Apr  6 08:48:02 2010
@@ -0,0 +1,202 @@
+/****************************************************************
+ * 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.imap.jpa.mail.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.OneToMany;
+import javax.persistence.OrderBy;
+
+import org.apache.james.imap.store.mail.model.AbstractDocument;
+import org.apache.james.imap.store.mail.model.Header;
+import org.apache.james.imap.store.mail.model.Property;
+import org.apache.james.imap.store.mail.model.PropertyBuilder;
+
+/**
+ * Abstract base class for JPA based implementations of {@link AbstractDocument}
+ *
+ */
+@MappedSuperclass
+public abstract class AbstractJPAMessage extends AbstractDocument{
+
+    @Id@GeneratedValue private long id;
+
+    /** Headers for this message */
+    @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.LAZY) private List<JPAHeader> headers;
+    /** The first body octet */
+    @Basic(optional=false) private int bodyStartOctet;
+    /** Number of octets in the full document content */
+    @Basic(optional=false) private long contentOctets;
+    /** MIME media type */
+    @Basic(optional=true) private String mediaType;
+    /** MIME sub type */
+    @Basic(optional=true) private String subType;
+    /** Meta data for this message */
+    @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.LAZY) @OrderBy("line") private List<JPAProperty> properties;
+    /** THE CRFL count when this document is textual, null otherwise */
+    @Basic(optional=true) private Long textualLineCount;
+    
+
+    @Deprecated
+    public AbstractJPAMessage() {}
+
+    public AbstractJPAMessage(final long contentOctets, final int bodyStartOctet, final List<JPAHeader> headers, final PropertyBuilder propertyBuilder) {
+        super();
+        this.contentOctets = contentOctets;
+        this.bodyStartOctet = bodyStartOctet;
+        this.headers = new ArrayList<JPAHeader>(headers);
+        textualLineCount = propertyBuilder.getTextualLineCount();
+        this.mediaType = propertyBuilder.getMediaType();
+        this.subType = propertyBuilder.getSubType();
+        final List<Property> properties = propertyBuilder.toProperties();
+        this.properties = new ArrayList<JPAProperty>(properties.size());
+        int order = 0;
+        for (final Property property:properties) {
+            this.properties.add(new JPAProperty(property, order++));
+        }
+
+    }
+
+    /**
+     * Create a copy of the given message
+     * 
+     * @param message
+     */
+    public AbstractJPAMessage(AbstractJPAMessage message) {
+    	
+        this.contentOctets = message.getFullContentOctets();
+        this.bodyStartOctet = (int) (message.getFullContentOctets() - message.getBodyOctets());
+        this.headers = new ArrayList<JPAHeader>();
+        
+        List<Header> originalHeaders = message.getHeaders();
+        for (int i = 0; i < originalHeaders.size(); i++) {
+            headers.add(new JPAHeader(originalHeaders.get(i)));
+        }
+
+        PropertyBuilder pBuilder = new PropertyBuilder(message.getProperties());
+        this.textualLineCount = pBuilder.getTextualLineCount();
+        this.mediaType = pBuilder.getMediaType();
+        this.subType = pBuilder.getSubType();
+        final List<Property> properties = pBuilder.toProperties();
+        this.properties = new ArrayList<JPAProperty>(properties.size());
+        int order = 0;
+        for (final Property property:properties) {
+            this.properties.add(new JPAProperty(property, order++));
+        }
+
+    }
+
+    /**
+     * @see org.apache.james.imap.store.mail.model.Document#getHeaders()
+     */
+    public List<Header> getHeaders() {
+        return new ArrayList<Header>(headers);
+    }
+
+
+    @Override
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + (int) (id ^ (id >>> 32));
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        final AbstractJPAMessage other = (AbstractJPAMessage) obj;
+        if (id != other.id)
+            return false;
+        return true;
+    }
+
+    public String toString()
+    {
+        final String retValue = 
+            "message("
+            + "id = " + id
+            + " )";
+        return retValue;
+    }
+
+    /**
+     * Gets the top level MIME content media type.
+     * 
+     * @return top level MIME content media type, or null if default
+     */
+    public String getMediaType() {
+        return mediaType;
+    }
+    
+    /**
+     * Gets the MIME content subtype.
+     * 
+     * @return the MIME content subtype, or null if default
+     */
+    public String getSubType() {
+        return subType;
+    }
+
+    /**
+     * Gets a read-only list of meta-data properties.
+     * For properties with multiple values, this list will contain
+     * several enteries with the same namespace and local name.
+     * @return unmodifiable list of meta-data, not null
+     */
+    public List<Property> getProperties() {
+        return new ArrayList<Property>(properties);
+    }
+    
+    /**
+     * Gets the number of CRLF in a textual document.
+     * @return CRLF count when document is textual,
+     * null otherwise
+     */
+    public Long getTextualLineCount() {
+        return textualLineCount;
+    }
+
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.imap.store.mail.model.Document#getFullContentOctets()
+     */
+    public long getFullContentOctets() {
+        return contentOctets;
+    }
+
+    @Override
+    protected int getBodyStartOctet() {
+        return bodyStartOctet;
+    }
+
+}

Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMailboxMembership.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMailboxMembership.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMailboxMembership.java (original)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMailboxMembership.java Tue Apr  6 08:48:02 2010
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.james.imap.jpa.mail.model;
 
+import java.io.InputStream;
 import java.io.Serializable;
 import java.util.Date;
 import java.util.List;
@@ -145,13 +146,13 @@ public class JPAMailboxMembership extend
     public JPAMailboxMembership() {}
 
     public JPAMailboxMembership(long mailboxId, long uid, Date internalDate, int size, Flags flags, 
-            byte[] content, int bodyStartOctet, final List<JPAHeader> headers, final PropertyBuilder propertyBuilder) {
+            InputStream content, int bodyStartOctet, final List<JPAHeader> headers, final PropertyBuilder propertyBuilder) {
         super();
         this.mailboxId = mailboxId;
         this.uid = uid;
         this.internalDate = internalDate;
         this.size = size;
-        this.message = new JPAMessage(content, bodyStartOctet, headers, propertyBuilder);
+        this.message = new JPAMessage(content, size, bodyStartOctet, headers, propertyBuilder);
         setFlags(flags);
     }
 

Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMessage.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMessage.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMessage.java (original)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMessage.java Tue Apr  6 08:48:02 2010
@@ -18,193 +18,70 @@
  ****************************************************************/
 package org.apache.james.imap.jpa.mail.model;
 
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
 import java.nio.ByteBuffer;
-import java.util.ArrayList;
 import java.util.List;
 
 import javax.persistence.Basic;
-import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
 import javax.persistence.Lob;
-import javax.persistence.OneToMany;
-import javax.persistence.OrderBy;
 
-import org.apache.james.imap.store.mail.model.AbstractDocument;
-import org.apache.james.imap.store.mail.model.Header;
-import org.apache.james.imap.store.mail.model.Property;
 import org.apache.james.imap.store.mail.model.PropertyBuilder;
 
 @Entity(name="Message")
-public class JPAMessage extends AbstractDocument {
-    /** Primary key */
-    @Id@GeneratedValue private long id;
+public class JPAMessage extends AbstractJPAMessage{
+
 
     /** The value for the body field. Lazy loaded */
     /** We use a max length to represent 1gb data. Thats prolly overkill, but who knows */
-    @Basic(optional=false, fetch=FetchType.LAZY) @Column(length=1048576000) @Lob private byte[] content;
-    /** Headers for this message */
-    @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.LAZY) private List<JPAHeader> headers;
-    /** The first body octet */
-    @Basic(optional=false) private int bodyStartOctet;
-    /** Number of octets in the full document content */
-    @Basic(optional=false) private long contentOctets;
-    /** MIME media type */
-    @Basic(optional=true) private String mediaType;
-    /** MIME sub type */
-    @Basic(optional=true) private String subType;
-    /** Meta data for this message */
-    @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.LAZY) @OrderBy("line") private List<JPAProperty> properties;
-    /** THE CRFL count when this document is textual, null otherwise */
-    @Basic(optional=true) private Long textualLineCount;
-    
-    /**
-     * For enhancement only.
-     */
+    @Basic(optional=false, fetch=FetchType.LAZY) @Column(length=1048576000)  @Lob private byte[] content;
+
     @Deprecated
     public JPAMessage() {}
 
-    public JPAMessage(byte[] content, final int bodyStartOctet, final List<JPAHeader> headers, final PropertyBuilder propertyBuilder) {
-        super();
-        this.content = content;
-        this.contentOctets = content.length;
-        this.bodyStartOctet = bodyStartOctet;
-        this.headers = new ArrayList<JPAHeader>(headers);
-        textualLineCount = propertyBuilder.getTextualLineCount();
-        this.mediaType = propertyBuilder.getMediaType();
-        this.subType = propertyBuilder.getSubType();
-        final List<Property> properties = propertyBuilder.toProperties();
-        this.properties = new ArrayList<JPAProperty>(properties.size());
-        int order = 0;
-        for (final Property property:properties) {
-            this.properties.add(new JPAProperty(property, order++));
+    public JPAMessage(final InputStream content, final long contentOctets, final int bodyStartOctet, final List<JPAHeader> headers, final PropertyBuilder propertyBuilder) {
+        super(contentOctets,bodyStartOctet,headers,propertyBuilder);
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        try {
+            byte[] buf = new byte[1024];
+            int i = 0;
+            while ((i = content.read(buf)) != -1) {
+                out.write(buf, 0, i);
+            }
+            this.content = out.toByteArray();
+            if (out != null)
+                out.close();
+
+        } catch (Exception e) {
+            this.content = new byte[0];
         }
-        
     }
 
-
     /**
      * Create a copy of the given message
      * 
      * @param message
      */
     public JPAMessage(JPAMessage message) {
-        ByteBuffer buf = message.getFullContent().duplicate();
+        super(message);
+        ByteBuffer buf = message.getFullContent().duplicate(); 
         int a = 0;
         this.content = new byte[buf.capacity()];
         while(buf.hasRemaining()) {
             content[a] = buf.get();
             a++;
-        }
-        this.contentOctets = content.length;
-        this.bodyStartOctet = (int) (message.getFullContentOctets() - message.getBodyOctets());
-        this.headers = new ArrayList<JPAHeader>();
-        
-        List<Header> originalHeaders = message.getHeaders();
-        for (int i = 0; i < originalHeaders.size(); i++) {
-            headers.add(new JPAHeader(originalHeaders.get(i)));
-        }
-
-        PropertyBuilder pBuilder = new PropertyBuilder(message.getProperties());
-        this.textualLineCount = pBuilder.getTextualLineCount();
-        this.mediaType = pBuilder.getMediaType();
-        this.subType = pBuilder.getSubType();
-        final List<Property> properties = pBuilder.toProperties();
-        this.properties = new ArrayList<JPAProperty>(properties.size());
-        int order = 0;
-        for (final Property property:properties) {
-            this.properties.add(new JPAProperty(property, order++));
-        }
-    }
-    /**
-     * @see org.apache.james.imap.store.mail.model.Document#getHeaders()
-     */
-    public List<Header> getHeaders() {
-        return new ArrayList<Header>(headers);
-    }
-
-
-    @Override
-    public int hashCode() {
-        final int PRIME = 31;
-        int result = 1;
-        result = PRIME * result + (int) (id ^ (id >>> 32));
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        final JPAMessage other = (JPAMessage) obj;
-        if (id != other.id)
-            return false;
-        return true;
-    }
-
-    public String toString()
-    {
-        final String retValue = 
-            "message("
-            + "id = " + id
-            + " )";
-        return retValue;
+        }     
     }
 
-    /**
-     * Gets the top level MIME content media type.
-     * 
-     * @return top level MIME content media type, or null if default
-     */
-    public String getMediaType() {
-        return mediaType;
-    }
-    
-    /**
-     * Gets the MIME content subtype.
-     * 
-     * @return the MIME content subtype, or null if default
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.imap.store.mail.model.Document#getFullContent()
      */
-    public String getSubType() {
-        return subType;
-    }
-
-    /**
-     * Gets a read-only list of meta-data properties.
-     * For properties with multiple values, this list will contain
-     * several enteries with the same namespace and local name.
-     * @return unmodifiable list of meta-data, not null
-     */
-    public List<Property> getProperties() {
-        return new ArrayList<Property>(properties);
-    }
-    
-    /**
-     * Gets the number of CRLF in a textual document.
-     * @return CRLF count when document is textual,
-     * null otherwise
-     */
-    public Long getTextualLineCount() {
-        return textualLineCount;
-    }
-
     public ByteBuffer getFullContent() {
-        return ByteBuffer.wrap(content).asReadOnlyBuffer();
-    }
-
-    public long getFullContentOctets() {
-        return contentOctets;
+        return ByteBuffer.wrap(content);
     }
 
-    @Override
-    protected int getBodyStartOctet() {
-        return bodyStartOctet;
-    }
 }

Added: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/openjpa/JPAStreamingMessage.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/openjpa/JPAStreamingMessage.java?rev=931050&view=auto
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/openjpa/JPAStreamingMessage.java (added)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/openjpa/JPAStreamingMessage.java Tue Apr  6 08:48:02 2010
@@ -0,0 +1,77 @@
+/****************************************************************
+ * 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.imap.jpa.mail.model.openjpa;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+
+import org.apache.james.imap.jpa.mail.model.AbstractJPAMessage;
+import org.apache.james.imap.jpa.mail.model.JPAHeader;
+import org.apache.james.imap.jpa.mail.model.JPAMessage;
+import org.apache.james.imap.store.mail.model.PropertyBuilder;
+import org.apache.openjpa.persistence.Persistent;
+
+/**
+ * JPA implementation of {@link AbstractJPAMessage} which use openjpas {@link Persistent} type to
+ * be able to stream the message content without loading it into the memory at all. 
+ * 
+ * This is not supported for all DB's yet. See {@link http://openjpa.apache.org/builds/latest/docs/manual/ref_guide_mapping_jpa.html}
+ * 
+ * If your DB is not supported by this, use {@link JPAMessage} 
+ *
+ */
+@Entity(name="Message")
+public class JPAStreamingMessage extends AbstractJPAMessage{
+
+
+	@Persistent(optional=false, fetch=FetchType.LAZY) @Column(length=1048576000)  private InputStream content;
+	 
+
+    @Deprecated
+    public JPAStreamingMessage() {}
+
+    public JPAStreamingMessage(final InputStream content, final long contentOctets, final int bodyStartOctet, final List<JPAHeader> headers, final PropertyBuilder propertyBuilder) {
+        super(contentOctets,bodyStartOctet,headers,propertyBuilder);
+        this.content = content;
+    }
+
+    /**
+     * Create a copy of the given message
+     * 
+     * @param message
+     */
+    public JPAStreamingMessage(JPAStreamingMessage message) {
+        super(message);
+        this.content = new ByteBufferInputStream(message.getFullContent().duplicate());
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.imap.store.mail.model.Document#getFullContent()
+     */
+    public ByteBuffer getFullContent() {
+        return getContentAsByteBuffer(content);
+    }
+
+}

Modified: james/imap/trunk/mailbox/src/main/java/org/apache/james/imap/mailbox/Mailbox.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/mailbox/src/main/java/org/apache/james/imap/mailbox/Mailbox.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/mailbox/src/main/java/org/apache/james/imap/mailbox/Mailbox.java (original)
+++ james/imap/trunk/mailbox/src/main/java/org/apache/james/imap/mailbox/Mailbox.java Tue Apr  6 08:48:02 2010
@@ -19,6 +19,7 @@
 
 package org.apache.james.imap.mailbox;
 
+import java.io.InputStream;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.Map;
@@ -103,7 +104,7 @@ public interface Mailbox {
      * @return uid for the newly added message
      * @throws MailboxException when message cannot be appended
      */
-    long appendMessage(byte[] message, Date internalDate, MailboxSession mailboxSession, 
+    long appendMessage(InputStream msgIn, Date internalDate, MailboxSession mailboxSession, 
             boolean isRecent, Flags flags) throws MailboxException;
 
     /**

Modified: james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java (original)
+++ james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java Tue Apr  6 08:48:02 2010
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.inmemory;
 
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
@@ -66,8 +68,26 @@ public class InMemoryStoreMailbox extend
 
     @Override
     protected MailboxMembership<Long> createMessage(Date internalDate, long uid, int size, int bodyStartOctet, 
-            byte[] document, Flags flags, List<Header> headers, PropertyBuilder propertyBuilder) {
-        return new SimpleMailboxMembership(internalDate, uid, size, bodyStartOctet, document, flags, headers, propertyBuilder, mailboxId);
+            InputStream  document, Flags flags, List<Header> headers, PropertyBuilder propertyBuilder) {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        byte[] byteContent;
+        try {
+            byte[] buf = new byte[1024];
+            int i = 0;
+            while ((i = document.read(buf)) != -1) {
+                out.write(buf, 0, i);
+            }
+            byteContent = out.toByteArray();
+            if (out != null)
+                out.close();
+
+        } catch (Exception e) {
+            byteContent = new byte[0];
+        }
+        
+        return new SimpleMailboxMembership(internalDate, uid, size, bodyStartOctet, byteContent, flags, headers, propertyBuilder, mailboxId);
+
+
     }
 
     @Override

Modified: james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/AppendRequest.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/AppendRequest.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/AppendRequest.java (original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/AppendRequest.java Tue Apr  6 08:48:02 2010
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.james.imap.message.request;
 
+import java.io.InputStream;
 import java.util.Date;
 
 import javax.mail.Flags;
@@ -31,10 +32,10 @@ public class AppendRequest extends Abstr
 
     private final Date datetime;
 
-    private final byte[] message;
+    private final InputStream message;
 
     public AppendRequest(ImapCommand command, String mailboxName, Flags flags,
-            Date datetime, byte[] message, String tag) {
+            Date datetime, InputStream message, String tag) {
         super(tag, command);
         this.mailboxName = mailboxName;
         this.flags = flags;
@@ -54,7 +55,7 @@ public class AppendRequest extends Abstr
         return mailboxName;
     }
 
-    public byte[] getMessage() {
+    public InputStream getMessage() {
         return message;
     }
 }

Modified: james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/BaseImap4Rev1MessageFactory.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/BaseImap4Rev1MessageFactory.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/BaseImap4Rev1MessageFactory.java (original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/BaseImap4Rev1MessageFactory.java Tue Apr  6 08:48:02 2010
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.james.imap.message.request;
 
+import java.io.InputStream;
 import java.util.Date;
 
 import javax.mail.Flags;
@@ -48,7 +49,7 @@ public class BaseImap4Rev1MessageFactory
 
     public ImapMessage createAppendMessage(ImapCommand command,
             String mailboxName, Flags flags, Date datetime,
-            byte[] message, String tag) {
+            InputStream message, String tag) {
         return new AppendRequest(command, mailboxName, flags, datetime,
                 message, tag);
     }

Modified: james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AppendProcessor.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AppendProcessor.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AppendProcessor.java (original)
+++ james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AppendProcessor.java Tue Apr  6 08:48:02 2010
@@ -19,6 +19,7 @@
 
 package org.apache.james.imap.processor;
 
+import java.io.InputStream;
 import java.util.Date;
 
 import javax.mail.Flags;
@@ -60,7 +61,7 @@ public class AppendProcessor extends Abs
             String tag, ImapCommand command, Responder responder) {
         final AppendRequest request = (AppendRequest) message;
         final String mailboxName = request.getMailboxName();
-        final byte[] messageBytes = request.getMessage();
+        final InputStream messageIn = request.getMessage();
         final Date datetime = request.getDatetime();
         final Flags flags = request.getFlags();
         try {
@@ -68,7 +69,7 @@ public class AppendProcessor extends Abs
             final String fullMailboxName = buildFullName(session, mailboxName);
             final MailboxManager mailboxManager = getMailboxManager();
             final Mailbox mailbox = mailboxManager.getMailbox(fullMailboxName, ImapSessionUtils.getMailboxSession(session));
-            appendToMailbox(messageBytes, datetime, flags, session, tag,
+            appendToMailbox(messageIn, datetime, flags, session, tag,
                     command, mailbox, responder, fullMailboxName);
         } catch (MailboxNotFoundException e) {
 //          Indicates that the mailbox does not exist
@@ -104,7 +105,7 @@ public class AppendProcessor extends Abs
                 StatusResponse.ResponseCode.tryCreate());
     }
 
-    private void appendToMailbox(final byte[] message, final Date datetime,
+    private void appendToMailbox(final InputStream message, final Date datetime,
             final Flags flagsToBeSet, final ImapSession session, final String tag,
             final ImapCommand command, final Mailbox mailbox, Responder responder, final String fullMailboxName) {
         try {

Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java Tue Apr  6 08:48:02 2010
@@ -19,8 +19,12 @@
 
 package org.apache.james.imap.store;
 
-import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -131,15 +135,32 @@ public abstract class StoreMailbox<Id> i
      * (non-Javadoc)
      * @see org.apache.james.imap.mailbox.Mailbox#appendMessage(byte[], java.util.Date, org.apache.james.imap.mailbox.MailboxSession, boolean, javax.mail.Flags)
      */
-    public long appendMessage(byte[] messageBytes, Date internalDate,
+    public long appendMessage(InputStream msgIn, Date internalDate,
             MailboxSession mailboxSession, boolean isRecent, Flags flagsToBeSet)
     throws MailboxException {
+
         final Mailbox<Id> mailbox = reserveNextUid();
         if (mailbox == null) {
             throw new MailboxNotFoundException("Mailbox has been deleted");
         } else {
+           
             
+            File file = null;
             try {
+                // Create a temporary file and copy the message to it. We will work with the file as
+                // source for the InputStream
+                file = File.createTempFile("imap", ".msg");
+                FileOutputStream out = new FileOutputStream(file);
+                
+                byte[] buf = new byte[1024];
+                int i = 0;
+                while ((i = msgIn.read(buf)) != -1) {
+                    out.write(buf, 0, i);
+                }
+                out.flush();
+                out.close();
+                
+                FileInputStream tmpMsgIn = new FileInputStream(file);
                 // To be thread safe, we first get our own copy and the
                 // exclusive
                 // Uid
@@ -150,8 +171,8 @@ public abstract class StoreMailbox<Id> i
                 // mail 4 is big and comes over a slow connection.
 
                 final long uid = mailbox.getLastUid();
-                final int size = messageBytes.length;
-                final int bodyStartOctet = bodyStartOctet(messageBytes);
+                final int size = tmpMsgIn.available();
+                final int bodyStartOctet = bodyStartOctet(new FileInputStream(file));
 
                 // Disable line length... This should be handled by the smtp server component and not the parser itself
                 // https://issues.apache.org/jira/browse/IMAP-122
@@ -161,7 +182,7 @@ public abstract class StoreMailbox<Id> i
                 final ConfigurableMimeTokenStream parser = new ConfigurableMimeTokenStream(config);
                
                 parser.setRecursionMode(MimeTokenStream.M_NO_RECURSE);
-                parser.parse(new ByteArrayInputStream(messageBytes));
+                parser.parse(new FileInputStream(file));
                 final List<Header> headers = new ArrayList<Header>(INITIAL_SIZE_HEADERS);
                 
                 int lineNumber = 0;
@@ -245,7 +266,7 @@ public abstract class StoreMailbox<Id> i
                     flags.add(Flags.Flag.RECENT);
                 }
                 
-                final MailboxMembership<Id> message = createMessage(internalDate, uid, size, bodyStartOctet, messageBytes, flags, headers, propertyBuilder);
+                final MailboxMembership<Id> message = createMessage(internalDate, uid, size, bodyStartOctet, new FileInputStream(file), flags, headers, propertyBuilder);
                 final MessageMapper<Id> mapper = createMessageMapper(session);
 
                 mapper.execute(new TransactionalMapper.Transaction() {
@@ -266,24 +287,55 @@ public abstract class StoreMailbox<Id> i
             } catch (MimeException e) {
                 e.printStackTrace();
                 throw new MailboxException(HumanReadableText.FAILURE_MAIL_PARSE, e);
+            } finally {
+                // delete the temporary file if one was specified
+                if (file != null) {
+                    file.delete();
+                }
             }
         }
     }
 
-    private int bodyStartOctet(byte[] messageBytes) {
-        int bodyStartOctet = messageBytes.length;
-        for (int i=0;i<messageBytes.length-4;i++) {
-            if (messageBytes[i] == 0x0D) {
-                if (messageBytes[i+1] == 0x0A) {
-                    if (messageBytes[i+2] == 0x0D) {
-                        if (messageBytes[i+3] == 0x0A) {
-                            bodyStartOctet = i+4;
+    /**
+     * Return the position in the given {@link InputStream} at which the Body of the 
+     * Message starts
+     * 
+     * @param msgIn
+     * @return bodyStartOctet
+     * @throws IOException
+     */
+    private int bodyStartOctet(InputStream msgIn) throws IOException{
+        // we need to pushback maximal 3 bytes
+        PushbackInputStream in = new PushbackInputStream(msgIn,3);
+        
+        int bodyStartOctet = in.available();
+        int i = -1;
+        int count = 0;
+        while ((i = in.read()) != -1 && in.available() > 4) {
+            if (i == 0x0D) {
+                int a = in.read();
+                if (a == 0x0A) {
+                    int b = in.read();
+
+                    if (b == 0x0D) {
+                        int c = in.read();
+
+                        if (c == 0x0A) {
+                            bodyStartOctet = count+4;
                             break;
                         }
+                        in.unread(c);
                     }
+                    in.unread(b);
                 }
+                in.unread(a);
             }
+            count++;
         }
+        
+        // close the stream
+        in.close();
+        
         return bodyStartOctet;
     }
 
@@ -294,14 +346,14 @@ public abstract class StoreMailbox<Id> i
      * @param uid
      * @param size
      * @param bodyStartOctet
-     * @param document
+     * @param documentIn
      * @param flags
      * @param headers
      * @param propertyBuilder
      * @return membership
      */
     protected abstract MailboxMembership<Id> createMessage(Date internalDate, final long uid, final int size, int bodyStartOctet, 
-            final byte[] document, final Flags flags, final List<Header> headers, PropertyBuilder propertyBuilder);
+            final InputStream documentIn, final Flags flags, final List<Header> headers, PropertyBuilder propertyBuilder);
     
     /**
      * Create a new {@link Header} for the given data

Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/model/AbstractDocument.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/model/AbstractDocument.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/model/AbstractDocument.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/model/AbstractDocument.java Tue Apr  6 08:48:02 2010
@@ -18,6 +18,9 @@
  ****************************************************************/
 package org.apache.james.imap.store.mail.model;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.nio.ByteBuffer;
 
 /**
@@ -26,6 +29,20 @@ import java.nio.ByteBuffer;
  */
 public abstract class AbstractDocument implements Document{
 
+    protected ByteBuffer getContentAsByteBuffer(InputStream content) {
+        ByteArrayOutputStream full = new ByteArrayOutputStream();
+        try {
+            byte[] buf = new byte[1024];
+            int i = 0;
+            while ((i = content.read(buf)) != -1) {
+                full.write(buf, 0, i);
+            }
+        } catch (IOException e) {
+            // what todo here ?
+        }
+        return ByteBuffer.wrap(full.toByteArray()).asReadOnlyBuffer();
+        
+    }
     /**
      * @see org.apache.james.imap.store.mail.model.Document#getBodyContent()
      */    
@@ -51,4 +68,24 @@ public abstract class AbstractDocument i
      */
     protected abstract int getBodyStartOctet();
     
+
+
+    public final class ByteBufferInputStream extends InputStream {
+        private ByteBuffer buf;
+
+        public ByteBufferInputStream(ByteBuffer buf)  {
+            this.buf = buf;
+        }
+        
+        public synchronized int read() throws IOException {             
+            return buf.hasRemaining() ? buf.get() : -1;
+        }
+
+        public synchronized int read(byte[] bytes, int off, int len) throws IOException {           
+            int rv = Math.min(len, buf.remaining());                
+            buf.get(bytes, off, rv);
+            return rv == 0 ? -1 : rv;
+        }
+    }
+
 }

Modified: james/imap/trunk/torque/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailbox.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/torque/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailbox.java?rev=931050&r1=931049&r2=931050&view=diff
==============================================================================
--- james/imap/trunk/torque/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailbox.java (original)
+++ james/imap/trunk/torque/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailbox.java Tue Apr  6 08:48:02 2010
@@ -19,7 +19,6 @@
 
 package org.apache.james.mailboxmanager.torque;
 
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -125,10 +124,9 @@ public class TorqueMailbox implements Ma
         LockException.tryLock(lock.readLock(), LOCK_TIMEOUT);
     }
 
-    public long appendMessage(byte[] message, Date internalDate,
+    public long appendMessage(InputStream messageIn, Date internalDate,
             MailboxSession mailboxSession, boolean isRecent, Flags flags)
     throws MailboxException {
-
         try {
             checkAccess();
 
@@ -136,6 +134,7 @@ public class TorqueMailbox implements Ma
 
             if (myMailboxRow != null) {
                 try {
+                    
                     // To be thread safe, we first get our own copy and the
                     // exclusive
                     // Uid
@@ -151,7 +150,7 @@ public class TorqueMailbox implements Ma
                     messageRow.setMailboxId(getMailboxRow().getMailboxId());
                     messageRow.setUid(uid);
                     messageRow.setInternalDate(internalDate);
-                    final MimeMessage mimeMessage = new MimeMessage(null, new ByteArrayInputStream(message));
+                    final MimeMessage mimeMessage = new MimeMessage(null, messageIn);
                     if (isRecent) {
                         mimeMessage.setFlag(Flags.Flag.RECENT, true);
                     }



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