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 no...@apache.org on 2010/09/13 13:06:15 UTC

svn commit: r996494 - in /james/imap/trunk: api/src/main/java/org/apache/james/imap/api/process/ processor/src/main/java/org/apache/james/imap/processor/ processor/src/main/java/org/apache/james/imap/processor/base/ processor/src/main/java/org/apache/j...

Author: norman
Date: Mon Sep 13 11:06:15 2010
New Revision: 996494

URL: http://svn.apache.org/viewvc?rev=996494&view=rev
Log:
Handle unknown uid or msn ranges in Copy,Search,Store and Fetch commands (IMAP-209)

Modified:
    james/imap/trunk/api/src/main/java/org/apache/james/imap/api/process/SelectedMailbox.java
    james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.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/CopyProcessor.java
    james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
    james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
    james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/base/UidToMsnConverter.java
    james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
    james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/fetch/FetchResponseBuilder.java

Modified: james/imap/trunk/api/src/main/java/org/apache/james/imap/api/process/SelectedMailbox.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/api/src/main/java/org/apache/james/imap/api/process/SelectedMailbox.java?rev=996494&r1=996493&r2=996494&view=diff
==============================================================================
--- james/imap/trunk/api/src/main/java/org/apache/james/imap/api/process/SelectedMailbox.java (original)
+++ james/imap/trunk/api/src/main/java/org/apache/james/imap/api/process/SelectedMailbox.java Mon Sep 13 11:06:15 2010
@@ -30,13 +30,15 @@ import org.apache.james.mailbox.MailboxP
  */
 public interface SelectedMailbox {
 
+	public final static int NO_SUCH_MESSAGE = -1;
+	
     /**
      * Deselect the Mailbox
      */
     public abstract void deselect();
 
     /**
-     * Return the msg index of the given uid
+     * Return the msg index of the given uid or {@link #NO_SUCH_MESSAGE} if no message with the given uid was found
      * 
      * @param uid
      * @return index
@@ -44,7 +46,8 @@ public interface SelectedMailbox {
     public int msn(long uid);
 
     /**
-     * Return the uid of the message for the given index
+     * Return the uid of the message for the given index or {@link #NO_SUCH_MESSAGE} if no message with the given index was found
+     * 
      * @param index
      * @return uid
      */
@@ -136,7 +139,8 @@ public interface SelectedMailbox {
     /**
      * Removes the given UID.
      * @param uid not null
-     * @return the message sequence number that the UID held before
+     * @return the message sequence number that the UID held before or {@link #NO_SUCH_MESSAGE} if no message with the given uid 
+     *         was found
      * being expunged
      */
     public int remove(Long uid);

Modified: james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java?rev=996494&r1=996493&r2=996494&view=diff
==============================================================================
--- james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java (original)
+++ james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java Mon Sep 13 11:06:15 2010
@@ -28,6 +28,7 @@ import org.apache.james.imap.api.ImapCom
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.display.HumanReadableText;
+import org.apache.james.imap.api.message.IdRange;
 import org.apache.james.imap.api.message.request.ImapRequest;
 import org.apache.james.imap.api.message.response.ImapResponseMessage;
 import org.apache.james.imap.api.message.response.StatusResponse;
@@ -177,6 +178,8 @@ abstract public class AbstractMailboxPro
             MessageResult mr = it.next();
             final long uid = mr.getUid();
             int msn = selected.msn(uid);
+            if (msn == SelectedMailbox.NO_SUCH_MESSAGE) throw new MailboxException("No message found with uid " + uid);
+            
             final Flags flags = mr.getFlags();
             final Long uidOut;
             if (useUid) {
@@ -355,5 +358,32 @@ abstract public class AbstractMailboxPro
         }
         return result;
     }
+    
+    /**
+     * Return a {@link MessageRange} for the given values. If the MessageRange can not be generated a {@link MailboxException} will 
+     * get thrown
+     * 
+     * @param selected
+     * @param range
+     * @param useUids
+     * @return
+     * @throws MailboxException
+     */
+    protected MessageRange messageRange(SelectedMailbox selected, IdRange range, boolean useUids) throws MailboxException{
+    	long lowVal = range.getLowVal();
+        long highVal = range.getHighVal();
+    	if (useUids == false) {
+    		if (lowVal != Long.MAX_VALUE) {
+                lowVal = selected.uid((int) lowVal);
+                if (lowVal == SelectedMailbox.NO_SUCH_MESSAGE) throw new MailboxException("No message found with msn " + lowVal);
+    		}
+    		if (highVal != Long.MAX_VALUE) {
+                highVal = selected.uid((int) highVal);
+                if (highVal == SelectedMailbox.NO_SUCH_MESSAGE) throw new MailboxException("No message found with msn " + highVal);
+    		}
+        }
+        MessageRange mRange = MessageRange.range(lowVal, highVal);
+        return mRange;
+    }
 
 }

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=996494&r1=996493&r2=996494&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 Mon Sep 13 11:06:15 2010
@@ -143,6 +143,9 @@ abstract class AbstractSelectionProcesso
         if (firstUnseen != null) {
             final long unseenUid = firstUnseen;
             int msn = selected.msn(unseenUid);
+
+            if (msn == SelectedMailbox.NO_SUCH_MESSAGE) throw new MailboxException("No message found with uid " + unseenUid);
+
             final StatusResponse untaggedOk = statusResponseFactory.untaggedOk(
                     HumanReadableText.UNSEEN, ResponseCode.unseen(msn));
             responder.respond(untaggedOk);

Modified: james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/CopyProcessor.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/CopyProcessor.java?rev=996494&r1=996493&r2=996494&view=diff
==============================================================================
--- james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/CopyProcessor.java (original)
+++ james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/CopyProcessor.java Mon Sep 13 11:06:15 2010
@@ -65,18 +65,8 @@ public class CopyProcessor extends Abstr
                         ResponseCode.tryCreate());
             } else {
                 for (int i = 0; i < idSet.length; i++) {
-                    final long highVal;
-                    final long lowVal;
-                    if (useUids) {
-                        highVal = idSet[i].getHighVal();
-                        lowVal = idSet[i].getLowVal();
-                    } else {
-                        highVal = session.getSelected().uid(
-                                (int) idSet[i].getHighVal());
-                        lowVal = session.getSelected().uid(
-                                (int) idSet[i].getLowVal());
-                    }
-                    MessageRange messageSet = MessageRange.range(lowVal, highVal);
+                    
+                    MessageRange messageSet = messageRange(currentMailbox, idSet[i], useUids);
 
                     mailboxManager.copyMessages(messageSet, currentMailbox.getPath(),
                                                 targetMailbox, mailboxSession);

Modified: james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/SearchProcessor.java?rev=996494&r1=996493&r2=996494&view=diff
==============================================================================
--- james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/SearchProcessor.java (original)
+++ james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/SearchProcessor.java Mon Sep 13 11:06:15 2010
@@ -78,6 +78,7 @@ public class SearchProcessor extends Abs
             unsolicitedResponses(session, responder, omitExpunged, useUids);
             okComplete(command, tag, responder);
         } catch (MailboxException e) {
+        	e.printStackTrace();
             no(command, tag, responder, HumanReadableText.SEARCH_FAILED);
         }
     }
@@ -107,6 +108,7 @@ public class SearchProcessor extends Abs
                 number = new Long(uid);
             } else {
                 final int msn = session.getSelected().msn(uid);
+                if (msn == SelectedMailbox.NO_SUCH_MESSAGE) throw new MailboxException("No message found with uid " + uid);
                 number = new Long(msn);
             }
             results.add(number);
@@ -114,7 +116,7 @@ public class SearchProcessor extends Abs
         return results;
     }
 
-    private SearchQuery toQuery(final SearchKey key, final ImapSession session) {
+    private SearchQuery toQuery(final SearchKey key, final ImapSession session) throws MailboxException {
         final SearchQuery result = new SearchQuery();
         final SelectedMailbox selected = session.getSelected();
         if (selected != null) {
@@ -126,7 +128,7 @@ public class SearchProcessor extends Abs
     }
 
     private SearchQuery.Criterion toCriterion(final SearchKey key,
-            final ImapSession session) {
+            final ImapSession session) throws MailboxException {
         final int type = key.getType();
         final DayMonthYear date = key.getDate();
         switch (type) {
@@ -224,7 +226,7 @@ public class SearchProcessor extends Abs
     }
 
     private Criterion sequence(IdRange[] sequenceNumbers,
-            final ImapSession session, boolean msn) {
+            final ImapSession session, boolean msn) throws MailboxException {
         final int length = sequenceNumbers.length;
         final SearchQuery.NumericRange[] ranges = new SearchQuery.NumericRange[length];
         for (int i = 0; i < length; i++) {
@@ -240,12 +242,15 @@ public class SearchProcessor extends Abs
                 } else {
                     final int highMsn = (int) highVal;
                     highUid = selected.uid(highMsn);
+                    if (highUid == -1) throw new MailboxException("No message found with msn " + highMsn);
                 }
                 if (lowVal == Long.MAX_VALUE) {
                     lowUid = Long.MAX_VALUE;
                 } else {
                     final int lowMsn = (int) lowVal;
                     lowUid = selected.uid(lowMsn);
+                    if (highUid == -1) throw new MailboxException("No message found with msn " + lowUid);
+
                 }
             } else {
                 lowUid = lowVal;
@@ -256,7 +261,7 @@ public class SearchProcessor extends Abs
         return SearchQuery.uid(ranges);
     }
 
-    private Criterion or(List<SearchKey> keys, final ImapSession session) {
+    private Criterion or(List<SearchKey> keys, final ImapSession session) throws MailboxException {
         final SearchKey keyOne = keys.get(0);
         final SearchKey keyTwo = keys.get(1);
         final Criterion criterionOne = toCriterion(keyOne, session);
@@ -265,14 +270,14 @@ public class SearchProcessor extends Abs
         return result;
     }
 
-    private Criterion not(List<SearchKey> keys, final ImapSession session) {
+    private Criterion not(List<SearchKey> keys, final ImapSession session) throws MailboxException {
         final SearchKey key = keys.get(0);
         final Criterion criterion = toCriterion(key, session);
         final Criterion result = SearchQuery.not(criterion);
         return result;
     }
 
-    private Criterion and(List<SearchKey> keys, final ImapSession session) {
+    private Criterion and(List<SearchKey> keys, final ImapSession session) throws MailboxException {
         final int size = keys.size();
         final List<Criterion> criteria = new ArrayList<Criterion>(size);
         for (final SearchKey key:keys) {

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=996494&r1=996493&r2=996494&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 Mon Sep 13 11:06:15 2010
@@ -77,17 +77,9 @@ public class StoreProcessor extends Abst
         try {
             final MessageManager mailbox = getSelectedMailbox(session);
             for (int i = 0; i < idSet.length; i++) {
-                final long lowVal;
-                final long highVal;
                 final SelectedMailbox selected = session.getSelected();
-                if (useUids) {
-                    lowVal = idSet[i].getLowVal();
-                    highVal = idSet[i].getHighVal();
-                } else {
-                    lowVal = selected.uid((int) idSet[i].getLowVal());
-                    highVal = selected.uid((int) idSet[i].getHighVal());
-                }
-                final MessageRange messageSet = MessageRange.range(lowVal, highVal);
+                MessageRange messageSet = messageRange(selected, idSet[i], useUids);
+
                 final MailboxSession mailboxSession = ImapSessionUtils
                         .getMailboxSession(session);
                 final Map<Long, Flags> flagsByUid = mailbox.setFlags(flags, value, replace,
@@ -96,6 +88,9 @@ public class StoreProcessor extends Abst
                     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) {

Modified: james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/base/UidToMsnConverter.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/base/UidToMsnConverter.java?rev=996494&r1=996493&r2=996494&view=diff
==============================================================================
--- james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/base/UidToMsnConverter.java (original)
+++ james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/base/UidToMsnConverter.java Mon Sep 13 11:06:15 2010
@@ -25,10 +25,16 @@ import java.util.List;
 import java.util.SortedMap;
 import java.util.TreeMap;
 
+import org.apache.james.imap.api.process.SelectedMailbox;
 import org.apache.james.mailbox.MailboxListener;
 
-//TODO: This is a major memory hog
-//TODO: Each concurrent session requires one, and typical clients now open many
+/**
+ * {@link MailboxListener} which takes care of maintaining a mapping between message uids and msn (index)
+ * 
+ *
+ * TODO: This is a major memory hog
+ * TODO: Each concurrent session requires one, and typical clients now open many
+ */
 public class UidToMsnConverter implements MailboxListener {
     private final SortedMap<Integer, Long> msnToUid;
 
@@ -60,9 +66,13 @@ public class UidToMsnConverter implement
         }
     }
 
-    public long getUid(int msn) {
+    /**
+     * @see SelectedMailbox#uid(int)
+     * 
+     */
+    public synchronized long getUid(int msn) {
         if (msn == -1) {
-            return -1;
+            return SelectedMailbox.NO_SUCH_MESSAGE;
         }
         Long uid = msnToUid.get(msn);
         if (uid != null) {
@@ -76,12 +86,15 @@ public class UidToMsnConverter implement
         }
     }
 
-    public int getMsn(long uid) {
+    /**
+     * @see SelectedMailbox#msn(int)
+     */
+    public synchronized int getMsn(long uid) {
         Integer msn = uidToMsn.get(uid);
         if (msn != null) {
             return msn.intValue();
         } else {
-            return -1;
+            return SelectedMailbox.NO_SUCH_MESSAGE;
         }
 
     }
@@ -94,7 +107,12 @@ public class UidToMsnConverter implement
         uidToMsn.put(uid, msn);
     }
 
-    public void expunge(final long uid) {
+    /**
+     * Expunge the message with the given uid
+     * 
+     * @param uid
+     */
+    public synchronized void expunge(final long uid) {
         final int msn = getMsn(uid);
         remove(msn, uid);
         final List<Integer> renumberMsns = new ArrayList<Integer>(msnToUid
@@ -113,7 +131,12 @@ public class UidToMsnConverter implement
         msnToUid.remove(msn);
     }
 
-    public void add(long uid) {
+    /**
+     * Add the give uid
+     * 
+     * @param uid
+     */
+    public synchronized void add(long uid) {
         if (!uidToMsn.containsKey(new Long(uid))) {
             highestMsn++;
             add(highestMsn, uid);
@@ -123,7 +146,7 @@ public class UidToMsnConverter implement
     /**
      * @see org.apache.james.mailbox.MailboxListener#event(org.apache.james.mailbox.MailboxListener.Event)
      */
-    public void event(Event event) {
+    public synchronized void event(Event event) {
         if (event instanceof MessageEvent) {
             final MessageEvent messageEvent = (MessageEvent) event;
             final long uid = messageEvent.getSubjectUid();
@@ -133,7 +156,10 @@ public class UidToMsnConverter implement
         }
     }
 
-    public void close() {
+    /**
+     * Close this {@link MailboxListener}
+     */
+    public synchronized void close() {
         closed = true;
     }
     
@@ -141,7 +167,7 @@ public class UidToMsnConverter implement
      * (non-Javadoc)
      * @see org.apache.james.mailbox.MailboxListener#isClosed()
      */
-    public boolean isClosed() {
+    public synchronized boolean isClosed() {
         return closed;
     }
 }

Modified: james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java?rev=996494&r1=996493&r2=996494&view=diff
==============================================================================
--- james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java (original)
+++ james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java Mon Sep 13 11:06:15 2010
@@ -85,18 +85,8 @@ public class FetchProcessor extends Abst
             for (int i = 0; i < idSet.length; i++) {
                 final FetchResponseBuilder builder = new FetchResponseBuilder(
                         new EnvelopeBuilder(session.getLog()));
-                final long highVal;
-                final long lowVal;
-                if (useUids) {
-                    highVal = idSet[i].getHighVal();
-                    lowVal = idSet[i].getLowVal();
-                } else {
-                    highVal = session.getSelected().uid(
-                            (int) idSet[i].getHighVal());
-                    lowVal = session.getSelected().uid(
-                            (int) idSet[i].getLowVal());
-                }
-                MessageRange messageSet = MessageRange.range(lowVal, highVal);
+                MessageRange messageSet = messageRange(session.getSelected(), idSet[i], useUids);
+
                 final MailboxSession mailboxSession = ImapSessionUtils
                         .getMailboxSession(session);
                 final Iterator<MessageResult> it = mailbox.getMessages(messageSet, resultToFetch, mailboxSession);

Modified: james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/fetch/FetchResponseBuilder.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/fetch/FetchResponseBuilder.java?rev=996494&r1=996493&r2=996494&view=diff
==============================================================================
--- james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/fetch/FetchResponseBuilder.java (original)
+++ james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/fetch/FetchResponseBuilder.java Mon Sep 13 11:06:15 2010
@@ -104,6 +104,9 @@ final class FetchResponseBuilder {
         final SelectedMailbox selected = session.getSelected();
         final long resultUid = result.getUid();
         final int resultMsn = selected.msn(resultUid);
+        
+        if (resultMsn == SelectedMailbox.NO_SUCH_MESSAGE) throw new MailboxException("No such message found with uid " + resultUid);
+        
         setMsn(resultMsn);
 
         // Check if this fetch will cause the "SEEN" flag to be set on this



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