james-server-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nor...@apache.org
Subject svn commit: r1145703 - in /james/imap/trunk: api/src/main/java/org/apache/james/imap/api/display/ api/src/main/java/org/apache/james/imap/api/message/response/ message/src/main/java/org/apache/james/imap/decode/parser/ message/src/main/java/org/apache/...
Date Tue, 12 Jul 2011 18:21:43 GMT
Author: norman
Date: Tue Jul 12 18:21:42 2011
New Revision: 1145703

URL: http://svn.apache.org/viewvc?rev=1145703&view=rev
Log:
Start to work on CONDSTORE extension. Still work in progress. See IMAP-305

Added:
    james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AbstractSelectionCommandParser.java
Modified:
    james/imap/trunk/api/src/main/java/org/apache/james/imap/api/display/HumanReadableText.java
    james/imap/trunk/api/src/main/java/org/apache/james/imap/api/message/response/StatusResponse.java
    james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java
    james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java
    james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StoreCommandParser.java
    james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/AbstractMailboxSelectionRequest.java
    james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/ExamineRequest.java
    james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/SelectRequest.java
    james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/StoreRequest.java
    james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
    james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/StoreProcessor.java

Modified: james/imap/trunk/api/src/main/java/org/apache/james/imap/api/display/HumanReadableText.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/api/src/main/java/org/apache/james/imap/api/display/HumanReadableText.java?rev=1145703&r1=1145702&r2=1145703&view=diff
==============================================================================
--- james/imap/trunk/api/src/main/java/org/apache/james/imap/api/display/HumanReadableText.java
(original)
+++ james/imap/trunk/api/src/main/java/org/apache/james/imap/api/display/HumanReadableText.java
Tue Jul 12 18:21:42 2011
@@ -39,6 +39,9 @@ public class HumanReadableText {
     }
 
     public static final HumanReadableText UIDNEXT = new HumanReadableText("org.apache.james.imap.UIDNEXT",
"Predicted next UID");
+    
+    public static final HumanReadableText HIGHEST_MOD_SEQ = new HumanReadableText("org.apache.james.imap.HIGHEST_MOD_SEQ",
"");
+    public static final HumanReadableText NO_MOD_SEQ = new HumanReadableText("org.apache.james.imap.NO_MOD_SEQ",
"Sorry, this mailbox format doesn't support modsequences");
 
     public static final HumanReadableText UID_VALIDITY = new HumanReadableText("org.apache.james.imap.UID_VALIDITY",
"UIDs valid");
 

Modified: james/imap/trunk/api/src/main/java/org/apache/james/imap/api/message/response/StatusResponse.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/api/src/main/java/org/apache/james/imap/api/message/response/StatusResponse.java?rev=1145703&r1=1145702&r2=1145703&view=diff
==============================================================================
--- james/imap/trunk/api/src/main/java/org/apache/james/imap/api/message/response/StatusResponse.java
(original)
+++ james/imap/trunk/api/src/main/java/org/apache/james/imap/api/message/response/StatusResponse.java
Tue Jul 12 18:21:42 2011
@@ -253,6 +253,28 @@ public interface StatusResponse extends 
             return new ResponseCode("UIDNEXT", uid);
         }
 
+        
+        /**
+         * Create a RFC4551 <code>HIGESTMODSEQ</code> response code
+         * 
+         * @param modSeq positive non-zero long
+         * @return <code>ResponseCode</code>
+         */
+        public static ResponseCode highestModSeq(long modSeq) {
+            return new ResponseCode("HIGESTMODSEQ", modSeq);
+        }
+        
+        /**
+         * Create a RFC4551 <code>NOMODSEQ</code> response code
+         * 
+         * @return <code>ResponseCode</code>
+         */
+        public static ResponseCode noModSeq() {
+            return new ResponseCode("NOMODSEQ");
+        }
+
+
+        
         /**
          * Creates an extension response code. Names that do not begin with 'X'
          * will have 'X' prepended

Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AbstractSelectionCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AbstractSelectionCommandParser.java?rev=1145703&view=auto
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AbstractSelectionCommandParser.java
(added)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AbstractSelectionCommandParser.java
Tue Jul 12 18:21:42 2011
@@ -0,0 +1,82 @@
+/****************************************************************
+ * 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.ImapMessage;
+import org.apache.james.imap.api.process.ImapSession;
+import org.apache.james.imap.decode.DecodingException;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.imap.decode.ImapRequestLineReader.CharacterValidator;
+import org.apache.james.imap.decode.base.AbstractImapCommandParser;
+import org.apache.james.imap.message.request.AbstractMailboxSelectionRequest;
+
+public abstract class AbstractSelectionCommandParser extends AbstractImapCommandParser{
+
+    public AbstractSelectionCommandParser(ImapCommand command) {
+        super(command);
+    }
+    
+
+
+    private final static byte[] UNCHANGEDSINCE = "(UNCHANGEDSINCE)".getBytes();
+
+    private int cap(char next) {
+        final int cap = next > 'Z' ? next ^ 32 : next;
+        return cap;
+    }
+    
+    /*
+     * (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.james.imap.api.process.ImapSession)
+     */
+    protected ImapMessage decode(ImapCommand command, ImapRequestLineReader request, String
tag, ImapSession session) throws DecodingException {
+        final String mailboxName = request.mailbox();
+        boolean condstore = false;
+
+        char c = Character.UNASSIGNED;
+        try {
+            c = request.nextWordChar();
+        } catch (DecodingException e) {
+
+        }
+        if (c == '(') {
+            request.consumeWord(new CharacterValidator() {
+                int pos = 0;
+                @Override
+                public boolean isValid(char chr) {
+                    return cap(chr) == UNCHANGEDSINCE[pos++];
+                }
+            });
+            condstore = true;
+            
+        }
+       
+        request.eol();
+        final ImapMessage result = createRequest(command, mailboxName, condstore, tag);
+        return result;
+    }
+    
+    protected abstract AbstractMailboxSelectionRequest createRequest(ImapCommand command,
String mailboxName, boolean condstore, String tag);
+}

Modified: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java?rev=1145703&r1=1145702&r2=1145703&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java
(original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java
Tue Jul 12 18:21:42 2011
@@ -20,36 +20,22 @@ package org.apache.james.imap.decode.par
 
 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.process.ImapSession;
-import org.apache.james.imap.decode.ImapRequestLineReader;
-import org.apache.james.imap.decode.DecodingException;
-import org.apache.james.imap.decode.base.AbstractImapCommandParser;
+import org.apache.james.imap.message.request.AbstractMailboxSelectionRequest;
 import org.apache.james.imap.message.request.ExamineRequest;
 
 /**
  * Parse EXAMINE commands
  */
-public class ExamineCommandParser extends AbstractImapCommandParser {
+public class ExamineCommandParser extends AbstractSelectionCommandParser {
 
     public ExamineCommandParser() {
         super(ImapCommand.authenticatedStateCommand(ImapConstants.EXAMINE_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.james.imap.api.process.ImapSession)
-     */
-    protected ImapMessage decode(ImapCommand command, ImapRequestLineReader request, String
tag, ImapSession session) throws DecodingException {
-        final String mailboxName = request.mailbox();
-        request.eol();
-        final ImapMessage result = new ExamineRequest(command, mailboxName, tag);
-        return result;
+    @Override
+    protected AbstractMailboxSelectionRequest createRequest(ImapCommand command, String mailboxName,
boolean condstore, String tag) {
+        return new ExamineRequest(command, mailboxName, condstore, tag);
     }
 
+
 }

Modified: 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=1145703&r1=1145702&r2=1145703&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java
(original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java
Tue Jul 12 18:21:42 2011
@@ -20,36 +20,22 @@ package org.apache.james.imap.decode.par
 
 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.process.ImapSession;
-import org.apache.james.imap.decode.ImapRequestLineReader;
-import org.apache.james.imap.decode.DecodingException;
-import org.apache.james.imap.decode.base.AbstractImapCommandParser;
+import org.apache.james.imap.message.request.AbstractMailboxSelectionRequest;
 import org.apache.james.imap.message.request.SelectRequest;
 
 /**
  * Parse SELECT commands
  */
-public class SelectCommandParser extends AbstractImapCommandParser {
+public class SelectCommandParser extends AbstractSelectionCommandParser {
 
     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.james.imap.api.process.ImapSession)
-     */
-    protected ImapMessage decode(ImapCommand command, ImapRequestLineReader request, String
tag, ImapSession session) throws DecodingException {
-        final String mailboxName = request.mailbox();
-        request.eol();
-        final ImapMessage result = new SelectRequest(command, mailboxName, tag);
-        return result;
+    @Override
+    protected AbstractMailboxSelectionRequest createRequest(ImapCommand command, String mailboxName,
boolean condstore, String tag) {
+        return new SelectRequest(command, mailboxName, condstore, tag);
     }
 
+
 }

Modified: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StoreCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StoreCommandParser.java?rev=1145703&r1=1145702&r2=1145703&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StoreCommandParser.java
(original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StoreCommandParser.java
Tue Jul 12 18:21:42 2011
@@ -28,6 +28,7 @@ import org.apache.james.imap.api.message
 import org.apache.james.imap.api.process.ImapSession;
 import org.apache.james.imap.decode.ImapRequestLineReader;
 import org.apache.james.imap.decode.DecodingException;
+import org.apache.james.imap.decode.ImapRequestLineReader.CharacterValidator;
 import org.apache.james.imap.message.request.StoreRequest;
 
 /**
@@ -35,10 +36,18 @@ import org.apache.james.imap.message.req
  */
 public class StoreCommandParser extends AbstractUidCommandParser {
 
+    private final static byte[] UNCHANGEDSINCE = "UNCHANGEDSINCE".getBytes();
+    
     public StoreCommandParser() {
         super(ImapCommand.selectedStateCommand(ImapConstants.STORE_COMMAND_NAME));
     }
 
+    private int cap(char next) {
+        final int cap = next > 'Z' ? next ^ 32 : next;
+        return cap;
+    }
+    
+
     /*
      * (non-Javadoc)
      * 
@@ -52,8 +61,24 @@ public class StoreCommandParser extends 
         final IdRange[] idSet = request.parseIdRange(session);
         final Boolean sign;
         boolean silent = false;
-
+        long unchangedSince = -1;
         char next = request.nextWordChar();
+        if (next == '(') {
+            // Seems like we have a CONDSTORE parameter
+            request.consume();
+            
+            request.consumeWord(new CharacterValidator() {
+                private int pos = 0;
+                public boolean isValid(char chr) {
+                    return cap(chr) == UNCHANGEDSINCE[pos++];
+                }
+            });
+            request.consumeChar(' ');
+            unchangedSince = request.number();
+            request.consumeChar(')');
+            next = request.nextWordChar();
+        }
+        
         if (next == '+') {
             sign = Boolean.TRUE;
             request.consume();
@@ -92,7 +117,7 @@ public class StoreCommandParser extends 
         }
 
         request.eol();
-        final ImapMessage result = new StoreRequest(command, idSet, silent, flags, useUids,
tag, sign);
+        final ImapMessage result = new StoreRequest(command, idSet, silent, flags, useUids,
tag, sign, unchangedSince);
         return result;
     }
 }

Modified: james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/AbstractMailboxSelectionRequest.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/AbstractMailboxSelectionRequest.java?rev=1145703&r1=1145702&r2=1145703&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/AbstractMailboxSelectionRequest.java
(original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/AbstractMailboxSelectionRequest.java
Tue Jul 12 18:21:42 2011
@@ -27,10 +27,12 @@ import org.apache.james.imap.api.message
  */
 public abstract class AbstractMailboxSelectionRequest extends AbstractImapRequest {
     private final String mailboxName;
+    private final boolean condstore;
 
-    public AbstractMailboxSelectionRequest(final ImapCommand command, final String mailboxName,
final String tag) {
+    public AbstractMailboxSelectionRequest(final ImapCommand command, final String mailboxName,
boolean condstore, final String tag) {
         super(tag, command);
         this.mailboxName = mailboxName;
+        this.condstore = condstore;
     }
 
     /**
@@ -41,5 +43,9 @@ public abstract class AbstractMailboxSel
     public final String getMailboxName() {
         return mailboxName;
     }
+    
+    public final boolean getCondstore() {
+        return condstore;
+    }
 
 }

Modified: james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/ExamineRequest.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/ExamineRequest.java?rev=1145703&r1=1145702&r2=1145703&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/ExamineRequest.java
(original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/ExamineRequest.java
Tue Jul 12 18:21:42 2011
@@ -21,8 +21,8 @@ package org.apache.james.imap.message.re
 import org.apache.james.imap.api.ImapCommand;
 
 public class ExamineRequest extends AbstractMailboxSelectionRequest {
-    public ExamineRequest(final ImapCommand command, final String mailboxName, final String
tag) {
-        super(command, mailboxName, tag);
+    public ExamineRequest(final ImapCommand command, final String mailboxName, final boolean
condstore, final String tag) {
+        super(command, mailboxName, condstore, tag);
     }
 
 }

Modified: james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/SelectRequest.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/SelectRequest.java?rev=1145703&r1=1145702&r2=1145703&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/SelectRequest.java
(original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/SelectRequest.java
Tue Jul 12 18:21:42 2011
@@ -22,7 +22,7 @@ import org.apache.james.imap.api.ImapCom
 
 public class SelectRequest extends AbstractMailboxSelectionRequest {
 
-    public SelectRequest(final ImapCommand command, final String mailboxName, final String
tag) {
-        super(command, mailboxName, tag);
+    public SelectRequest(final ImapCommand command, final String mailboxName, boolean condstore,
final String tag) {
+        super(command, mailboxName, condstore, tag);
     }
 }

Modified: james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/StoreRequest.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/StoreRequest.java?rev=1145703&r1=1145702&r2=1145703&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/StoreRequest.java
(original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/StoreRequest.java
Tue Jul 12 18:21:42 2011
@@ -37,7 +37,9 @@ public class StoreRequest extends Abstra
 
     private final boolean signedPlus;
 
-    public StoreRequest(final ImapCommand command, final IdRange[] idSet, final boolean silent,
final Flags flags, final boolean useUids, final String tag, final Boolean sign) {
+    private long unchangedSince;
+
+    public StoreRequest(final ImapCommand command, final IdRange[] idSet, final boolean silent,
final Flags flags, final boolean useUids, final String tag, final Boolean sign, final long
unchangedSince) {
         super(tag, command);
         this.idSet = idSet;
         this.silent = silent;
@@ -53,6 +55,7 @@ public class StoreRequest extends Abstra
             signedMinus = true;
             signedPlus = false;
         }
+        this.unchangedSince = unchangedSince;
     }
 
     /**
@@ -95,6 +98,10 @@ public class StoreRequest extends Abstra
     public final boolean isUseUids() {
         return useUids;
     }
+    
+    public final long getUnchangedSince() {
+        return unchangedSince;
+    }
 
     public String toString() {
         final StringBuffer buffer = new StringBuffer(100);

Modified: james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java?rev=1145703&r1=1145702&r2=1145703&view=diff
==============================================================================
--- james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
(original)
+++ james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
Tue Jul 12 18:21:42 2011
@@ -109,10 +109,22 @@ abstract class AbstractSelectionProcesso
         uidValidity(responder, metaData);
         unseen(responder, metaData, selected);
         permanentFlags(responder, metaData, selected);
+        higestModSeq(responder, metaData, selected);
         uidNext(responder, metaData);
         taggedOk(responder, tag, command, metaData);
     }
 
+    private void higestModSeq(Responder responder, MetaData metaData, SelectedMailbox selected)
{
+        final StatusResponse untaggedOk;
+        if (metaData.isModSeqPermanent()) {
+            final long highestModSeq = metaData.getHighestModSeq();
+            untaggedOk = statusResponseFactory.untaggedOk(HumanReadableText.HIGHEST_MOD_SEQ,
ResponseCode.highestModSeq(highestModSeq));
+        } else {
+            untaggedOk = statusResponseFactory.untaggedOk(HumanReadableText.NO_MOD_SEQ, ResponseCode.noModSeq());
+        }
+        responder.respond(untaggedOk);        
+    }
+
     private void uidNext(final Responder responder, final MessageManager.MetaData metaData)
throws MailboxException {
         final long uid = metaData.getUidNext();
         final StatusResponse untaggedOk = statusResponseFactory.untaggedOk(HumanReadableText.UIDNEXT,
ResponseCode.uidNext(uid));

Modified: james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/StoreProcessor.java?rev=1145703&r1=1145702&r2=1145703&view=diff
==============================================================================
--- james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
(original)
+++ james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
Tue Jul 12 18:21:42 2011
@@ -19,6 +19,9 @@
 
 package org.apache.james.imap.processor;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 import javax.mail.Flags;
@@ -27,12 +30,14 @@ import org.apache.james.imap.api.ImapCom
 import org.apache.james.imap.api.ImapSessionUtils;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.IdRange;
+import org.apache.james.imap.api.message.response.StatusResponse;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapProcessor;
 import org.apache.james.imap.api.process.ImapSession;
 import org.apache.james.imap.api.process.SelectedMailbox;
 import org.apache.james.imap.message.request.StoreRequest;
 import org.apache.james.imap.message.response.FetchResponse;
+import org.apache.james.imap.processor.base.FetchGroupImpl;
 import org.apache.james.mailbox.MailboxException;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
@@ -40,6 +45,7 @@ import org.apache.james.mailbox.MessageM
 import org.apache.james.mailbox.MessageManager.MetaData.FetchGroup;
 import org.apache.james.mailbox.MessageRange;
 import org.apache.james.mailbox.MessageRangeException;
+import org.apache.james.mailbox.MessageResult;
 
 public class StoreProcessor extends AbstractMailboxProcessor<StoreRequest> {
 
@@ -49,74 +55,60 @@ public class StoreProcessor extends Abst
 
     protected void doProcess(StoreRequest request, ImapSession session, String tag, ImapCommand
command, Responder responder) {
         final IdRange[] idSet = request.getIdSet();
-        final Flags flags = request.getFlags();
         final boolean useUids = request.isUseUids();
-        final boolean silent = request.isSilent();
-        final boolean isSignedPlus = request.isSignedPlus();
-        final boolean isSignedMinus = request.isSignedMinus();
+        final long unchangedSince = request.getUnchangedSince();
 
-        final boolean replace;
-        final boolean value;
-        if (isSignedMinus) {
-            value = false;
-            replace = false;
-        } else if (isSignedPlus) {
-            value = true;
-            replace = false;
-        } else {
-            replace = true;
-            value = true;
-        }
         try {
             final MessageManager mailbox = getSelectedMailbox(session);
+            final MailboxSession mailboxSession = ImapSessionUtils.getMailboxSession(session);
+
+            if (unchangedSince != -1 && mailbox.isModSeqPermanent(mailboxSession)
== false ) {
+                // Check if the mailbox did not support modsequences. If so return a tagged
bad response.
+                // See RFC4551 3.1.2. NOMODSEQ Response Code 
+                taggedBad(command, tag, responder, HumanReadableText.NO_MOD_SEQ);
+                return;
+            }
+            List<Long> failedUids = new ArrayList<Long>();
+
             for (int i = 0; i < idSet.length; i++) {
                 final SelectedMailbox selected = session.getSelected();
                 MessageRange messageSet = messageRange(selected, idSet[i], useUids);
                 if (messageSet != null) {
-                    final MailboxSession mailboxSession = ImapSessionUtils.getMailboxSession(session);
-                    final Map<Long, Flags> flagsByUid = mailbox.setFlags(flags, value,
replace, messageSet, mailboxSession);
-                    // As the STORE command is allowed to create a new "flag/keyword", we
need to send a FLAGS and PERMANENTFLAGS response before the FETCH response
-                    // if some new flag/keyword was used
-                    // See IMAP-303
-                    if (selected.hasNewApplicableFlags()) {
-                        flags(responder, selected);
-                        permanentFlags(responder, mailbox.getMetaData(false, mailboxSession,
FetchGroup.NO_COUNT), selected);
-                        selected.resetNewApplicableFlags();
-                    }
                     
-                    if (!silent) {
-     
-                        for (Map.Entry<Long, Flags> entry : flagsByUid.entrySet())
{
-                            final long uid = entry.getKey();
-                            final int msn = selected.msn(uid);
-
-                            if (msn == SelectedMailbox.NO_SUCH_MESSAGE)
-                                throw new MailboxException("No message found with uid " +
uid);
-
-                            final Flags resultFlags = entry.getValue();
-                            final Long resultUid;
-                            if (useUids) {
-                                resultUid = uid;
+                    if (unchangedSince != -1) {
+                        List<Long> uids = new ArrayList<Long>();
+
+                        Iterator<MessageResult> results = mailbox.getMessages(messageSet,
FetchGroupImpl.MINIMAL, mailboxSession);
+                        while(results.hasNext()) {
+                            MessageResult r = results.next();
+                            long uid = r.getUid();
+                            if (r.getModSeq() <= unchangedSince) {
+                                uids.add(uid);
                             } else {
-                                resultUid = null;
-                            }
-                            
-                            
-                            if (selected.isRecent(uid)) {
-                                resultFlags.add(Flags.Flag.RECENT);
+                                failedUids.add(uid);
                             }
-                           
-                            final FetchResponse response = new FetchResponse(msn, resultFlags,
resultUid, null, null, null, null, null, null);
-                            responder.respond(response);
                         }
+                        List<MessageRange> mRanges = MessageRange.toRanges(uids);
+                        for (int a = 0 ; a < mRanges.size(); a++) {
+                            setFlags(request, mailboxSession, mailbox, mRanges.get(a), selected,
tag, command, responder);
+                        }
+                    } else {
+                        setFlags(request, mailboxSession, mailbox, messageSet, selected,
tag, command, responder);
                     }
+                    
                 }
 
                 
             }
             final boolean omitExpunged = (!useUids);
             unsolicitedResponses(session, responder, omitExpunged, useUids);
-            okComplete(command, tag, responder);
+            if (failedUids.isEmpty()) {
+                okComplete(command, tag, responder);
+            } else {
+                // TODO: Fix me!
+                final StatusResponse response = getStatusResponseFactory().taggedOk(tag,
command, HumanReadableText.COMPLETED);
+                responder.respond(response);
+            }
         } catch (MessageRangeException e) {
             session.getLog().debug("Store failed", e); 
             taggedBad(command, tag, responder, HumanReadableText.INVALID_MESSAGESET);
@@ -125,4 +117,63 @@ public class StoreProcessor extends Abst
             no(command, tag, responder, HumanReadableText.SAVE_FAILED);
         }
     }
+    
+    private void setFlags(StoreRequest request, MailboxSession mailboxSession, MessageManager
mailbox, MessageRange messageSet, SelectedMailbox selected, String tag, ImapCommand command,
Responder responder) throws MailboxException {
+        
+        final Flags flags = request.getFlags();
+        final boolean useUids = request.isUseUids();
+        final boolean silent = request.isSilent();
+        final boolean isSignedPlus = request.isSignedPlus();
+        final boolean isSignedMinus = request.isSignedMinus();
+
+        final boolean replace;
+        final boolean value;
+        if (isSignedMinus) {
+            value = false;
+            replace = false;
+        } else if (isSignedPlus) {
+            value = true;
+            replace = false;
+        } else {
+            replace = true;
+            value = true;
+        }
+        
+        final Map<Long, Flags> flagsByUid = mailbox.setFlags(flags, value, replace,
messageSet, mailboxSession);
+        // As the STORE command is allowed to create a new "flag/keyword", we need to send
a FLAGS and PERMANENTFLAGS response before the FETCH response
+        // if some new flag/keyword was used
+        // See IMAP-303
+        if (selected.hasNewApplicableFlags()) {
+            flags(responder, selected);
+            permanentFlags(responder, mailbox.getMetaData(false, mailboxSession, FetchGroup.NO_COUNT),
selected);
+            selected.resetNewApplicableFlags();
+        }
+        
+        if (!silent) {
+
+            for (Map.Entry<Long, Flags> entry : flagsByUid.entrySet()) {
+                final long uid = entry.getKey();
+                final int msn = selected.msn(uid);
+
+                if (msn == SelectedMailbox.NO_SUCH_MESSAGE)
+                    throw new MailboxException("No message found with uid " + uid);
+
+                final Flags resultFlags = entry.getValue();
+                final Long resultUid;
+                if (useUids) {
+                    resultUid = uid;
+                } else {
+                    resultUid = null;
+                }
+                
+                
+                if (selected.isRecent(uid)) {
+                    resultFlags.add(Flags.Flag.RECENT);
+                }
+               
+                final FetchResponse response = new FetchResponse(msn, resultFlags, resultUid,
null, null, null, null, null, null);
+                responder.respond(response);
+            }
+        }
+    }
 }



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


Mime
View raw message