Author: rdonkin
Date: Sun Nov 25 11:38:01 2007
New Revision: 598041

URL: http://svn.apache.org/viewvc?rev=598041&view=rev
Log:
Eliminate intermediary string buffer for FETCH body elements.

Added:
    
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/response/imap4rev1/Literal.java
Modified:
    
james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/MessageResult.java
    
james/server/trunk/core-library/src/test/java/org/apache/james/mailboxmanager/MessageResultUtilsTest.java
    
james/server/trunk/experimental-seda-imap-function/src/main/java/org/apache/james/experimental/imapserver/encode/writer/ChannelImapResponseWriter.java
    
james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/ImapConstants.java
    
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/response/imap4rev1/FetchResponse.java
    
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/ImapResponseComposer.java
    
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/ImapResponseWriter.java
    
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/base/ImapResponseComposerImpl.java
    
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/imap4rev1/FetchResponseEncoder.java
    
james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/base/ByteImapResponseWriter.java
    
james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/imap4rev1/legacy/MockImapResponseWriter.java
    
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/FetchProcessor.java
    
james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageRowUtils.java

Modified: 
james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/MessageResult.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/MessageResult.java?rev=598041&r1=598040&r2=598041&view=diff
==============================================================================
--- 
james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/MessageResult.java
 (original)
+++ 
james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/MessageResult.java
 Sun Nov 25 11:38:01 2007
@@ -19,6 +19,8 @@
 
 package org.apache.james.mailboxmanager;
 
+import java.io.IOException;
+import java.nio.channels.WritableByteChannel;
 import java.util.Date;
 import java.util.Iterator;
 
@@ -191,13 +193,21 @@
          * @param buffer <code>StringBuffer</code>, not null
          * @throws MessagingException
          */
-        public void writeTo(StringBuffer buffer) throws 
MailboxManagerException;
+        public void writeTo(StringBuffer buffer);
+        
+        /**
+         * Writes content to the given channel.
+         * @param channel <code>Channel</code> open, not null
+         * @throws MailboxManagerException
+         * @throws IOException when channel IO fails
+         */
+        public void writeTo(WritableByteChannel channel) throws IOException;
         
         /**
          * Size (in octets) of the content.
          * @return number of octets to be written
          * @throws MessagingException
          */
-        public long size() throws MailboxManagerException;
+        public long size();
     }
 }

Modified: 
james/server/trunk/core-library/src/test/java/org/apache/james/mailboxmanager/MessageResultUtilsTest.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/core-library/src/test/java/org/apache/james/mailboxmanager/MessageResultUtilsTest.java?rev=598041&r1=598040&r2=598041&view=diff
==============================================================================
--- 
james/server/trunk/core-library/src/test/java/org/apache/james/mailboxmanager/MessageResultUtilsTest.java
 (original)
+++ 
james/server/trunk/core-library/src/test/java/org/apache/james/mailboxmanager/MessageResultUtilsTest.java
 Sun Nov 25 11:38:01 2007
@@ -19,6 +19,8 @@
 
 package org.apache.james.mailboxmanager;
 
+import java.io.IOException;
+import java.nio.channels.WritableByteChannel;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -43,11 +45,11 @@
             value = "Value";
         }
         
-        public long size() throws MailboxManagerException {
+        public long size() {
             return 0;
         }
 
-        public void writeTo(StringBuffer buffer) throws 
MailboxManagerException {
+        public void writeTo(StringBuffer buffer) {
         }
         
         public String getName() {
@@ -56,6 +58,10 @@
 
         public String getValue() {
             return value;
+        }
+
+        public void writeTo(WritableByteChannel channel) throws IOException {
+            
         }
         
     }

Modified: 
james/server/trunk/experimental-seda-imap-function/src/main/java/org/apache/james/experimental/imapserver/encode/writer/ChannelImapResponseWriter.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/experimental-seda-imap-function/src/main/java/org/apache/james/experimental/imapserver/encode/writer/ChannelImapResponseWriter.java?rev=598041&r1=598040&r2=598041&view=diff
==============================================================================
--- 
james/server/trunk/experimental-seda-imap-function/src/main/java/org/apache/james/experimental/imapserver/encode/writer/ChannelImapResponseWriter.java
 (original)
+++ 
james/server/trunk/experimental-seda-imap-function/src/main/java/org/apache/james/experimental/imapserver/encode/writer/ChannelImapResponseWriter.java
 Sun Nov 25 11:38:01 2007
@@ -26,6 +26,7 @@
 
 import org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.james.api.imap.ImapConstants;
+import org.apache.james.imap.message.response.imap4rev1.Literal;
 import org.apache.james.imapserver.codec.encode.ImapResponseWriter;
 
 /**
@@ -191,5 +192,14 @@
         } else {
             write(BYTES_SPACE);
         }
+    }
+
+    public void literal(Literal literal) throws IOException {
+        space();
+        write(BYTES_OPEN_BRACE);
+        writeASCII(Long.toString(literal.size()));
+        write(BYTES_CLOSE_BRACE);
+        write(BYTES_LINE_END);
+        literal.writeTo(out);
     }
 }

Modified: 
james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/ImapConstants.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/ImapConstants.java?rev=598041&r1=598040&r2=598041&view=diff
==============================================================================
--- 
james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/ImapConstants.java
 (original)
+++ 
james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/ImapConstants.java
 Sun Nov 25 11:38:01 2007
@@ -46,6 +46,10 @@
     public static final byte[] BYTES_DQUOTE = {BYTE_DQUOTE};
     public static final byte BYTE_CLOSE_SQUARE_BRACKET = 0x5D;
     public static final byte[] BYTES_CLOSE_SQUARE_BRACKET = 
{BYTE_CLOSE_SQUARE_BRACKET};
+    public static final byte BYTE_OPEN_BRACE = 0x7B;
+    public static final byte[] BYTES_OPEN_BRACE = {BYTE_OPEN_BRACE};
+    public static final byte BYTE_CLOSE_BRACE = 0x7D;
+    public static final byte[] BYTES_CLOSE_BRACE = {BYTE_CLOSE_BRACE};
     public static final byte[] BYTES_LINE_END = {0x0D, 0x0A};
     
     public static final char OPENING_PARENTHESIS = '(';

Modified: 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/response/imap4rev1/FetchResponse.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/response/imap4rev1/FetchResponse.java?rev=598041&r1=598040&r2=598041&view=diff
==============================================================================
--- 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/response/imap4rev1/FetchResponse.java
 (original)
+++ 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/response/imap4rev1/FetchResponse.java
 Sun Nov 25 11:38:01 2007
@@ -18,7 +18,10 @@
  ****************************************************************/
 package org.apache.james.imap.message.response.imap4rev1;
 
+import java.io.IOException;
+import java.nio.channels.WritableByteChannel;
 import java.util.Date;
+import java.util.List;
 
 import javax.mail.Flags;
 
@@ -26,86 +29,112 @@
 
 public final class FetchResponse implements ImapResponseMessage {
 
-        private final int messageNumber;
-        private final Flags flags;
-        private final Long uid;
-        private final Date internalDate;
-        private final Integer size;
-        private final StringBuffer misc;
-        private final StringBuffer elements;
-        
-        public FetchResponse(final int messageNumber, final Flags flags, final 
Long uid,
-                final Date internalDate, final Integer size, StringBuffer 
misc, StringBuffer elements) {
-            super();
-            this.messageNumber = messageNumber;
-            this.flags = flags;
-            this.uid = uid;
-            this.internalDate = internalDate;
-            this.size = size;
-            this.misc = misc;
-            this.elements = elements;
-        }
-        
-        /**
-         * Gets the number of the message whose details 
-         * have been fetched.
-         * @return message number
-         */
-        public final int getMessageNumber() {
-            return messageNumber;
-        }
-        
-        /**
-         * Gets the fetched flags.
-         * @return [EMAIL PROTECTED] Flags} fetched,
-         * or null if the <code>FETCH</code> did not include <code>FLAGS</code>
-         */
-        public Flags getFlags() {
-            return flags;
-        }
-        
-        /**
-         * Gets the unique id for the fetched message.
-         * @return message uid, 
-         * or null if the <code>FETCH</code> did not include <code>UID</code>
-         */
-        public Long getUid() {
-            return uid;
-        }
-
-        /**
-         * Gets the internal date for the fetched message.
-         * @return the internalDate,
-         * or null if the <code>FETCH</code> did not include 
<code>INTERNALDATE</code>
+    private final int messageNumber;
+    private final Flags flags;
+    private final Long uid;
+    private final Date internalDate;
+    private final Integer size;
+    private final StringBuffer misc;
+    private final List elements;
+
+    public FetchResponse(final int messageNumber, final Flags flags, final 
Long uid,
+            final Date internalDate, final Integer size, StringBuffer misc, 
List elements) {
+        super();
+        this.messageNumber = messageNumber;
+        this.flags = flags;
+        this.uid = uid;
+        this.internalDate = internalDate;
+        this.size = size;
+        this.misc = misc;
+        this.elements = elements;
+    }
+
+    /**
+     * Gets the number of the message whose details 
+     * have been fetched.
+     * @return message number
+     */
+    public final int getMessageNumber() {
+        return messageNumber;
+    }
+
+    /**
+     * Gets the fetched flags.
+     * @return [EMAIL PROTECTED] Flags} fetched,
+     * or null if the <code>FETCH</code> did not include <code>FLAGS</code>
+     */
+    public Flags getFlags() {
+        return flags;
+    }
+
+    /**
+     * Gets the unique id for the fetched message.
+     * @return message uid, 
+     * or null if the <code>FETCH</code> did not include <code>UID</code>
+     */
+    public Long getUid() {
+        return uid;
+    }
+
+    /**
+     * Gets the internal date for the fetched message.
+     * @return the internalDate,
+     * or null if the <code>FETCH</code> did not include 
<code>INTERNALDATE</code>
+     */
+    public final Date getInternalDate() {
+        return internalDate;
+    }
+
+    /**
+     * Gets the size for the fetched message.
+     * @return the size,
+     * or null if the <code>FETCH</code> did not include <code>SIZE</code>
+     */
+    public final Integer getSize() {
+        return size;
+    }
+
+    /**
+     * TODO: replace
+     * @return <code>List</code> of <code>BodyElement</code>'s, 
+     * or null if the <code>FETCH</code> did not include body elements
+     */
+    public final List getElements() {
+        return elements;
+    }
+
+    /**
+     * TODO: replace
+     * @return the misc
+     */
+    public final StringBuffer getMisc() {
+        return misc;
+    }
+    
+    /**
+     * BODY FETCH element content.
+     */
+    public interface BodyElement extends Literal {
+        
+        /**
+         * The full name of the element fetched.
+         * As per <code>FETCH</code> command input.
+         * @return name, not null
+         */
+        public String getName();
+        
+        /**
+         * Size of the literal content data.
+         * @return number of octets which [EMAIL PROTECTED] 
#writeTo(WritableByteChannel)}
+         * will put onto the channel
+         */
+        public long size();
+        
+        /**
+         * Writes the contents of this body element to the channel.
+         * @param channel <code>Channel</code>, not null
+         * @throws IOException
          */
-        public final Date getInternalDate() {
-            return internalDate;
-        }
-
-        /**
-         * Gets the size for the fetched message.
-         * @return the size,
-         * or null if the <code>FETCH</code> did not include <code>SIZE</code>
-         */
-        public final Integer getSize() {
-            return size;
-        }
-
-        /**
-         * TODO: replace
-         * @return the elements
-         */
-        public final StringBuffer getElements() {
-            return elements;
-        }
-
-        /**
-         * TODO: replace
-         * @return the misc
-         */
-        public final StringBuffer getMisc() {
-            return misc;
-        }
-        
-        
+        public void writeTo(WritableByteChannel channel) throws IOException;
+    }
 }

Added: 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/response/imap4rev1/Literal.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/response/imap4rev1/Literal.java?rev=598041&view=auto
==============================================================================
--- 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/response/imap4rev1/Literal.java
 (added)
+++ 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/response/imap4rev1/Literal.java
 Sun Nov 25 11:38:01 2007
@@ -0,0 +1,39 @@
+/****************************************************************
+ * 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.message.response.imap4rev1;
+
+import java.io.IOException;
+import java.nio.channels.WritableByteChannel;
+
+public interface Literal {
+    /**
+     * Size of the literal content data.
+     * @return number of octets which [EMAIL PROTECTED] 
#writeTo(WritableByteChannel)}
+     * will put onto the channel
+     */
+    public long size();
+    
+    /**
+     * Writes the contents of this body element to the channel.
+     * @param channel <code>Channel</code>, not null
+     * @throws IOException
+     */
+    public void writeTo(WritableByteChannel channel) throws IOException;
+}

Modified: 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/ImapResponseComposer.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/ImapResponseComposer.java?rev=598041&r1=598040&r2=598041&view=diff
==============================================================================
--- 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/ImapResponseComposer.java
 (original)
+++ 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/ImapResponseComposer.java
 Sun Nov 25 11:38:01 2007
@@ -25,6 +25,7 @@
 import javax.mail.Flags;
 
 import org.apache.james.api.imap.ImapCommand;
+import org.apache.james.imap.message.response.imap4rev1.Literal;
 
 public interface ImapResponseComposer {
 
@@ -227,5 +228,7 @@
             String type, String responseCode, String text) throws IOException;
     
     public void quote(String message) throws IOException;
+
+    public void literal(Literal literal) throws IOException;
 
 }

Modified: 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/ImapResponseWriter.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/ImapResponseWriter.java?rev=598041&r1=598040&r2=598041&view=diff
==============================================================================
--- 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/ImapResponseWriter.java
 (original)
+++ 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/ImapResponseWriter.java
 Sun Nov 25 11:38:01 2007
@@ -21,6 +21,8 @@
 
 import java.io.IOException;
 
+import org.apache.james.imap.message.response.imap4rev1.Literal;
+
 /**
  * <p>Writes IMAP response.</p>
  * <p>Factors out basic IMAP reponse writing operations 
@@ -80,4 +82,12 @@
      *
      */
     void end() throws IOException;
+    
+    /**
+     * Writes literal content
+     * @param literal <code>Literal</code> to be written,
+     * not null
+     * @throws IOException
+     */
+    void literal(Literal literal) throws IOException;
 }

Modified: 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/base/ImapResponseComposerImpl.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/base/ImapResponseComposerImpl.java?rev=598041&r1=598040&r2=598041&view=diff
==============================================================================
--- 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/base/ImapResponseComposerImpl.java
 (original)
+++ 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/base/ImapResponseComposerImpl.java
 Sun Nov 25 11:38:01 2007
@@ -30,6 +30,8 @@
 import org.apache.james.api.imap.ImapCommand;
 import org.apache.james.api.imap.ImapConstants;
 import org.apache.james.api.imap.message.MessageFlags;
+import org.apache.james.imap.message.response.imap4rev1.Literal;
+import 
org.apache.james.imap.message.response.imap4rev1.FetchResponse.BodyElement;
 import org.apache.james.imapserver.codec.encode.ImapResponseComposer;
 import org.apache.james.imapserver.codec.encode.ImapResponseWriter;
 
@@ -449,4 +451,9 @@
         message(FETCH);
         openParen();
     }
+
+    public void literal(Literal literal) throws IOException {
+        writer.literal(literal);
+    }
+
 }

Modified: 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/imap4rev1/FetchResponseEncoder.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/imap4rev1/FetchResponseEncoder.java?rev=598041&r1=598040&r2=598041&view=diff
==============================================================================
--- 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/imap4rev1/FetchResponseEncoder.java
 (original)
+++ 
james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/imap4rev1/FetchResponseEncoder.java
 Sun Nov 25 11:38:01 2007
@@ -21,6 +21,8 @@
 
 import java.io.IOException;
 import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
 
 import javax.mail.Flags;
 
@@ -52,11 +54,21 @@
             encodeSize(composer, fetchResponse);
             encode(composer, fetchResponse.getMisc());
             encodeUid(composer, fetchResponse);
-            encode(composer, fetchResponse.getElements());
+            encodeBodyElements(composer, fetchResponse.getElements());
             composer.closeFetchResponse();
         }
     }
     
+    private void encodeBodyElements(final ImapResponseComposer composer, final 
List elements) throws IOException {
+        if (elements != null) {
+            for (final Iterator it = elements.iterator();it.hasNext();) {
+                FetchResponse.BodyElement element = 
(FetchResponse.BodyElement) it.next();
+                composer.message(element.getName());
+                composer.literal(element);
+            }
+        }
+    }
+
     private void encode(ImapResponseComposer composer, StringBuffer buffer) 
throws IOException {
         if (buffer != null && buffer.length() > 0) {
             composer.message(buffer.substring(1));

Modified: 
james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/base/ByteImapResponseWriter.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/base/ByteImapResponseWriter.java?rev=598041&r1=598040&r2=598041&view=diff
==============================================================================
--- 
james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/base/ByteImapResponseWriter.java
 (original)
+++ 
james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/base/ByteImapResponseWriter.java
 Sun Nov 25 11:38:01 2007
@@ -20,10 +20,14 @@
 package org.apache.james.imapserver.codec.encode.base;
 
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.io.PrintWriter;
+import java.nio.channels.Channels;
+import java.nio.channels.WritableByteChannel;
 
 import org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.james.api.imap.ImapConstants;
+import org.apache.james.imap.message.response.imap4rev1.Literal;
 import org.apache.james.imapserver.codec.encode.ImapResponseWriter;
 
 /**
@@ -153,5 +157,13 @@
         } else {
             writer.print(SP_CHAR);
         }
+    }
+
+    public void literal(Literal literal) throws IOException {
+        space();
+        writer.flush();
+        WritableByteChannel channel = Channels.newChannel(out);
+        literal.writeTo(channel);
+        writer.flush();
     }
 }

Modified: 
james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/imap4rev1/legacy/MockImapResponseWriter.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/imap4rev1/legacy/MockImapResponseWriter.java?rev=598041&r1=598040&r2=598041&view=diff
==============================================================================
--- 
james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/imap4rev1/legacy/MockImapResponseWriter.java
 (original)
+++ 
james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/imap4rev1/legacy/MockImapResponseWriter.java
 Sun Nov 25 11:38:01 2007
@@ -19,9 +19,11 @@
 
 package org.apache.james.imapserver.codec.encode.imap4rev1.legacy;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.james.imap.message.response.imap4rev1.Literal;
 import org.apache.james.imapserver.codec.encode.ImapResponseWriter;
 
 public class MockImapResponseWriter implements ImapResponseWriter {
@@ -315,6 +317,41 @@
         
         
     }
+
+    public void literal(Literal literal) throws IOException {
+        operations.add(new LiteralOperation(literal));
+    }
     
+    public static final class LiteralOperation {
+        public final Literal literal;
+        public LiteralOperation(Literal literal) {
+            this.literal = literal;
+        }
+
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = 1;
+            result = PRIME * result + ((literal == null) ? 0 : 
literal.hashCode());
+            return result;
+        }
+        
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            final LiteralOperation other = (LiteralOperation) obj;
+            if (literal == null) {
+                if (other.literal != null)
+                    return false;
+            } else if (!literal.equals(other.literal))
+                return false;
+            return true;
+        }
+        
+        
+    }
     
 }

Modified: 
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/FetchProcessor.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/FetchProcessor.java?rev=598041&r1=598040&r2=598041&view=diff
==============================================================================
--- 
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/FetchProcessor.java
 (original)
+++ 
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/FetchProcessor.java
 Sun Nov 25 11:38:01 2007
@@ -19,6 +19,9 @@
 
 package org.apache.james.imapserver.processor.imap4rev1;
 
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
@@ -43,6 +46,7 @@
 import org.apache.james.api.imap.process.ImapSession;
 import org.apache.james.imap.message.request.imap4rev1.FetchRequest;
 import org.apache.james.imap.message.response.imap4rev1.FetchResponse;
+import 
org.apache.james.imap.message.response.imap4rev1.FetchResponse.BodyElement;
 import org.apache.james.imapserver.processor.base.AbstractImapRequestProcessor;
 import org.apache.james.imapserver.processor.base.AuthorizationException;
 import org.apache.james.imapserver.processor.base.ImapSessionUtils;
@@ -53,6 +57,7 @@
 import org.apache.james.mailboxmanager.MessageResult;
 import org.apache.james.mailboxmanager.MessageResultUtils;
 import org.apache.james.mailboxmanager.UnsupportedCriteriaException;
+import org.apache.james.mailboxmanager.MessageResult.Content;
 import org.apache.james.mailboxmanager.impl.GeneralMessageSetImpl;
 import org.apache.james.mailboxmanager.mailbox.ImapMailboxSession;
 
@@ -161,7 +166,7 @@
         private Date internalDate;
         private Integer size;
         private StringBuffer misc;
-        private StringBuffer elements;
+        private List elements;
         
         public FetchResponseBuilder(final Logger logger) {
             super();
@@ -264,21 +269,15 @@
 
                 // BODY part responses.
                 Collection elements = fetch.getBodyElements();
-                this.elements = new StringBuffer();
+                this.elements = new ArrayList();
                 for (Iterator iterator = elements.iterator(); 
iterator.hasNext();) {
-                    BodyFetchElement fetchElement = (BodyFetchElement) iterator
-                            .next();
-                    this.elements.append(ImapConstants.SP);
-                    this.elements.append(fetchElement.getResponseName());
-                    this.elements.append(ImapConstants.SP);
-
-                    // Various mechanisms for returning message body.
-                    String sectionSpecifier = fetchElement.getParameters();
-
-                    try {
-                        handleBodyFetch(result, sectionSpecifier, 
this.elements);
-                    } catch (MessagingException e) {
-                        throw new MailboxException(e.getMessage(), e);
+                    BodyFetchElement fetchElement = (BodyFetchElement) 
iterator.next();
+                    final String sectionSpecifier = 
fetchElement.getParameters();
+                    final String responseName = fetchElement.getResponseName();
+                    final FetchResponse.BodyElement element 
+                        = bodyFetch(result, sectionSpecifier, responseName);
+                    if (element != null) {
+                        this.elements.add(element);
                     }
                 }
                 return build();
@@ -302,36 +301,36 @@
             reset(msn);
         }
 
-        private void handleBodyFetch(final MessageResult result,
-                String sectionSpecifier, StringBuffer response)
-                throws ProtocolException, MessagingException {
+        private FetchResponse.BodyElement bodyFetch(final MessageResult 
messageResult,
+                String sectionSpecifier, String name) throws 
MessagingException {
+            final FetchResponse.BodyElement result;
             // TODO: section specifier should be fully parsed during parsing 
phase
             if (sectionSpecifier.length() == 0) {
-                final MessageResult.Content fullMessage = 
result.getFullMessage();
-                addLiteralContent(fullMessage, response);
+                final MessageResult.Content fullMessage = 
messageResult.getFullMessage();
+                result = new ContentBodyElement(name, fullMessage);
             } else if (sectionSpecifier.equalsIgnoreCase("HEADER")) {
-                final Iterator headers = result.iterateHeaders();
+                final Iterator headers = messageResult.iterateHeaders();
                 List lines = MessageResultUtils.getAll(headers);
-                addHeaders(lines, response);
+                result = new HeaderBodyElement(name, lines);
             } else if (sectionSpecifier.startsWith("HEADER.FIELDS.NOT ")) {
                 String[] excludeNames = extractHeaderList(sectionSpecifier,
                         "HEADER.FIELDS.NOT ".length());
-                final Iterator headers = result.iterateHeaders();
+                final Iterator headers = messageResult.iterateHeaders();
                 List lines = MessageResultUtils.getNotMatching(excludeNames, 
headers);
-                addHeaders(lines, response);
+                result = new HeaderBodyElement(name, lines);
             } else if (sectionSpecifier.startsWith("HEADER.FIELDS ")) {
                 String[] includeNames = extractHeaderList(sectionSpecifier,
                         "HEADER.FIELDS ".length());
-                final Iterator headers = result.iterateHeaders();
+                final Iterator headers = messageResult.iterateHeaders();
                 List lines = MessageResultUtils.getMatching(includeNames, 
headers);
-                addHeaders(lines, response);
+                result = new HeaderBodyElement(name, lines);
             } else if (sectionSpecifier.equalsIgnoreCase("MIME")) {
                 // TODO implement
-                throw new ProtocolException("MIME not yet implemented.");
+                throw new MailboxManagerException("MIME not yet implemented.");
 
             } else if (sectionSpecifier.equalsIgnoreCase("TEXT")) {
-                final MessageResult.Content messageBody = 
result.getMessageBody();
-                addLiteralContent(messageBody, response);
+                final MessageResult.Content messageBody = 
messageResult.getMessageBody();
+                result = new ContentBodyElement(name, messageBody);
 
             } else {
                 // Should be a part specifier followed by a section specifier.
@@ -339,7 +338,7 @@
                 // If so, get the number, get the part, and call this 
recursively.
                 int dotPos = sectionSpecifier.indexOf('.');
                 if (dotPos == -1) {
-                    throw new ProtocolException("Malformed fetch attribute: "
+                    throw new MailboxManagerException("Malformed fetch 
attribute: "
                             + sectionSpecifier);
                 }
                 int partNumber = Integer.parseInt(sectionSpecifier.substring(0,
@@ -351,23 +350,13 @@
                 // with the new partSectionSpecifier.
                 // MimeMessage part;
                 // handleBodyFetch( part, partSectionSpecifier, response );
-                throw new ProtocolException(
+                throw new MailboxManagerException(
                         "Mime parts not yet implemented for fetch.");
             }
+            return result;
 
         }
 
-        private void addLiteralContent(final MessageResult.Content content,
-                final StringBuffer response) throws MessagingException {
-            response.append('{');
-            final long length = content.size();
-            response.append(length); // TODO JD addLiteral: why was it
-                                        // bytes.length +1 here?
-            response.append('}');
-            response.append("\r\n");
-            content.writeTo(response);
-        }
-
         // TODO should do this at parse time.
         private String[] extractHeaderList(String headerList, int prefixLen) {
             // Remove the trailing and leading ')('
@@ -391,26 +380,82 @@
 
             return (String[]) strings.toArray(new String[0]);
         }
+    }
+    
+    private static final class HeaderBodyElement implements BodyElement {
+        private final String name;
+        private final List headers;
+        private final long size;
+        
+        public HeaderBodyElement(final String name, final List headers) {
+            super();
+            this.name = name;
+            this.headers = headers;
+            size = calculateSize(headers);
+        }
 
-        private void addHeaders(List headerLines, StringBuffer response)
-                throws MessagingException {
+        public String getName() {
+            return name;
+        }
+        
+        private long calculateSize(List headers) {
             int count = 0;
-            for (final Iterator it = headerLines.iterator(); it.hasNext();) {
+            for (final Iterator it = headers.iterator(); it.hasNext();) {
                 MessageResult.Header header = (MessageResult.Header) it.next();
                 count += header.size() + 2;
             }
-            response.append('{');
-            response.append(count + 2);
-            response.append('}');
-            response.append("\r\n");
+            return count + 2;
+        }
+
+        public long size() {
+            return size;
+        }
 
-            for (final Iterator it = headerLines.iterator(); it.hasNext();) {
+        public void writeTo(WritableByteChannel channel) throws IOException {
+            ByteBuffer endLine = ByteBuffer.wrap(ImapConstants.BYTES_LINE_END);
+            endLine.rewind();
+            for (final Iterator it = headers.iterator(); it.hasNext();) {
                 MessageResult.Header header = (MessageResult.Header) it.next();
-                header.writeTo(response);
-                response.append("\r\n");
+                header.writeTo(channel);
+                while (channel.write(endLine) > 0) {}
+                endLine.rewind();
             }
-            response.append("\r\n");
+            while (channel.write(endLine) > 0) {}
         }
+        
+    }
+    
+    private static final class ContentBodyElement implements BodyElement {
+        private final String name;
+        private final MessageResult.Content content;
+        
+        public ContentBodyElement(final String name, final Content content) {
+            super();
+            this.name = name;
+            this.content = content;
+        }
+
+        /**
+         * @see 
org.apache.james.imap.message.response.imap4rev1.FetchResponse.BodyElement#getName()
+         */
+        public String getName() {
+            return name;
+        }
+        
+        /**
+         * @see 
org.apache.james.imap.message.response.imap4rev1.FetchResponse.BodyElement#size()
+         */
+        public long size() {
+            return content.size();
+        }
+        
+        /**
+         * @see 
org.apache.james.imap.message.response.imap4rev1.FetchResponse.BodyElement#writeTo(WritableByteChannel)
+         */
+        public void writeTo(WritableByteChannel channel) throws IOException {
+            content.writeTo(channel);
+        }
+        
         
     }
 }

Modified: 
james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageRowUtils.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageRowUtils.java?rev=598041&r1=598040&r2=598041&view=diff
==============================================================================
--- 
james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageRowUtils.java
 (original)
+++ 
james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageRowUtils.java
 Sun Nov 25 11:38:01 2007
@@ -19,6 +19,10 @@
 
 package org.apache.james.mailboxmanager.torque;
 
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -42,6 +46,10 @@
 
 public class MessageRowUtils {
 
+    public static final byte[] BYTES_NEW_LINE = {0x0D, 0x0A};
+    public static final byte[] BYTES_HEADER_FIELD_VALUE_SEP = {0x3A, 0x20};
+    private static final Charset US_ASCII = Charset.forName("US-ASCII");
+    
     private static final class Header implements MessageResult.Header, 
MessageResult.Content {
             private final String name;
             private final String value;
@@ -65,11 +73,11 @@
                 return value;
             }
     
-            public long size() throws MailboxManagerException {
+            public long size() {
                 return size;
             }
     
-            public void writeTo(StringBuffer buffer) throws 
MailboxManagerException {
+            public void writeTo(StringBuffer buffer) {
     // TODO: sort out encoding
                 for (int i=0; i<name.length();i++) {
                     buffer.append((char)(byte) name.charAt(i));
@@ -80,7 +88,19 @@
                     buffer.append((char)(byte) value.charAt(i));
                 }
             }
+
+            public void writeTo(WritableByteChannel channel) throws 
IOException {
+                writeAll(channel, US_ASCII.encode(name));
+                ByteBuffer buffer = 
ByteBuffer.wrap(BYTES_HEADER_FIELD_VALUE_SEP);
+                writeAll(channel, buffer);
+                writeAll(channel, US_ASCII.encode(value));
+            }
             
+            private void writeAll(WritableByteChannel channel, ByteBuffer 
buffer) throws IOException {
+                while (channel.write(buffer) > 0) {
+                    // write more
+                }
+            }
         }
 
     private final static class ByteContent implements MessageResult.Content {
@@ -92,13 +112,20 @@
             size = contents.length + MessageUtils.countUnnormalLines(contents);
         }
         
-        public long size() throws MailboxManagerException {
+        public long size() {
             return size;
         }
         
-        public void writeTo(StringBuffer buffer) throws 
MailboxManagerException {
+        public void writeTo(StringBuffer buffer) {
             MessageUtils.normalisedWriteTo(contents, buffer);
         }
+
+        public void writeTo(WritableByteChannel channel) throws IOException {
+            ByteBuffer buffer = ByteBuffer.wrap(contents);
+            while (channel.write(buffer) > 0) {
+                // write more
+            }
+        }
     }
 
     private final static class FullContent implements MessageResult.Content {
@@ -112,7 +139,7 @@
             this.size = caculateSize();
         }
     
-        private long caculateSize() throws MailboxManagerException{
+        private long caculateSize() {
             long result = contents.length + 
MessageUtils.countUnnormalLines(contents);
             result += 2;
             for (final Iterator it=headers.iterator(); it.hasNext();) {
@@ -125,7 +152,7 @@
             return result;
         }
     
-        public void writeTo(StringBuffer buffer) throws 
MailboxManagerException {
+        public void writeTo(StringBuffer buffer) {
             for (final Iterator it=headers.iterator(); it.hasNext();) {
                 final MessageResult.Header header = (MessageResult.Header) 
it.next();
                 if (header != null) {
@@ -139,8 +166,30 @@
             MessageUtils.normalisedWriteTo(contents, buffer);
         }
     
-        public long size() throws MailboxManagerException {
+        public long size() {
             return size;
+        }
+
+        public void writeTo(WritableByteChannel channel) throws IOException {
+            ByteBuffer newLine = ByteBuffer.wrap(BYTES_NEW_LINE);
+            for (final Iterator it=headers.iterator(); it.hasNext();) {
+                final MessageResult.Header header = (MessageResult.Header) 
it.next();
+                if (header != null) {
+                    header.writeTo(channel);
+                }
+                newLine.rewind();
+                writeAll(channel, newLine);
+            }
+            newLine.rewind();
+            writeAll(channel, newLine);
+            final ByteBuffer wrap = ByteBuffer.wrap(contents);
+            writeAll(channel, wrap);
+        }
+
+        private void writeAll(WritableByteChannel channel, ByteBuffer buffer) 
throws IOException {
+            while (channel.write(buffer) > 0) {
+                // write more
+            }
         }
     }
 



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to