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