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 rd...@apache.org on 2008/03/22 09:53:39 UTC

svn commit: r639967 [1/2] - in /james/server/trunk: experimental-seda-imap-function/src/main/java/org/apache/james/experimental/imapserver/ experimental-seda-imap-function/src/main/java/org/apache/james/experimental/imapserver/encode/writer/ imap-api/s...

Author: rdonkin
Date: Sat Mar 22 01:53:26 2008
New Revision: 639967

URL: http://svn.apache.org/viewvc?rev=639967&view=rev
Log:
Basic CHARSET implementation for SEARCH

Added:
    james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/MockLogger.java
    james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserCharsetTest.java
Modified:
    james/server/trunk/experimental-seda-imap-function/src/main/java/org/apache/james/experimental/imapserver/DefaultImapDecoderFactory.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-api/src/main/java/org/apache/james/api/imap/display/HumanReadableTextKey.java
    james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/message/response/imap4rev1/StatusResponse.java
    james/server/trunk/imap-api/src/test/java/org/apache/james/api/imap/message/response/imap4rev1/AbstractTestForStatusResponseFactory.java
    james/server/trunk/imap-api/src/test/java/org/apache/james/api/imap/message/response/imap4rev1/StatusResponseTest.java
    james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/request/base/BaseImap4Rev1MessageFactory.java
    james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/ImapRequestLineReader.java
    james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/MessagingImapCommandParser.java
    james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/base/AbstractImapCommandParser.java
    james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/AppendCommandParser.java
    james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/Imap4Rev1CommandParserFactory.java
    james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/ListCommandParser.java
    james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParser.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/StatusResponseEncoder.java
    james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserNotTest.java
    james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserOrTest.java
    james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeySequenceSetTest.java
    james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeyTest.java
    james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/AbstractTestImapResponseComposer.java
    james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/ImapResponseTest.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/base/ImapResponseComposerImplTest.java
    james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/imap4rev1/StatusResponseEncoderTest.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/AppendProcessor.java

Modified: james/server/trunk/experimental-seda-imap-function/src/main/java/org/apache/james/experimental/imapserver/DefaultImapDecoderFactory.java
URL: http://svn.apache.org/viewvc/james/server/trunk/experimental-seda-imap-function/src/main/java/org/apache/james/experimental/imapserver/DefaultImapDecoderFactory.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/experimental-seda-imap-function/src/main/java/org/apache/james/experimental/imapserver/DefaultImapDecoderFactory.java (original)
+++ james/server/trunk/experimental-seda-imap-function/src/main/java/org/apache/james/experimental/imapserver/DefaultImapDecoderFactory.java Sat Mar 22 01:53:26 2008
@@ -23,6 +23,7 @@
 import org.apache.james.api.imap.imap4rev1.Imap4Rev1MessageFactory;
 import org.apache.james.imap.command.imap4rev1.StandardImap4Rev1CommandFactory;
 import org.apache.james.imap.message.request.base.BaseImap4Rev1MessageFactory;
+import org.apache.james.imap.message.response.imap4rev1.status.UnpooledStatusResponseFactory;
 import org.apache.james.imapserver.codec.decode.ImapCommandParserFactory;
 import org.apache.james.imapserver.codec.decode.ImapDecoder;
 import org.apache.james.imapserver.codec.decode.ImapDecoderFactory;
@@ -38,7 +39,7 @@
         final Imap4Rev1MessageFactory messageFactory = new BaseImap4Rev1MessageFactory();
         final Imap4Rev1CommandFactory commandFactory = new StandardImap4Rev1CommandFactory();
         final ImapCommandParserFactory imapCommands = new Imap4Rev1CommandParserFactory(
-                messageFactory, commandFactory);
+                messageFactory, commandFactory, new UnpooledStatusResponseFactory());
         final ImapDecoder result = new DefaultImapDecoder(messageFactory,
                 imapCommands);
         return result;

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=639967&r1=639966&r2=639967&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 Sat Mar 22 01:53:26 2008
@@ -168,13 +168,21 @@
     }
 
     public void closeParen() throws IOException {
-        write(BYTES_CLOSING_PARENTHESIS);
+        closeBracket(BYTES_CLOSING_PARENTHESIS);
+    }
+
+    private void closeBracket(final byte[] bracket) throws IOException {
+        write(bracket);
         clearSkipNextSpace();
     }
 
     public void openParen() throws IOException {
+        openBracket(BYTES_OPENING_PARENTHESIS);
+    }
+
+    private void openBracket(final byte[] bracket) throws IOException {
         space();
-        write(BYTES_OPENING_PARENTHESIS);
+        write(bracket);
         skipNextSpace();
     }
     
@@ -201,5 +209,13 @@
         write(BYTES_CLOSE_BRACE);
         write(BYTES_LINE_END);
         literal.writeTo(out);
+    }
+
+    public void closeSquareBracket() throws IOException {
+        closeBracket(BYTES_CLOSE_SQUARE_BRACKET);
+    }
+
+    public void openSquareBracket() throws IOException {
+        openBracket(BYTES_OPEN_SQUARE_BRACKET);
     }
 }

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=639967&r1=639966&r2=639967&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 Sat Mar 22 01:53:26 2008
@@ -44,6 +44,8 @@
     public static final byte BYTE_BACK_SLASH = 0x5C;
     public static final byte BYTE_QUESTION = 0x3F;
     public static final byte[] BYTES_DQUOTE = {BYTE_DQUOTE};
+    public static final byte BYTE_OPEN_SQUARE_BRACKET = 0x5B;
+    public static final byte[] BYTES_OPEN_SQUARE_BRACKET = {BYTE_OPEN_SQUARE_BRACKET};
     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;
@@ -54,6 +56,9 @@
     
     public static final char OPENING_PARENTHESIS = '(';
     public static final char CLOSING_PARENTHESIS = ')';
+    public static final char OPENING_SQUARE_BRACKET = '[';
+    public static final char CLOSING_SQUARE_BRACKET = ']';
+    
     public static final char SP_CHAR = ' ';
     public static final char DQUOTE ='\"';
     

Modified: james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/display/HumanReadableTextKey.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/display/HumanReadableTextKey.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/display/HumanReadableTextKey.java (original)
+++ james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/display/HumanReadableTextKey.java Sat Mar 22 01:53:26 2008
@@ -54,6 +54,10 @@
         = new HumanReadableTextKey("org.apache.james.imap.UNSUPPORTED_CRITERIA",
                 "failed. One or more search criteria is unsupported.");
     
+    public static final HumanReadableTextKey BAD_CHARSET 
+        = new HumanReadableTextKey("org.apache.james.imap.BAD_CHARSET",
+                "failed. Charset is unsupported.");
+    
     public static final HumanReadableTextKey MAILBOX_IS_READ_ONLY 
         = new HumanReadableTextKey("org.apache.james.imap.MAILBOX_IS_READ_ONLY",
                 "failed. Mailbox is read only.");

Modified: james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/message/response/imap4rev1/StatusResponse.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/message/response/imap4rev1/StatusResponse.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/message/response/imap4rev1/StatusResponse.java (original)
+++ james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/message/response/imap4rev1/StatusResponse.java Sat Mar 22 01:53:26 2008
@@ -19,6 +19,9 @@
 
 package org.apache.james.api.imap.message.response.imap4rev1;
 
+import java.util.Collection;
+import java.util.Collections;
+
 import org.apache.james.api.imap.ImapCommand;
 import org.apache.james.api.imap.display.HumanReadableTextKey;
 import org.apache.james.api.imap.message.response.ImapResponseMessage;
@@ -125,24 +128,102 @@
      * Enumerates response codes.
      */
     public static final class ResponseCode {
+  
         /** RFC2060 <code>ALERT</code> response code */
-        public static final ResponseCode ALERT = new ResponseCode("[ALERT]");
-        /** RFC2060 <code>NEWNAME</code> response code */
-        public static final ResponseCode NEWNAME = new ResponseCode("[NEWNAME]");
+        private static final ResponseCode ALERT = new ResponseCode("ALERT");
         /** RFC2060 <code>PARSE</code> response code */
-        public static final ResponseCode PARSE = new ResponseCode("[PARSE]");
-        /** RFC2060 <code>PERMANENTFLAGS</code> response code */
-        public static final ResponseCode PERMANENTFLAGS = new ResponseCode("[PERMANENTFLAGS]");
+        private static final ResponseCode PARSE = new ResponseCode("PARSE");
         /** RFC2060 <code>READ_ONLY</code> response code */
-        public static final ResponseCode READ_ONLY = new ResponseCode("[READ-ONLY]");
+        private static final ResponseCode READ_ONLY = new ResponseCode("READ-ONLY");
         /** RFC2060 <code>READ_WRITE</code> response code */
-        public static final ResponseCode READ_WRITE = new ResponseCode("[READ-WRITE]");
+        private static final ResponseCode READ_WRITE = new ResponseCode("READ-WRITE");
         /** RFC2060 <code>TRYCREATE</code> response code */
-        public static final ResponseCode TRYCREATE = new ResponseCode("[TRYCREATE]");
-        /** RFC2060 <code>UIDVALIDITY</code> response code */
-        public static final ResponseCode UIDVALIDITY = new ResponseCode("[UIDVALIDITY]");
-        /** RFC2060 <code>UNSEEN</code> response code */
-        public static final ResponseCode UNSEEN = new ResponseCode("[UNSEEN]");
+        private static final ResponseCode TRYCREATE = new ResponseCode("TRYCREATE");
+       
+        /**
+         * Creates a RFC2060 <code>ALERT</code> response code.
+         * @return <code>ResponseCode</code>, not null
+         */
+        public static final ResponseCode alert() {
+            return ALERT;
+        }
+        
+        /**
+         * Creates a RFC2060 <code>BADCHARSET</code> response code.
+         * @param charsetNames <code>Collection<String></code> containing charset names
+         * @return <code>ResponseCode</code>, not null
+         */
+        public static final ResponseCode badCharset(Collection charsetNames) {
+            return new ResponseCode("BADCHARSET", charsetNames);
+        }
+        
+        /**
+         * Creates a RFC2060 <code>PARSE</code> response code.
+         * @return <code>ResponseCode</code>, not null
+         */
+        public static final ResponseCode parse() {
+            return PARSE;
+        }
+        
+        /**
+         * Creates a RFC2060 <code>PERMENANTFLAGS</code> response code.
+         * @param flagNames <code>Collection<String></code> containing flag names
+         * @return <code>ResponseCode</code>, not null
+         */
+        public static final ResponseCode permanentFlags(Collection flagNames) {
+            return new ResponseCode("PERMANENTFLAGS", flagNames);
+        }
+        
+        /**
+         * Creates a RFC2060 <code>READ-ONLY</code> response code.
+         * @return <code>ResponseCode</code>, not null
+         */
+        public static final ResponseCode readOnly() {
+            return READ_ONLY;
+        }
+        
+        /**
+         * Creates a RFC2060 <code>READ-WRITE</code> response code.
+         * @return <code>ResponseCode</code>, not null
+         */
+        public static final ResponseCode readWrite() {
+            return READ_WRITE;
+        }
+        
+        /**
+         * Creates a RFC2060 <code>TRYCREATE</code> response code.
+         * @return <code>ResponseCode</code>, not null
+         */
+        public static final ResponseCode tryCreate() {
+            return TRYCREATE;
+        }
+        
+        /**
+         * Creates a RFC2060 <code>UIDVALIDITY</code> response code.
+         * @param uid positive non-zero integer
+         * @return <code>ResponseCode</code>, not null
+         */
+        public static final ResponseCode uidValidity(int uid) {
+            return new ResponseCode("UIDVALIDITY", uid);
+        }
+        
+        /**
+         * Creates a RFC2060 <code>UNSEEN</code> response code.
+         * @param numberUnseen positive non-zero integer
+         * @return <code>ResponseCode</code>, not null
+         */
+        public static final ResponseCode unseen(int numberUnseen) {
+            return new ResponseCode("UNSEEN", numberUnseen);
+        }
+        
+        /**
+         * Creates a RFC2060 <code>UIDNEXT</code> response code.
+         * @param uid positive non-zero integer
+         * @return <code>ResponseCode</code>, not null
+         */
+        public static final ResponseCode uidNext(int uid) {
+            return new ResponseCode("UIDNEXT", uid);
+        }
         
         /**
          * Creates an extension response code.
@@ -151,32 +232,66 @@
          * @return <code>ResponseCode</code>, not null
          */
         public static ResponseCode createExtension(String name) {
-            StringBuffer buffer = new StringBuffer();
-            buffer.append('[');
+            StringBuffer buffer = new StringBuffer(name.length() + 2);
             if (!name.startsWith("X")) {
                 buffer.append('X');
             }
             buffer.append(name);
-            buffer.append(']');
             final ResponseCode result = new ResponseCode(buffer.toString());
             return result;
         }
         
         private final String code;
+        private final Collection parameters;
+        private final int number;
 
         private ResponseCode(final String code) {
+            this(code, Collections.EMPTY_LIST, 0);
+        }
+        
+        private ResponseCode(final String code, final int number) {
+            this(code, Collections.EMPTY_LIST, number);
+        }
+        
+        private ResponseCode(final String code, final Collection parameters) {
+            this(code, parameters, 0);
+        }
+        
+        private ResponseCode(final String code, final Collection parameters, final int number) {
             super();
             this.code = code;
+            this.parameters = parameters;
+            this.number = number;
         }
 
         public final String getCode() {
             return code;
         }
+        
+        /**
+         * Gets number for this response.
+         * @return the number, 
+         * or zero if no number has been set
+         */
+        public final int getNumber() {
+            return number;
+        }
 
+        /**
+         * Gets parameters for this code.
+         * @return the parameters <code>Collection</code>
+         * of <code>String</code> parameters, not null
+         */
+        public final Collection getParameters() {
+            return parameters;
+        }        
+        
         public int hashCode() {
             final int PRIME = 31;
             int result = 1;
             result = PRIME * result + ((code == null) ? 0 : code.hashCode());
+            result = PRIME * result + number;
+            result = PRIME * result + ((parameters == null) ? 0 : parameters.hashCode());
             return result;
         }
 
@@ -193,9 +308,16 @@
                     return false;
             } else if (!code.equals(other.code))
                 return false;
+            if (number != other.number)
+                return false;
+            if (parameters == null) {
+                if (other.parameters != null)
+                    return false;
+            } else if (!parameters.equals(other.parameters))
+                return false;
             return true;
         }
-        
+
         public String toString() {
             return code;
         }

Modified: james/server/trunk/imap-api/src/test/java/org/apache/james/api/imap/message/response/imap4rev1/AbstractTestForStatusResponseFactory.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-api/src/test/java/org/apache/james/api/imap/message/response/imap4rev1/AbstractTestForStatusResponseFactory.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-api/src/test/java/org/apache/james/api/imap/message/response/imap4rev1/AbstractTestForStatusResponseFactory.java (original)
+++ james/server/trunk/imap-api/src/test/java/org/apache/james/api/imap/message/response/imap4rev1/AbstractTestForStatusResponseFactory.java Sat Mar 22 01:53:26 2008
@@ -27,7 +27,7 @@
 
     private static final String TAG = "ATAG";
     private static final HumanReadableTextKey KEY = new HumanReadableTextKey("KEY", "TEXT");
-    private static final StatusResponse.ResponseCode CODE = StatusResponse.ResponseCode.ALERT;
+    private static final StatusResponse.ResponseCode CODE = StatusResponse.ResponseCode.alert();
     
     private ImapCommand command;
     

Modified: james/server/trunk/imap-api/src/test/java/org/apache/james/api/imap/message/response/imap4rev1/StatusResponseTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-api/src/test/java/org/apache/james/api/imap/message/response/imap4rev1/StatusResponseTest.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-api/src/test/java/org/apache/james/api/imap/message/response/imap4rev1/StatusResponseTest.java (original)
+++ james/server/trunk/imap-api/src/test/java/org/apache/james/api/imap/message/response/imap4rev1/StatusResponseTest.java Sat Mar 22 01:53:26 2008
@@ -30,7 +30,7 @@
     }
 
     public void testResponseCodeExtension() throws Exception {
-        assertEquals("Preserve names beginning with X", "[XEXTENSION]", StatusResponse.ResponseCode.createExtension("XEXTENSION").getCode());
-        assertEquals("Correct other names", "[XEXTENSION]", StatusResponse.ResponseCode.createExtension("EXTENSION").getCode());
+        assertEquals("Preserve names beginning with X", "XEXTENSION", StatusResponse.ResponseCode.createExtension("XEXTENSION").getCode());
+        assertEquals("Correct other names", "XEXTENSION", StatusResponse.ResponseCode.createExtension("EXTENSION").getCode());
     }
 }

Modified: james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/request/base/BaseImap4Rev1MessageFactory.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/request/base/BaseImap4Rev1MessageFactory.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/request/base/BaseImap4Rev1MessageFactory.java (original)
+++ james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imap/message/request/base/BaseImap4Rev1MessageFactory.java Sat Mar 22 01:53:26 2008
@@ -160,7 +160,5 @@
 
     public ImapMessage createCheckMessage(ImapCommand command, String tag) {
         return new CheckRequest(command, tag);
-    }  
-    
-    
+    }
 }

Modified: james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/ImapRequestLineReader.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/ImapRequestLineReader.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/ImapRequestLineReader.java (original)
+++ james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/ImapRequestLineReader.java Sat Mar 22 01:53:26 2008
@@ -146,6 +146,8 @@
     /**
      * Reads and consumes a number of characters from the underlying reader,
      * filling the char array provided.
+     * TODO: remove unnecessary copying of bits; line reader should maintain an internal
+     * ByteBuffer; 
      * @param holder A char array which will be filled with chars read from the underlying reader.
      * @throws ProtocolException If a char can't be read into each array element.
      */

Modified: james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/MessagingImapCommandParser.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/MessagingImapCommandParser.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/MessagingImapCommandParser.java (original)
+++ james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/MessagingImapCommandParser.java Sat Mar 22 01:53:26 2008
@@ -19,6 +19,7 @@
 package org.apache.james.imapserver.codec.decode;
 
 import org.apache.james.api.imap.imap4rev1.Imap4Rev1MessageFactory;
+import org.apache.james.api.imap.message.response.imap4rev1.StatusResponseFactory;
 
 public interface MessagingImapCommandParser {
 
@@ -26,4 +27,7 @@
 
     public abstract void setMessageFactory(Imap4Rev1MessageFactory messageFactory);
 
+    public abstract StatusResponseFactory getStatusResponseFactory();
+    
+    public abstract void setStatusResponseFactory(StatusResponseFactory statusResponseFactory) ;
 }

Modified: james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/base/AbstractImapCommandParser.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/base/AbstractImapCommandParser.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/base/AbstractImapCommandParser.java (original)
+++ james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/base/AbstractImapCommandParser.java Sat Mar 22 01:53:26 2008
@@ -19,6 +19,12 @@
 
 package org.apache.james.imapserver.codec.decode.base;
 
+import java.nio.ByteBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
 import java.util.ArrayList;
 import java.util.Date;
 
@@ -32,6 +38,7 @@
 import org.apache.james.api.imap.imap4rev1.Imap4Rev1MessageFactory;
 import org.apache.james.api.imap.message.IdRange;
 import org.apache.james.api.imap.message.request.DayMonthYear;
+import org.apache.james.api.imap.message.response.imap4rev1.StatusResponseFactory;
 import org.apache.james.imapserver.codec.decode.DecoderUtils;
 import org.apache.james.imapserver.codec.decode.ImapCommandParser;
 import org.apache.james.imapserver.codec.decode.ImapRequestLineReader;
@@ -45,8 +52,11 @@
  */
 public abstract class AbstractImapCommandParser extends AbstractLogEnabled implements ImapCommandParser, MessagingImapCommandParser
 {
+    private static final Charset US_ASCII = Charset.forName("US-ASCII");
+    
     private ImapCommand command;
     private Imap4Rev1MessageFactory messageFactory;
+    private StatusResponseFactory statusResponseFactory;
     
     public AbstractImapCommandParser() {
         super();
@@ -74,6 +84,15 @@
         this.messageFactory = messageFactory;
     }
 
+    public final StatusResponseFactory getStatusResponseFactory() {
+        return statusResponseFactory;
+    }
+
+    public final void setStatusResponseFactory(
+            StatusResponseFactory statusResponseFactory) {
+        this.statusResponseFactory = statusResponseFactory;
+    }
+
     /**
      * Parses a request into a command message
      * for later processing.
@@ -131,12 +150,20 @@
      */
     public String astring(ImapRequestLineReader request) throws ProtocolException
     {
+        return astring(request, null);
+    }
+    
+    /**
+     * Reads an argument of type "astring" from the request.
+     */
+    public String astring(ImapRequestLineReader request, Charset charset) throws ProtocolException
+    {
         char next = request.nextWordChar();
         switch ( next ) {
             case '"':
                 return consumeQuoted( request );
             case '{':
-                return consumeLiteral( request );
+                return consumeLiteral( request, charset );
             default:
                 return atom( request );
         }
@@ -152,7 +179,7 @@
             case '"':
                 return consumeQuoted( request );
             case '{':
-                return consumeLiteral( request );
+                return consumeLiteral( request, null );
             default:
                 String value = atom( request );
                 if ( "NIL".equals( value ) ) {
@@ -277,44 +304,66 @@
      *      "{" charCount "}" CRLF *CHAR8
      * Note before calling, the request should be positioned so that nextChar
      * is '{'. Leading whitespace is not skipped in this method.
+     * @param charset ,
+     * or null for <code>US-ASCII</code>
      */
-    protected String consumeLiteral( ImapRequestLineReader request )
+    protected String consumeLiteral( final ImapRequestLineReader request, final Charset charset )
             throws ProtocolException
     {
-        // The 1st character must be '{'
-        consumeChar( request, '{' );
-
-        StringBuffer digits = new StringBuffer();
-        char next = request.nextChar();
-        while ( next != '}' && next != '+' )
-        {
-            digits.append( next );
-            request.consume();
-            next = request.nextChar();
-        }
-
-        // If the number is *not* suffixed with a '+', we *are* using a synchronized literal,
-        // and we need to send command continuation request before reading data.
-        boolean synchronizedLiteral = true;
-        // '+' indicates a non-synchronized literal (no command continuation request)
-        if ( next == '+' ) {
-            synchronizedLiteral = false;
-            consumeChar(request, '+' );
-        }
-
-        // Consume the '}' and the newline
-        consumeChar( request, '}' );
-        consumeCRLF( request );
-
-        if ( synchronizedLiteral ) {
-            request.commandContinuationRequest();
+        if (charset == null) {
+            return consumeLiteral(request, US_ASCII);
+        } else {
+            // The 1st character must be '{'
+            consumeChar( request, '{' );
+    
+            StringBuffer digits = new StringBuffer();
+            char next = request.nextChar();
+            while ( next != '}' && next != '+' )
+            {
+                digits.append( next );
+                request.consume();
+                next = request.nextChar();
+            }
+    
+            // If the number is *not* suffixed with a '+', we *are* using a synchronized literal,
+            // and we need to send command continuation request before reading data.
+            boolean synchronizedLiteral = true;
+            // '+' indicates a non-synchronized literal (no command continuation request)
+            if ( next == '+' ) {
+                synchronizedLiteral = false;
+                consumeChar(request, '+' );
+            }
+    
+            // Consume the '}' and the newline
+            consumeChar( request, '}' );
+            consumeCRLF( request );
+    
+            if ( synchronizedLiteral ) {
+                request.commandContinuationRequest();
+            }
+    
+            final int size = Integer.parseInt( digits.toString() );
+            final byte[] bytes = new byte[size];
+            request.read( bytes );
+            final ByteBuffer buffer = ByteBuffer.wrap(bytes);
+            try {
+                
+                final String result = charset.newDecoder()
+                    .onMalformedInput(CodingErrorAction.REPORT)
+                    .onUnmappableCharacter(CodingErrorAction.REPORT)
+                    .decode(buffer).toString();
+                return result;
+                
+            } catch (IllegalStateException e) {
+                throw new ProtocolException ("Bad character encoding", e);
+            } catch (MalformedInputException e) {
+                throw new ProtocolException ("Bad character encoding", e);
+            } catch (UnmappableCharacterException e) {
+                throw new ProtocolException ("Bad character encoding", e);
+            } catch (CharacterCodingException e) {
+                throw new ProtocolException ("Bad character encoding", e);
+            }
         }
-
-        int size = Integer.parseInt( digits.toString() );
-        byte[] buffer = new byte[size];
-        request.read( buffer );
-
-        return new String( buffer );
     }
 
     /**

Modified: james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/AppendCommandParser.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/AppendCommandParser.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/AppendCommandParser.java (original)
+++ james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/AppendCommandParser.java Sat Mar 22 01:53:26 2008
@@ -91,7 +91,7 @@
             throws ProtocolException
     {
         request.nextWordChar();
-        String mailString = consumeLiteral(request);
+        String mailString = consumeLiteral(request, null);
         MimeMessage mm = null;
 
         try {

Modified: james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/Imap4Rev1CommandParserFactory.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/Imap4Rev1CommandParserFactory.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/Imap4Rev1CommandParserFactory.java (original)
+++ james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/Imap4Rev1CommandParserFactory.java Sat Mar 22 01:53:26 2008
@@ -28,6 +28,7 @@
 import org.apache.james.api.imap.ImapConstants;
 import org.apache.james.api.imap.imap4rev1.Imap4Rev1CommandFactory;
 import org.apache.james.api.imap.imap4rev1.Imap4Rev1MessageFactory;
+import org.apache.james.api.imap.message.response.imap4rev1.StatusResponseFactory;
 import org.apache.james.imapserver.codec.decode.DelegatingImapCommandParser;
 import org.apache.james.imapserver.codec.decode.ImapCommandParser;
 import org.apache.james.imapserver.codec.decode.ImapCommandParserFactory;
@@ -44,12 +45,15 @@
 {
     private Map _imapCommands;
     private final Imap4Rev1MessageFactory messageFactory;
+    private final StatusResponseFactory statusResponseFactory;
     private final Imap4Rev1CommandFactory commandFactory;
     
-    public Imap4Rev1CommandParserFactory(final Imap4Rev1MessageFactory messageFactory, final Imap4Rev1CommandFactory commandFactory)
+    public Imap4Rev1CommandParserFactory(final Imap4Rev1MessageFactory messageFactory, final Imap4Rev1CommandFactory commandFactory,
+            final StatusResponseFactory statusResponseFactory)
     {
         this.messageFactory = messageFactory;
         this.commandFactory = commandFactory;
+        this.statusResponseFactory = statusResponseFactory;
         _imapCommands = new HashMap();
 
         // Commands valid in any state
@@ -144,7 +148,9 @@
         }
         
         if (cmd instanceof MessagingImapCommandParser) {
-            ((MessagingImapCommandParser) cmd).setMessageFactory(messageFactory);
+            final MessagingImapCommandParser messagingImapCommandParser = (MessagingImapCommandParser) cmd;
+            messagingImapCommandParser.setMessageFactory(messageFactory);
+            messagingImapCommandParser.setStatusResponseFactory(statusResponseFactory);
         }
         
         if (cmd instanceof InitialisableCommandFactory) {

Modified: james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/ListCommandParser.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/ListCommandParser.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/ListCommandParser.java (original)
+++ james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/ListCommandParser.java Sat Mar 22 01:53:26 2008
@@ -53,7 +53,7 @@
             case '"':
                 return consumeQuoted( request );
             case '{':
-                return consumeLiteral( request );
+                return consumeLiteral( request, null );
             default:
                 return consumeWord( request, new ListCharValidator() );
         }

Modified: james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParser.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParser.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParser.java (original)
+++ james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParser.java Sat Mar 22 01:53:26 2008
@@ -18,21 +18,35 @@
  ****************************************************************/
 package org.apache.james.imapserver.codec.decode.imap4rev1;
 
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.james.api.imap.ImapCommand;
 import org.apache.james.api.imap.ImapMessage;
 import org.apache.james.api.imap.ProtocolException;
+import org.apache.james.api.imap.display.HumanReadableTextKey;
 import org.apache.james.api.imap.imap4rev1.Imap4Rev1CommandFactory;
 import org.apache.james.api.imap.message.IdRange;
 import org.apache.james.api.imap.message.request.DayMonthYear;
 import org.apache.james.api.imap.message.request.SearchKey;
+import org.apache.james.api.imap.message.response.imap4rev1.StatusResponse;
+import org.apache.james.api.imap.message.response.imap4rev1.StatusResponseFactory;
+import org.apache.james.api.imap.message.response.imap4rev1.StatusResponse.ResponseCode;
 import org.apache.james.imapserver.codec.decode.ImapRequestLineReader;
 import org.apache.james.imapserver.codec.decode.InitialisableCommandFactory;
 
 class SearchCommandParser extends AbstractUidCommandParser implements InitialisableCommandFactory
 {   
+    /** Lazy loaded */
+    private Collection charsetNames;
+    
     public SearchCommandParser() {
     }
 
@@ -47,36 +61,41 @@
     
     /**
      * Parses the request argument into a valid search term.
+     * @param request <code>ImapRequestLineReader</code>, not null
+     * @param charset <code>Charset</code> or null if there is no charset
+     * @param isFirstToken true when this is the first token read, 
+     * false otherwise
      */
-    public SearchKey searchKey( ImapRequestLineReader request ) throws ProtocolException {
+    public SearchKey searchKey( ImapRequestLineReader request, Charset charset, boolean isFirstToken ) 
+            throws ProtocolException, IllegalCharsetNameException, UnsupportedCharsetException {
         final char next = request.nextChar();
         if (next >= '0' && next <= '9' || next == '*') {
             return sequenceSet(request);
         } else if (next == '(') {
-            return paren(request);
+            return paren(request, charset);
         } else {
             final int cap = consumeAndCap(request);
             switch (cap) {
                 case 'A': return a(request);
-                case 'B': return b(request);
-                case 'C': return cc(request);
+                case 'B': return b(request, charset);
+                case 'C': return c(request, isFirstToken, charset);
                 case 'D': return d(request);
                 case 'E': throw new ProtocolException("Unknown search key");
-                case 'F': return f(request);
+                case 'F': return f(request, charset);
                 case 'G': throw new ProtocolException("Unknown search key");
-                case 'H': return header(request);
+                case 'H': return header(request, charset);
                 case 'I': throw new ProtocolException("Unknown search key");
                 case 'J': throw new ProtocolException("Unknown search key");
                 case 'K': return keyword(request);
                 case 'L': return larger(request);
                 case 'M': throw new ProtocolException("Unknown search key");
-                case 'N': return n(request);
-                case 'O': return o(request);
+                case 'N': return n(request, charset);
+                case 'O': return o(request, charset);
                 case 'P': throw new ProtocolException("Unknown search key");
                 case 'Q': throw new ProtocolException("Unknown search key");
                 case 'R': return recent(request);
-                case 'S': return s(request);
-                case 'T': return t(request);
+                case 'S': return s(request, charset);
+                case 'T': return t(request, charset);
                 case 'U': return u(request);
                 default:
                     throw new ProtocolException("Unknown search key");
@@ -84,21 +103,21 @@
         }
     }
 
-    private SearchKey paren(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey paren(ImapRequestLineReader request, Charset charset) throws ProtocolException {
         request.consume();
         List keys = new ArrayList();
-        addUntilParen(request, keys);
+        addUntilParen(request, keys, charset);
         return SearchKey.buildAnd(keys);
     }
 
-    private void addUntilParen(ImapRequestLineReader request, List keys) throws ProtocolException {
+    private void addUntilParen(ImapRequestLineReader request, List keys, Charset charset) throws ProtocolException {
         final char next = request.nextWordChar();
         if (next == ')') {
             request.consume();
         } else {
-            final SearchKey key = searchKey( request );
+            final SearchKey key = searchKey( request, null, false );
             keys.add(key);
-            addUntilParen(request, keys);
+            addUntilParen(request, keys, charset);
         }
     }
 
@@ -108,15 +127,44 @@
         return cap;
     }
 
-    private SearchKey cc(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey cc(ImapRequestLineReader request, final Charset charset) throws ProtocolException {
         final SearchKey result;
-        nextIsC(request);
         nextIsSpace(request);
-        final String value = astring(request);
+        final String value = astring(request, charset);
         result = SearchKey.buildCc(value);
         return result;
     }
 
+    private SearchKey c(ImapRequestLineReader request, final boolean isFirstToken, final Charset charset) 
+            throws ProtocolException, IllegalCharsetNameException, UnsupportedCharsetException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'C': return cc(request, charset);
+            case 'H': return charset(request, isFirstToken);
+            default:
+                throw new ProtocolException("Unknown search key");
+        }
+    }
+    
+    private SearchKey charset(ImapRequestLineReader request, final boolean isFirstToken) 
+            throws ProtocolException, IllegalCharsetNameException, UnsupportedCharsetException {
+        final SearchKey result;
+        nextIsA(request);
+        nextIsR(request);
+        nextIsS(request);
+        nextIsE(request);
+        nextIsT(request);
+        nextIsSpace(request);
+        if (!isFirstToken) {
+            throw new ProtocolException("Unknown search key");
+        }
+        final String value = astring(request);
+        final Charset charset = Charset.forName(value);
+        request.nextWordChar();
+        result = searchKey(request, charset, false);
+        return result;
+    }
+    
     private SearchKey u(ImapRequestLineReader request) throws ProtocolException {
         final int next = consumeAndCap(request);
         switch (next) {
@@ -150,23 +198,23 @@
         }
     }
     
-    private SearchKey t(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey t(ImapRequestLineReader request, final Charset charset) throws ProtocolException {
         final int next = consumeAndCap(request);
         switch (next) {
-            case 'E': return text(request);
-            case 'O': return to(request);
+            case 'E': return text(request, charset);
+            case 'O': return to(request, charset);
             default:
                 throw new ProtocolException("Unknown search key");
         }
     }
     
-    private SearchKey s(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey s(ImapRequestLineReader request, final Charset charset) throws ProtocolException {
         final int next = consumeAndCap(request);
         switch (next) {
             case 'E': return se(request);
             case 'I': return since(request);
             case 'M': return smaller(request);
-            case 'U': return subject(request);
+            case 'U': return subject(request, charset);
             default:
                 throw new ProtocolException("Unknown search key");
         }
@@ -202,32 +250,32 @@
         }
     }
     
-    private SearchKey o(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey o(ImapRequestLineReader request, Charset charset) throws ProtocolException {
         final int next = consumeAndCap(request);
         switch (next) {
             case 'L': return old(request);
             case 'N': return on(request);
-            case 'R': return or(request);
+            case 'R': return or(request, charset);
             default:
                 throw new ProtocolException("Unknown search key");
         }
     }
     
-    private SearchKey n(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey n(ImapRequestLineReader request, Charset charset) throws ProtocolException {
         final int next = consumeAndCap(request);
         switch (next) {
             case 'E': return _new(request);
-            case 'O': return not(request);
+            case 'O': return not(request, charset);
             default:
                 throw new ProtocolException("Unknown search key");
         }
     }
     
-    private SearchKey f(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey f(ImapRequestLineReader request, final Charset charset) throws ProtocolException {
         final int next = consumeAndCap(request);
         switch (next) {
             case 'L': return flagged(request);
-            case 'R': return from(request);
+            case 'R': return from(request, charset);
             default:
                 throw new ProtocolException("Unknown search key");
         }
@@ -272,7 +320,7 @@
     }
     
     
-    private SearchKey header(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey header(ImapRequestLineReader request, final Charset charset) throws ProtocolException {
         final SearchKey result;
         nextIsE(request);
         nextIsA(request);
@@ -280,9 +328,9 @@
         nextIsE(request);
         nextIsR(request);
         nextIsSpace(request);
-        final String field = astring(request);
+        final String field = astring(request, charset);
         nextIsSpace(request);
-        final String value = astring(request);
+        final String value = astring(request, charset);
         result = SearchKey.buildHeader(field, value);
         return result;
     }
@@ -313,12 +361,12 @@
         return result;
     }
     
-    private SearchKey from(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey from(ImapRequestLineReader request, final Charset charset) throws ProtocolException {
         final SearchKey result;
         nextIsO(request);
         nextIsM(request);
         nextIsSpace(request);
-        final String value = astring(request);
+        final String value = astring(request, charset);
         result = SearchKey.buildFrom(value);
         return result;
     }
@@ -395,21 +443,21 @@
         return result;
     }
     
-    private SearchKey or(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey or(ImapRequestLineReader request, Charset charset) throws ProtocolException {
         final SearchKey result;
         nextIsSpace(request);
-        final SearchKey firstKey = searchKey(request);
+        final SearchKey firstKey = searchKey(request, charset, false);
         nextIsSpace(request);
-        final SearchKey secondKey = searchKey(request);
+        final SearchKey secondKey = searchKey(request, charset, false);
         result = SearchKey.buildOr(firstKey, secondKey);
         return result;
     }
     
-    private SearchKey not(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey not(ImapRequestLineReader request, Charset charset) throws ProtocolException {
         final SearchKey result;
         nextIsT(request);
         nextIsSpace(request);
-        final SearchKey nextKey = searchKey(request);
+        final SearchKey nextKey = searchKey(request, charset, false);
         result = SearchKey.buildNot(nextKey);
         return result;
     }
@@ -459,23 +507,23 @@
         return result;
     }
     
-    private SearchKey b(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey b(ImapRequestLineReader request, Charset charset) throws ProtocolException {
         final int next = consumeAndCap(request);
         switch (next) {
-            case 'C': return bcc(request);
+            case 'C': return bcc(request, charset);
             case 'E': return before(request);
-            case 'O': return body(request);
+            case 'O': return body(request, charset);
             default:
                 throw new ProtocolException("Unknown search key");
         }
     }
 
-    private SearchKey body(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey body(ImapRequestLineReader request, final Charset charset) throws ProtocolException {
         final SearchKey result;
         nextIsD(request);
         nextIsY(request);
         nextIsSpace(request);
-        final String value = astring(request);
+        final String value = astring(request, charset);
         result = SearchKey.buildBody(value);
         return result;
     }
@@ -545,21 +593,21 @@
         return result;
     }
 
-    private SearchKey bcc(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey bcc(ImapRequestLineReader request, Charset charset) throws ProtocolException {
         final SearchKey result;
         nextIsC(request);
         nextIsSpace(request);
-        final String value = astring(request);
+        final String value = astring(request, charset);
         result = SearchKey.buildBcc(value);
         return result;
     }
     
-    private SearchKey text(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey text(ImapRequestLineReader request, final Charset charset) throws ProtocolException {
         final SearchKey result;
         nextIsX(request);
         nextIsT(request);
         nextIsSpace(request);
-        final String value = astring(request);
+        final String value = astring(request, charset);
         result = SearchKey.buildText(value);
         return result;
     }
@@ -579,15 +627,15 @@
         return result;
     }
     
-    private SearchKey to(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey to(ImapRequestLineReader request, final Charset charset) throws ProtocolException {
         final SearchKey result;
         nextIsSpace(request);
-        final String value = astring(request);
+        final String value = astring(request, charset);
         result = SearchKey.buildTo(value);
         return result;
     }
     
-    private SearchKey subject(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey subject(ImapRequestLineReader request, final Charset charset) throws ProtocolException {
         final SearchKey result;
         nextIsB(request);
         nextIsJ(request);
@@ -595,7 +643,7 @@
         nextIsC(request);
         nextIsT(request);
         nextIsSpace(request);
-        final String value = astring(request);
+        final String value = astring(request, charset);
         result = SearchKey.buildSubject(value);
         return result;
     }
@@ -719,16 +767,16 @@
         }
     }
     
-    public SearchKey decode(ImapRequestLineReader request) throws ProtocolException {
+    public SearchKey decode(ImapRequestLineReader request) throws ProtocolException, IllegalCharsetNameException, UnsupportedCharsetException {
         request.nextWordChar();
-        final SearchKey firstKey = searchKey( request );
+        final SearchKey firstKey = searchKey( request, null, true );
         final SearchKey result;
         if (request.nextChar() == ' ') {
             List keys = new ArrayList();
             keys.add(firstKey);
             while (request.nextChar() == ' ') {
                 request.nextWordChar();
-                final SearchKey key = searchKey( request );
+                final SearchKey key = searchKey( request, null, false );
                 keys.add(key);
             }
             result = SearchKey.buildAnd(keys);
@@ -739,12 +787,38 @@
         return result;
     }
     
-    protected ImapMessage decode(ImapCommand command, ImapRequestLineReader request, String tag, boolean useUids) throws ProtocolException {
-        // Parse the search term from the request
-        final SearchKey key = decode( request );
-        
-        final ImapMessage result = getMessageFactory().createSearchMessage(command, key, useUids, tag);
+    private ImapMessage unsupportedCharset(final String tag, final ImapCommand command) {
+        loadCharsetNames();
+        final StatusResponseFactory factory = getStatusResponseFactory();
+        final ResponseCode badCharset = StatusResponse.ResponseCode.badCharset(charsetNames);
+        final StatusResponse result = factory.taggedNo(tag, command, HumanReadableTextKey.BAD_CHARSET, badCharset);
         return result;
     }
 
+    private synchronized void loadCharsetNames() {
+        if (charsetNames == null) {
+            charsetNames = new HashSet();
+            for (final Iterator it = Charset.availableCharsets().values().iterator(); it.hasNext();) {
+                final Charset charset = (Charset) it.next();
+                final Set aliases = charset.aliases();
+                charsetNames.addAll(aliases);
+            }
+        }
+    }
+    
+    protected ImapMessage decode(ImapCommand command, ImapRequestLineReader request, String tag, boolean useUids) throws ProtocolException {
+        try {
+            // Parse the search term from the request
+            final SearchKey key = decode( request );
+            
+            final ImapMessage result = getMessageFactory().createSearchMessage(command, key, useUids, tag);
+            return result;
+        } catch (IllegalCharsetNameException e) {
+            getLogger().debug(e.getMessage());
+            return unsupportedCharset(tag, command);
+        } catch (UnsupportedCharsetException e) {
+            getLogger().debug(e.getMessage());
+            return unsupportedCharset(tag, command);
+        }
+    }
 }

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=639967&r1=639966&r2=639967&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 Sat Mar 22 01:53:26 2008
@@ -20,6 +20,7 @@
 package org.apache.james.imapserver.codec.encode;
 
 import java.io.IOException;
+import java.util.Collection;
 import java.util.List;
 
 import javax.mail.Flags;
@@ -270,7 +271,7 @@
     public abstract void tag(String tag) throws IOException;
 
     public abstract void statusResponse(String tag, ImapCommand command,
-            String type, String responseCode, String text) throws IOException;
+            String type, String responseCode, Collection parameters, long number, String text) throws IOException;
     
     public abstract void statusResponse(Long messages, Long recent,
             Long uidNext, Long uidValidity, Long unseen, String mailboxName) 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=639967&r1=639966&r2=639967&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 Sat Mar 22 01:53:26 2008
@@ -84,6 +84,19 @@
     void closeParen() throws IOException;
 
     /**
+     * Closes a square bracket - writes a <code>[</code>.
+     * @throws IOException
+     */
+    void openSquareBracket() throws IOException;
+
+    /**
+     * Closes a square bracket - writes a <code>]</code>.
+     * @throws IOException
+     */
+    void closeSquareBracket() throws IOException;
+    
+    
+    /**
      * Ends a response.
      *
      */

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=639967&r1=639966&r2=639967&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 Sat Mar 22 01:53:26 2008
@@ -20,6 +20,7 @@
 package org.apache.james.imapserver.codec.encode.base;
 
 import java.io.IOException;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 
@@ -343,9 +344,10 @@
     
     /**
      * @throws IOException 
-     * @see org.apache.james.imapserver.codec.encode.ImapResponseComposer#statusResponse(java.lang.String, org.apache.james.api.imap.ImapCommand, java.lang.String, java.lang.String, java.lang.String)
+     * @see org.apache.james.imapserver.codec.encode.ImapResponseComposer#statusResponse(java.lang.String, org.apache.james.api.imap.ImapCommand, java.lang.String, java.lang.String, Collection, long, java.lang.String)
      */
-    public void statusResponse(String tag, ImapCommand command, String type, String responseCode, String text) throws IOException {
+    public void statusResponse(String tag, ImapCommand command, String type, String responseCode, 
+            Collection parameters, long number, String text) throws IOException {
         if (tag == null) {
             untagged();
         } else {
@@ -353,7 +355,20 @@
         }
         message(type);
         if (responseCode != null) {
+            openSquareBracket();
             message(responseCode);
+            if (parameters != null && ! parameters.isEmpty()) {
+                openParen();
+                for (Iterator it = parameters.iterator();it.hasNext();) {
+                    final String parameter = (String) it.next();
+                    message(parameter);
+                }
+                closeParen();
+            }
+            if (number > 0) {
+                message(number);
+            }
+            closeSquareBracket();
         }
         if (command != null) {
             commandName(command);
@@ -546,5 +561,13 @@
 
     public void skipNextSpace() throws IOException {
         writer.skipNextSpace();
+    }
+
+    public void closeSquareBracket() throws IOException {
+        writer.closeSquareBracket();
+    }
+
+    public void openSquareBracket() throws IOException {
+        writer.openSquareBracket();
     }
 }

Modified: james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/imap4rev1/StatusResponseEncoder.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/imap4rev1/StatusResponseEncoder.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/imap4rev1/StatusResponseEncoder.java (original)
+++ james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/encode/imap4rev1/StatusResponseEncoder.java Sat Mar 22 01:53:26 2008
@@ -20,10 +20,14 @@
 package org.apache.james.imapserver.codec.encode.imap4rev1;
 
 import java.io.IOException;
+import java.util.Collection;
 
+import org.apache.james.api.imap.ImapCommand;
 import org.apache.james.api.imap.ImapMessage;
 import org.apache.james.api.imap.display.HumanReadableTextKey;
 import org.apache.james.api.imap.message.response.imap4rev1.StatusResponse;
+import org.apache.james.api.imap.message.response.imap4rev1.StatusResponse.ResponseCode;
+import org.apache.james.api.imap.message.response.imap4rev1.StatusResponse.Type;
 import org.apache.james.imapserver.codec.encode.ImapEncoder;
 import org.apache.james.imapserver.codec.encode.ImapResponseComposer;
 import org.apache.james.imapserver.codec.encode.base.AbstractChainedImapEncoder;
@@ -37,9 +41,24 @@
     protected void doEncode(ImapMessage acceptableMessage,
             ImapResponseComposer composer) throws IOException {
         StatusResponse response = (StatusResponse) acceptableMessage;
-        composer.statusResponse(response.getTag(), response.getCommand(), 
-                asString(response.getServerResponseType()), asString(response.getResponseCode()),
-                asString(response.getTextKey()));
+        final Type serverResponseType = response.getServerResponseType();
+        final String type = asString(serverResponseType);
+        final ResponseCode responseCode = response.getResponseCode();
+        final String code = asString(responseCode);
+        final String tag = response.getTag();
+        final ImapCommand command = response.getCommand();
+        final HumanReadableTextKey textKey = response.getTextKey();
+        final String text = asString(textKey);
+        final Collection parameters;
+        final int number;
+        if (responseCode == null) {
+            parameters = null;
+            number = 0;
+        } else { 
+            parameters = responseCode.getParameters();
+            number = responseCode.getNumber();
+        }
+        composer.statusResponse(tag, command, type, code, parameters, number, text);
     }
 
     private String asString(HumanReadableTextKey text)

Added: james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/MockLogger.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/MockLogger.java?rev=639967&view=auto
==============================================================================
--- james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/MockLogger.java (added)
+++ james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/MockLogger.java Sat Mar 22 01:53:26 2008
@@ -0,0 +1,83 @@
+/****************************************************************
+ * 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.imapserver.codec.decode.imap4rev1;
+
+import org.apache.avalon.framework.logger.Logger;
+
+final class MockLogger implements Logger {
+    public void debug(String arg0) {
+    }
+
+    public void debug(String arg0, Throwable arg1) {
+    }
+
+    public void error(String arg0) {
+    }
+
+    public void error(String arg0, Throwable arg1) {
+    }
+
+    public void fatalError(String arg0) {
+    }
+
+    public void fatalError(String arg0, Throwable arg1) {
+    }
+
+    public Logger getChildLogger(String arg0) {
+        return null;
+    }
+
+    public void info(String arg0) {
+    }
+
+    public void info(String arg0, Throwable arg1) {
+    }
+
+    public boolean isDebugEnabled() {
+        return false;
+    }
+
+    public boolean isErrorEnabled() {
+        return false;
+    }
+
+    public boolean isFatalErrorEnabled() {
+        return false;
+    }
+
+    public boolean isInfoEnabled() {
+        return false;
+    }
+
+    public boolean isWarnEnabled() {
+        return false;
+    }
+
+    public void warn(String arg0) {
+        
+    }
+
+    public void warn(String arg0, Throwable arg1) {
+        
+    }
+}
\ No newline at end of file

Added: james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserCharsetTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserCharsetTest.java?rev=639967&view=auto
==============================================================================
--- james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserCharsetTest.java (added)
+++ james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserCharsetTest.java Sat Mar 22 01:53:26 2008
@@ -0,0 +1,168 @@
+/****************************************************************
+ * 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.imapserver.codec.decode.imap4rev1;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.Charset;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.james.api.imap.ImapCommand;
+import org.apache.james.api.imap.ImapMessage;
+import org.apache.james.api.imap.display.HumanReadableTextKey;
+import org.apache.james.api.imap.imap4rev1.Imap4Rev1CommandFactory;
+import org.apache.james.api.imap.imap4rev1.Imap4Rev1MessageFactory;
+import org.apache.james.api.imap.message.request.SearchKey;
+import org.apache.james.api.imap.message.response.imap4rev1.StatusResponse;
+import org.apache.james.api.imap.message.response.imap4rev1.StatusResponseFactory;
+import org.apache.james.imapserver.codec.decode.ImapRequestLineReader;
+import org.jmock.Mock;
+import org.jmock.MockObjectTestCase;
+
+public class SearchCommandParserCharsetTest extends MockObjectTestCase {
+
+    private static final Charset UTF8 = Charset.forName("UTF-8");
+    private static final Charset ASCII = Charset.forName("US-ASCII");
+    private static final String TAG = "A1";
+    private static final String ASCII_SEARCH_TERM = "A Search Term";
+    private static final String NON_ASCII_SEARCH_TERM = "\u043A\u0430\u043A \u0414\u0435\u043B\u0430?";
+    private static final byte[] BYTES_NON_ASCII_SEARCH_TERM = NON_ASCII_SEARCH_TERM.getBytes(UTF8); 
+    private static final byte[] BYTES_UTF8_NON_ASCII_SEARCH_TERM = add(" {16}\r\n".getBytes(ASCII), BYTES_NON_ASCII_SEARCH_TERM);
+    private static final byte[] CHARSET = "CHARSET UTF-8 ".getBytes(ASCII);
+    
+    private static final byte[] add(byte[] one, byte[] two) {
+        byte[] results = new byte[one.length + two.length];
+        System.arraycopy(one, 0, results, 0, one.length);
+        System.arraycopy(two, 0, results, one.length, two.length);
+        return results;
+    }
+    
+    SearchCommandParser parser;
+    Mock mockStatusResponseFactory;
+    Mock mockCommandFactory;
+    Mock mockMessageFactory;
+    Mock mockCommand;
+    Mock mockMessage;
+    ImapCommand command;
+    ImapMessage message;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        parser = new SearchCommandParser();
+        mockCommandFactory = mock(Imap4Rev1CommandFactory.class);
+        mockCommandFactory.expects(once()).method("getSearch");
+        mockMessageFactory = mock(Imap4Rev1MessageFactory.class);
+        mockCommand = mock(ImapCommand.class);
+        command = (ImapCommand) mockCommand.proxy();
+        mockMessage = mock(ImapMessage.class);
+        mockStatusResponseFactory = mock(StatusResponseFactory.class);
+        message = (ImapMessage) mockMessage.proxy();
+        parser.init((Imap4Rev1CommandFactory) mockCommandFactory.proxy());
+        parser.setMessageFactory((Imap4Rev1MessageFactory) mockMessageFactory.proxy());
+        parser.setStatusResponseFactory((StatusResponseFactory) mockStatusResponseFactory.proxy());
+        parser.enableLogging(new MockLogger());
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+    
+    public void testBadCharset() throws Exception {
+        Collection charsetNames = new HashSet();
+        for (final Iterator it = Charset.availableCharsets().values().iterator(); it.hasNext();) {
+            final Charset charset = (Charset) it.next();
+            final Set aliases = charset.aliases();
+            charsetNames.addAll(aliases);
+        }
+        mockStatusResponseFactory.expects(once()).method("taggedNo").with(eq(TAG), same(command), eq(HumanReadableTextKey.BAD_CHARSET), eq(StatusResponse.ResponseCode.badCharset(charsetNames)));
+        ImapRequestLineReader reader = new ImapRequestLineReader(new ByteArrayInputStream("CHARSET BOGUS ".getBytes("US-ASCII")), 
+                new ByteArrayOutputStream());
+        parser.decode(command, reader, TAG, false);
+    }
+    
+    public void testBCCShouldConvertCharset() throws Exception {
+        SearchKey key = SearchKey.buildBcc(NON_ASCII_SEARCH_TERM);
+        checkUTF8Valid("BCC".getBytes("US-ASCII"), key);
+    }
+    
+    public void testBODYShouldConvertCharset() throws Exception {
+        SearchKey key = SearchKey.buildBody(NON_ASCII_SEARCH_TERM);
+        checkUTF8Valid("BODY".getBytes("US-ASCII"), key);
+    }
+    
+    public void testCCShouldConvertCharset() throws Exception {
+        SearchKey key = SearchKey.buildCc(NON_ASCII_SEARCH_TERM);
+        checkUTF8Valid("CC".getBytes("US-ASCII"), key);   
+    }
+    
+    public void testFROMShouldConvertCharset() throws Exception {
+        SearchKey key = SearchKey.buildFrom(NON_ASCII_SEARCH_TERM);
+        checkUTF8Valid("FROM".getBytes("US-ASCII"), key);
+    }
+    
+    public void testHEADERShouldConvertCharset() throws Exception {
+        SearchKey key = SearchKey.buildHeader("whatever", NON_ASCII_SEARCH_TERM);
+        checkUTF8Valid("HEADER whatever".getBytes("US-ASCII"), key);
+    }
+    
+    public void testSUBJECTShouldConvertCharset() throws Exception {
+        SearchKey key = SearchKey.buildSubject(NON_ASCII_SEARCH_TERM);
+        checkUTF8Valid("SUBJECT".getBytes("US-ASCII"), key);
+    }
+    
+    public void testTEXTShouldConvertCharset() throws Exception {
+        SearchKey key = SearchKey.buildText(NON_ASCII_SEARCH_TERM);
+        checkUTF8Valid("TEXT".getBytes("US-ASCII"), key);
+    }
+    
+    public void testTOShouldConvertCharset() throws Exception {
+        SearchKey key = SearchKey.buildTo(NON_ASCII_SEARCH_TERM);
+        checkUTF8Valid("TO".getBytes("US-ASCII"), key);
+    }
+    
+    public void testASCIICharset() throws Exception {
+        SearchKey key = SearchKey.buildBcc(ASCII_SEARCH_TERM);
+        checkValid("CHARSET US-ASCII BCC \"" + ASCII_SEARCH_TERM + "\"", key, true, "US-ASCII");
+    }
+    
+    public void testSimpleUTF8Charset() throws Exception {
+        SearchKey key = SearchKey.buildBcc(ASCII_SEARCH_TERM);
+        checkValid("CHARSET UTF-8 BCC \"" + ASCII_SEARCH_TERM + "\"", key, true, "US-ASCII");
+    }
+    
+    private void checkUTF8Valid(byte[] term, final SearchKey key) throws Exception {
+        ImapRequestLineReader reader = new ImapRequestLineReader(new ByteArrayInputStream(add(add(CHARSET, term), BYTES_UTF8_NON_ASCII_SEARCH_TERM)), 
+                new ByteArrayOutputStream());
+        final SearchKey searchKey = parser.searchKey(reader, null, true);
+        assertEquals(key, searchKey);
+    }
+    
+    private void checkValid(String input, final SearchKey key, boolean isFirst, String charset) throws Exception {
+        ImapRequestLineReader reader = new ImapRequestLineReader(new ByteArrayInputStream(input.getBytes(charset)), 
+                new ByteArrayOutputStream());
+
+        final SearchKey searchKey = parser.searchKey(reader, null, isFirst);
+        assertEquals(key, searchKey);
+    }
+    
+}

Modified: james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserNotTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserNotTest.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserNotTest.java (original)
+++ james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserNotTest.java Sat Mar 22 01:53:26 2008
@@ -116,6 +116,6 @@
         ImapRequestLineReader reader = new ImapRequestLineReader(new ByteArrayInputStream(input.getBytes("US-ASCII")), 
                 new ByteArrayOutputStream());
 
-        assertEquals(key, parser.searchKey(reader));
+        assertEquals(key, parser.searchKey(reader, null, false));
     }
 }

Modified: james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserOrTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserOrTest.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserOrTest.java (original)
+++ james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserOrTest.java Sat Mar 22 01:53:26 2008
@@ -175,7 +175,7 @@
         ImapRequestLineReader reader = new ImapRequestLineReader(new ByteArrayInputStream(input.getBytes("US-ASCII")), 
                 new ByteArrayOutputStream());
 
-        assertEquals(key, parser.searchKey(reader));
+        assertEquals(key, parser.searchKey(reader, null, false));
     }
     
     public class Input {

Modified: james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeySequenceSetTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeySequenceSetTest.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeySequenceSetTest.java (original)
+++ james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeySequenceSetTest.java Sat Mar 22 01:53:26 2008
@@ -103,7 +103,7 @@
         ImapRequestLineReader reader = new ImapRequestLineReader(new ByteArrayInputStream(input.getBytes("US-ASCII")), 
                 new ByteArrayOutputStream());
 
-        final SearchKey searchKey = parser.searchKey(reader);
+        final SearchKey searchKey = parser.searchKey(reader, null, false);
         assertEquals(key, searchKey);
     }
 }

Modified: james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeyTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeyTest.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeyTest.java (original)
+++ james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeyTest.java Sat Mar 22 01:53:26 2008
@@ -369,7 +369,7 @@
         ImapRequestLineReader reader = new ImapRequestLineReader(new ByteArrayInputStream(input.getBytes("US-ASCII")), 
                 new ByteArrayOutputStream());
 
-        assertEquals(key, parser.searchKey(reader));
+        assertEquals(key, parser.searchKey(reader, null, false));
     }
 
     public void testShouldParseDeleted() throws Exception {
@@ -691,7 +691,7 @@
                 new ByteArrayOutputStream());
 
         try {
-            parser.searchKey(reader);
+            parser.searchKey(reader, null, false);
             fail("Expected protocol exception to be throw since input is invalid");
         } catch (ProtocolException e) {
             //expected

Modified: james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/AbstractTestImapResponseComposer.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/AbstractTestImapResponseComposer.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/AbstractTestImapResponseComposer.java (original)
+++ james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/AbstractTestImapResponseComposer.java Sat Mar 22 01:53:26 2008
@@ -20,20 +20,27 @@
 package org.apache.james.imapserver.codec.encode;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 
 import javax.mail.Flags;
 
-import junit.framework.TestCase;
+import org.apache.james.api.imap.ImapCommand;
+import org.jmock.Mock;
+import org.jmock.MockObjectTestCase;
 
-public abstract class AbstractTestImapResponseComposer extends TestCase {
+public abstract class AbstractTestImapResponseComposer extends MockObjectTestCase {
 
     private static final long[] ONE_TWO_THREE = {1, 2, 3};
     private static final long[] FIBS = {1, 1, 2, 3, 5, 8, 13, 21, 34, 65, 99};
     private static final long[] EMPTY = {};
     
+    Mock mockCommand;
+    
     protected void setUp() throws Exception {
         super.setUp();
+        mockCommand = mock(ImapCommand.class);
     }
 
     protected void tearDown() throws Exception {
@@ -110,6 +117,26 @@
         checkFlagsEncode(" FLAGS (\\Answered \\Deleted \\Draft \\Flagged \\Seen)", flags);
     }
     
+    public void testShouldEncodeUnparameterisedStatus() throws Exception {
+        checkStatusResponseEncode("A1 NO [ALERT] APPEND failed\r\n", "A1", command("APPEND"),
+                "NO", "ALERT", Collections.EMPTY_LIST, 0, "failed");
+        checkStatusResponseEncode("A1 BAD [TRYCREATE] SELECT whatever\r\n", "A1", command("SELECT"),
+                "BAD", "TRYCREATE", Collections.EMPTY_LIST, 0, "whatever");
+    }
+    
+    public void testShouldEncodeListParameterStatus() throws Exception {
+        Collection parameters = new ArrayList();
+        parameters.add("ONE");
+        parameters.add("TWO");
+        parameters.add("THREE");
+        checkStatusResponseEncode("A1 NO [BADCHARSET (ONE TWO THREE)] APPEND failed\r\n", "A1", command("APPEND"),
+                "NO", "BADCHARSET", parameters, 0, "failed");
+    }
+    
+    public void testShouldEncodeNumberParameterStatus() throws Exception {
+        checkStatusResponseEncode("A1 NO [UIDNEXT 10] APPEND failed\r\n", "A1", command("APPEND"),
+                "NO", "UIDNEXT", null, 10, "failed");
+    }
     
     private void checkFlagsEncode(String expected, Flags flags) throws Exception {
         StringBuffer buffer = new StringBuffer();
@@ -165,4 +192,23 @@
             Long uidNext, Long uidValidity, Long unseen, String mailbox) throws Exception;
     
     protected abstract void clear() throws Exception;
+    
+    protected abstract byte[] encodeStatusResponse(String tag, ImapCommand command, String type, 
+            String responseCode, Collection parameters, int number, String text) throws Exception;
+        
+    private void checkStatusResponseEncode(String expected, String tag, ImapCommand command, String type, 
+            String responseCode, Collection parameters, int number, String text) throws Exception {
+        StringBuffer buffer = new StringBuffer();
+        byte[] output = encodeStatusResponse(tag, command, type, responseCode, parameters, number, text);
+        for (int i=0;i<output.length;i++) {
+            buffer.append((char) output[i]);
+        }
+        assertEquals(expected, buffer.toString());
+        clear();
+    }
+    
+    private ImapCommand command(String name) {
+        mockCommand.expects(once()).method("getName").will(returnValue(name));
+        return (ImapCommand) mockCommand.proxy();
+    }
 }

Modified: james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/ImapResponseTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/ImapResponseTest.java?rev=639967&r1=639966&r2=639967&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/ImapResponseTest.java (original)
+++ james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/encode/ImapResponseTest.java Sat Mar 22 01:53:26 2008
@@ -94,9 +94,9 @@
         assertEquals(new MockImapResponseWriter.UntaggedOperation(), writer.operations.get(0));
         assertEquals(new MockImapResponseWriter.TextMessageOperation(ImapResponseComposerImpl.FLAGS), 
                 writer.operations.get(1));
-        assertEquals(new MockImapResponseWriter.ParenOperation(true),
+        assertEquals(new MockImapResponseWriter.BracketOperation(true, false),
                 writer.operations.get(2));
-        assertEquals(new MockImapResponseWriter.ParenOperation(false),
+        assertEquals(new MockImapResponseWriter.BracketOperation(false, false),
                 writer.operations.get(3));
         assertEquals(new MockImapResponseWriter.EndOperation(), 
                 writer.operations.get(4));

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=639967&r1=639966&r2=639967&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 Sat Mar 22 01:53:26 2008
@@ -127,13 +127,21 @@
     }
     
     public void closeParen() {
-        writer.print(CLOSING_PARENTHESIS);
+        closeBracket(CLOSING_PARENTHESIS);
+    }
+
+    private void closeBracket(final char bracket) {
+        writer.print(bracket);
         clearSkipNextSpace();
     }
 
     public void openParen() {
+        openBracket(OPENING_PARENTHESIS);
+    }
+
+    private void openBracket(final char bracket) {
         space();
-        writer.print(OPENING_PARENTHESIS);
+        writer.print(bracket);
         skipNextSpace();
     }
     
@@ -165,5 +173,13 @@
         WritableByteChannel channel = Channels.newChannel(out);
         literal.writeTo(channel);
         writer.flush();
+    }
+
+    public void closeSquareBracket() throws IOException {
+        closeBracket(CLOSING_SQUARE_BRACKET);
+    }
+
+    public void openSquareBracket() throws IOException {
+        openBracket(OPENING_SQUARE_BRACKET);
     }
 }



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