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/01/29 20:59:34 UTC

svn commit: r616502 [1/2] - in /james/server/trunk: core-library/src/main/java/org/apache/james/mailboxmanager/manager/ imap-api/src/main/java/org/apache/james/api/imap/display/ imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/...

Author: rdonkin
Date: Tue Jan 29 11:59:29 2008
New Revision: 616502

URL: http://svn.apache.org/viewvc?rev=616502&view=rev
Log:
Switch subscribe and unsubscribe to use revised interfaces.

Added:
    james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/IMAPSubscriber.java
    james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SubscriptionException.java
    james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/UserMetaDataIMAPSubscriber.java
    james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/UserMetaDataIMAPSubscriberTest.java
Modified:
    james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/manager/MailboxManagerProvider.java
    james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/display/HumanReadableTextKey.java
    james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/AbstractListingProcessor.java
    james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/Imap4Rev1ProcessorFactory.java
    james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/LSubProcessor.java
    james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/ListProcessor.java
    james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SubscribeProcessor.java
    james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/UnsubscribeProcessor.java
    james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/main/DefaultImapProcessorFactory.java
    james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/AbstractTestListProcessor.java
    james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/LSubProcessorTest.java
    james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/ListProcessorTest.java
    james/server/trunk/phoenix-deployment/src/java/org/apache/james/imapserver/phoenix/PhoenixImapProcessorFactory.java
    james/server/trunk/phoenix-deployment/src/test/org/apache/james/experimental/imapserver/HostSystemFactory.java
    james/server/trunk/user-api/src/main/java/org/apache/james/api/user/UserMetaDataRespository.java

Modified: james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/manager/MailboxManagerProvider.java
URL: http://svn.apache.org/viewvc/james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/manager/MailboxManagerProvider.java?rev=616502&r1=616501&r2=616502&view=diff
==============================================================================
--- james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/manager/MailboxManagerProvider.java (original)
+++ james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/manager/MailboxManagerProvider.java Tue Jan 29 11:59:29 2008
@@ -26,6 +26,9 @@
 
 public interface MailboxManagerProvider {
     
+    public static final String ROLE 
+        =  "org.apache.james.mailboxmanager.manager.MailboxManagerProvider";
+    
     public MailboxManager getMailboxManager() throws MailboxManagerException;
     
     /**

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=616502&r1=616501&r2=616502&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 Tue Jan 29 11:59:29 2008
@@ -26,6 +26,14 @@
  */
 public class HumanReadableTextKey {
 
+    public static final HumanReadableTextKey GENERIC_UNSUBSCRIPTION_FAILURE 
+    = new HumanReadableTextKey("org.apache.james.imap.GENERIC_SUBSCRIPTION_FAILURE", 
+    "Cannot unsubscribe."); 
+    
+    public static final HumanReadableTextKey GENERIC_SUBSCRIPTION_FAILURE 
+    = new HumanReadableTextKey("org.apache.james.imap.GENERIC_SUBSCRIPTION_FAILURE", 
+    "Cannot subscribe."); 
+    
     public static final HumanReadableTextKey FAILURE_NO_SUCH_MAILBOX 
         = new HumanReadableTextKey("org.apache.james.imap.FAILURE_NO_SUCH_MAILBOX", 
                 "failed. No such mailbox.");

Modified: james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/AbstractListingProcessor.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/AbstractListingProcessor.java?rev=616502&r1=616501&r2=616502&view=diff
==============================================================================
--- james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/AbstractListingProcessor.java (original)
+++ james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/AbstractListingProcessor.java Tue Jan 29 11:59:29 2008
@@ -1,237 +0,0 @@
-/****************************************************************
- * 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.processor.imap4rev1;
-
-import org.apache.avalon.framework.logger.Logger;
-import org.apache.james.api.imap.ImapCommand;
-import org.apache.james.api.imap.ImapConstants;
-import org.apache.james.api.imap.ProtocolException;
-import org.apache.james.api.imap.message.response.ImapResponseMessage;
-import org.apache.james.api.imap.message.response.imap4rev1.StatusResponseFactory;
-import org.apache.james.api.imap.process.ImapProcessor;
-import org.apache.james.api.imap.process.ImapSession;
-import org.apache.james.imapserver.processor.base.AbstractMailboxAwareProcessor;
-import org.apache.james.imapserver.processor.base.AuthorizationException;
-import org.apache.james.imapserver.processor.base.ImapSessionUtils;
-import org.apache.james.imapserver.store.MailboxException;
-import org.apache.james.mailboxmanager.ListResult;
-import org.apache.james.mailboxmanager.MailboxManagerException;
-import org.apache.james.mailboxmanager.impl.ListResultImpl;
-import org.apache.james.mailboxmanager.manager.MailboxExpression;
-import org.apache.james.mailboxmanager.manager.MailboxManager;
-import org.apache.james.mailboxmanager.manager.MailboxManagerProvider;
-import org.apache.james.services.User;
-
-abstract class AbstractListingProcessor extends AbstractMailboxAwareProcessor {
-
-    private final boolean subscribedOnly;
-    
-    
-    public AbstractListingProcessor(final ImapProcessor next,
-            final MailboxManagerProvider mailboxManagerProvider, 
-            final StatusResponseFactory factory, final boolean subscribedOnly) {
-        super(next, mailboxManagerProvider, factory);
-        this.subscribedOnly = subscribedOnly;
-    }
-
-    protected final void doProcess(
-            final String baseReferenceName, 
-            final String mailboxPattern,
-            final ImapSession session, 
-            final String tag, ImapCommand command,
-            final Responder responder)
-            throws MailboxException, AuthorizationException, ProtocolException {
-
-        String referenceName = baseReferenceName;
-        // Should the #user.userName section be removed from names returned?
-        final boolean removeUserPrefix;
-
-        final ListResult[] listResults;
-
-        final User user = ImapSessionUtils.getUser(session);
-        final String personalNamespace = ImapConstants.USER_NAMESPACE
-                + ImapConstants.HIERARCHY_DELIMITER_CHAR + user.getUserName();
-
-        if (mailboxPattern.length() == 0) {
-            // An empty mailboxPattern signifies a request for the hierarchy
-            // delimiter
-            // and root name of the referenceName argument
-
-            String referenceRoot;
-            if (referenceName.startsWith(ImapConstants.NAMESPACE_PREFIX)) {
-                // A qualified reference name - get the first element,
-                // and don't remove the user prefix
-                removeUserPrefix = false;
-                int firstDelimiter = referenceName
-                        .indexOf(ImapConstants.HIERARCHY_DELIMITER_CHAR);
-                if (firstDelimiter == -1) {
-                    referenceRoot = referenceName;
-                } else {
-                    referenceRoot = referenceName.substring(0, firstDelimiter);
-                }
-            } else {
-                // A relative reference name - need to remove user prefix from
-                // results.
-                referenceRoot = "";
-                removeUserPrefix = true;
-
-            }
-
-            // Get the mailbox for the reference name.
-            listResults = new ListResult[1];
-            listResults[0] = new ListResultImpl(referenceRoot,
-                    ImapConstants.HIERARCHY_DELIMITER);
-        } else {
-
-            // If the mailboxPattern is fully qualified, ignore the
-            // reference name.
-            if (mailboxPattern.charAt(0) == ImapConstants.NAMESPACE_PREFIX_CHAR) {
-                referenceName = "";
-            }
-
-            // If the search pattern is relative, need to remove user prefix
-            // from results.
-            removeUserPrefix = ((referenceName + mailboxPattern).charAt(0) != ImapConstants.NAMESPACE_PREFIX_CHAR);
-
-            if (removeUserPrefix) {
-                referenceName = personalNamespace + "." + referenceName;
-            }
-
-            listResults = doList(session, referenceName, mailboxPattern);
-        }
-
-        int prefixLength = personalNamespace.length();
-
-        for (int i = 0; i < listResults.length; i++) {
-            final ListResult listResult = listResults[i];
-            processResult(responder, removeUserPrefix, prefixLength, listResult);
-        }   
-        
-        okComplete(command, tag, responder);
-    }
-
-    void processResult(final Responder responder, final boolean removeUserPrefix, 
-            int prefixLength, final ListResult listResult) {
-        final String delimiter = listResult.getHierarchyDelimiter();
-        final String mailboxName = mailboxName(removeUserPrefix, prefixLength, listResult);
-
-        final String[] attrs = listResult.getAttributes();
-        boolean noInferior = false;
-        boolean noSelect = false;
-        boolean marked = false;
-        boolean unmarked = false;
-        if (attrs != null) {
-            final int length = attrs.length;
-            for (int i=0;i<length;i++) {
-                final String attribute = attrs[i];
-                if (ImapConstants.NAME_ATTRIBUTE_NOINFERIORS.equals(attribute)) {
-                    noInferior = true;
-                } else if (ImapConstants.NAME_ATTRIBUTE_NOSELECT.equals(attribute)) {
-                    noSelect = true;
-                    // RFC 3501 does not allow Marked or Unmarked on a NoSelect mailbox
-                    if (marked || unmarked) {
-                        logMarkedUnmarkedNoSelectMailbox(mailboxName);
-                        marked = false;
-                        unmarked = false;
-                    }
-                } else if (ImapConstants.NAME_ATTRIBUTE_MARKED.equals(attribute)) {
-                    if (noSelect) {
-                        // RFC 3501 does not allow NoSelect mailboxes to be Marked
-                        marked = false;
-                        logMarkedUnmarkedNoSelectMailbox(mailboxName);
-                    } else {
-                        marked = true;
-                        if (unmarked) {
-                            // RFC3501 does not allow marked and unmarked to be returned
-                            // When the mailbox has both marked and unmarked set,
-                            // the implementation is free to choose which to return.
-                            // Choose to return marked.
-                            logMarkedUnmarkedMailbox(mailboxName);
-                            unmarked = false;
-                        }
-                    }
-                } else if (ImapConstants.NAME_ATTRIBUTE_UNMARKED.equals(attribute)) {
-                    if (noSelect) {
-                        // RFC 3501 does not allow NoSelect mailboxes to be UnMarked
-                        marked = false;
-                        logMarkedUnmarkedNoSelectMailbox(mailboxName);
-                    } else {
-                        if (marked) {
-                            // RFC3501 does not allow marked and unmarked to be returned
-                            // When the mailbox has both marked and unmarked set,
-                            // the implementation is free to choose which to return.
-                            // Choose to return marked.
-                            logMarkedUnmarkedMailbox(mailboxName);
-                        } else {
-                            unmarked = true;
-                        }
-                    }
-                }
-            }
-        }
-        
-        responder.respond(createResponse(noInferior, noSelect, marked, unmarked, 
-                delimiter, mailboxName));
-    }
-
-    private void logMarkedUnmarkedNoSelectMailbox(final String mailboxName) {
-        final Logger logger = getLogger();
-        if (logger != null && logger.isDebugEnabled()) {
-            logger.debug("Marked or unmarked flags set on NoSelect mailbox: " + mailboxName);
-        }
-    }
-    
-    private void logMarkedUnmarkedMailbox(final String mailboxName) {
-        final Logger logger = getLogger();
-        if (logger != null && logger.isDebugEnabled()) {
-            logger.debug("Marked and unmarked flags set on mailbox: " + mailboxName);
-        }
-    }
-
-    private String mailboxName(final boolean removeUserPrefix, int prefixLength, final ListResult listResult) {
-        final String mailboxName;
-        final String name = listResult.getName();
-        if (removeUserPrefix) {
-            if (name.length() <= prefixLength) {
-                mailboxName = "";
-            } else {
-                mailboxName = name.substring(prefixLength + 1);
-            }
-        } else {
-            mailboxName = name;
-        }
-        return mailboxName;
-    }
-
-    protected abstract ImapResponseMessage createResponse(final boolean noinferior, 
-            final boolean noselect, final boolean marked, final boolean unmarked, 
-            final String hierarchyDelimiter, final String mailboxName);
-   
-    protected final ListResult[] doList(ImapSession session, String base,
-            String pattern) throws MailboxException {
-        try {
-            final MailboxManager mailboxManager = getMailboxManager(session);
-            final ListResult[] result = mailboxManager.list(new MailboxExpression(base,pattern, '*', '%'));
-            return result;
-        } catch (MailboxManagerException e) {
-            throw new MailboxException(e);
-        }
-    }
-}

Added: james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/IMAPSubscriber.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/IMAPSubscriber.java?rev=616502&view=auto
==============================================================================
--- james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/IMAPSubscriber.java (added)
+++ james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/IMAPSubscriber.java Tue Jan 29 11:59:29 2008
@@ -0,0 +1,49 @@
+/****************************************************************
+ * 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.processor.imap4rev1;
+
+import java.util.Collection;
+
+/**
+ * Processes IMAP subscriptions.
+ */
+public interface IMAPSubscriber {
+
+    /**
+     * Subscribes the user to the given mailbox.
+     * @param user the user name, not null
+     * @param mailbox the mailbox name, not null
+     */
+    public void subscribe(String user, String mailbox) throws SubscriptionException;
+    
+    /**
+     * Unsubscribes the user from the given mailbox.
+     * @param user the user name, not null
+     * @param mailbox the mailbox name, not null
+     */
+    public void unsubscribe(String user, String mailbox) throws SubscriptionException;
+    
+    /**
+     * Lists current subscriptions for the given user.
+     * @param user the user name, not null
+     * @return a <code>Collection<String></code> of mailbox names
+     */
+    public Collection subscriptions(String user) throws SubscriptionException;
+}

Modified: james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/Imap4Rev1ProcessorFactory.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/Imap4Rev1ProcessorFactory.java?rev=616502&r1=616501&r2=616502&view=diff
==============================================================================
--- james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/Imap4Rev1ProcessorFactory.java (original)
+++ james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/Imap4Rev1ProcessorFactory.java Tue Jan 29 11:59:29 2008
@@ -32,7 +32,8 @@
     public static final ImapProcessor createDefaultChain(
             final ImapProcessor chainEndProcessor, final UsersRepository users,
             final MailboxManagerProvider mailboxManagerProvider, 
-            final StatusResponseFactory statusResponseFactory) {
+            final StatusResponseFactory statusResponseFactory,
+            final IMAPSubscriber subscriber) {
         
         final LogoutProcessor logoutProcessor = new LogoutProcessor(
                 chainEndProcessor, statusResponseFactory);
@@ -51,9 +52,9 @@
         final CloseProcessor closeProcessor = new CloseProcessor(
                 createProcessor,statusResponseFactory);
         final UnsubscribeProcessor unsubscribeProcessor = new UnsubscribeProcessor(
-                closeProcessor, mailboxManagerProvider, statusResponseFactory);
+                closeProcessor, statusResponseFactory, subscriber);
         final SubscribeProcessor subscribeProcessor = new SubscribeProcessor(
-                unsubscribeProcessor, mailboxManagerProvider, statusResponseFactory);
+                unsubscribeProcessor, statusResponseFactory, subscriber);
         final CopyProcessor copyProcessor = new CopyProcessor(
                 subscribeProcessor, mailboxManagerProvider, statusResponseFactory);
         final AuthenticateProcessor authenticateProcessor = new AuthenticateProcessor(

Modified: james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/LSubProcessor.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/LSubProcessor.java?rev=616502&r1=616501&r2=616502&view=diff
==============================================================================
--- james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/LSubProcessor.java (original)
+++ james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/LSubProcessor.java Tue Jan 29 11:59:29 2008
@@ -19,7 +19,9 @@
 
 package org.apache.james.imapserver.processor.imap4rev1;
 
+import org.apache.avalon.framework.logger.Logger;
 import org.apache.james.api.imap.ImapCommand;
+import org.apache.james.api.imap.ImapConstants;
 import org.apache.james.api.imap.ImapMessage;
 import org.apache.james.api.imap.ProtocolException;
 import org.apache.james.api.imap.message.request.ImapRequest;
@@ -29,15 +31,23 @@
 import org.apache.james.api.imap.process.ImapSession;
 import org.apache.james.imap.message.request.imap4rev1.LsubRequest;
 import org.apache.james.imap.message.response.imap4rev1.server.LSubResponse;
+import org.apache.james.imapserver.processor.base.AbstractMailboxAwareProcessor;
 import org.apache.james.imapserver.processor.base.AuthorizationException;
+import org.apache.james.imapserver.processor.base.ImapSessionUtils;
 import org.apache.james.imapserver.store.MailboxException;
+import org.apache.james.mailboxmanager.ListResult;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+import org.apache.james.mailboxmanager.impl.ListResultImpl;
+import org.apache.james.mailboxmanager.manager.MailboxExpression;
+import org.apache.james.mailboxmanager.manager.MailboxManager;
 import org.apache.james.mailboxmanager.manager.MailboxManagerProvider;
+import org.apache.james.services.User;
 
-public class LSubProcessor extends AbstractListingProcessor {
+public class LSubProcessor extends AbstractMailboxAwareProcessor {
 
     public LSubProcessor(final ImapProcessor next,
             final MailboxManagerProvider mailboxManagerProvider, final StatusResponseFactory factory) {
-        super(next, mailboxManagerProvider, factory, true);
+        super(next, mailboxManagerProvider, factory);
     }
 
     protected boolean isAcceptable(ImapMessage message) {
@@ -56,5 +66,186 @@
 
     protected ImapResponseMessage createResponse(boolean noInferior, boolean noSelect, boolean marked, boolean unmarked, String hierarchyDelimiter, String mailboxName) {
         return new LSubResponse(noInferior, noSelect, marked, unmarked, hierarchyDelimiter, mailboxName);
+    }
+    
+
+    protected final void doProcess(
+            final String baseReferenceName, 
+            final String mailboxPattern,
+            final ImapSession session, 
+            final String tag, ImapCommand command,
+            final Responder responder)
+            throws MailboxException, AuthorizationException, ProtocolException {
+
+        String referenceName = baseReferenceName;
+        // Should the #user.userName section be removed from names returned?
+        final boolean removeUserPrefix;
+
+        final ListResult[] listResults;
+
+        final User user = ImapSessionUtils.getUser(session);
+        final String personalNamespace = ImapConstants.USER_NAMESPACE
+                + ImapConstants.HIERARCHY_DELIMITER_CHAR + user.getUserName();
+
+        if (mailboxPattern.length() == 0) {
+            // An empty mailboxPattern signifies a request for the hierarchy
+            // delimiter
+            // and root name of the referenceName argument
+
+            String referenceRoot;
+            if (referenceName.startsWith(ImapConstants.NAMESPACE_PREFIX)) {
+                // A qualified reference name - get the first element,
+                // and don't remove the user prefix
+                removeUserPrefix = false;
+                int firstDelimiter = referenceName
+                        .indexOf(ImapConstants.HIERARCHY_DELIMITER_CHAR);
+                if (firstDelimiter == -1) {
+                    referenceRoot = referenceName;
+                } else {
+                    referenceRoot = referenceName.substring(0, firstDelimiter);
+                }
+            } else {
+                // A relative reference name - need to remove user prefix from
+                // results.
+                referenceRoot = "";
+                removeUserPrefix = true;
+
+            }
+
+            // Get the mailbox for the reference name.
+            listResults = new ListResult[1];
+            listResults[0] = new ListResultImpl(referenceRoot,
+                    ImapConstants.HIERARCHY_DELIMITER);
+        } else {
+
+            // If the mailboxPattern is fully qualified, ignore the
+            // reference name.
+            if (mailboxPattern.charAt(0) == ImapConstants.NAMESPACE_PREFIX_CHAR) {
+                referenceName = "";
+            }
+
+            // If the search pattern is relative, need to remove user prefix
+            // from results.
+            removeUserPrefix = ((referenceName + mailboxPattern).charAt(0) != ImapConstants.NAMESPACE_PREFIX_CHAR);
+
+            if (removeUserPrefix) {
+                referenceName = personalNamespace + "." + referenceName;
+            }
+
+            listResults = doList(session, referenceName, mailboxPattern);
+        }
+
+        int prefixLength = personalNamespace.length();
+
+        for (int i = 0; i < listResults.length; i++) {
+            final ListResult listResult = listResults[i];
+            processResult(responder, removeUserPrefix, prefixLength, listResult);
+        }   
+        
+        okComplete(command, tag, responder);
+    }
+
+    void processResult(final Responder responder, final boolean removeUserPrefix, 
+            int prefixLength, final ListResult listResult) {
+        final String delimiter = listResult.getHierarchyDelimiter();
+        final String mailboxName = mailboxName(removeUserPrefix, prefixLength, listResult);
+
+        final String[] attrs = listResult.getAttributes();
+        boolean noInferior = false;
+        boolean noSelect = false;
+        boolean marked = false;
+        boolean unmarked = false;
+        if (attrs != null) {
+            final int length = attrs.length;
+            for (int i=0;i<length;i++) {
+                final String attribute = attrs[i];
+                if (ImapConstants.NAME_ATTRIBUTE_NOINFERIORS.equals(attribute)) {
+                    noInferior = true;
+                } else if (ImapConstants.NAME_ATTRIBUTE_NOSELECT.equals(attribute)) {
+                    noSelect = true;
+                    // RFC 3501 does not allow Marked or Unmarked on a NoSelect mailbox
+                    if (marked || unmarked) {
+                        logMarkedUnmarkedNoSelectMailbox(mailboxName);
+                        marked = false;
+                        unmarked = false;
+                    }
+                } else if (ImapConstants.NAME_ATTRIBUTE_MARKED.equals(attribute)) {
+                    if (noSelect) {
+                        // RFC 3501 does not allow NoSelect mailboxes to be Marked
+                        marked = false;
+                        logMarkedUnmarkedNoSelectMailbox(mailboxName);
+                    } else {
+                        marked = true;
+                        if (unmarked) {
+                            // RFC3501 does not allow marked and unmarked to be returned
+                            // When the mailbox has both marked and unmarked set,
+                            // the implementation is free to choose which to return.
+                            // Choose to return marked.
+                            logMarkedUnmarkedMailbox(mailboxName);
+                            unmarked = false;
+                        }
+                    }
+                } else if (ImapConstants.NAME_ATTRIBUTE_UNMARKED.equals(attribute)) {
+                    if (noSelect) {
+                        // RFC 3501 does not allow NoSelect mailboxes to be UnMarked
+                        marked = false;
+                        logMarkedUnmarkedNoSelectMailbox(mailboxName);
+                    } else {
+                        if (marked) {
+                            // RFC3501 does not allow marked and unmarked to be returned
+                            // When the mailbox has both marked and unmarked set,
+                            // the implementation is free to choose which to return.
+                            // Choose to return marked.
+                            logMarkedUnmarkedMailbox(mailboxName);
+                        } else {
+                            unmarked = true;
+                        }
+                    }
+                }
+            }
+        }
+        
+        responder.respond(createResponse(noInferior, noSelect, marked, unmarked, 
+                delimiter, mailboxName));
+    }
+
+    private void logMarkedUnmarkedNoSelectMailbox(final String mailboxName) {
+        final Logger logger = getLogger();
+        if (logger != null && logger.isDebugEnabled()) {
+            logger.debug("Marked or unmarked flags set on NoSelect mailbox: " + mailboxName);
+        }
+    }
+    
+    private void logMarkedUnmarkedMailbox(final String mailboxName) {
+        final Logger logger = getLogger();
+        if (logger != null && logger.isDebugEnabled()) {
+            logger.debug("Marked and unmarked flags set on mailbox: " + mailboxName);
+        }
+    }
+
+    private String mailboxName(final boolean removeUserPrefix, int prefixLength, final ListResult listResult) {
+        final String mailboxName;
+        final String name = listResult.getName();
+        if (removeUserPrefix) {
+            if (name.length() <= prefixLength) {
+                mailboxName = "";
+            } else {
+                mailboxName = name.substring(prefixLength + 1);
+            }
+        } else {
+            mailboxName = name;
+        }
+        return mailboxName;
+    }
+   
+    protected final ListResult[] doList(ImapSession session, String base,
+            String pattern) throws MailboxException {
+        try {
+            final MailboxManager mailboxManager = getMailboxManager(session);
+            final ListResult[] result = mailboxManager.list(new MailboxExpression(base,pattern, '*', '%'));
+            return result;
+        } catch (MailboxManagerException e) {
+            throw new MailboxException(e);
+        }
     }
 }

Modified: james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/ListProcessor.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/ListProcessor.java?rev=616502&r1=616501&r2=616502&view=diff
==============================================================================
--- james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/ListProcessor.java (original)
+++ james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/ListProcessor.java Tue Jan 29 11:59:29 2008
@@ -19,7 +19,9 @@
 
 package org.apache.james.imapserver.processor.imap4rev1;
 
+import org.apache.avalon.framework.logger.Logger;
 import org.apache.james.api.imap.ImapCommand;
+import org.apache.james.api.imap.ImapConstants;
 import org.apache.james.api.imap.ImapMessage;
 import org.apache.james.api.imap.ProtocolException;
 import org.apache.james.api.imap.message.request.ImapRequest;
@@ -29,15 +31,23 @@
 import org.apache.james.api.imap.process.ImapSession;
 import org.apache.james.imap.message.request.imap4rev1.ListRequest;
 import org.apache.james.imap.message.response.imap4rev1.server.ListResponse;
+import org.apache.james.imapserver.processor.base.AbstractMailboxAwareProcessor;
 import org.apache.james.imapserver.processor.base.AuthorizationException;
+import org.apache.james.imapserver.processor.base.ImapSessionUtils;
 import org.apache.james.imapserver.store.MailboxException;
+import org.apache.james.mailboxmanager.ListResult;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+import org.apache.james.mailboxmanager.impl.ListResultImpl;
+import org.apache.james.mailboxmanager.manager.MailboxExpression;
+import org.apache.james.mailboxmanager.manager.MailboxManager;
 import org.apache.james.mailboxmanager.manager.MailboxManagerProvider;
+import org.apache.james.services.User;
 
-public class ListProcessor extends AbstractListingProcessor {
+public class ListProcessor extends AbstractMailboxAwareProcessor {
 
     public ListProcessor(final ImapProcessor next,
             final MailboxManagerProvider mailboxManagerProvider, final StatusResponseFactory factory) {
-        super(next, mailboxManagerProvider, factory, false);
+        super(next, mailboxManagerProvider, factory);
     }
 
     protected boolean isAcceptable(ImapMessage message) {
@@ -57,5 +67,186 @@
 
     protected ImapResponseMessage createResponse(boolean noInferior, boolean noSelect, boolean marked, boolean unmarked, String hierarchyDelimiter, String mailboxName) {
         return new ListResponse(noInferior, noSelect, marked, unmarked, hierarchyDelimiter, mailboxName);
+    }
+    
+
+    protected final void doProcess(
+            final String baseReferenceName, 
+            final String mailboxPattern,
+            final ImapSession session, 
+            final String tag, ImapCommand command,
+            final Responder responder)
+            throws MailboxException, AuthorizationException, ProtocolException {
+
+        String referenceName = baseReferenceName;
+        // Should the #user.userName section be removed from names returned?
+        final boolean removeUserPrefix;
+
+        final ListResult[] listResults;
+
+        final User user = ImapSessionUtils.getUser(session);
+        final String personalNamespace = ImapConstants.USER_NAMESPACE
+                + ImapConstants.HIERARCHY_DELIMITER_CHAR + user.getUserName();
+
+        if (mailboxPattern.length() == 0) {
+            // An empty mailboxPattern signifies a request for the hierarchy
+            // delimiter
+            // and root name of the referenceName argument
+
+            String referenceRoot;
+            if (referenceName.startsWith(ImapConstants.NAMESPACE_PREFIX)) {
+                // A qualified reference name - get the first element,
+                // and don't remove the user prefix
+                removeUserPrefix = false;
+                int firstDelimiter = referenceName
+                        .indexOf(ImapConstants.HIERARCHY_DELIMITER_CHAR);
+                if (firstDelimiter == -1) {
+                    referenceRoot = referenceName;
+                } else {
+                    referenceRoot = referenceName.substring(0, firstDelimiter);
+                }
+            } else {
+                // A relative reference name - need to remove user prefix from
+                // results.
+                referenceRoot = "";
+                removeUserPrefix = true;
+
+            }
+
+            // Get the mailbox for the reference name.
+            listResults = new ListResult[1];
+            listResults[0] = new ListResultImpl(referenceRoot,
+                    ImapConstants.HIERARCHY_DELIMITER);
+        } else {
+
+            // If the mailboxPattern is fully qualified, ignore the
+            // reference name.
+            if (mailboxPattern.charAt(0) == ImapConstants.NAMESPACE_PREFIX_CHAR) {
+                referenceName = "";
+            }
+
+            // If the search pattern is relative, need to remove user prefix
+            // from results.
+            removeUserPrefix = ((referenceName + mailboxPattern).charAt(0) != ImapConstants.NAMESPACE_PREFIX_CHAR);
+
+            if (removeUserPrefix) {
+                referenceName = personalNamespace + "." + referenceName;
+            }
+
+            listResults = doList(session, referenceName, mailboxPattern);
+        }
+
+        int prefixLength = personalNamespace.length();
+
+        for (int i = 0; i < listResults.length; i++) {
+            final ListResult listResult = listResults[i];
+            processResult(responder, removeUserPrefix, prefixLength, listResult);
+        }   
+        
+        okComplete(command, tag, responder);
+    }
+
+    void processResult(final Responder responder, final boolean removeUserPrefix, 
+            int prefixLength, final ListResult listResult) {
+        final String delimiter = listResult.getHierarchyDelimiter();
+        final String mailboxName = mailboxName(removeUserPrefix, prefixLength, listResult);
+
+        final String[] attrs = listResult.getAttributes();
+        boolean noInferior = false;
+        boolean noSelect = false;
+        boolean marked = false;
+        boolean unmarked = false;
+        if (attrs != null) {
+            final int length = attrs.length;
+            for (int i=0;i<length;i++) {
+                final String attribute = attrs[i];
+                if (ImapConstants.NAME_ATTRIBUTE_NOINFERIORS.equals(attribute)) {
+                    noInferior = true;
+                } else if (ImapConstants.NAME_ATTRIBUTE_NOSELECT.equals(attribute)) {
+                    noSelect = true;
+                    // RFC 3501 does not allow Marked or Unmarked on a NoSelect mailbox
+                    if (marked || unmarked) {
+                        logMarkedUnmarkedNoSelectMailbox(mailboxName);
+                        marked = false;
+                        unmarked = false;
+                    }
+                } else if (ImapConstants.NAME_ATTRIBUTE_MARKED.equals(attribute)) {
+                    if (noSelect) {
+                        // RFC 3501 does not allow NoSelect mailboxes to be Marked
+                        marked = false;
+                        logMarkedUnmarkedNoSelectMailbox(mailboxName);
+                    } else {
+                        marked = true;
+                        if (unmarked) {
+                            // RFC3501 does not allow marked and unmarked to be returned
+                            // When the mailbox has both marked and unmarked set,
+                            // the implementation is free to choose which to return.
+                            // Choose to return marked.
+                            logMarkedUnmarkedMailbox(mailboxName);
+                            unmarked = false;
+                        }
+                    }
+                } else if (ImapConstants.NAME_ATTRIBUTE_UNMARKED.equals(attribute)) {
+                    if (noSelect) {
+                        // RFC 3501 does not allow NoSelect mailboxes to be UnMarked
+                        marked = false;
+                        logMarkedUnmarkedNoSelectMailbox(mailboxName);
+                    } else {
+                        if (marked) {
+                            // RFC3501 does not allow marked and unmarked to be returned
+                            // When the mailbox has both marked and unmarked set,
+                            // the implementation is free to choose which to return.
+                            // Choose to return marked.
+                            logMarkedUnmarkedMailbox(mailboxName);
+                        } else {
+                            unmarked = true;
+                        }
+                    }
+                }
+            }
+        }
+        
+        responder.respond(createResponse(noInferior, noSelect, marked, unmarked, 
+                delimiter, mailboxName));
+    }
+
+    private void logMarkedUnmarkedNoSelectMailbox(final String mailboxName) {
+        final Logger logger = getLogger();
+        if (logger != null && logger.isDebugEnabled()) {
+            logger.debug("Marked or unmarked flags set on NoSelect mailbox: " + mailboxName);
+        }
+    }
+    
+    private void logMarkedUnmarkedMailbox(final String mailboxName) {
+        final Logger logger = getLogger();
+        if (logger != null && logger.isDebugEnabled()) {
+            logger.debug("Marked and unmarked flags set on mailbox: " + mailboxName);
+        }
+    }
+
+    private String mailboxName(final boolean removeUserPrefix, int prefixLength, final ListResult listResult) {
+        final String mailboxName;
+        final String name = listResult.getName();
+        if (removeUserPrefix) {
+            if (name.length() <= prefixLength) {
+                mailboxName = "";
+            } else {
+                mailboxName = name.substring(prefixLength + 1);
+            }
+        } else {
+            mailboxName = name;
+        }
+        return mailboxName;
+    }
+   
+    protected final ListResult[] doList(ImapSession session, String base,
+            String pattern) throws MailboxException {
+        try {
+            final MailboxManager mailboxManager = getMailboxManager(session);
+            final ListResult[] result = mailboxManager.list(new MailboxExpression(base,pattern, '*', '%'));
+            return result;
+        } catch (MailboxManagerException e) {
+            throw new MailboxException(e);
+        }
     }
 }

Modified: james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SubscribeProcessor.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SubscribeProcessor.java?rev=616502&r1=616501&r2=616502&view=diff
==============================================================================
--- james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SubscribeProcessor.java (original)
+++ james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SubscribeProcessor.java Tue Jan 29 11:59:29 2008
@@ -21,24 +21,24 @@
 
 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.message.request.ImapRequest;
 import org.apache.james.api.imap.message.response.imap4rev1.StatusResponseFactory;
 import org.apache.james.api.imap.process.ImapProcessor;
 import org.apache.james.api.imap.process.ImapSession;
 import org.apache.james.imap.message.request.imap4rev1.SubscribeRequest;
-import org.apache.james.imapserver.processor.base.AbstractMailboxAwareProcessor;
-import org.apache.james.imapserver.processor.base.AuthorizationException;
-import org.apache.james.imapserver.store.MailboxException;
-import org.apache.james.mailboxmanager.MailboxManagerException;
-import org.apache.james.mailboxmanager.manager.MailboxManager;
-import org.apache.james.mailboxmanager.manager.MailboxManagerProvider;
+import org.apache.james.imapserver.processor.base.AbstractImapRequestProcessor;
+import org.apache.james.imapserver.processor.base.ImapSessionUtils;
+import org.apache.james.services.User;
 
-public class SubscribeProcessor extends AbstractMailboxAwareProcessor {
+public class SubscribeProcessor extends AbstractImapRequestProcessor {
 
+    private final IMAPSubscriber subscriber;
+    
     public SubscribeProcessor(final ImapProcessor next,
-            final MailboxManagerProvider mailboxManagerProvider, final StatusResponseFactory factory) {
-        super(next, mailboxManagerProvider, factory);
+            final StatusResponseFactory factory, final IMAPSubscriber subscriber) {
+        super(next, factory);
+        this.subscriber = subscriber;
     }
 
     protected boolean isAcceptable(ImapMessage message) {
@@ -46,18 +46,29 @@
     }
 
     protected void doProcess(ImapRequest message,
-            ImapSession session, String tag, ImapCommand command, Responder responder)
-            throws MailboxException, AuthorizationException, ProtocolException {
+            ImapSession session, String tag, ImapCommand command, Responder responder) {
         final SubscribeRequest request = (SubscribeRequest) message;
         final String mailboxName = request.getMailboxName();
+        final User user = ImapSessionUtils.getUser(session);
+        final String userName = user.getUserName();
         try {
-            final String fullMailboxName = buildFullName(session, mailboxName);
-            final MailboxManager mailboxManager = getMailboxManager(session);
-            mailboxManager.setSubscription(fullMailboxName, true);
-        } catch (MailboxManagerException e) {
-            throw new MailboxException(e);
+            subscriber.subscribe(userName, mailboxName);
+            
+            unsolicitedResponses(session, responder, false);
+            okComplete(command, tag, responder);
+            
+        } catch (SubscriptionException e) {
+            getLogger().debug("Subscription failed", e);
+            unsolicitedResponses(session, responder, false);
+            
+            final HumanReadableTextKey exceptionKey = e.getKey();
+            final HumanReadableTextKey displayTextKey;
+            if (exceptionKey == null) {
+                displayTextKey = HumanReadableTextKey.GENERIC_SUBSCRIPTION_FAILURE;
+            } else {
+                displayTextKey = exceptionKey;
+            }
+            no(command, tag, responder, displayTextKey);
         }
-        okComplete(command, tag, responder);
-        unsolicitedResponses(session, responder, false);
     }
 }

Added: james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SubscriptionException.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SubscriptionException.java?rev=616502&view=auto
==============================================================================
--- james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SubscriptionException.java (added)
+++ james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SubscriptionException.java Tue Jan 29 11:59:29 2008
@@ -0,0 +1,57 @@
+/****************************************************************
+ * 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.processor.imap4rev1;
+
+import org.apache.james.api.imap.display.HumanReadableTextKey;
+
+/**
+ * Indicates exception during subscription processing.
+ */
+public class SubscriptionException extends Exception {
+
+    private static final long serialVersionUID = -2057022968413471837L;
+
+    private final HumanReadableTextKey key;
+    
+    public SubscriptionException(HumanReadableTextKey key, Throwable cause) {
+        super(key.toString(), cause);
+        this.key = key;
+    }
+
+    public SubscriptionException(HumanReadableTextKey key) {
+        super(key.toString());
+        this.key = key;
+    }
+
+    public SubscriptionException(Throwable cause) {
+        super(cause);
+        key = null;
+    }
+
+    /**
+     * Gets the message key.
+     * @return the key, possibly null
+     */
+    public final HumanReadableTextKey getKey() {
+        return key;
+    }
+    
+    
+}

Modified: james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/UnsubscribeProcessor.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/UnsubscribeProcessor.java?rev=616502&r1=616501&r2=616502&view=diff
==============================================================================
--- james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/UnsubscribeProcessor.java (original)
+++ james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/UnsubscribeProcessor.java Tue Jan 29 11:59:29 2008
@@ -22,23 +22,26 @@
 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.message.request.ImapRequest;
 import org.apache.james.api.imap.message.response.imap4rev1.StatusResponseFactory;
 import org.apache.james.api.imap.process.ImapProcessor;
 import org.apache.james.api.imap.process.ImapSession;
 import org.apache.james.imap.message.request.imap4rev1.UnsubscribeRequest;
-import org.apache.james.imapserver.processor.base.AbstractMailboxAwareProcessor;
+import org.apache.james.imapserver.processor.base.AbstractImapRequestProcessor;
 import org.apache.james.imapserver.processor.base.AuthorizationException;
+import org.apache.james.imapserver.processor.base.ImapSessionUtils;
 import org.apache.james.imapserver.store.MailboxException;
-import org.apache.james.mailboxmanager.MailboxManagerException;
-import org.apache.james.mailboxmanager.manager.MailboxManager;
-import org.apache.james.mailboxmanager.manager.MailboxManagerProvider;
+import org.apache.james.services.User;
 
-public class UnsubscribeProcessor extends AbstractMailboxAwareProcessor {
+public class UnsubscribeProcessor extends AbstractImapRequestProcessor {
 
-    public UnsubscribeProcessor(final ImapProcessor next,
-            final MailboxManagerProvider mailboxManagerProvider, final StatusResponseFactory factory) {
-        super(next, mailboxManagerProvider, factory);
+    private final IMAPSubscriber subscriber;
+    
+    public UnsubscribeProcessor(final ImapProcessor next, final StatusResponseFactory factory,
+            final IMAPSubscriber subscriber) {
+        super(next, factory);
+        this.subscriber = subscriber;
     }
 
     protected boolean isAcceptable(ImapMessage message) {
@@ -50,14 +53,26 @@
             throws MailboxException, AuthorizationException, ProtocolException {
         final UnsubscribeRequest request = (UnsubscribeRequest) message;
         final String mailboxName = request.getMailboxName();
+        final User user = ImapSessionUtils.getUser(session);
+        final String userName = user.getUserName();
         try {
-            final String fullMailboxName = buildFullName(session, mailboxName);
-            final MailboxManager mailboxManager = getMailboxManager(session);
-            mailboxManager.setSubscription(fullMailboxName, false);
-        } catch (MailboxManagerException e) {
-            throw new MailboxException(e);
+            subscriber.subscribe(userName, mailboxName);
+            
+            unsolicitedResponses(session, responder, false);
+            okComplete(command, tag, responder);
+            
+        } catch (SubscriptionException e) {
+            getLogger().debug("Subscription failed", e);
+            unsolicitedResponses(session, responder, false);
+            
+            final HumanReadableTextKey exceptionKey = e.getKey();
+            final HumanReadableTextKey displayTextKey;
+            if (exceptionKey == null) {
+                displayTextKey = HumanReadableTextKey.GENERIC_UNSUBSCRIPTION_FAILURE;
+            } else {
+                displayTextKey = exceptionKey;
+            }
+            no(command, tag, responder, displayTextKey);
         }
-        okComplete(command, tag, responder);
-        unsolicitedResponses(session, responder, false);
     }
 }

Added: james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/UserMetaDataIMAPSubscriber.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/UserMetaDataIMAPSubscriber.java?rev=616502&view=auto
==============================================================================
--- james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/UserMetaDataIMAPSubscriber.java (added)
+++ james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/UserMetaDataIMAPSubscriber.java Tue Jan 29 11:59:29 2008
@@ -0,0 +1,145 @@
+/****************************************************************
+ * 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.processor.imap4rev1;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.james.api.user.UserMetaDataRespository;
+import org.apache.james.api.user.UserRepositoryException;
+
+/**
+ * Stores subscription data in the user meta-data repository.
+ */
+public class UserMetaDataIMAPSubscriber implements IMAPSubscriber {
+
+    public static final String META_DATA_KEY
+        ="org.apache.james.imapserver.processor.imap4rev1.SUBSCRIPTIONS";
+    
+    private Log log = LogFactory.getLog(UserMetaDataIMAPSubscriber.class);
+    
+    private final UserMetaDataRespository repository;
+    private final Map userSubscriptionsByUser;
+    
+    public UserMetaDataIMAPSubscriber(final UserMetaDataRespository repository) {
+        super();
+        this.repository = repository;
+        userSubscriptionsByUser = new HashMap();
+    }
+
+    public void subscribe(String user, String mailbox)
+            throws SubscriptionException {
+        try {
+            final UserSubscription subscription = getUserSubscription(user);
+            subscription.subscribe(mailbox);
+        } catch (UserRepositoryException e) {
+            throw new SubscriptionException(e);
+        }
+    }
+
+    public Collection subscriptions(String user) throws SubscriptionException {
+        try {
+            final UserSubscription subscription = getUserSubscription(user);
+            final Collection results = (Collection) subscription.subscriptions().clone();
+            return results;
+        } catch (UserRepositoryException e) {
+            throw new SubscriptionException(e);
+        }
+    }
+
+    public void unsubscribe(String user, String mailbox) throws SubscriptionException {
+        try {
+            final UserSubscription subscription = getUserSubscription(user);
+            subscription.unsubscribe(mailbox);   
+        } catch (UserRepositoryException e) {
+            throw new SubscriptionException(e);
+        }
+    }
+    
+    private synchronized UserSubscription getUserSubscription(final String user) {
+        UserSubscription subscription = (UserSubscription) userSubscriptionsByUser.get(user);
+        if (subscription == null) {
+            subscription = new UserSubscription(user, repository, log);
+        }
+        return subscription;
+    }
+    
+    /**
+     * Manages subscriptions for a user.
+     * Subscriptions are stored in a single collection.
+     * This class synchronizes access for write operations.
+     */
+    private static final class UserSubscription {
+        
+        private final String user;
+        private final UserMetaDataRespository repository;
+        private Log log;
+        
+        public UserSubscription(final String user, final UserMetaDataRespository repository,
+                Log log) {
+            super();
+            this.user = user;
+            this.repository = repository;
+        }
+
+        public synchronized void subscribe(String mailbox) throws UserRepositoryException {
+            final HashSet existingSubscriptions = subscriptions();
+            if (!existingSubscriptions.contains(mailbox)) {
+                final HashSet newSubscriptions;
+                if (existingSubscriptions == null) {
+                    newSubscriptions = new HashSet();
+                } else {
+                    existingSubscriptions.add(mailbox);
+                    newSubscriptions = existingSubscriptions;
+                }
+                repository.setAttribute(user, newSubscriptions, META_DATA_KEY);
+            }
+        }
+        
+        public synchronized void unsubscribe(String mailbox) throws UserRepositoryException {
+            final HashSet subscriptions = subscriptions();
+            if (subscriptions.remove(mailbox)) {
+                repository.setAttribute(user, subscriptions, META_DATA_KEY);
+            }
+        }
+        
+        public HashSet subscriptions() throws UserRepositoryException {
+            try {
+                final HashSet storedSubscriptions = (HashSet) repository.getAttribute(user, META_DATA_KEY);
+                final HashSet results;
+                if (storedSubscriptions == null) {
+                    results = new HashSet();
+                } else {
+                    results = storedSubscriptions;
+                }
+                return results;
+            } catch (ClassCastException e) {
+                log.error("ClassCastException during retrieval. Reseting subscriptions for user " + user);
+                log.debug("HashSet expected but not retrieved.", e);
+                return new HashSet();
+            }
+            
+        }
+    }
+}

Modified: james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/main/DefaultImapProcessorFactory.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/main/DefaultImapProcessorFactory.java?rev=616502&r1=616501&r2=616502&view=diff
==============================================================================
--- james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/main/DefaultImapProcessorFactory.java (original)
+++ james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/main/DefaultImapProcessorFactory.java Tue Jan 29 11:59:29 2008
@@ -22,10 +22,13 @@
 import org.apache.james.api.imap.message.response.imap4rev1.StatusResponseFactory;
 import org.apache.james.api.imap.process.ImapProcessor;
 import org.apache.james.api.imap.process.ImapProcessorFactory;
+import org.apache.james.api.user.UserMetaDataRespository;
 import org.apache.james.imap.message.response.imap4rev1.status.UnpooledStatusResponseFactory;
 import org.apache.james.imapserver.processor.base.ImapResponseMessageProcessor;
 import org.apache.james.imapserver.processor.base.UnknownRequestImapProcessor;
+import org.apache.james.imapserver.processor.imap4rev1.IMAPSubscriber;
 import org.apache.james.imapserver.processor.imap4rev1.Imap4Rev1ProcessorFactory;
+import org.apache.james.imapserver.processor.imap4rev1.UserMetaDataIMAPSubscriber;
 import org.apache.james.mailboxmanager.manager.MailboxManagerProvider;
 import org.apache.james.services.UsersRepository;
 
@@ -35,19 +38,22 @@
 public class DefaultImapProcessorFactory implements ImapProcessorFactory {
 
     public static final ImapProcessor createDefaultProcessor(final UsersRepository usersRepository,
-            final MailboxManagerProvider mailboxManagerProvider) {
+            final MailboxManagerProvider mailboxManagerProvider, final UserMetaDataRespository userMetaDataRepository) {
         final StatusResponseFactory statusResponseFactory = new UnpooledStatusResponseFactory();
         final UnknownRequestImapProcessor unknownRequestImapProcessor = new UnknownRequestImapProcessor();
+        final IMAPSubscriber subscriber = new UserMetaDataIMAPSubscriber(userMetaDataRepository);
         final ImapProcessor imap4rev1Chain = Imap4Rev1ProcessorFactory.createDefaultChain(unknownRequestImapProcessor, 
-                usersRepository, mailboxManagerProvider, statusResponseFactory);
+                usersRepository, mailboxManagerProvider, statusResponseFactory, subscriber);
         final ImapProcessor result = new ImapResponseMessageProcessor(imap4rev1Chain);
         return result;
     }
     
     private UsersRepository usersRepository;
     private MailboxManagerProvider mailboxManagerProvider;
+    private UserMetaDataRespository userMetaDataRepository;
     
-    public final void configure(UsersRepository usersRepository, MailboxManagerProvider mailboxManagerProvider) {
+    public final void configure(UsersRepository usersRepository, MailboxManagerProvider mailboxManagerProvider, 
+            UserMetaDataRespository userMetaDataRepository) {
         setUsersRepository(usersRepository);
         setMailboxManagerProvider(mailboxManagerProvider);
     }
@@ -68,8 +74,17 @@
     public final void setUsersRepository(UsersRepository usersRepository) {
         this.usersRepository = usersRepository;
     }
+    
+    public final UserMetaDataRespository getUserMetaDataRepository() {
+        return userMetaDataRepository;
+    }
+
+    public final void setUserMetaDataRepository(
+            UserMetaDataRespository userMetaDataRepository) {
+        this.userMetaDataRepository = userMetaDataRepository;
+    }
 
     public ImapProcessor buildImapProcessor() {
-        return createDefaultProcessor(usersRepository, mailboxManagerProvider);
+        return createDefaultProcessor(usersRepository, mailboxManagerProvider, userMetaDataRepository);
     }
 }

Modified: james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/AbstractTestListProcessor.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/AbstractTestListProcessor.java?rev=616502&r1=616501&r2=616502&view=diff
==============================================================================
--- james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/AbstractTestListProcessor.java (original)
+++ james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/AbstractTestListProcessor.java Tue Jan 29 11:59:29 2008
@@ -1,163 +0,0 @@
-/****************************************************************
- * 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.processor.imap4rev1;
-
-import org.apache.james.api.imap.ImapCommand;
-import org.apache.james.api.imap.ImapConstants;
-import org.apache.james.api.imap.message.response.imap4rev1.StatusResponseFactory;
-import org.apache.james.api.imap.process.ImapProcessor;
-import org.apache.james.api.imap.process.ImapSession;
-import org.apache.james.imap.message.response.imap4rev1.server.AbstractListingResponse;
-import org.apache.james.mailboxmanager.ListResult;
-import org.apache.james.mailboxmanager.manager.MailboxManagerProvider;
-import org.jmock.Mock;
-import org.jmock.MockObjectTestCase;
-
-public abstract class AbstractTestListProcessor extends MockObjectTestCase {
-
-    AbstractListingProcessor processor;
-    Mock next;
-    Mock provider;
-    Mock responder;
-    Mock result;
-    Mock session;
-    Mock command;
-    Mock serverResponseFactory;
-    
-    protected void setUp() throws Exception {
-        super.setUp();
-        serverResponseFactory = mock(StatusResponseFactory.class);
-        session = mock(ImapSession.class);
-        command = mock(ImapCommand.class);
-        next = mock(ImapProcessor.class);
-        responder = mock(ImapProcessor.Responder.class);
-        result = mock(ListResult.class);
-        provider = mock(MailboxManagerProvider.class);
-        processor = createProcessor((ImapProcessor) next.proxy(), 
-                (MailboxManagerProvider) provider.proxy(), (StatusResponseFactory) serverResponseFactory.proxy());
-    }
-
-    protected void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    abstract AbstractListingProcessor createProcessor(ImapProcessor next,
-            MailboxManagerProvider provider, StatusResponseFactory factory);
-    
-    abstract AbstractListingResponse createResponse(final boolean noinferior, 
-            final boolean noselect, final boolean marked, final boolean unmarked, 
-            final String hierarchyDelimiter, final String mailboxName);
-    
-    void setUpResult(String[] attributes, String hierarchyDelimiter, String name) {
-        result.expects(once()).method("getAttributes").will(returnValue(attributes));
-        result.expects(once()).method("getHierarchyDelimiter").will(returnValue(hierarchyDelimiter));
-        result.expects(once()).method("getName").will(returnValue(name));
-    }
-    
-    public void testNoInferiors() throws Exception {
-        String[] attributes = {"\\noise", ImapConstants.NAME_ATTRIBUTE_NOINFERIORS, "\\bogus"};
-        setUpResult(attributes, ".", "#INBOX");
-        responder.expects(once()).method("respond").with(
-                eq(createResponse(true, false, false, false, ".", "#INBOX")));
-        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
-                false, 0, (ListResult) result.proxy());
-    }
-    
-    public void testNoSelect() throws Exception {
-        String[] attributes = {"\\noise", ImapConstants.NAME_ATTRIBUTE_NOSELECT, "\\bogus"};
-        setUpResult(attributes, ".", "#INBOX");
-        responder.expects(once()).method("respond").with(
-                eq(createResponse(false, true, false, false, ".", "#INBOX")));
-        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
-                false, 0, (ListResult) result.proxy());
-    }
-    
-    public void testUnMarked() throws Exception {
-        String[] attributes = {"\\noise", ImapConstants.NAME_ATTRIBUTE_UNMARKED, "\\bogus"};
-        setUpResult(attributes, ".", "#INBOX");
-        responder.expects(once()).method("respond").with(
-                eq(createResponse(false, false, false, true, ".", "#INBOX")));
-        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
-                false, 0, (ListResult) result.proxy());
-    }
-    
-    public void testMarked() throws Exception {
-        String[] attributes = {"\\noise", ImapConstants.NAME_ATTRIBUTE_MARKED, "\\bogus"};
-        setUpResult(attributes, ".", "#INBOX");
-        responder.expects(once()).method("respond").with(
-                eq(createResponse(false, false, true, false, ".", "#INBOX")));
-        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
-                false, 0, (ListResult) result.proxy());
-    }
-    
-    public void testMarkedAndUnmarked() throws Exception {
-        String[] attributes = {"\\noise", ImapConstants.NAME_ATTRIBUTE_MARKED, ImapConstants.NAME_ATTRIBUTE_UNMARKED, "\\bogus"};
-        setUpResult(attributes, ".", "#INBOX");
-        responder.expects(once()).method("respond").with(
-                eq(createResponse(false, false, true, false, ".", "#INBOX")));
-        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
-                false, 0, (ListResult) result.proxy());
-    }
-    
-    public void testUnmarkedAndMarked() throws Exception {
-        String[] attributes = {"\\noise", ImapConstants.NAME_ATTRIBUTE_UNMARKED, ImapConstants.NAME_ATTRIBUTE_MARKED, "\\bogus"};
-        setUpResult(attributes, ".", "#INBOX");
-        responder.expects(once()).method("respond").with(
-                eq(createResponse(false, false, true, false, ".", "#INBOX")));
-        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
-                false, 0, (ListResult) result.proxy());
-    }
-    
-    public void testNoSelectUnmarkedAndMarked() throws Exception {
-        String[] attributes = {"\\noise", ImapConstants.NAME_ATTRIBUTE_NOSELECT, ImapConstants.NAME_ATTRIBUTE_UNMARKED, ImapConstants.NAME_ATTRIBUTE_MARKED, "\\bogus"};
-        setUpResult(attributes, ".", "#INBOX");
-        responder.expects(once()).method("respond").with(
-                eq(createResponse(false, true, false, false, ".", "#INBOX")));
-        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
-                false, 0, (ListResult) result.proxy());
-    }
-    
-    public void testUnmarkedAndMarkedNoSelect() throws Exception {
-        String[] attributes = {"\\noise",  ImapConstants.NAME_ATTRIBUTE_UNMARKED, ImapConstants.NAME_ATTRIBUTE_MARKED, ImapConstants.NAME_ATTRIBUTE_NOSELECT, "\\bogus"};
-        setUpResult(attributes, ".", "#INBOX");
-        responder.expects(once()).method("respond").with(
-                eq(createResponse(false, true, false, false, ".", "#INBOX")));
-        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
-                false, 0, (ListResult) result.proxy());
-    }
-    
-    public void testUnmarkedNoSelectAndMarked() throws Exception {
-        String[] attributes = {"\\noise",  ImapConstants.NAME_ATTRIBUTE_UNMARKED, ImapConstants.NAME_ATTRIBUTE_NOSELECT, ImapConstants.NAME_ATTRIBUTE_MARKED, "\\bogus"};
-        setUpResult(attributes, ".", "#INBOX");
-        responder.expects(once()).method("respond").with(
-                eq(createResponse(false, true, false, false, ".", "#INBOX")));
-        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
-                false, 0, (ListResult) result.proxy());
-    }
-    
-    public void testNoinferiorsUnmarkedNoSelectAndMarked() throws Exception {
-        String[] attributes = {"\\noise",  ImapConstants.NAME_ATTRIBUTE_NOINFERIORS, ImapConstants.NAME_ATTRIBUTE_UNMARKED, ImapConstants.NAME_ATTRIBUTE_NOSELECT, ImapConstants.NAME_ATTRIBUTE_MARKED, "\\bogus"};
-        setUpResult(attributes, ".", "#INBOX");
-        responder.expects(once()).method("respond").with(
-                eq(createResponse(true, true, false, false, ".", "#INBOX")));
-        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
-                false, 0, (ListResult) result.proxy());
-    }
-}

Modified: james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/LSubProcessorTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/LSubProcessorTest.java?rev=616502&r1=616501&r2=616502&view=diff
==============================================================================
--- james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/LSubProcessorTest.java (original)
+++ james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/LSubProcessorTest.java Tue Jan 29 11:59:29 2008
@@ -19,29 +19,147 @@
 
 package org.apache.james.imapserver.processor.imap4rev1;
 
+import org.apache.james.api.imap.ImapCommand;
+import org.apache.james.api.imap.ImapConstants;
 import org.apache.james.api.imap.message.response.imap4rev1.StatusResponseFactory;
 import org.apache.james.api.imap.process.ImapProcessor;
-import org.apache.james.imap.message.response.imap4rev1.server.AbstractListingResponse;
+import org.apache.james.api.imap.process.ImapSession;
 import org.apache.james.imap.message.response.imap4rev1.server.LSubResponse;
+import org.apache.james.mailboxmanager.ListResult;
 import org.apache.james.mailboxmanager.manager.MailboxManagerProvider;
+import org.jmock.Mock;
+import org.jmock.MockObjectTestCase;
 
-public class LSubProcessorTest extends AbstractTestListProcessor {
+public class LSubProcessorTest extends MockObjectTestCase {
 
+
+    LSubProcessor processor;
+    Mock next;
+    Mock provider;
+    Mock responder;
+    Mock result;
+    Mock session;
+    Mock command;
+    Mock serverResponseFactory;
+    
     protected void setUp() throws Exception {
-        super.setUp();
+        serverResponseFactory = mock(StatusResponseFactory.class);
+        session = mock(ImapSession.class);
+        command = mock(ImapCommand.class);
+        next = mock(ImapProcessor.class);
+        responder = mock(ImapProcessor.Responder.class);
+        result = mock(ListResult.class);
+        provider = mock(MailboxManagerProvider.class);
+        processor = createProcessor((ImapProcessor) next.proxy(), 
+                (MailboxManagerProvider) provider.proxy(), (StatusResponseFactory) serverResponseFactory.proxy());
     }
 
     protected void tearDown() throws Exception {
         super.tearDown();
     }
 
-    AbstractListingProcessor createProcessor(ImapProcessor next, MailboxManagerProvider provider, StatusResponseFactory factory) {
+    LSubProcessor createProcessor(ImapProcessor next, MailboxManagerProvider provider, StatusResponseFactory factory) {
         return new LSubProcessor(next, provider, factory);
     }
 
-    AbstractListingResponse createResponse(boolean noinferior, boolean noselect, boolean marked, 
+    LSubResponse createResponse(boolean noinferior, boolean noselect, boolean marked, 
             boolean unmarked, String hierarchyDelimiter, String mailboxName) {
         return new LSubResponse(noinferior, noselect, marked, unmarked, hierarchyDelimiter, mailboxName);
     }
 
+    void setUpResult(String[] attributes, String hierarchyDelimiter, String name) {
+        result.expects(once()).method("getAttributes").will(returnValue(attributes));
+        result.expects(once()).method("getHierarchyDelimiter").will(returnValue(hierarchyDelimiter));
+        result.expects(once()).method("getName").will(returnValue(name));
+    }
+    
+    public void testNoInferiors() throws Exception {
+        String[] attributes = {"\\noise", ImapConstants.NAME_ATTRIBUTE_NOINFERIORS, "\\bogus"};
+        setUpResult(attributes, ".", "#INBOX");
+        responder.expects(once()).method("respond").with(
+                eq(createResponse(true, false, false, false, ".", "#INBOX")));
+        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
+                false, 0, (ListResult) result.proxy());
+    }
+    
+    public void testNoSelect() throws Exception {
+        String[] attributes = {"\\noise", ImapConstants.NAME_ATTRIBUTE_NOSELECT, "\\bogus"};
+        setUpResult(attributes, ".", "#INBOX");
+        responder.expects(once()).method("respond").with(
+                eq(createResponse(false, true, false, false, ".", "#INBOX")));
+        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
+                false, 0, (ListResult) result.proxy());
+    }
+    
+    public void testUnMarked() throws Exception {
+        String[] attributes = {"\\noise", ImapConstants.NAME_ATTRIBUTE_UNMARKED, "\\bogus"};
+        setUpResult(attributes, ".", "#INBOX");
+        responder.expects(once()).method("respond").with(
+                eq(createResponse(false, false, false, true, ".", "#INBOX")));
+        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
+                false, 0, (ListResult) result.proxy());
+    }
+    
+    public void testMarked() throws Exception {
+        String[] attributes = {"\\noise", ImapConstants.NAME_ATTRIBUTE_MARKED, "\\bogus"};
+        setUpResult(attributes, ".", "#INBOX");
+        responder.expects(once()).method("respond").with(
+                eq(createResponse(false, false, true, false, ".", "#INBOX")));
+        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
+                false, 0, (ListResult) result.proxy());
+    }
+    
+    public void testMarkedAndUnmarked() throws Exception {
+        String[] attributes = {"\\noise", ImapConstants.NAME_ATTRIBUTE_MARKED, ImapConstants.NAME_ATTRIBUTE_UNMARKED, "\\bogus"};
+        setUpResult(attributes, ".", "#INBOX");
+        responder.expects(once()).method("respond").with(
+                eq(createResponse(false, false, true, false, ".", "#INBOX")));
+        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
+                false, 0, (ListResult) result.proxy());
+    }
+    
+    public void testUnmarkedAndMarked() throws Exception {
+        String[] attributes = {"\\noise", ImapConstants.NAME_ATTRIBUTE_UNMARKED, ImapConstants.NAME_ATTRIBUTE_MARKED, "\\bogus"};
+        setUpResult(attributes, ".", "#INBOX");
+        responder.expects(once()).method("respond").with(
+                eq(createResponse(false, false, true, false, ".", "#INBOX")));
+        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
+                false, 0, (ListResult) result.proxy());
+    }
+    
+    public void testNoSelectUnmarkedAndMarked() throws Exception {
+        String[] attributes = {"\\noise", ImapConstants.NAME_ATTRIBUTE_NOSELECT, ImapConstants.NAME_ATTRIBUTE_UNMARKED, ImapConstants.NAME_ATTRIBUTE_MARKED, "\\bogus"};
+        setUpResult(attributes, ".", "#INBOX");
+        responder.expects(once()).method("respond").with(
+                eq(createResponse(false, true, false, false, ".", "#INBOX")));
+        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
+                false, 0, (ListResult) result.proxy());
+    }
+    
+    public void testUnmarkedAndMarkedNoSelect() throws Exception {
+        String[] attributes = {"\\noise",  ImapConstants.NAME_ATTRIBUTE_UNMARKED, ImapConstants.NAME_ATTRIBUTE_MARKED, ImapConstants.NAME_ATTRIBUTE_NOSELECT, "\\bogus"};
+        setUpResult(attributes, ".", "#INBOX");
+        responder.expects(once()).method("respond").with(
+                eq(createResponse(false, true, false, false, ".", "#INBOX")));
+        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
+                false, 0, (ListResult) result.proxy());
+    }
+    
+    public void testUnmarkedNoSelectAndMarked() throws Exception {
+        String[] attributes = {"\\noise",  ImapConstants.NAME_ATTRIBUTE_UNMARKED, ImapConstants.NAME_ATTRIBUTE_NOSELECT, ImapConstants.NAME_ATTRIBUTE_MARKED, "\\bogus"};
+        setUpResult(attributes, ".", "#INBOX");
+        responder.expects(once()).method("respond").with(
+                eq(createResponse(false, true, false, false, ".", "#INBOX")));
+        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
+                false, 0, (ListResult) result.proxy());
+    }
+    
+    public void testNoinferiorsUnmarkedNoSelectAndMarked() throws Exception {
+        String[] attributes = {"\\noise",  ImapConstants.NAME_ATTRIBUTE_NOINFERIORS, ImapConstants.NAME_ATTRIBUTE_UNMARKED, ImapConstants.NAME_ATTRIBUTE_NOSELECT, ImapConstants.NAME_ATTRIBUTE_MARKED, "\\bogus"};
+        setUpResult(attributes, ".", "#INBOX");
+        responder.expects(once()).method("respond").with(
+                eq(createResponse(true, true, false, false, ".", "#INBOX")));
+        processor.processResult((ImapProcessor.Responder) responder.proxy(), 
+                false, 0, (ListResult) result.proxy());
+    }    
 }



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