http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java index 1be6f66..a0e1f0f 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java @@ -40,9 +40,11 @@ import org.apache.james.imap.api.ImapConstants; import org.apache.james.imap.api.display.CharsetUtil; import org.apache.james.imap.api.display.HumanReadableText; import org.apache.james.imap.api.message.IdRange; +import org.apache.james.imap.api.message.UidRange; import org.apache.james.imap.api.message.request.DayMonthYear; import org.apache.james.imap.api.process.ImapSession; import org.apache.james.imap.api.process.SearchResUtil; +import org.apache.james.mailbox.MessageUid; import org.apache.james.protocols.imap.DecodingException; import org.apache.james.protocols.imap.utils.DecoderUtils; import org.apache.james.protocols.imap.utils.FastByteArrayOutputStream; @@ -686,6 +688,39 @@ public abstract class ImapRequestLineReader { } /** + * Reads a "message set" argument, and parses into an IdSet. This also support the use of $ as sequence-set as stated in SEARCHRES RFC5182 + */ + public UidRange[] parseUidRange() throws DecodingException { + CharacterValidator validator = new MessageSetCharValidator(); + // Don't fail to parse id ranges which are enclosed by "(..)" + // See IMAP-283 + String nextWord = consumeWord(validator, true); + + int commaPos = nextWord.indexOf(','); + if (commaPos == -1) { + return new UidRange[] { parseUidRange(nextWord) }; + } + + ArrayList<UidRange> rangeList = new ArrayList<UidRange>(); + int pos = 0; + while (commaPos != -1) { + String range = nextWord.substring(pos, commaPos); + UidRange set = parseUidRange(range); + rangeList.add(set); + + pos = commaPos + 1; + commaPos = nextWord.indexOf(',', pos); + } + String range = nextWord.substring(pos); + rangeList.add(parseUidRange(range)); + + // merge the ranges to minimize the needed queries. + // See IMAP-211 + List<UidRange> merged = UidRange.mergeRanges(rangeList); + return merged.toArray(new UidRange[merged.size()]); + } + + /** * Reads the first non-space character in the current line. This method will continue * to resume if meet space character until meet the non-space character. * @@ -745,6 +780,46 @@ public abstract class ImapRequestLineReader { } } + /** + * Parse a range which use a ":" as delimiter + */ + private UidRange parseUidRange(String range) throws DecodingException { + int pos = range.indexOf(':'); + try { + if (pos == -1) { + + // Check if its a single "*" and so should return last message + // in mailbox. See IMAP-289 + if (range.length() == 1 && range.charAt(0) == '*') { + return new UidRange(MessageUid.MAX_VALUE); + } else { + long value = parseUnsignedInteger(range); + return new UidRange(MessageUid.of(value)); + } + } else { + // Make sure we detect the low and high value + // See https://issues.apache.org/jira/browse/IMAP-212 + long val1 = parseUnsignedInteger(range.substring(0, pos)); + long val2 = parseUnsignedInteger(range.substring(pos + 1)); + + // handle "*:*" ranges. See IMAP-289 + if (val1 == Long.MAX_VALUE && val2 == Long.MAX_VALUE) { + return new UidRange(MessageUid.MAX_VALUE); + } else if (val1 <= val2) { + return new UidRange(MessageUid.of(val1), MessageUid.of(val2)); + } else if (val1 == Long.MAX_VALUE) { + // *:<num> message range must be converted to <num>:* + // See IMAP-290 + return new UidRange(MessageUid.of(val2), MessageUid.MAX_VALUE); + } else { + return new UidRange(MessageUid.of(val2), MessageUid.of(val1)); + } + } + } catch (NumberFormatException e) { + throw new DecodingException(HumanReadableText.INVALID_MESSAGESET, "Invalid message set.", e); + } + } + private long parseUnsignedInteger(String value) throws DecodingException { if (value.length() == 1 && value.charAt(0) == '*') { return Long.MAX_VALUE;
http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AbstractSelectionCommandParser.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AbstractSelectionCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AbstractSelectionCommandParser.java index 43b6714..91313fc 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AbstractSelectionCommandParser.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AbstractSelectionCommandParser.java @@ -23,11 +23,13 @@ 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.UidRange; import org.apache.james.imap.api.process.ImapSession; 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; +import org.apache.james.mailbox.MessageUid; import org.apache.james.protocols.imap.DecodingException; public abstract class AbstractSelectionCommandParser extends AbstractImapCommandParser{ @@ -41,19 +43,13 @@ public abstract class AbstractSelectionCommandParser extends AbstractImapCommand - /** - * @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; Long lastKnownUidValidity = null; Long knownModSeq = null; - IdRange[] uidSet = null; - IdRange[] knownUidSet = null; + UidRange[] uidSet = null; + UidRange[] knownUidSet = null; IdRange[] knownSequenceSet = null; char c = Character.UNASSIGNED; @@ -110,10 +106,10 @@ public abstract class AbstractSelectionCommandParser extends AbstractImapCommand // Consume the SP request.consumeChar(' '); - uidSet = request.parseIdRange(); + uidSet = request.parseUidRange(); // Check for * - checkIdRanges(uidSet, false); + checkUidRanges(uidSet, false); nc = request.nextChar(); if (nc == ' ') { @@ -123,11 +119,11 @@ public abstract class AbstractSelectionCommandParser extends AbstractImapCommand request.consumeChar('('); knownSequenceSet = request.parseIdRange(); request.consumeChar(' '); - knownUidSet = request.parseIdRange(); + knownUidSet = request.parseUidRange(); // Check for * and check if its in ascending order checkIdRanges(knownSequenceSet, true); - checkIdRanges(knownUidSet, true); + checkUidRanges(knownUidSet, true); // This is enclosed in () so remove ) request.consumeChar(')'); @@ -191,18 +187,48 @@ public abstract class AbstractSelectionCommandParser extends AbstractImapCommand } /** - * Create a new {@link AbstractMailboxSelectionRequest} for the given arguments + * Check if the {@link IdRange}'s are formatted like stated in the QRESYNC RFC. + * + * From RFC5162: + * + * known-uids = sequence-set + * ;; sequence of UIDs, "*" is not allowed + * + * known-sequence-set = sequence-set + * ;; set of message numbers corresponding to + * ;; the UIDs in known-uid-set, in ascending order. + * ;; * is not allowed. + * + * known-uid-set = sequence-set + * ;; set of UIDs corresponding to the messages in + * ;; known-sequence-set, in ascending order. + * ;; * is not allowed. * - * @param command - * @param mailboxName - * @param condstore - * @param lastKnownUidValidity - * @param knownModSeq - * @param uidSet - * @param knownUidSet - * @param knownSequenceSet - * @param tag - * @return request + * + * @param ranges + * @param checkOrder + * @throws DecodingException + */ + private void checkUidRanges(UidRange[] ranges, boolean checkOrder) throws DecodingException { + MessageUid last = MessageUid.MIN_VALUE; + for (UidRange r : ranges) { + + MessageUid low = r.getLowVal(); + MessageUid high = r.getHighVal(); + if (low.equals(MessageUid.MAX_VALUE) || high.equals(MessageUid.MAX_VALUE)) { + throw new DecodingException(HumanReadableText.INVALID_MESSAGESET, "* is not allowed in the sequence-set"); + } + if (checkOrder) { + if (low.compareTo(last) < 0) { + throw new DecodingException(HumanReadableText.INVALID_MESSAGESET, "Sequence-set must be in ascending order"); + } else { + last = high; + } + } + } + } + /** + * Create a new {@link AbstractMailboxSelectionRequest} for the given arguments */ - protected abstract AbstractMailboxSelectionRequest createRequest(ImapCommand command, String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, IdRange[] uidSet, IdRange[] knownUidSet, IdRange[] knownSequenceSet, String tag); + protected abstract AbstractMailboxSelectionRequest createRequest(ImapCommand command, String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, String tag); } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java index 0068843..3a9e06b 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java @@ -21,6 +21,7 @@ package org.apache.james.imap.decode.parser; import org.apache.james.imap.api.ImapCommand; import org.apache.james.imap.api.ImapConstants; import org.apache.james.imap.api.message.IdRange; +import org.apache.james.imap.api.message.UidRange; import org.apache.james.imap.message.request.AbstractMailboxSelectionRequest; import org.apache.james.imap.message.request.ExamineRequest; @@ -34,7 +35,7 @@ public class ExamineCommandParser extends AbstractSelectionCommandParser { } @Override - protected AbstractMailboxSelectionRequest createRequest(ImapCommand command, String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, IdRange[] uidSet, IdRange[] knownUidSet, IdRange[] knownSequenceSet, String tag) { + protected AbstractMailboxSelectionRequest createRequest(ImapCommand command, String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, String tag) { return new ExamineRequest(command, mailboxName, condstore, lastKnownUidValidity, knownModSeq, uidSet, knownUidSet, knownSequenceSet, tag); } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java index ffef6da..ec81ef6 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java @@ -31,6 +31,7 @@ import org.apache.james.imap.api.ImapMessage; import org.apache.james.imap.api.display.CharsetUtil; import org.apache.james.imap.api.display.HumanReadableText; import org.apache.james.imap.api.message.IdRange; +import org.apache.james.imap.api.message.UidRange; import org.apache.james.imap.api.message.request.DayMonthYear; import org.apache.james.imap.api.message.request.SearchKey; import org.apache.james.imap.api.message.request.SearchOperation; @@ -721,7 +722,7 @@ public class SearchCommandParser extends AbstractUidCommandParser { final SearchKey result; nextIsD(request); nextIsSpace(request); - final IdRange[] range = request.parseIdRange(); + final UidRange[] range = request.parseUidRange(); result = SearchKey.buildUidSet(range); return result; } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java index 5182ef9..e2dba16 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java @@ -21,6 +21,7 @@ package org.apache.james.imap.decode.parser; import org.apache.james.imap.api.ImapCommand; import org.apache.james.imap.api.ImapConstants; import org.apache.james.imap.api.message.IdRange; +import org.apache.james.imap.api.message.UidRange; import org.apache.james.imap.message.request.AbstractMailboxSelectionRequest; import org.apache.james.imap.message.request.SelectRequest; @@ -34,7 +35,7 @@ public class SelectCommandParser extends AbstractSelectionCommandParser { } @Override - protected AbstractMailboxSelectionRequest createRequest(ImapCommand command, String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, IdRange[] uidSet, IdRange[] knownUidSet, IdRange[] knownSequenceSet, String tag) { + protected AbstractMailboxSelectionRequest createRequest(ImapCommand command, String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, String tag) { return new SelectRequest(command, mailboxName, condstore, lastKnownUidValidity, knownModSeq, uidSet, knownUidSet, knownSequenceSet, tag); } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/encode/ESearchResponseEncoder.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/encode/ESearchResponseEncoder.java b/protocols/imap/src/main/java/org/apache/james/imap/encode/ESearchResponseEncoder.java index 4f72493..440344d 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/encode/ESearchResponseEncoder.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/encode/ESearchResponseEncoder.java @@ -23,6 +23,7 @@ import java.util.List; import org.apache.james.imap.api.ImapMessage; import org.apache.james.imap.api.message.IdRange; +import org.apache.james.imap.api.message.UidRange; import org.apache.james.imap.api.message.request.SearchResultOption; import org.apache.james.imap.api.process.ImapSession; import org.apache.james.imap.encode.base.AbstractChainedImapEncoder; @@ -37,11 +38,6 @@ public class ESearchResponseEncoder extends AbstractChainedImapEncoder { super(next); } - /** - * @see org.apache.james.imap.encode.base.AbstractChainedImapEncoder#doEncode - * (org.apache.james.imap.api.ImapMessage, org.apache.james.imap.encode.ImapResponseComposer, - * org.apache.james.imap.api.process.ImapSession) - */ protected void doEncode(ImapMessage acceptableMessage, ImapResponseComposer composer, ImapSession session) throws IOException { ESearchResponse response = (ESearchResponse) acceptableMessage; String tag = response.getTag(); @@ -49,6 +45,7 @@ public class ESearchResponseEncoder extends AbstractChainedImapEncoder { long max = response.getMaxUid(); long count = response.getCount(); IdRange[] all = response.getAll(); + UidRange[] allUids = response.getAllUids(); boolean useUid = response.getUseUid(); Long highestModSeq = response.getHighestModSeq(); List<SearchResultOption> options = response.getSearchResultOptions(); @@ -66,10 +63,14 @@ public class ESearchResponseEncoder extends AbstractChainedImapEncoder { if (options.contains(SearchResultOption.COUNT)) { composer.message(SearchResultOption.COUNT.name()).message(count); } - if (all != null && all.length > 0 && options.contains(SearchResultOption.ALL)) { + if (!useUid && all != null && all.length > 0 && options.contains(SearchResultOption.ALL)) { composer.message(SearchResultOption.ALL.name()); composer.sequenceSet(all); } + if (useUid && allUids != null && allUids.length > 0 && options.contains(SearchResultOption.ALL)) { + composer.message(SearchResultOption.ALL.name()); + composer.sequenceSet(allUids); + } // Add the MODSEQ to the response if needed. // http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java b/protocols/imap/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java index 1e1f834..81c8975 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java @@ -36,6 +36,7 @@ import org.apache.james.imap.api.process.ImapSession; import org.apache.james.imap.encode.base.AbstractChainedImapEncoder; import org.apache.james.imap.message.response.FetchResponse; import org.apache.james.imap.message.response.FetchResponse.Structure; +import org.apache.james.mailbox.MessageUid; import org.slf4j.Logger; public class FetchResponseEncoder extends AbstractChainedImapEncoder { @@ -290,10 +291,10 @@ public class FetchResponseEncoder extends AbstractChainedImapEncoder { } private void encodeUid(ImapResponseComposer composer, FetchResponse fetchResponse) throws IOException { - final Long uid = fetchResponse.getUid(); + final MessageUid uid = fetchResponse.getUid(); if (uid != null) { composer.message(ImapConstants.UID); - composer.message(uid.longValue()); + composer.message(uid.asLong()); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/encode/ImapResponseComposer.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/encode/ImapResponseComposer.java b/protocols/imap/src/main/java/org/apache/james/imap/encode/ImapResponseComposer.java index d08880b..d40a8cd 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/encode/ImapResponseComposer.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/encode/ImapResponseComposer.java @@ -26,6 +26,7 @@ import javax.mail.Flags; import org.apache.james.imap.api.ImapCommand; import org.apache.james.imap.api.display.CharsetUtil; import org.apache.james.imap.api.message.IdRange; +import org.apache.james.imap.api.message.UidRange; import org.apache.james.imap.message.response.Literal; public interface ImapResponseComposer { @@ -132,14 +133,15 @@ public interface ImapResponseComposer { /** * Write the given sequence-set - * - * @param ranges - * @return composer - * @throws IOException */ - ImapResponseComposer sequenceSet(IdRange[] ranges) throws IOException; + ImapResponseComposer sequenceSet(UidRange[] ranges) throws IOException; /** + * Write the given sequence-set + */ + ImapResponseComposer sequenceSet(IdRange[] ranges) throws IOException; + + /** * Write a CRLF and flush the composer which will write the content of it to * the socket * http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/encode/MailboxStatusResponseEncoder.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/encode/MailboxStatusResponseEncoder.java b/protocols/imap/src/main/java/org/apache/james/imap/encode/MailboxStatusResponseEncoder.java index b4a17fc..bebbe7d 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/encode/MailboxStatusResponseEncoder.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/encode/MailboxStatusResponseEncoder.java @@ -26,6 +26,7 @@ import org.apache.james.imap.api.ImapMessage; import org.apache.james.imap.api.process.ImapSession; import org.apache.james.imap.encode.base.AbstractChainedImapEncoder; import org.apache.james.imap.message.response.MailboxStatusResponse; +import org.apache.james.mailbox.MessageUid; /** * Encodes <code>STATUS</code> responses. @@ -40,7 +41,7 @@ public class MailboxStatusResponseEncoder extends AbstractChainedImapEncoder imp MailboxStatusResponse response = (MailboxStatusResponse) acceptableMessage; Long messages = response.getMessages(); Long recent = response.getRecent(); - Long uidNext = response.getUidNext(); + MessageUid uidNext = response.getUidNext(); Long highestModSeq = response.getHighestModSeq(); Long uidValidity = response.getUidValidity(); Long unseen = response.getUnseen(); @@ -65,7 +66,7 @@ public class MailboxStatusResponseEncoder extends AbstractChainedImapEncoder imp if (uidNext != null) { composer.message(STATUS_UIDNEXT); - final long uidNextValue = uidNext.longValue(); + final long uidNextValue = uidNext.asLong(); composer.message(uidNextValue); } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/encode/base/ImapResponseComposerImpl.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/encode/base/ImapResponseComposerImpl.java b/protocols/imap/src/main/java/org/apache/james/imap/encode/base/ImapResponseComposerImpl.java index ee1127d..cadf2cf 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/encode/base/ImapResponseComposerImpl.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/encode/base/ImapResponseComposerImpl.java @@ -28,6 +28,7 @@ import org.apache.james.imap.api.ImapCommand; import org.apache.james.imap.api.ImapConstants; import org.apache.james.imap.api.display.CharsetUtil; import org.apache.james.imap.api.message.IdRange; +import org.apache.james.imap.api.message.UidRange; import org.apache.james.imap.encode.ImapResponseComposer; import org.apache.james.imap.encode.ImapResponseWriter; import org.apache.james.imap.message.response.Literal; @@ -401,9 +402,18 @@ public class ImapResponseComposerImpl implements ImapConstants, ImapResponseComp } } - /** - * @see org.apache.james.imap.encode.ImapResponseComposer#sequenceSet(org.apache.james.imap.api.message.IdRange[]) - */ + public ImapResponseComposer sequenceSet(UidRange[] ranges) throws IOException { + StringBuilder sb = new StringBuilder(); + for (int i = 0 ; i< ranges.length; i++) { + UidRange range = ranges[i]; + sb.append(range.getFormattedString()); + if (i + 1 < ranges.length) { + sb.append(","); + } + } + return message(sb.toString()); + } + public ImapResponseComposer sequenceSet(IdRange[] ranges) throws IOException { StringBuilder sb = new StringBuilder(); for (int i = 0 ; i< ranges.length; i++) { @@ -416,5 +426,4 @@ public class ImapResponseComposerImpl implements ImapConstants, ImapResponseComp return message(sb.toString()); } - } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/message/request/AbstractMailboxSelectionRequest.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/request/AbstractMailboxSelectionRequest.java b/protocols/imap/src/main/java/org/apache/james/imap/message/request/AbstractMailboxSelectionRequest.java index 69d2b9c..cddfd1f 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/message/request/AbstractMailboxSelectionRequest.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/message/request/AbstractMailboxSelectionRequest.java @@ -21,6 +21,7 @@ package org.apache.james.imap.message.request; import org.apache.james.imap.api.ImapCommand; import org.apache.james.imap.api.message.IdRange; +import org.apache.james.imap.api.message.UidRange; import org.apache.james.imap.api.message.request.ImapRequest; /** @@ -33,11 +34,11 @@ public abstract class AbstractMailboxSelectionRequest extends AbstractImapReques private final boolean condstore; private final Long lastKnownUidValidity; private final Long knownModSeq; - private final IdRange[] uidSet; - private final IdRange[] knownUidSet; + private final UidRange[] uidSet; + private final UidRange[] knownUidSet; private final IdRange[] knownSequenceSet; - public AbstractMailboxSelectionRequest(ImapCommand command, String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, IdRange[] uidSet, IdRange[] knownUidSet, IdRange[] knownSequenceSet, String tag) { + public AbstractMailboxSelectionRequest(ImapCommand command, String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, String tag) { super(tag, command); this.mailboxName = mailboxName; this.condstore = condstore; @@ -93,10 +94,8 @@ public abstract class AbstractMailboxSelectionRequest extends AbstractImapReques /** * Return the known uid set or null if it was not given. This is a OPTIONAL parameter when * using the <code>QRESYNC</code> option. - * - * @return uidSet */ - public final IdRange[] getUidSet() { + public final UidRange[] getUidSet() { return uidSet; } @@ -114,10 +113,8 @@ public abstract class AbstractMailboxSelectionRequest extends AbstractImapReques /** * Return the known uid set or null if it was not given. This known uid set has the corresponding message numbers in {@link #getKnownSequenceSet()}. This is a OPTIONAL parameter when * using the <code>QRESYNC</code> option. - * - * @return knownUidSet */ - public final IdRange[] getKnownUidSet() { + public final UidRange[] getKnownUidSet() { return knownUidSet; } } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/message/request/ExamineRequest.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/request/ExamineRequest.java b/protocols/imap/src/main/java/org/apache/james/imap/message/request/ExamineRequest.java index 8a39d38..d47e69c 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/message/request/ExamineRequest.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/message/request/ExamineRequest.java @@ -20,9 +20,10 @@ package org.apache.james.imap.message.request; import org.apache.james.imap.api.ImapCommand; import org.apache.james.imap.api.message.IdRange; +import org.apache.james.imap.api.message.UidRange; public class ExamineRequest extends AbstractMailboxSelectionRequest { - public ExamineRequest(ImapCommand command, String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, IdRange[] uidSet, IdRange[] knownUidSet, IdRange[] knownSequenceSet, String tag) { + public ExamineRequest(ImapCommand command, String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, String tag) { super(command, mailboxName, condstore, lastKnownUidValidity, knownModSeq, uidSet, knownUidSet, knownSequenceSet, tag); } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/message/request/SelectRequest.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/request/SelectRequest.java b/protocols/imap/src/main/java/org/apache/james/imap/message/request/SelectRequest.java index 1c14cd6..451e2e3 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/message/request/SelectRequest.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/message/request/SelectRequest.java @@ -20,10 +20,11 @@ package org.apache.james.imap.message.request; import org.apache.james.imap.api.ImapCommand; import org.apache.james.imap.api.message.IdRange; +import org.apache.james.imap.api.message.UidRange; public class SelectRequest extends AbstractMailboxSelectionRequest { - public SelectRequest(ImapCommand command, String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, IdRange[] uidSet, IdRange[] knownUidSet, IdRange[] knownSequenceSet, String tag) { + public SelectRequest(ImapCommand command, String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, String tag) { super(command, mailboxName, condstore, lastKnownUidValidity, knownModSeq, uidSet, knownUidSet, knownSequenceSet, tag); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/message/response/ESearchResponse.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/response/ESearchResponse.java b/protocols/imap/src/main/java/org/apache/james/imap/message/response/ESearchResponse.java index 1ad92eb..3244853 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/message/response/ESearchResponse.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/message/response/ESearchResponse.java @@ -22,6 +22,7 @@ package org.apache.james.imap.message.response; import java.util.List; import org.apache.james.imap.api.message.IdRange; +import org.apache.james.imap.api.message.UidRange; import org.apache.james.imap.api.message.request.SearchResultOption; import org.apache.james.imap.api.message.response.ImapResponseMessage; @@ -35,8 +36,9 @@ public class ESearchResponse implements ImapResponseMessage{ private final boolean useUid; private final List<SearchResultOption> options; private final Long highestModSeq; + private UidRange[] allUids; - public ESearchResponse(long minUid, long maxUid, long count, IdRange[] all, Long highestModSeq, String tag, boolean useUid, List<SearchResultOption> options) { + public ESearchResponse(long minUid, long maxUid, long count, IdRange[] all, UidRange[] allUids, Long highestModSeq, String tag, boolean useUid, List<SearchResultOption> options) { super(); this.options = options; this.minUid = minUid; @@ -44,6 +46,7 @@ public class ESearchResponse implements ImapResponseMessage{ this.count = count; this.all = all; this.tag = tag; + this.allUids = allUids; this.useUid = useUid; this.highestModSeq = highestModSeq; } @@ -63,6 +66,10 @@ public class ESearchResponse implements ImapResponseMessage{ public IdRange[] getAll() { return all; } + + public UidRange[] getAllUids() { + return allUids; + } public String getTag() { return tag; http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/message/response/FetchResponse.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/response/FetchResponse.java b/protocols/imap/src/main/java/org/apache/james/imap/message/response/FetchResponse.java index e232c87..35c6991 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/message/response/FetchResponse.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/message/response/FetchResponse.java @@ -26,6 +26,7 @@ import java.util.Map; import javax.mail.Flags; import org.apache.james.imap.api.message.response.ImapResponseMessage; +import org.apache.james.mailbox.MessageUid; public final class FetchResponse implements ImapResponseMessage { @@ -33,7 +34,7 @@ public final class FetchResponse implements ImapResponseMessage { private final Flags flags; - private final Long uid; + private final MessageUid uid; private final Date internalDate; @@ -49,7 +50,7 @@ public final class FetchResponse implements ImapResponseMessage { private final Long modSeq; - public FetchResponse(int messageNumber, Flags flags, Long uid, Long modSeq, Date internalDate, Long size, Envelope envelope, Structure body, Structure bodystructure, List<BodyElement> elements) { + public FetchResponse(int messageNumber, Flags flags, MessageUid uid, Long modSeq, Date internalDate, Long size, Envelope envelope, Structure body, Structure bodystructure, List<BodyElement> elements) { super(); this.messageNumber = messageNumber; this.flags = flags; @@ -108,7 +109,7 @@ public final class FetchResponse implements ImapResponseMessage { * @return message uid, or null if the <code>FETCH</code> did not include * <code>UID</code> */ - public Long getUid() { + public MessageUid getUid() { return uid; } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/message/response/MailboxStatusResponse.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/response/MailboxStatusResponse.java b/protocols/imap/src/main/java/org/apache/james/imap/message/response/MailboxStatusResponse.java index 2cbf72b..0773c88 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/message/response/MailboxStatusResponse.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/message/response/MailboxStatusResponse.java @@ -20,6 +20,7 @@ package org.apache.james.imap.message.response; import org.apache.james.imap.api.message.response.ImapResponseMessage; +import org.apache.james.mailbox.MessageUid; /** * Represents a <code>STATUS</code> response. See <code>RFC3501 7.2.4</code>. @@ -30,7 +31,7 @@ public class MailboxStatusResponse implements ImapResponseMessage { private final Long recent; - private final Long uidNext; + private final MessageUid uidNext; private final Long uidValidity; @@ -40,7 +41,7 @@ public class MailboxStatusResponse implements ImapResponseMessage { private final Long highestModSeq; - public MailboxStatusResponse(Long messages, Long recent, Long uidNext, Long highestModSeq, Long uidValidity, Long unseen, String mailbox) { + public MailboxStatusResponse(Long messages, Long recent, MessageUid uidNext, Long highestModSeq, Long uidValidity, Long unseen, String mailbox) { super(); this.messages = messages; this.recent = recent; @@ -75,7 +76,7 @@ public class MailboxStatusResponse implements ImapResponseMessage { * * @return the mailbox uidNext (if requested) or null (if not) */ - public final Long getUidNext() { + public final MessageUid getUidNext() { return uidNext; } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/message/response/VanishedResponse.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/response/VanishedResponse.java b/protocols/imap/src/main/java/org/apache/james/imap/message/response/VanishedResponse.java index 7df3fcd..c3f0917 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/message/response/VanishedResponse.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/message/response/VanishedResponse.java @@ -19,34 +19,30 @@ package org.apache.james.imap.message.response; -import org.apache.james.imap.api.message.IdRange; +import org.apache.james.imap.api.message.UidRange; import org.apache.james.imap.api.message.response.ImapResponseMessage; public class VanishedResponse implements ImapResponseMessage{ - private final IdRange[] uids; + private final UidRange[] uids; private final boolean earlier; - public VanishedResponse(IdRange[] uids, boolean earlier) { + public VanishedResponse(UidRange[] vanishedIdRanges, boolean earlier) { this.earlier = earlier; - this.uids = uids; + this.uids = vanishedIdRanges; } /** * Return the uids which where expunged - * - * @return uids */ - public final IdRange[] getUids() { + public final UidRange[] getUids() { return uids; } /** * Return true if the <code>VANISHED</code> response was caused * because of an earlier SELECT/EXAMINE (QRESYNC) or UID FETCH (VANISHED) - * - * @return earlier */ public final boolean isEarlier() { return earlier; http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java index 34d5441..03dde23 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java @@ -31,6 +31,7 @@ import org.apache.james.imap.api.ImapConstants; 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.UidRange; 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; @@ -49,6 +50,7 @@ import org.apache.james.imap.processor.base.AbstractChainedProcessor; import org.apache.james.mailbox.MailboxManager; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageManager; +import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.MessageManager.MetaData; import org.apache.james.mailbox.MessageManager.MetaData.FetchGroup; import org.apache.james.mailbox.exception.MailboxException; @@ -61,7 +63,8 @@ import org.apache.james.mailbox.model.MessageRange.Type; import org.apache.james.mailbox.model.MessageResult; import org.apache.james.mailbox.model.MessageResultIterator; import org.apache.james.mailbox.model.SearchQuery; -import org.apache.james.mailbox.model.SearchQuery.NumericRange; + +import com.google.common.base.Optional; abstract public class AbstractMailboxProcessor<M extends ImapRequest> extends AbstractChainedProcessor<M> { @@ -140,7 +143,7 @@ abstract public class AbstractMailboxProcessor<M extends ImapRequest> extends Ab } // Expunged messages if (!omitExpunged) { - final Collection<Long> expungedUids = selected.expungedUids(); + final Collection<MessageUid> expungedUids = selected.expungedUids(); if (!expungedUids.isEmpty()) { // Check if QRESYNC was enabled. If so we MUST use VANISHED responses if (EnableProcessor.getEnabledCapabilities(session).contains(ImapConstants.SUPPORTS_QRESYNC)) { @@ -164,25 +167,23 @@ abstract public class AbstractMailboxProcessor<M extends ImapRequest> extends Ab selected.resetEvents(); } - private void addExpungedResponses(SelectedMailbox selected, Collection<Long> expungedUids, ImapProcessor.Responder responder) { - for (Long uid : expungedUids) { - final long uidValue = uid.longValue(); + private void addExpungedResponses(SelectedMailbox selected, Collection<MessageUid> expungedUids, ImapProcessor.Responder responder) { + for (MessageUid uid : expungedUids) { // we need to remove the message in the loop to the sequence numbers // are updated correctly. // See 7.4.1. EXPUNGE Response - final int msn = selected.remove(uidValue); + final int msn = selected.remove(uid); ExpungeResponse response = new ExpungeResponse(msn); responder.respond(response); } } - private void addVanishedResponse(SelectedMailbox selected, Collection<Long> expungedUids, ImapProcessor.Responder responder) { - for (Long uid : expungedUids) { - final long uidValue = uid.longValue(); - selected.remove(uidValue); + private void addVanishedResponse(SelectedMailbox selected, Collection<MessageUid> expungedUids, ImapProcessor.Responder responder) { + for (MessageUid uid : expungedUids) { + selected.remove(uid); } - IdRange[] uidRange = idRanges(MessageRange.toRanges(expungedUids)); + UidRange[] uidRange = uidRanges(MessageRange.toRanges(expungedUids)); responder.respond(new VanishedResponse(uidRange, false)); } @@ -205,7 +206,7 @@ abstract public class AbstractMailboxProcessor<M extends ImapRequest> extends Ab selected.resetNewApplicableFlags(); } - final Collection<Long> flagUpdateUids = selected.flagUpdateUids(); + final Collection<MessageUid> flagUpdateUids = selected.flagUpdateUids(); if (!flagUpdateUids.isEmpty()) { Iterator<MessageRange> ranges = MessageRange.toRanges(flagUpdateUids).iterator(); while(ranges.hasNext()) { @@ -227,7 +228,7 @@ abstract public class AbstractMailboxProcessor<M extends ImapRequest> extends Ab final MessageResultIterator it = mailbox.getMessages(messageSet, FetchGroupImpl.MINIMAL, mailboxSession); while (it.hasNext()) { MessageResult mr = it.next(); - final long uid = mr.getUid(); + final MessageUid uid = mr.getUid(); int msn = selected.msn(uid); if (msn == SelectedMailbox.NO_SUCH_MESSAGE) { if (session.getLog().isDebugEnabled()) { @@ -245,7 +246,7 @@ abstract public class AbstractMailboxProcessor<M extends ImapRequest> extends Ab boolean condstoreEnabled = EnableProcessor.getEnabledCapabilities(session).contains(ImapConstants.SUPPORTS_CONDSTORE); final Flags flags = mr.getFlags(); - final Long uidOut; + final MessageUid uidOut; if (useUid || qresyncEnabled) { uidOut = uid; } else { @@ -443,67 +444,81 @@ abstract public class AbstractMailboxProcessor<M extends ImapRequest> extends Ab /** * 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 range or null - * @throws MailboxException */ protected MessageRange messageRange(SelectedMailbox selected, IdRange range, boolean useUids) throws MessageRangeException { long lowVal = range.getLowVal(); long highVal = range.getHighVal(); if (useUids == false) { - // Take care of "*" and "*:*" values by return the last message in - // the mailbox. See IMAP-289 - if (lowVal == Long.MAX_VALUE && highVal == Long.MAX_VALUE) { - highVal = selected.getLastUid(); - if (highVal == SelectedMailbox.NO_SUCH_MESSAGE) { - throw new MessageRangeException("Mailbox is empty"); - } - return MessageRange.one(highVal); - } - - if (lowVal != Long.MIN_VALUE) { - lowVal = selected.uid((int) lowVal); - if (lowVal == SelectedMailbox.NO_SUCH_MESSAGE) - throw new MessageRangeException("No message found with msn " + lowVal); - } else { - lowVal = selected.getFirstUid(); - if (lowVal == SelectedMailbox.NO_SUCH_MESSAGE) { - throw new MessageRangeException("Mailbox is empty"); - } - } - if (highVal != Long.MAX_VALUE) { - highVal = selected.uid((int) highVal); - if (highVal == SelectedMailbox.NO_SUCH_MESSAGE) - throw new MessageRangeException("No message found with msn " + highVal); - } else { - highVal = selected.getLastUid(); - if (highVal == SelectedMailbox.NO_SUCH_MESSAGE) { - throw new MessageRangeException("Mailbox is empty"); - } - } - + return msnRangeToMessageRange(selected, lowVal, highVal); } else { if (selected.existsCount() <= 0) { return null; } // Take care of "*" and "*:*" values by return the last message in // the mailbox. See IMAP-289 + MessageUid lastUid = selected.getLastUid().or(MessageUid.MIN_VALUE); if (lowVal == Long.MAX_VALUE && highVal == Long.MAX_VALUE) { - return MessageRange.one(selected.getLastUid()); - } else if (highVal == Long.MAX_VALUE && selected.getLastUid() < lowVal) { + return MessageRange.one(lastUid); + } else if (highVal == Long.MAX_VALUE && lastUid.compareTo(MessageUid.of(lowVal)) < 0) { // Sequence uid ranges which use *:<uid-higher-then-last-uid> // MUST return at least the highest uid in the mailbox // See IMAP-291 - return MessageRange.one(selected.getLastUid()); + return MessageRange.one(lastUid); } + return MessageRange.range(MessageUid.of(lowVal), MessageUid.of(highVal)); } - return MessageRange.range(lowVal, highVal); } + private MessageRange msnRangeToMessageRange(SelectedMailbox selected, long lowVal, long highVal) + throws MessageRangeException { + // Take care of "*" and "*:*" values by return the last message in + // the mailbox. See IMAP-289 + if (lowVal == Long.MAX_VALUE && highVal == Long.MAX_VALUE) { + Optional<MessageUid> last = selected.getLastUid(); + if (!last.isPresent()) { + throw new MessageRangeException("Mailbox is empty"); + } + return last.get().toRange(); + } + + MessageUid lowUid = msnlowValToUid(selected, lowVal); + MessageUid highUid = msnHighValToUid(selected, highVal); + return MessageRange.range(lowUid, highUid); + } + + private MessageUid msnlowValToUid(SelectedMailbox selected, long lowVal) throws MessageRangeException { + Optional<MessageUid> uid; + if (lowVal != Long.MIN_VALUE) { + uid = selected.uid((int) lowVal); + if (!uid.isPresent()) { + throw new MessageRangeException("No message found with msn " + lowVal); + } + } else { + uid = selected.getFirstUid(); + if (!uid.isPresent()) { + throw new MessageRangeException("Mailbox is empty"); + } + } + return uid.get(); + } + + + private MessageUid msnHighValToUid(SelectedMailbox selected, long highVal) throws MessageRangeException { + Optional<MessageUid> uid; + if (highVal != Long.MAX_VALUE) { + uid = selected.uid((int) highVal); + if (!uid.isPresent()) { + throw new MessageRangeException("No message found with msn " + highVal); + } + } else { + uid = selected.getLastUid(); + if (!uid.isPresent()) { + throw new MessageRangeException("Mailbox is empty"); + } + } + return uid.get(); + } /** * Format MessageRange to RANGE format applying selected folder min & max * UIDs constraints @@ -517,33 +532,33 @@ abstract public class AbstractMailboxProcessor<M extends ImapRequest> extends Ab */ protected MessageRange normalizeMessageRange(SelectedMailbox selected, MessageRange range) throws MessageRangeException { Type rangeType = range.getType(); - long start; - long end; + MessageUid start; + MessageUid end; switch (rangeType) { case ONE: return range; case ALL: - start = selected.getFirstUid(); - end = selected.getLastUid(); + start = selected.getFirstUid().or(MessageUid.MIN_VALUE); + end = selected.getLastUid().or(MessageUid.MAX_VALUE); return MessageRange.range(start, end); case RANGE: start = range.getUidFrom(); - if (start < 1 || start == Long.MAX_VALUE || start < selected.getFirstUid()) { - start = selected.getFirstUid(); + if (start.equals(MessageUid.MAX_VALUE) || start.compareTo(selected.getFirstUid().or(MessageUid.MIN_VALUE)) < 0) { + start = selected.getFirstUid().or(MessageUid.MIN_VALUE); } end = range.getUidTo(); - if (end < 1 || end == Long.MAX_VALUE || end > selected.getLastUid()) { - end = selected.getLastUid(); + if (end.equals(MessageUid.MAX_VALUE) || end.compareTo(selected.getLastUid().or(MessageUid.MAX_VALUE)) > 0) { + end = selected.getLastUid().or(MessageUid.MAX_VALUE); } return MessageRange.range(start, end); case FROM: start = range.getUidFrom(); - if (start < 1 || start == Long.MAX_VALUE || start < selected.getFirstUid()) { - start = selected.getFirstUid(); + if (start.equals(MessageUid.MAX_VALUE) || start.compareTo(selected.getFirstUid().or(MessageUid.MIN_VALUE)) < 0) { + start = selected.getFirstUid().or(MessageUid.MIN_VALUE); } - - end = selected.getLastUid(); + + end = selected.getLastUid().or(MessageUid.MAX_VALUE); return MessageRange.range(start, end); default: throw new MessageRangeException("Unknown message range type: " + rangeType); @@ -553,14 +568,6 @@ abstract public class AbstractMailboxProcessor<M extends ImapRequest> extends Ab /** * Send VANISHED responses if needed. - * - * @param session - * @param mailbox - * @param ranges - * @param changedSince - * @param metaData - * @param responder - * @throws MailboxException */ protected void respondVanished(MailboxSession session, MessageManager mailbox, List<MessageRange> ranges, long changedSince, MetaData metaData, Responder responder) throws MailboxException { // RFC5162 4.2. Server Implementations Storing Minimal State @@ -575,31 +582,32 @@ abstract public class AbstractMailboxProcessor<M extends ImapRequest> extends Ab // can ignore this data. if (metaData.getHighestModSeq() > changedSince) { SearchQuery searchQuery = new SearchQuery(); - NumericRange[] nRanges = new NumericRange[ranges.size()]; - Set<Long> vanishedUids = new HashSet<Long>(); + SearchQuery.UidRange[] nRanges = new SearchQuery.UidRange[ranges.size()]; + Set<MessageUid> vanishedUids = new HashSet<MessageUid>(); for (int i = 0; i < ranges.size(); i++) { MessageRange r = ranges.get(i); - NumericRange nr; + SearchQuery.UidRange nr; if (r.getType() == Type.ONE) { - nr = new NumericRange(r.getUidFrom()); + nr = new SearchQuery.UidRange(r.getUidFrom()); } else { - nr = new NumericRange(r.getUidFrom(), r.getUidTo()); + nr = new SearchQuery.UidRange(r.getUidFrom(), r.getUidTo()); } - long from = nr.getLowValue(); - long to = nr.getHighValue(); - while(from <= to) { - vanishedUids.add(from++); + MessageUid from = nr.getLowValue(); + MessageUid to = nr.getHighValue(); + while(from.compareTo(to) <= 0) { + vanishedUids.add(from); + from = from.next(); } nRanges[i] = nr; } searchQuery.andCriteria(SearchQuery.uid(nRanges)); searchQuery.andCriteria(SearchQuery.modSeqGreaterThan(changedSince)); - Iterator<Long> uids = mailbox.search(searchQuery, session); + Iterator<MessageUid> uids = mailbox.search(searchQuery, session); while(uids.hasNext()) { vanishedUids.remove(uids.next()); } - IdRange[] vanishedIdRanges = idRanges(MessageRange.toRanges(vanishedUids)); + UidRange[] vanishedIdRanges = uidRanges(MessageRange.toRanges(vanishedUids)); responder.respond(new VanishedResponse(vanishedIdRanges, true)); } @@ -608,17 +616,17 @@ abstract public class AbstractMailboxProcessor<M extends ImapRequest> extends Ab // TODO: Do we need to handle wildcards here ? - protected IdRange[] idRanges(Collection<MessageRange> mRanges) { - IdRange[] idRanges = new IdRange[mRanges.size()]; + protected UidRange[] uidRanges(Collection<MessageRange> mRanges) { + UidRange[] idRanges = new UidRange[mRanges.size()]; Iterator<MessageRange> mIt = mRanges.iterator(); int i = 0; while(mIt.hasNext()) { MessageRange mr = mIt.next(); - IdRange ir; + UidRange ir; if (mr.getType() == Type.ONE) { - ir = new IdRange(mr.getUidFrom()); + ir = new UidRange(mr.getUidFrom()); } else { - ir = new IdRange(mr.getUidFrom(), mr.getUidTo()); + ir = new UidRange(mr.getUidFrom(), mr.getUidTo()); } idRanges[i++] = ir; } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMessageRangeProcessor.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMessageRangeProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMessageRangeProcessor.java index a900afa..7dd271d 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMessageRangeProcessor.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMessageRangeProcessor.java @@ -87,7 +87,7 @@ public abstract class AbstractMessageRangeProcessor<M extends AbstractMessageRan // Disable this as this is now done directly in the scope of the copy operation. // See MAILBOX-85 //mailbox.setFlags(new Flags(Flags.Flag.RECENT), true, false, mr, mailboxSession); - resultRanges.add(new IdRange(mr.getUidFrom(), mr.getUidTo())); + resultRanges.add(new IdRange(mr.getUidFrom().asLong(), mr.getUidTo().asLong())); } } } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java index b8596e4..3bd594f 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java @@ -30,6 +30,7 @@ import org.apache.james.imap.api.ImapMessage; 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.UidRange; import org.apache.james.imap.api.message.response.StatusResponse; import org.apache.james.imap.api.message.response.StatusResponse.ResponseCode; import org.apache.james.imap.api.message.response.StatusResponseFactory; @@ -46,6 +47,7 @@ import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageManager; import org.apache.james.mailbox.MessageManager.MetaData; import org.apache.james.mailbox.MessageManager.MetaData.FetchGroup; +import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.exception.MailboxNotFoundException; import org.apache.james.mailbox.exception.MessageRangeException; @@ -97,7 +99,7 @@ abstract class AbstractSelectionProcessor<M extends AbstractMailboxSelectionRequ Long lastKnownUidValidity = request.getLastKnownUidValidity(); Long modSeq = request.getKnownModSeq(); IdRange[] knownSequences = request.getKnownSequenceSet(); - IdRange[] knownUids = request.getKnownUidSet(); + UidRange[] knownUids = request.getKnownUidSet(); // Check if a QRESYNC parameter was used and if so if QRESYNC was enabled before. // If it was not enabled before its needed to return a BAD response @@ -117,7 +119,7 @@ abstract class AbstractSelectionProcessor<M extends AbstractMailboxSelectionRequ final MessageManager.MetaData metaData = selectMailbox(fullMailboxPath, session); final SelectedMailbox selected = session.getSelected(); - Long firstUnseen = metaData.getFirstUnseen(); + MessageUid firstUnseen = metaData.getFirstUnseen(); flags(responder, selected); exists(responder, metaData); @@ -171,14 +173,14 @@ abstract class AbstractSelectionProcessor<M extends AbstractMailboxSelectionRequ SearchQuery sq = new SearchQuery(); sq.andCriteria(SearchQuery.modSeqGreaterThan(request.getKnownModSeq())); - IdRange[] uidSet = request.getUidSet(); + UidRange[] uidSet = request.getUidSet(); if (uidSet == null) { // See mailbox had some messages stored before, if not we don't need to query at all - long uidNext = metaData.getUidNext(); - if ( uidNext != 1) { + MessageUid uidNext = metaData.getUidNext(); + if (!uidNext.isFirst()) { // Use UIDNEXT -1 as max uid as stated in the QRESYNC RFC - uidSet = new IdRange[] {new IdRange(1, uidNext -1)}; + uidSet = new UidRange[] {new UidRange(MessageUid.MIN_VALUE, uidNext.previous())}; } } @@ -212,9 +214,9 @@ abstract class AbstractSelectionProcessor<M extends AbstractMailboxSelectionRequ if (knownSequences != null && knownUids != null) { // Add all uids which are contained in the knownuidsset to a List so we can later access them via the index - List<Long> knownUidsList = new ArrayList<Long>(); - for (IdRange range : knownUids) { - for (Long uid : range) { + List<MessageUid> knownUidsList = new ArrayList<MessageUid>(); + for (UidRange range : knownUids) { + for (MessageUid uid : range) { knownUidsList.add(uid); } } @@ -222,7 +224,7 @@ abstract class AbstractSelectionProcessor<M extends AbstractMailboxSelectionRequ // loop over the known sequences and check the UID for MSN X again the known UID X - long firstUid = 1; + MessageUid firstUid = MessageUid.MIN_VALUE; int index = 0; for (IdRange knownSequence : knownSequences) { boolean done = false; @@ -231,10 +233,10 @@ abstract class AbstractSelectionProcessor<M extends AbstractMailboxSelectionRequ // Check if we have uids left to check against if (knownUidsList.size() > index++) { int msn = uid.intValue(); - long knownUid = knownUidsList.get(index); + MessageUid knownUid = knownUidsList.get(index); // Check if the uid mathc if not we are done here - if (selected.uid(msn) != knownUid) { + if (selected.uid(msn).asSet().contains(knownUid)) { done = true; break; } else { @@ -250,21 +252,20 @@ abstract class AbstractSelectionProcessor<M extends AbstractMailboxSelectionRequ // We found the first uid to start with if (done) { - firstUid++; + firstUid = firstUid.next(); // Ok now its time to filter out the IdRanges which we are not interested in - List<IdRange> filteredUidSet = new ArrayList<IdRange>(); - for (IdRange r : uidSet) { - if (r.getLowVal() < firstUid) { - if (r.getHighVal() > firstUid) { - r.setLowVal(firstUid); - filteredUidSet.add(r); + List<UidRange> filteredUidSet = new ArrayList<UidRange>(); + for (UidRange r : uidSet) { + if (r.getLowVal().compareTo(firstUid) < 0) { + if (r.getHighVal().compareTo(firstUid) > 0) { + filteredUidSet.add(new UidRange(firstUid, r.getHighVal())); } } else { filteredUidSet.add(r); } } - uidSet = filteredUidSet.toArray(new IdRange[0]); + uidSet = filteredUidSet.toArray(new UidRange[0]); break; } @@ -274,8 +275,8 @@ abstract class AbstractSelectionProcessor<M extends AbstractMailboxSelectionRequ } List<MessageRange> ranges = new ArrayList<MessageRange>(); - for (IdRange range : uidSet) { - MessageRange messageSet = messageRange(session.getSelected(), range, true); + for (UidRange range : uidSet) { + MessageRange messageSet = range.toMessageRange(); if (messageSet != null) { MessageRange normalizedMessageSet = normalizeMessageRange(session.getSelected(), messageSet); ranges.add(normalizedMessageSet); @@ -336,7 +337,7 @@ abstract class AbstractSelectionProcessor<M extends AbstractMailboxSelectionRequ } private void uidNext(Responder responder, MessageManager.MetaData metaData) throws MailboxException { - final long uid = metaData.getUidNext(); + final MessageUid uid = metaData.getUidNext(); final StatusResponse untaggedOk = statusResponseFactory.untaggedOk(HumanReadableText.UIDNEXT, ResponseCode.uidNext(uid)); responder.respond(untaggedOk); } @@ -353,9 +354,9 @@ abstract class AbstractSelectionProcessor<M extends AbstractMailboxSelectionRequ responder.respond(taggedOk); } - private boolean unseen(Responder responder, Long firstUnseen, SelectedMailbox selected, MailboxSession session) throws MailboxException { + private boolean unseen(Responder responder, MessageUid firstUnseen, SelectedMailbox selected, MailboxSession session) throws MailboxException { if (firstUnseen != null) { - final long unseenUid = firstUnseen; + final MessageUid unseenUid = firstUnseen; int msn = selected.msn(unseenUid); if (msn == SelectedMailbox.NO_SUCH_MESSAGE) { @@ -423,8 +424,8 @@ abstract class AbstractSelectionProcessor<M extends AbstractMailboxSelectionRequ private void addRecent(MessageManager.MetaData metaData, SelectedMailbox sessionMailbox) throws MailboxException { - final List<Long> recentUids = metaData.getRecent(); - for (Long uid : recentUids) { + final List<MessageUid> recentUids = metaData.getRecent(); + for (MessageUid uid : recentUids) { sessionMailbox.addRecent(uid); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/processor/AppendProcessor.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AppendProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AppendProcessor.java index a9bcc9d..05b2f76 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AppendProcessor.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AppendProcessor.java @@ -28,7 +28,7 @@ import javax.mail.Flags; import org.apache.james.imap.api.ImapCommand; 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.UidRange; import org.apache.james.imap.api.message.response.StatusResponse; import org.apache.james.imap.api.message.response.StatusResponse.ResponseCode; import org.apache.james.imap.api.message.response.StatusResponseFactory; @@ -40,6 +40,7 @@ import org.apache.james.mailbox.MailboxManager; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageManager; import org.apache.james.mailbox.MessageManager.MetaData.FetchGroup; +import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.exception.MailboxNotFoundException; import org.apache.james.mailbox.model.MailboxPath; @@ -132,7 +133,7 @@ public class AppendProcessor extends AbstractMailboxProcessor<AppendRequest> { final SelectedMailbox selectedMailbox = session.getSelected(); final MailboxManager mailboxManager = getMailboxManager(); final boolean isSelectedMailbox = selectedMailbox != null && selectedMailbox.getPath().equals(mailboxPath); - final long uid = mailbox.appendMessage(message, datetime, mailboxSession, !isSelectedMailbox, flagsToBeSet); + final MessageUid uid = mailbox.appendMessage(message, datetime, mailboxSession, !isSelectedMailbox, flagsToBeSet); if (isSelectedMailbox) { selectedMailbox.addRecent(uid); } @@ -144,7 +145,7 @@ public class AppendProcessor extends AbstractMailboxProcessor<AppendRequest> { // in case of MULTIAPPEND support we will push more then one UID // here - okComplete(command, tag, ResponseCode.appendUid(uidValidity, new IdRange[] { new IdRange(uid) }), responder); + okComplete(command, tag, ResponseCode.appendUid(uidValidity, new UidRange[] { new UidRange(uid) }), responder); } catch (MailboxNotFoundException e) { // Indicates that the mailbox does not exist // So TRY CREATE http://git-wip-us.apache.org/repos/asf/james-project/blob/34242a5b/protocols/imap/src/main/java/org/apache/james/imap/processor/ExpungeProcessor.java ---------------------------------------------------------------------- diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/ExpungeProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/ExpungeProcessor.java index 7f3fae9..2c1a2a5 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/processor/ExpungeProcessor.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/ExpungeProcessor.java @@ -40,6 +40,7 @@ import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageManager; import org.apache.james.mailbox.MessageManager.MetaData; import org.apache.james.mailbox.MessageManager.MetaData.FetchGroup; +import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.exception.MessageRangeException; import org.apache.james.mailbox.model.MessageRange; @@ -104,12 +105,12 @@ public class ExpungeProcessor extends AbstractMailboxProcessor<ExpungeRequest> i } private int expunge(MessageManager mailbox, MessageRange range, ImapSession session, MailboxSession mailboxSession) throws MailboxException { - final Iterator<Long> it = mailbox.expunge(range, mailboxSession); + final Iterator<MessageUid> it = mailbox.expunge(range, mailboxSession); final SelectedMailbox selected = session.getSelected(); int expunged = 0; if (mailboxSession != null) { while (it.hasNext()) { - final long uid = it.next(); + final MessageUid uid = it.next(); selected.removeRecent(uid); expunged++; } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
