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 er...@apache.org on 2010/08/28 15:55:58 UTC

svn commit: r990364 [3/5] - in /james/imap/trunk: ./ decode/ decode/src/ message/ message/src/main/java/org/apache/james/imap/decode/ message/src/main/java/org/apache/james/imap/decode/base/ message/src/main/java/org/apache/james/imap/decode/main/ mess...

Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java?rev=990364&view=auto
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java (added)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java Sat Aug 28 13:55:56 2010
@@ -0,0 +1,247 @@
+/****************************************************************
+ * 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.decode.parser;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.james.imap.api.ImapMessageFactory;
+import org.apache.james.imap.api.ImapCommand;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.api.ImapMessage;
+import org.apache.james.imap.api.display.HumanReadableText;
+import org.apache.james.imap.api.message.BodyFetchElement;
+import org.apache.james.imap.api.message.FetchData;
+import org.apache.james.imap.api.message.IdRange;
+import org.apache.james.imap.decode.FetchPartPathDecoder;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.imap.decode.DecodingException;
+
+/**
+ * Parse FETCH commands
+ *
+ */
+public class FetchCommandParser extends AbstractUidCommandParser {
+
+    public FetchCommandParser() {
+        super(ImapCommand.selectedStateCommand(ImapConstants.FETCH_COMMAND_NAME));
+    }
+
+    /**
+     * Create a {@link FetchData} by reading from the {@link ImapRequestLineReader}
+     * 
+     * @param request
+     * @return fetchData
+     * @throws DecodingException
+     */
+    protected FetchData fetchRequest(ImapRequestLineReader request)
+            throws DecodingException {
+        FetchData fetch = new FetchData();
+
+        char next = nextNonSpaceChar(request);
+        if (request.nextChar() == '(') {
+            consumeChar(request, '(');
+
+            next = nextNonSpaceChar(request);
+            while (next != ')') {
+                addNextElement(request, fetch);
+                next = nextNonSpaceChar(request);
+            }
+            consumeChar(request, ')');
+        } else {
+            addNextElement(request, fetch);
+
+        }
+
+        return fetch;
+    }
+
+    private void addNextElement(ImapRequestLineReader reader, FetchData fetch)
+            throws DecodingException {
+        // String name = element.toString();
+        String name = readWord(reader, " [)\r\n");
+        char next = reader.nextChar();
+        // Simple elements with no '[]' parameters.
+        if (next != '[') {
+            if ("FAST".equalsIgnoreCase(name)) {
+                fetch.setFlags(true);
+                fetch.setInternalDate(true);
+                fetch.setSize(true);
+            } else if ("FULL".equalsIgnoreCase(name)) {
+                fetch.setFlags(true);
+                fetch.setInternalDate(true);
+                fetch.setSize(true);
+                fetch.setEnvelope(true);
+                fetch.setBody(true);
+            } else if ("ALL".equalsIgnoreCase(name)) {
+                fetch.setFlags(true);
+                fetch.setInternalDate(true);
+                fetch.setSize(true);
+                fetch.setEnvelope(true);
+            } else if ("FLAGS".equalsIgnoreCase(name)) {
+                fetch.setFlags(true);
+            } else if ("RFC822.SIZE".equalsIgnoreCase(name)) {
+                fetch.setSize(true);
+            } else if ("ENVELOPE".equalsIgnoreCase(name)) {
+                fetch.setEnvelope(true);
+            } else if ("INTERNALDATE".equalsIgnoreCase(name)) {
+                fetch.setInternalDate(true);
+            } else if ("BODY".equalsIgnoreCase(name)) {
+                fetch.setBody(true);
+            } else if ("BODYSTRUCTURE".equalsIgnoreCase(name)) {
+                fetch.setBodyStructure(true);
+            } else if ("UID".equalsIgnoreCase(name)) {
+                fetch.setUid(true);
+            } else if ("RFC822".equalsIgnoreCase(name)) {
+                fetch.add(BodyFetchElement.createRFC822(), false);
+            } else if ("RFC822.HEADER".equalsIgnoreCase(name)) {
+                fetch.add(BodyFetchElement.createRFC822Header(), true);
+            } else if ("RFC822.TEXT".equalsIgnoreCase(name)) {
+                fetch.add(BodyFetchElement.createRFC822Text(), false);
+            } else {
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Invalid fetch attribute: " + name);
+            }
+        } else {
+            consumeChar(reader, '[');
+
+            String parameter = readWord(reader, "]");
+
+            consumeChar(reader, ']');
+
+            final Long firstOctet;
+            final Long numberOfOctets;
+            if (reader.nextChar() == '<') {
+                consumeChar(reader, '<');
+                firstOctet = new Long(number(reader));
+                if (reader.nextChar() == '.') {
+                    consumeChar(reader, '.');
+                    numberOfOctets = new Long(nzNumber(reader));
+                } else {
+                    numberOfOctets = null;
+                }
+                consumeChar(reader, '>');
+            } else {
+                firstOctet = null;
+                numberOfOctets = null;
+            }
+
+            final BodyFetchElement bodyFetchElement = createBodyElement(
+                    parameter, firstOctet, numberOfOctets);
+            final boolean isPeek = isPeek(name);
+            fetch.add(bodyFetchElement, isPeek);
+        }
+    }
+
+    private boolean isPeek(String name) throws DecodingException {
+        final boolean isPeek;
+        if ("BODY".equalsIgnoreCase(name)) {
+            isPeek = false;
+        } else if ("BODY.PEEK".equalsIgnoreCase(name)) {
+            isPeek = true;
+        } else {
+            throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, 
+                    "Invalid fetch attibute: " + name + "[]");
+        }
+        return isPeek;
+    }
+
+    private BodyFetchElement createBodyElement(String parameter,
+            Long firstOctet, Long numberOfOctets) throws DecodingException {
+        final String responseName = "BODY[" + parameter + "]";
+        FetchPartPathDecoder decoder = new FetchPartPathDecoder();
+        decoder.decode(parameter);
+        final int sectionType = getSectionType(decoder);
+
+        final List<String> names = decoder.getNames();
+        final int[] path = decoder.getPath();
+        final BodyFetchElement bodyFetchElement = new BodyFetchElement(
+                responseName, sectionType, path, names, firstOctet,
+                numberOfOctets);
+        return bodyFetchElement;
+    }
+
+    private int getSectionType(FetchPartPathDecoder decoder)
+            throws DecodingException {
+        final int specifier = decoder.getSpecifier();
+        final int sectionType;
+        switch (specifier) {
+            case FetchPartPathDecoder.CONTENT:
+                sectionType = BodyFetchElement.CONTENT;
+                break;
+            case FetchPartPathDecoder.HEADER:
+                sectionType = BodyFetchElement.HEADER;
+                break;
+            case FetchPartPathDecoder.HEADER_FIELDS:
+                sectionType = BodyFetchElement.HEADER_FIELDS;
+                break;
+            case FetchPartPathDecoder.HEADER_NOT_FIELDS:
+                sectionType = BodyFetchElement.HEADER_NOT_FIELDS;
+                break;
+            case FetchPartPathDecoder.MIME:
+                sectionType = BodyFetchElement.MIME;
+                break;
+            case FetchPartPathDecoder.TEXT:
+                sectionType = BodyFetchElement.TEXT;
+                break;
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Section type is unsupported.");
+        }
+        return sectionType;
+    }
+
+    private String readWord(ImapRequestLineReader request, String terminator)
+            throws DecodingException {
+        StringBuffer buf = new StringBuffer();
+        char next = request.nextChar();
+        while (terminator.indexOf(next) == -1) {
+            buf.append(next);
+            request.consume();
+            next = request.nextChar();
+        }
+        return buf.toString();
+    }
+
+    private char nextNonSpaceChar(ImapRequestLineReader request)
+            throws DecodingException {
+        char next = request.nextChar();
+        while (next == ' ') {
+            request.consume();
+            next = request.nextChar();
+        }
+        return next;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.imap.decode.parser.AbstractUidCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, boolean, org.apache.commons.logging.Log)
+     */
+    protected ImapMessage decode(ImapCommand command,
+            ImapRequestLineReader request, String tag, boolean useUids, Log logger)
+            throws DecodingException {
+        IdRange[] idSet = parseIdRange(request);
+        FetchData fetch = fetchRequest(request);
+        endLine(request);
+
+        final ImapMessageFactory factory = getMessageFactory();
+        final ImapMessage result = factory.createFetchMessage(command, useUids,
+                idSet, fetch, tag);
+        return result;
+    }
+
+}

Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ImapParserFactory.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ImapParserFactory.java?rev=990364&view=auto
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ImapParserFactory.java (added)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ImapParserFactory.java Sat Aug 28 13:55:56 2010
@@ -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.imap.decode.parser;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.james.imap.api.ImapMessageFactory;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.api.message.response.StatusResponseFactory;
+import org.apache.james.imap.decode.DelegatingImapCommandParser;
+import org.apache.james.imap.decode.ImapCommandParser;
+import org.apache.james.imap.decode.ImapCommandParserFactory;
+import org.apache.james.imap.decode.MessagingImapCommandParser;
+
+/**
+ * A factory for ImapCommand instances, provided based on the command name.
+ * Command instances are created on demand, when first accessed.
+ * 
+ */
+public class ImapParserFactory implements
+        ImapCommandParserFactory {
+    private Map<String, Class<?>> _imapCommands;
+
+    private final ImapMessageFactory messageFactory;
+
+    private final StatusResponseFactory statusResponseFactory;
+
+
+    public ImapParserFactory(
+            final ImapMessageFactory messageFactory,
+            final StatusResponseFactory statusResponseFactory) {
+        this.messageFactory = messageFactory;
+        this.statusResponseFactory = statusResponseFactory;
+        _imapCommands = new HashMap<String, Class<?>>();
+
+        // Commands valid in any state
+        // CAPABILITY, NOOP, and LOGOUT
+        _imapCommands.put(ImapConstants.CAPABILITY_COMMAND_NAME,
+                CapabilityCommandParser.class);
+        _imapCommands.put(ImapConstants.NOOP_COMMAND_NAME,
+                NoopCommandParser.class);
+        _imapCommands.put(ImapConstants.LOGOUT_COMMAND_NAME,
+                LogoutCommandParser.class);
+
+        // Commands valid in NON_AUTHENTICATED state.
+        // AUTHENTICATE and LOGIN
+        _imapCommands.put(ImapConstants.AUTHENTICATE_COMMAND_NAME,
+                AuthenticateCommandParser.class);
+        _imapCommands.put(ImapConstants.LOGIN_COMMAND_NAME,
+                LoginCommandParser.class);
+
+        // Commands valid in AUTHENTICATED or SELECTED state.
+        // RFC2060: SELECT, EXAMINE, CREATE, DELETE, RENAME, SUBSCRIBE,
+        // UNSUBSCRIBE, LIST, LSUB, STATUS, and APPEND
+        _imapCommands.put(ImapConstants.SELECT_COMMAND_NAME,
+                SelectCommandParser.class);
+        _imapCommands.put(ImapConstants.EXAMINE_COMMAND_NAME,
+                ExamineCommandParser.class);
+        _imapCommands.put(ImapConstants.CREATE_COMMAND_NAME,
+                CreateCommandParser.class);
+        _imapCommands.put(ImapConstants.DELETE_COMMAND_NAME,
+                DeleteCommandParser.class);
+        _imapCommands.put(ImapConstants.RENAME_COMMAND_NAME,
+                RenameCommandParser.class);
+        _imapCommands.put(ImapConstants.SUBSCRIBE_COMMAND_NAME,
+                SubscribeCommandParser.class);
+        _imapCommands.put(ImapConstants.UNSUBSCRIBE_COMMAND_NAME,
+                UnsubscribeCommandParser.class);
+        _imapCommands.put(ImapConstants.LIST_COMMAND_NAME,
+                ListCommandParser.class);
+        _imapCommands.put(ImapConstants.LSUB_COMMAND_NAME,
+                LsubCommandParser.class);
+        _imapCommands.put(ImapConstants.STATUS_COMMAND_NAME,
+                StatusCommandParser.class);
+        _imapCommands.put(ImapConstants.APPEND_COMMAND_NAME,
+                AppendCommandParser.class);
+
+        // RFC2342 NAMESPACE
+        _imapCommands.put( ImapConstants.NAMESPACE_COMMAND_NAME, NamespaceCommandParser.class );
+
+        // RFC2086 GETACL, SETACL, DELETEACL, LISTRIGHTS, MYRIGHTS
+        // _imapCommands.put( "GETACL", GetAclCommand.class );
+        // _imapCommands.put( "SETACL", SetAclCommand.class );
+        // _imapCommands.put( "DELETEACL", DeleteAclCommand.class );
+        // _imapCommands.put( "LISTRIGHTS", ListRightsCommand.class );
+        // _imapCommands.put( "MYRIGHTS", MyRightsCommand.class );
+
+        // Commands only valid in SELECTED state.
+        // CHECK, CLOSE, EXPUNGE, SEARCH, FETCH, STORE, COPY, and UID
+        _imapCommands.put(ImapConstants.CHECK_COMMAND_NAME,
+                CheckCommandParser.class);
+        _imapCommands.put(ImapConstants.CLOSE_COMMAND_NAME,
+                CloseCommandParser.class);
+        _imapCommands.put(ImapConstants.EXPUNGE_COMMAND_NAME,
+                ExpungeCommandParser.class);
+        _imapCommands.put(ImapConstants.COPY_COMMAND_NAME,
+                CopyCommandParser.class);
+        _imapCommands.put(ImapConstants.SEARCH_COMMAND_NAME,
+                SearchCommandParser.class);
+        _imapCommands.put(ImapConstants.FETCH_COMMAND_NAME,
+                FetchCommandParser.class);
+        _imapCommands.put(ImapConstants.STORE_COMMAND_NAME,
+                StoreCommandParser.class);
+        _imapCommands.put(ImapConstants.UID_COMMAND_NAME,
+                UidCommandParser.class);
+        _imapCommands.put(ImapConstants.STARTTLS, StartTLSCommandParser.class);
+    }
+
+    /**
+     * @see org.apache.james.imap.decode.parser.ImapCommandParserFactory#getParser(java.lang.String)
+     */
+    public ImapCommandParser getParser(String commandName) {
+        Class<?> cmdClass = (Class<?>) _imapCommands.get(commandName.toUpperCase());
+
+        if (cmdClass == null) {
+            return null;
+        } else {
+            return createCommand(cmdClass);
+        }
+    }
+
+    private ImapCommandParser createCommand(Class<?> commandClass) {
+        try {
+            ImapCommandParser cmd = (ImapCommandParser) commandClass
+                    .newInstance();
+            initialiseParser(cmd);
+            return cmd;
+        } catch (Exception e) {
+            // TODO: would probably be better to manage this in protocol
+            // TODO: this runtime will produce a nasty disconnect for the client
+            throw new RuntimeException("Could not create command instance: "
+                    + commandClass.getName(), e);
+        }
+    }
+
+    protected void initialiseParser(ImapCommandParser cmd) {
+        
+        if (cmd instanceof DelegatingImapCommandParser) {
+            ((DelegatingImapCommandParser) cmd).setParserFactory(this);
+        }
+
+        if (cmd instanceof MessagingImapCommandParser) {
+            final MessagingImapCommandParser messagingImapCommandParser = (MessagingImapCommandParser) cmd;
+            messagingImapCommandParser.setMessageFactory(messageFactory);
+            messagingImapCommandParser
+                    .setStatusResponseFactory(statusResponseFactory);
+        }
+    }
+
+}

Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ListCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ListCommandParser.java?rev=990364&view=auto
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ListCommandParser.java (added)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ListCommandParser.java Sat Aug 28 13:55:56 2010
@@ -0,0 +1,96 @@
+/****************************************************************
+ * 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.decode.parser;
+
+import org.apache.commons.logging.Log;
+import org.apache.james.imap.api.ImapMessageFactory;
+import org.apache.james.imap.api.ImapCommand;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.api.ImapMessage;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.imap.decode.DecodingException;
+
+/**
+ * Parse LIST commands
+ *
+ */
+public class ListCommandParser extends AbstractUidCommandParser {
+
+    public ListCommandParser() {
+        super(ImapCommand.authenticatedStateCommand(ImapConstants.LIST_COMMAND_NAME));
+    }
+
+    protected ListCommandParser(final ImapCommand command) {
+        super(command);
+    }
+
+
+    /**
+     * Reads an argument of type "list_mailbox" from the request, which is the
+     * second argument for a LIST or LSUB command. Valid values are a "string"
+     * argument, an "atom" with wildcard characters.
+     * 
+     * @return An argument of type "list_mailbox"
+     */
+    public String listMailbox(ImapRequestLineReader request)
+            throws DecodingException {
+        char next = request.nextWordChar();
+        switch (next) {
+            case '"':
+                return consumeQuoted(request);
+            case '{':
+                return consumeLiteral(request, null);
+            default:
+                return consumeWord(request, new ListCharValidator());
+        }
+    }
+
+    private class ListCharValidator extends ATOM_CHARValidator {
+        public boolean isValid(char chr) {
+            if (isListWildcard(chr)) {
+                return true;
+            }
+            return super.isValid(chr);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.imap.decode.parser.AbstractUidCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, boolean, org.apache.commons.logging.Log)
+     */
+    protected ImapMessage decode(ImapCommand command,
+            ImapRequestLineReader request, String tag, boolean useUids, Log logger)
+            throws DecodingException {
+        String referenceName = mailbox(request);
+        String mailboxPattern = listMailbox(request);
+        endLine(request);
+        final ImapMessage result = createMessage(command, referenceName,
+                mailboxPattern, tag);
+        return result;
+    }
+
+    protected ImapMessage createMessage(ImapCommand command,
+            final String referenceName, final String mailboxPattern,
+            final String tag) {
+        final ImapMessageFactory factory = getMessageFactory();
+        final ImapMessage result = factory.createListMessage(command,
+                referenceName, mailboxPattern, tag);
+        return result;
+    }
+}

Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/LoginCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/LoginCommandParser.java?rev=990364&view=auto
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/LoginCommandParser.java (added)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/LoginCommandParser.java Sat Aug 28 13:55:56 2010
@@ -0,0 +1,53 @@
+/****************************************************************
+ * 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.decode.parser;
+
+import org.apache.commons.logging.Log;
+import org.apache.james.imap.api.ImapCommand;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.api.ImapMessage;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.imap.decode.DecodingException;
+import org.apache.james.imap.decode.base.AbstractImapCommandParser;
+
+/**
+ * Parse LOGIN commands
+ *
+ */
+public class LoginCommandParser extends AbstractImapCommandParser {
+
+    public LoginCommandParser() {
+        super(ImapCommand.nonAuthenticatedStateCommand(ImapConstants.LOGIN_COMMAND_NAME));
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
+     */
+    protected ImapMessage decode(ImapCommand command,
+            ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
+        final String userid = astring(request);
+        final String password = astring(request);
+        endLine(request);
+        final ImapMessage result = getMessageFactory().createLoginMessage(
+                command, userid, password, tag);
+        return result;
+    }
+
+}

Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/LogoutCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/LogoutCommandParser.java?rev=990364&view=auto
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/LogoutCommandParser.java (added)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/LogoutCommandParser.java Sat Aug 28 13:55:56 2010
@@ -0,0 +1,51 @@
+/****************************************************************
+ * 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.decode.parser;
+
+import org.apache.commons.logging.Log;
+import org.apache.james.imap.api.ImapCommand;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.api.ImapMessage;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.imap.decode.DecodingException;
+import org.apache.james.imap.decode.base.AbstractImapCommandParser;
+
+/**
+ * Parse LOGOUT commands
+ *
+ */
+public class LogoutCommandParser extends AbstractImapCommandParser {
+
+    public LogoutCommandParser() {
+        super(ImapCommand.anyStateCommand(ImapConstants.LOGOUT_COMMAND_NAME));
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
+     */
+    protected ImapMessage decode(ImapCommand command,
+            ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
+        endLine(request);
+        final ImapMessage result = getMessageFactory().createLogoutMessage(
+                command, tag);
+        return result;
+    }
+
+}

Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/LsubCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/LsubCommandParser.java?rev=990364&view=auto
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/LsubCommandParser.java (added)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/LsubCommandParser.java Sat Aug 28 13:55:56 2010
@@ -0,0 +1,45 @@
+/****************************************************************
+ * 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.decode.parser;
+
+import org.apache.james.imap.api.ImapCommand;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.api.ImapMessage;
+
+/**
+ * Parse LSUB commands
+ *
+ */
+public class LsubCommandParser extends ListCommandParser {
+
+    public LsubCommandParser() {
+        super(ImapCommand.authenticatedStateCommand(ImapConstants.LSUB_COMMAND_NAME));
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.imap.decode.parser.ListCommandParser#createMessage(org.apache.james.imap.api.ImapCommand, java.lang.String, java.lang.String, java.lang.String)
+     */
+    protected ImapMessage createMessage(ImapCommand command,
+            String referenceName, String mailboxPattern, String tag) {
+        final ImapMessage result = getMessageFactory().createLsubMessage(
+                command, referenceName, mailboxPattern, tag);
+        return result;
+    }
+}

Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/NamespaceCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/NamespaceCommandParser.java?rev=990364&view=auto
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/NamespaceCommandParser.java (added)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/NamespaceCommandParser.java Sat Aug 28 13:55:56 2010
@@ -0,0 +1,48 @@
+/****************************************************************
+ * 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.decode.parser;
+
+import org.apache.commons.logging.Log;
+import org.apache.james.imap.api.ImapCommand;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.api.ImapMessage;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.imap.decode.DecodingException;
+import org.apache.james.imap.decode.base.AbstractImapCommandParser;
+
+/**
+ * Parse NAMESPACE commands
+ *
+ */
+public class NamespaceCommandParser extends AbstractImapCommandParser {
+
+    public NamespaceCommandParser() {
+        super(ImapCommand.authenticatedStateCommand(ImapConstants.NAMESPACE_COMMAND_NAME));
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
+     */
+    protected ImapMessage decode(ImapCommand command,
+            ImapRequestLineReader request, String tag, Log logger)
+            throws DecodingException {
+        return getMessageFactory().createNamespaceMessage(command, tag);
+    }
+}

Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/NoopCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/NoopCommandParser.java?rev=990364&view=auto
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/NoopCommandParser.java (added)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/NoopCommandParser.java Sat Aug 28 13:55:56 2010
@@ -0,0 +1,51 @@
+/****************************************************************
+ * 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.decode.parser;
+
+import org.apache.commons.logging.Log;
+import org.apache.james.imap.api.ImapCommand;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.api.ImapMessage;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.imap.decode.DecodingException;
+import org.apache.james.imap.decode.base.AbstractImapCommandParser;
+
+/**
+ *
+ * Parses NOOP commands
+ *
+ */
+public class NoopCommandParser extends AbstractImapCommandParser {
+
+    public NoopCommandParser() {
+        super(ImapCommand.anyStateCommand(ImapConstants.NOOP_COMMAND_NAME));
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
+     */
+    protected ImapMessage decode(ImapCommand command,
+            ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
+        endLine(request);
+        final ImapMessage result = getMessageFactory().createNoopMessage(command, tag);
+        return result;
+    }
+
+}

Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/RenameCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/RenameCommandParser.java?rev=990364&view=auto
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/RenameCommandParser.java (added)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/RenameCommandParser.java Sat Aug 28 13:55:56 2010
@@ -0,0 +1,53 @@
+/****************************************************************
+ * 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.decode.parser;
+
+import org.apache.commons.logging.Log;
+import org.apache.james.imap.api.ImapCommand;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.api.ImapMessage;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.imap.decode.DecodingException;
+import org.apache.james.imap.decode.base.AbstractImapCommandParser;
+
+/**
+ * Parses RENAME command
+ *
+ */
+public class RenameCommandParser extends AbstractImapCommandParser {
+
+    public RenameCommandParser() {
+        super(ImapCommand.authenticatedStateCommand(ImapConstants.RENAME_COMMAND_NAME));
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
+     */
+    protected ImapMessage decode(ImapCommand command,
+            ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
+        final String existingName = mailbox(request);
+        final String newName = mailbox(request);
+        endLine(request);
+        final ImapMessage result = getMessageFactory().createRenameMessage(
+                command, existingName, newName, tag);
+        return result;
+    }
+
+}

Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java?rev=990364&view=auto
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java (added)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java Sat Aug 28 13:55:56 2010
@@ -0,0 +1,964 @@
+/****************************************************************
+ * 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.decode.parser;
+
+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.commons.logging.Log;
+import org.apache.james.imap.api.ImapCommand;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.api.ImapMessage;
+import org.apache.james.imap.api.display.HumanReadableText;
+import org.apache.james.imap.api.message.IdRange;
+import org.apache.james.imap.api.message.request.DayMonthYear;
+import org.apache.james.imap.api.message.request.SearchKey;
+import org.apache.james.imap.api.message.response.StatusResponse;
+import org.apache.james.imap.api.message.response.StatusResponseFactory;
+import org.apache.james.imap.api.message.response.StatusResponse.ResponseCode;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.imap.decode.DecodingException;
+
+/**
+ * Parse SEARCH commands
+ *
+ */
+public class SearchCommandParser extends AbstractUidCommandParser {
+
+    /** Lazy loaded */
+    private Collection<String> charsetNames;
+
+    public SearchCommandParser() {
+        super(ImapCommand.selectedStateCommand(ImapConstants.SEARCH_COMMAND_NAME));
+    }
+
+    /**
+     * 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
+     */
+    protected SearchKey searchKey(ImapRequestLineReader request, Charset charset,
+            boolean isFirstToken) throws DecodingException,
+            IllegalCharsetNameException, UnsupportedCharsetException {
+        final char next = request.nextChar();
+        if (next >= '0' && next <= '9' || next == '*') {
+            return sequenceSet(request);
+        } else if (next == '(') {
+            return paren(request, charset);
+        } else {
+            final int cap = consumeAndCap(request);
+            switch (cap) {
+                case 'A':
+                    return a(request);
+                case 'B':
+                    return b(request, charset);
+                case 'C':
+                    return c(request, isFirstToken, charset);
+                case 'D':
+                    return d(request);
+                case 'E':
+                    throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+                case 'F':
+                    return f(request, charset);
+                case 'G':
+                    throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+                case 'H':
+                    return header(request, charset);
+                case 'I':
+                    throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+                case 'J':
+                    throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+                case 'K':
+                    return keyword(request);
+                case 'L':
+                    return larger(request);
+                case 'M':
+                    throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+                case 'N':
+                    return n(request, charset);
+                case 'O':
+                    return o(request, charset);
+                case 'P':
+                    throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+                case 'Q':
+                    throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+                case 'R':
+                    return recent(request);
+                case 'S':
+                    return s(request, charset);
+                case 'T':
+                    return t(request, charset);
+                case 'U':
+                    return u(request);
+                default:
+                    throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+            }
+        }
+    }
+
+    private SearchKey paren(ImapRequestLineReader request, Charset charset)
+            throws DecodingException {
+        request.consume();
+        List<SearchKey> keys = new ArrayList<SearchKey>();
+        addUntilParen(request, keys, charset);
+        return SearchKey.buildAnd(keys);
+    }
+
+    private void addUntilParen(ImapRequestLineReader request, List<SearchKey> keys,
+            Charset charset) throws DecodingException {
+        final char next = request.nextWordChar();
+        if (next == ')') {
+            request.consume();
+        } else {
+            final SearchKey key = searchKey(request, null, false);
+            keys.add(key);
+            addUntilParen(request, keys, charset);
+        }
+    }
+
+    private int consumeAndCap(ImapRequestLineReader request)
+            throws DecodingException {
+        final char next = request.consume();
+        final int cap = next > 'Z' ? next ^ 32 : next;
+        return cap;
+    }
+
+    private SearchKey cc(ImapRequestLineReader request, final Charset charset)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsSpace(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 DecodingException, IllegalCharsetNameException,
+            UnsupportedCharsetException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'C':
+                return cc(request, charset);
+            case 'H':
+                return charset(request, isFirstToken);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey charset(ImapRequestLineReader request,
+            final boolean isFirstToken) throws DecodingException,
+            IllegalCharsetNameException, UnsupportedCharsetException {
+        final SearchKey result;
+        nextIsA(request);
+        nextIsR(request);
+        nextIsS(request);
+        nextIsE(request);
+        nextIsT(request);
+        nextIsSpace(request);
+        if (!isFirstToken) {
+            throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "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 DecodingException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'I':
+                return uid(request);
+            case 'N':
+                return un(request);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey un(ImapRequestLineReader request)
+            throws DecodingException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'A':
+                return unanswered(request);
+            case 'D':
+                return und(request);
+            case 'F':
+                return unflagged(request);
+            case 'K':
+                return unkeyword(request);
+            case 'S':
+                return unseen(request);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey und(ImapRequestLineReader request)
+            throws DecodingException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'E':
+                return undeleted(request);
+            case 'R':
+                return undraft(request);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey t(ImapRequestLineReader request, final Charset charset)
+            throws DecodingException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'E':
+                return text(request, charset);
+            case 'O':
+                return to(request, charset);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey s(ImapRequestLineReader request, final Charset charset)
+            throws DecodingException {
+        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, charset);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey se(ImapRequestLineReader request)
+            throws DecodingException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'E':
+                return seen(request);
+            case 'N':
+                return sen(request);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey sen(ImapRequestLineReader request)
+            throws DecodingException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'T':
+                return sent(request);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey sent(ImapRequestLineReader request)
+            throws DecodingException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'B':
+                return sentBefore(request);
+            case 'O':
+                return sentOn(request);
+            case 'S':
+                return sentSince(request);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey o(ImapRequestLineReader request, Charset charset)
+            throws DecodingException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'L':
+                return old(request);
+            case 'N':
+                return on(request);
+            case 'R':
+                return or(request, charset);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey n(ImapRequestLineReader request, Charset charset)
+            throws DecodingException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'E':
+                return _new(request);
+            case 'O':
+                return not(request, charset);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey f(ImapRequestLineReader request, final Charset charset)
+            throws DecodingException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'L':
+                return flagged(request);
+            case 'R':
+                return from(request, charset);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey d(ImapRequestLineReader request) throws DecodingException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'E':
+                return deleted(request);
+            case 'R':
+                return draft(request);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey keyword(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsE(request);
+        nextIsY(request);
+        nextIsW(request);
+        nextIsO(request);
+        nextIsR(request);
+        nextIsD(request);
+        nextIsSpace(request);
+        final String value = atom(request);
+        result = SearchKey.buildKeyword(value);
+        return result;
+    }
+
+    private SearchKey unkeyword(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsE(request);
+        nextIsY(request);
+        nextIsW(request);
+        nextIsO(request);
+        nextIsR(request);
+        nextIsD(request);
+        nextIsSpace(request);
+        final String value = atom(request);
+        result = SearchKey.buildUnkeyword(value);
+        return result;
+    }
+
+    private SearchKey header(ImapRequestLineReader request,
+            final Charset charset) throws DecodingException {
+        final SearchKey result;
+        nextIsE(request);
+        nextIsA(request);
+        nextIsD(request);
+        nextIsE(request);
+        nextIsR(request);
+        nextIsSpace(request);
+        final String field = astring(request, charset);
+        nextIsSpace(request);
+        final String value = astring(request, charset);
+        result = SearchKey.buildHeader(field, value);
+        return result;
+    }
+
+    private SearchKey larger(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsA(request);
+        nextIsR(request);
+        nextIsG(request);
+        nextIsE(request);
+        nextIsR(request);
+        nextIsSpace(request);
+        final long value = number(request);
+        result = SearchKey.buildLarger(value);
+        return result;
+    }
+
+    private SearchKey smaller(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsA(request);
+        nextIsL(request);
+        nextIsL(request);
+        nextIsE(request);
+        nextIsR(request);
+        nextIsSpace(request);
+        final long value = number(request);
+        result = SearchKey.buildSmaller(value);
+        return result;
+    }
+
+    private SearchKey from(ImapRequestLineReader request, final Charset charset)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsO(request);
+        nextIsM(request);
+        nextIsSpace(request);
+        final String value = astring(request, charset);
+        result = SearchKey.buildFrom(value);
+        return result;
+    }
+
+    private SearchKey flagged(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsA(request);
+        nextIsG(request);
+        nextIsG(request);
+        nextIsE(request);
+        nextIsD(request);
+        result = SearchKey.buildFlagged();
+        return result;
+    }
+
+    private SearchKey unseen(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsE(request);
+        nextIsE(request);
+        nextIsN(request);
+        result = SearchKey.buildUnseen();
+        return result;
+    }
+
+    private SearchKey undraft(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsA(request);
+        nextIsF(request);
+        nextIsT(request);
+        result = SearchKey.buildUndraft();
+        return result;
+    }
+
+    private SearchKey undeleted(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsL(request);
+        nextIsE(request);
+        nextIsT(request);
+        nextIsE(request);
+        nextIsD(request);
+        result = SearchKey.buildUndeleted();
+        return result;
+    }
+
+    private SearchKey unflagged(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsL(request);
+        nextIsA(request);
+        nextIsG(request);
+        nextIsG(request);
+        nextIsE(request);
+        nextIsD(request);
+        result = SearchKey.buildUnflagged();
+        return result;
+    }
+
+    private SearchKey unanswered(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsN(request);
+        nextIsS(request);
+        nextIsW(request);
+        nextIsE(request);
+        nextIsR(request);
+        nextIsE(request);
+        nextIsD(request);
+        result = SearchKey.buildUnanswered();
+        return result;
+    }
+
+    private SearchKey old(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsD(request);
+        result = SearchKey.buildOld();
+        return result;
+    }
+
+    private SearchKey or(ImapRequestLineReader request, Charset charset)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsSpace(request);
+        final SearchKey firstKey = searchKey(request, charset, false);
+        nextIsSpace(request);
+        final SearchKey secondKey = searchKey(request, charset, false);
+        result = SearchKey.buildOr(firstKey, secondKey);
+        return result;
+    }
+
+    private SearchKey not(ImapRequestLineReader request, Charset charset)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsT(request);
+        nextIsSpace(request);
+        final SearchKey nextKey = searchKey(request, charset, false);
+        result = SearchKey.buildNot(nextKey);
+        return result;
+    }
+
+    private SearchKey _new(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsW(request);
+        result = SearchKey.buildNew();
+        return result;
+    }
+
+    private SearchKey recent(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsE(request);
+        nextIsC(request);
+        nextIsE(request);
+        nextIsN(request);
+        nextIsT(request);
+        result = SearchKey.buildRecent();
+        return result;
+    }
+
+    private SearchKey seen(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsN(request);
+        result = SearchKey.buildSeen();
+        return result;
+    }
+
+    private SearchKey draft(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsA(request);
+        nextIsF(request);
+        nextIsT(request);
+        result = SearchKey.buildDraft();
+        return result;
+    }
+
+    private SearchKey deleted(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsL(request);
+        nextIsE(request);
+        nextIsT(request);
+        nextIsE(request);
+        nextIsD(request);
+        result = SearchKey.buildDeleted();
+        return result;
+    }
+
+    private SearchKey b(ImapRequestLineReader request, Charset charset)
+            throws DecodingException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'C':
+                return bcc(request, charset);
+            case 'E':
+                return before(request);
+            case 'O':
+                return body(request, charset);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey body(ImapRequestLineReader request, final Charset charset)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsD(request);
+        nextIsY(request);
+        nextIsSpace(request);
+        final String value = astring(request, charset);
+        result = SearchKey.buildBody(value);
+        return result;
+    }
+
+    private SearchKey on(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsSpace(request);
+        final DayMonthYear value = date(request);
+        result = SearchKey.buildOn(value);
+        return result;
+    }
+
+    private SearchKey sentBefore(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsE(request);
+        nextIsF(request);
+        nextIsO(request);
+        nextIsR(request);
+        nextIsE(request);
+        nextIsSpace(request);
+        final DayMonthYear value = date(request);
+        result = SearchKey.buildSentBefore(value);
+        return result;
+    }
+
+    private SearchKey sentSince(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsI(request);
+        nextIsN(request);
+        nextIsC(request);
+        nextIsE(request);
+        nextIsSpace(request);
+        final DayMonthYear value = date(request);
+        result = SearchKey.buildSentSince(value);
+        return result;
+    }
+
+    private SearchKey since(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsN(request);
+        nextIsC(request);
+        nextIsE(request);
+        nextIsSpace(request);
+        final DayMonthYear value = date(request);
+        result = SearchKey.buildSince(value);
+        return result;
+    }
+
+    private SearchKey sentOn(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsN(request);
+        nextIsSpace(request);
+        final DayMonthYear value = date(request);
+        result = SearchKey.buildSentOn(value);
+        return result;
+    }
+
+    private SearchKey before(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsF(request);
+        nextIsO(request);
+        nextIsR(request);
+        nextIsE(request);
+        nextIsSpace(request);
+        final DayMonthYear value = date(request);
+        result = SearchKey.buildBefore(value);
+        return result;
+    }
+
+    private SearchKey bcc(ImapRequestLineReader request, Charset charset)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsC(request);
+        nextIsSpace(request);
+        final String value = astring(request, charset);
+        result = SearchKey.buildBcc(value);
+        return result;
+    }
+
+    private SearchKey text(ImapRequestLineReader request, final Charset charset)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsX(request);
+        nextIsT(request);
+        nextIsSpace(request);
+        final String value = astring(request, charset);
+        result = SearchKey.buildText(value);
+        return result;
+    }
+
+    private SearchKey uid(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsD(request);
+        nextIsSpace(request);
+        final IdRange[] range = parseIdRange(request);
+        result = SearchKey.buildUidSet(range);
+        return result;
+    }
+
+    private SearchKey sequenceSet(ImapRequestLineReader request)
+            throws DecodingException {
+        final IdRange[] range = parseIdRange(request);
+        final SearchKey result = SearchKey.buildSequenceSet(range);
+        return result;
+    }
+
+    private SearchKey to(ImapRequestLineReader request, final Charset charset)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsSpace(request);
+        final String value = astring(request, charset);
+        result = SearchKey.buildTo(value);
+        return result;
+    }
+
+    private SearchKey subject(ImapRequestLineReader request,
+            final Charset charset) throws DecodingException {
+        final SearchKey result;
+        nextIsB(request);
+        nextIsJ(request);
+        nextIsE(request);
+        nextIsC(request);
+        nextIsT(request);
+        nextIsSpace(request);
+        final String value = astring(request, charset);
+        result = SearchKey.buildSubject(value);
+        return result;
+    }
+
+    private SearchKey a(ImapRequestLineReader request) throws DecodingException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'L':
+                return all(request);
+            case 'N':
+                return answered(request);
+            default:
+                throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private SearchKey answered(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsS(request);
+        nextIsW(request);
+        nextIsE(request);
+        nextIsR(request);
+        nextIsE(request);
+        nextIsD(request);
+        result = SearchKey.buildAnswered();
+        return result;
+    }
+
+    private SearchKey all(ImapRequestLineReader request)
+            throws DecodingException {
+        final SearchKey result;
+        nextIsL(request);
+        result = SearchKey.buildAll();
+        return result;
+    }
+
+    private void nextIsSpace(ImapRequestLineReader request)
+            throws DecodingException {
+        final char next = request.consume();
+        if (next != ' ') {
+            throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    private void nextIsG(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'G', 'g');
+    }
+
+    private void nextIsM(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'M', 'm');
+    }
+
+    private void nextIsI(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'I', 'i');
+    }
+
+    private void nextIsN(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'N', 'n');
+    }
+
+    private void nextIsA(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'A', 'a');
+    }
+
+    private void nextIsT(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'T', 't');
+    }
+
+    private void nextIsY(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'Y', 'y');
+    }
+
+    private void nextIsX(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'X', 'x');
+    }
+
+    private void nextIsO(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'O', 'o');
+    }
+
+    private void nextIsF(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'F', 'f');
+    }
+
+    private void nextIsJ(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'J', 'j');
+    }
+
+    private void nextIsC(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'C', 'c');
+    }
+
+    private void nextIsD(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'D', 'd');
+    }
+
+    private void nextIsB(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'B', 'b');
+    }
+
+    private void nextIsR(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'R', 'r');
+    }
+
+    private void nextIsE(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'E', 'e');
+    }
+
+    private void nextIsW(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'W', 'w');
+    }
+
+    private void nextIsS(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'S', 's');
+    }
+
+    private void nextIsL(ImapRequestLineReader request)
+            throws DecodingException {
+        nextIs(request, 'L', 'l');
+    }
+
+    private void nextIs(ImapRequestLineReader request, final char upper,
+            final char lower) throws DecodingException {
+        final char next = request.consume();
+        if (next != upper && next != lower) {
+            throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
+        }
+    }
+
+    public SearchKey decode(ImapRequestLineReader request)
+            throws DecodingException, IllegalCharsetNameException,
+            UnsupportedCharsetException {
+        request.nextWordChar();
+        final SearchKey firstKey = searchKey(request, null, true);
+        final SearchKey result;
+        if (request.nextChar() == ' ') {
+            List<SearchKey> keys = new ArrayList<SearchKey>();
+            keys.add(firstKey);
+            while (request.nextChar() == ' ') {
+                request.nextWordChar();
+                final SearchKey key = searchKey(request, null, false);
+                keys.add(key);
+            }
+            result = SearchKey.buildAnd(keys);
+        } else {
+            result = firstKey;
+        }
+        endLine(request);
+        return result;
+    }
+
+    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,
+                HumanReadableText.BAD_CHARSET, badCharset);
+        return result;
+    }
+
+    private synchronized void loadCharsetNames() {
+        if (charsetNames == null) {
+            charsetNames = new HashSet<String>();
+            for (final Iterator<Charset> it = Charset.availableCharsets().values()
+                    .iterator(); it.hasNext();) {
+                final Charset charset = it.next();
+                final Set<String> aliases = charset.aliases();
+                charsetNames.addAll(aliases);
+            }
+        }
+    }
+
+    protected ImapMessage decode(ImapCommand command,
+            ImapRequestLineReader request, String tag, boolean useUids, Log logger)
+            throws DecodingException {
+        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) {
+            logger.debug(e.getMessage());
+            return unsupportedCharset(tag, command);
+        } catch (UnsupportedCharsetException e) {
+            logger.debug(e.getMessage());
+            return unsupportedCharset(tag, command);
+        }
+    }
+}

Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java?rev=990364&view=auto
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java (added)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java Sat Aug 28 13:55:56 2010
@@ -0,0 +1,52 @@
+/****************************************************************
+ * 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.decode.parser;
+
+import org.apache.commons.logging.Log;
+import org.apache.james.imap.api.ImapCommand;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.api.ImapMessage;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.imap.decode.DecodingException;
+import org.apache.james.imap.decode.base.AbstractImapCommandParser;
+
+/**
+ * Parse SELECT commands
+ *
+ */
+public class SelectCommandParser extends AbstractImapCommandParser {
+
+    public SelectCommandParser() {
+        super(ImapCommand.authenticatedStateCommand(ImapConstants.SELECT_COMMAND_NAME));
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
+     */
+    protected ImapMessage decode(ImapCommand command,
+            ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
+        final String mailboxName = mailbox(request);
+        endLine(request);
+        final ImapMessage result = getMessageFactory().createSelectMessage(
+                command, mailboxName, tag);
+        return result;
+    }
+
+}

Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StartTLSCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StartTLSCommandParser.java?rev=990364&view=auto
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StartTLSCommandParser.java (added)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StartTLSCommandParser.java Sat Aug 28 13:55:56 2010
@@ -0,0 +1,45 @@
+/****************************************************************
+ * 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.decode.parser;
+
+import org.apache.commons.logging.Log;
+import org.apache.james.imap.api.ImapCommand;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.api.ImapMessage;
+import org.apache.james.imap.decode.DecodingException;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.imap.decode.base.AbstractImapCommandParser;
+
+/**
+ * Parse STARTTLS commands
+ *
+ */
+public class StartTLSCommandParser extends AbstractImapCommandParser{
+
+    public StartTLSCommandParser() {
+        super(ImapCommand.nonAuthenticatedStateCommand(ImapConstants.STARTTLS));
+    }
+
+    @Override
+    protected ImapMessage decode(ImapCommand command, ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
+        endLine(request);
+        return getMessageFactory().createStartTLSMessage(command, tag);
+    }
+
+}

Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StatusCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StatusCommandParser.java?rev=990364&view=auto
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StatusCommandParser.java (added)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StatusCommandParser.java Sat Aug 28 13:55:56 2010
@@ -0,0 +1,96 @@
+/****************************************************************
+ * 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.decode.parser;
+
+import org.apache.commons.logging.Log;
+import org.apache.james.imap.api.ImapMessageFactory;
+import org.apache.james.imap.api.ImapCommand;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.api.ImapMessage;
+import org.apache.james.imap.api.display.HumanReadableText;
+import org.apache.james.imap.api.message.StatusDataItems;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.imap.decode.DecodingException;
+import org.apache.james.imap.decode.base.AbstractImapCommandParser;
+
+/**
+ * Parse STATUS commands
+ *
+ */
+public class StatusCommandParser extends AbstractImapCommandParser {
+    public StatusCommandParser() {
+        super(ImapCommand.authenticatedStateCommand(ImapConstants.STATUS_COMMAND_NAME));
+    }
+
+    StatusDataItems statusDataItems(ImapRequestLineReader request)
+            throws DecodingException {
+        StatusDataItems items = new StatusDataItems();
+
+        request.nextWordChar();
+        consumeChar(request, '(');
+        CharacterValidator validator = new NoopCharValidator();
+        String nextWord = consumeWord(request, validator);
+
+        while (!nextWord.endsWith(")")) {
+            addItem(nextWord, items);
+            nextWord = consumeWord(request, validator);
+        }
+        // Got the closing ")", may be attached to a word.
+        if (nextWord.length() > 1) {
+            addItem(nextWord.substring(0, nextWord.length() - 1), items);
+        }
+
+        return items;
+    }
+
+    private void addItem(String nextWord, StatusDataItems items)
+            throws DecodingException {
+
+        if (nextWord.equals(ImapConstants.STATUS_MESSAGES)) {
+            items.setMessages(true);
+        } else if (nextWord.equals(ImapConstants.STATUS_RECENT)) {
+            items.setRecent(true);
+        } else if (nextWord.equals(ImapConstants.STATUS_UIDNEXT)) {
+            items.setUidNext(true);
+        } else if (nextWord.equals(ImapConstants.STATUS_UIDVALIDITY)) {
+            items.setUidValidity(true);
+        } else if (nextWord.equals(ImapConstants.STATUS_UNSEEN)) {
+            items.setUnseen(true);
+        } else {
+            throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, 
+                    "Unknown status item: '" + nextWord + "'");
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
+     */
+    protected ImapMessage decode(ImapCommand command,
+            ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
+        final String mailboxName = mailbox(request);
+        final StatusDataItems statusDataItems = statusDataItems(request);
+        endLine(request);
+        final ImapMessageFactory factory = getMessageFactory();
+        final ImapMessage result = factory.createStatusMessage(command,
+                mailboxName, statusDataItems, tag);
+        
+        return result;
+    }
+}



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