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