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 2011/05/30 20:01:06 UTC
svn commit: r1129279 - in /james/imap/trunk:
api/src/main/java/org/apache/james/imap/api/message/request/
api/src/main/java/org/apache/james/imap/api/process/
message/src/main/java/org/apache/james/imap/decode/
message/src/main/java/org/apache/james/im...
Author: norman
Date: Mon May 30 18:01:06 2011
New Revision: 1129279
URL: http://svn.apache.org/viewvc?rev=1129279&view=rev
Log:
Add support for SEARCHRES. See IMAP-309
Added:
james/imap/trunk/api/src/main/java/org/apache/james/imap/api/process/SearchResUtil.java
Modified:
james/imap/trunk/api/src/main/java/org/apache/james/imap/api/message/request/SearchResultOption.java
james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java
james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CopyCommandParser.java
james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExpungeCommandParser.java
james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java
james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java
james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StoreCommandParser.java
james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserAndParenthesesTest.java
james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserCharsetTest.java
james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserNotTest.java
james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserOrTest.java
james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserQuotedCharsetTest.java
james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserSearchKeySequenceSetTest.java
james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserSearchKeyTest.java
james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserTopLevelAndTest.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/SearchProcessor.java
Modified: james/imap/trunk/api/src/main/java/org/apache/james/imap/api/message/request/SearchResultOption.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/api/src/main/java/org/apache/james/imap/api/message/request/SearchResultOption.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/api/src/main/java/org/apache/james/imap/api/message/request/SearchResultOption.java (original)
+++ james/imap/trunk/api/src/main/java/org/apache/james/imap/api/message/request/SearchResultOption.java Mon May 30 18:01:06 2011
@@ -19,7 +19,7 @@
package org.apache.james.imap.api.message.request;
/**
- * Represent ESEARCH result options. See RFC4731
+ * Represent ESEARCH result options. See RFC4731 and RFC5182
*
*/
public enum SearchResultOption {
@@ -41,5 +41,12 @@ public enum SearchResultOption {
/**
* Return the count of matched messages
*/
- COUNT
+ COUNT,
+
+ /**
+ * Save the last ESEARCH returned sequence-set's.
+ *
+ * See RFC5182 2.4. Interaction with ESEARCH Extension
+ */
+ SAVE
}
Added: james/imap/trunk/api/src/main/java/org/apache/james/imap/api/process/SearchResUtil.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/api/src/main/java/org/apache/james/imap/api/process/SearchResUtil.java?rev=1129279&view=auto
==============================================================================
--- james/imap/trunk/api/src/main/java/org/apache/james/imap/api/process/SearchResUtil.java (added)
+++ james/imap/trunk/api/src/main/java/org/apache/james/imap/api/process/SearchResUtil.java Mon May 30 18:01:06 2011
@@ -0,0 +1,68 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.imap.api.process;
+
+import java.util.Arrays;
+
+import org.apache.james.imap.api.message.IdRange;
+
+/**
+ * Utility class which is used to support the SEARCHRES extension
+ *
+ */
+public class SearchResUtil {
+
+ private final static String SEARCHRES_SAVED_SET = "SEARCHRES_SAVED_SET";
+
+ /**
+ * Return the saved sequence-set which you can refer to with $. This method will
+ * return a IdRange[0] If no sequence-set is saved
+ *
+ * @param session
+ * @return sequenceSet
+ */
+ public static IdRange[] getSavedSequenceSet(ImapSession session) {
+ Object obj = session.getAttribute(SEARCHRES_SAVED_SET);
+ if (obj != null) {
+ return (IdRange[]) obj;
+ } else {
+ return new IdRange[0];
+ }
+ }
+
+ /**
+ * Save the given sequence-set which you can refer to later with $.
+ *
+ * @param session
+ * @param ranges
+ */
+ public static void saveSequenceSet(ImapSession session, IdRange[] ranges) {
+ session.setAttribute(SEARCHRES_SAVED_SET, IdRange.mergeRanges(Arrays.asList(ranges)).toArray(new IdRange[0]));
+ }
+
+ /**
+ * Reset the saved sequence-set
+ *
+ * @param session
+ */
+ public static void resetSavedSequenceSet(ImapSession session) {
+ session.setAttribute(SEARCHRES_SAVED_SET, null);
+ }
+}
Modified: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java (original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java Mon May 30 18:01:06 2011
@@ -42,6 +42,8 @@ import org.apache.james.imap.api.ImapCon
import org.apache.james.imap.api.display.HumanReadableText;
import org.apache.james.imap.api.message.IdRange;
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;
/**
* Wraps the client input reader with a bunch of convenience methods, allowing
@@ -574,10 +576,25 @@ public abstract class ImapRequestLineRea
}
/**
- * Reads a "message set" argument, and parses into an IdSet. Currently only
- * supports a single range of values.
+ * Reads a "message set" argument, and parses into an IdSet.
*/
public IdRange[] parseIdRange() throws DecodingException {
+ return parseIdRange(null);
+ }
+
+ /**
+ * 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 IdRange[] parseIdRange(ImapSession session) throws DecodingException {
+ if (session != null) {
+ char c = nextWordChar();
+ // Special handling for SEARCHRES extension. See RFC5182
+ if (c == '$') {
+ consume();
+ return SearchResUtil.getSavedSequenceSet(session);
+ }
+ }
+
CharacterValidator validator = new MessageSetCharValidator();
// Don't fail to parse id ranges which are enclosed by "(..)"
// See IMAP-283
@@ -607,6 +624,7 @@ public abstract class ImapRequestLineRea
return (IdRange[]) merged.toArray(new IdRange[merged.size()]);
}
+
/**
* Parse a range which use a ":" as delimiter
*
Modified: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CopyCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CopyCommandParser.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CopyCommandParser.java (original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CopyCommandParser.java Mon May 30 18:01:06 2011
@@ -46,7 +46,7 @@ public class CopyCommandParser extends A
* boolean, org.apache.james.imap.api.process.ImapSession)
*/
protected ImapMessage decode(ImapCommand command, ImapRequestLineReader request, String tag, boolean useUids, ImapSession session) throws DecodingException {
- IdRange[] idSet = request.parseIdRange();
+ IdRange[] idSet = request.parseIdRange(session);
String mailboxName = request.mailbox();
request.eol();
final ImapMessage result = new CopyRequest(command, idSet, mailboxName, useUids, tag);
Modified: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExpungeCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExpungeCommandParser.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExpungeCommandParser.java (original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExpungeCommandParser.java Mon May 30 18:01:06 2011
@@ -48,7 +48,7 @@ public class ExpungeCommandParser extend
protected ImapMessage decode(ImapCommand command, ImapRequestLineReader request, String tag, boolean useUids, ImapSession session) throws DecodingException {
IdRange[] uidSet = null;
if (useUids) {
- uidSet = request.parseIdRange();
+ uidSet = request.parseIdRange(session);
}
request.eol();
Modified: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java (original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java Mon May 30 18:01:06 2011
@@ -227,7 +227,7 @@ public class FetchCommandParser extends
* boolean, org.apache.james.imap.api.process.ImapSession)
*/
protected ImapMessage decode(ImapCommand command, ImapRequestLineReader request, String tag, boolean useUids, ImapSession session) throws DecodingException {
- IdRange[] idSet = request.parseIdRange();
+ IdRange[] idSet = request.parseIdRange(session);
FetchData fetch = fetchRequest(request);
request.eol();
Modified: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java (original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java Mon May 30 18:01:06 2011
@@ -68,21 +68,23 @@ public class SearchCommandParser extends
* @param isFirstToken
* true when this is the first token read, false otherwise
*/
- protected SearchKey searchKey(ImapRequestLineReader request, Charset charset, boolean isFirstToken) throws DecodingException, IllegalCharsetNameException, UnsupportedCharsetException {
+ protected SearchKey searchKey(ImapSession session, ImapRequestLineReader request, Charset charset, boolean isFirstToken) throws DecodingException, IllegalCharsetNameException, UnsupportedCharsetException {
final char next = request.nextChar();
- if (next >= '0' && next <= '9' || next == '*') {
- return sequenceSet(request);
+
+ if (next >= '0' && next <= '9' || next == '*' || next == '$') {
+ return sequenceSet(session, request);
} else if (next == '(') {
- return paren(request, charset);
+ return paren(session, request, charset);
} else {
final int cap = consumeAndCap(request);
switch (cap) {
+
case 'A':
return a(request);
case 'B':
return b(request, charset);
case 'C':
- return c(request, isFirstToken, charset);
+ return c(session, request, isFirstToken, charset);
case 'D':
return d(request);
case 'E':
@@ -104,9 +106,9 @@ public class SearchCommandParser extends
case 'M':
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
case 'N':
- return n(request, charset);
+ return n(session, request, charset);
case 'O':
- return o(request, charset);
+ return o(session, request, charset);
case 'P':
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
case 'Q':
@@ -129,21 +131,21 @@ public class SearchCommandParser extends
}
}
- private SearchKey paren(ImapRequestLineReader request, Charset charset) throws DecodingException {
+ private SearchKey paren(ImapSession session, ImapRequestLineReader request, Charset charset) throws DecodingException {
request.consume();
List<SearchKey> keys = new ArrayList<SearchKey>();
- addUntilParen(request, keys, charset);
+ addUntilParen(session, request, keys, charset);
return SearchKey.buildAnd(keys);
}
- private void addUntilParen(ImapRequestLineReader request, List<SearchKey> keys, Charset charset) throws DecodingException {
+ private void addUntilParen(ImapSession session, ImapRequestLineReader request, List<SearchKey> keys, Charset charset) throws DecodingException {
final char next = request.nextWordChar();
if (next == ')') {
request.consume();
} else {
- final SearchKey key = searchKey(request, null, false);
+ final SearchKey key = searchKey(session, request, null, false);
keys.add(key);
- addUntilParen(request, keys, charset);
+ addUntilParen(session, request, keys, charset);
}
}
@@ -165,19 +167,19 @@ public class SearchCommandParser extends
return result;
}
- private SearchKey c(ImapRequestLineReader request, final boolean isFirstToken, final Charset charset) throws DecodingException, IllegalCharsetNameException, UnsupportedCharsetException {
+ private SearchKey c(ImapSession session, ImapRequestLineReader request, final boolean isFirstToken, final Charset charset) throws DecodingException, IllegalCharsetNameException, UnsupportedCharsetException {
final int next = consumeAndCap(request);
switch (next) {
case 'C':
return cc(request, charset);
case 'H':
- return charset(request, isFirstToken);
+ return charset(session, request, isFirstToken);
default:
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
}
}
- private SearchKey charset(ImapRequestLineReader request, final boolean isFirstToken) throws DecodingException, IllegalCharsetNameException, UnsupportedCharsetException {
+ private SearchKey charset(ImapSession session, ImapRequestLineReader request, final boolean isFirstToken) throws DecodingException, IllegalCharsetNameException, UnsupportedCharsetException {
final SearchKey result;
nextIsA(request);
nextIsR(request);
@@ -191,7 +193,7 @@ public class SearchCommandParser extends
final String value = request.astring();
final Charset charset = Charset.forName(value);
request.nextWordChar();
- result = searchKey(request, charset, false);
+ result = searchKey(session, request, charset, false);
return result;
}
@@ -301,7 +303,7 @@ public class SearchCommandParser extends
}
}
- private SearchKey o(ImapRequestLineReader request, Charset charset) throws DecodingException {
+ private SearchKey o(ImapSession session, ImapRequestLineReader request, Charset charset) throws DecodingException {
final int next = consumeAndCap(request);
switch (next) {
case 'L':
@@ -309,7 +311,7 @@ public class SearchCommandParser extends
case 'N':
return on(request);
case 'R':
- return or(request, charset);
+ return or(session, request, charset);
default:
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
}
@@ -326,13 +328,13 @@ public class SearchCommandParser extends
}
}
- private SearchKey n(ImapRequestLineReader request, Charset charset) throws DecodingException {
+ private SearchKey n(ImapSession session, ImapRequestLineReader request, Charset charset) throws DecodingException {
final int next = consumeAndCap(request);
switch (next) {
case 'E':
return _new(request);
case 'O':
- return not(request, charset);
+ return not(session, request, charset);
default:
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
}
@@ -526,21 +528,21 @@ public class SearchCommandParser extends
return result;
}
- private SearchKey or(ImapRequestLineReader request, Charset charset) throws DecodingException {
+ private SearchKey or(ImapSession session, ImapRequestLineReader request, Charset charset) throws DecodingException {
final SearchKey result;
nextIsSpace(request);
- final SearchKey firstKey = searchKey(request, charset, false);
+ final SearchKey firstKey = searchKey(session, request, charset, false);
nextIsSpace(request);
- final SearchKey secondKey = searchKey(request, charset, false);
+ final SearchKey secondKey = searchKey(session, request, charset, false);
result = SearchKey.buildOr(firstKey, secondKey);
return result;
}
- private SearchKey not(ImapRequestLineReader request, Charset charset) throws DecodingException {
+ private SearchKey not(ImapSession session, ImapRequestLineReader request, Charset charset) throws DecodingException {
final SearchKey result;
nextIsT(request);
nextIsSpace(request);
- final SearchKey nextKey = searchKey(request, charset, false);
+ final SearchKey nextKey = searchKey(session, request, charset, false);
result = SearchKey.buildNot(nextKey);
return result;
}
@@ -707,8 +709,8 @@ public class SearchCommandParser extends
return result;
}
- private SearchKey sequenceSet(ImapRequestLineReader request) throws DecodingException {
- final IdRange[] range = request.parseIdRange();
+ private SearchKey sequenceSet(ImapSession session, ImapRequestLineReader request) throws DecodingException {
+ final IdRange[] range = request.parseIdRange(session);
final SearchKey result = SearchKey.buildSequenceSet(range);
return result;
}
@@ -850,6 +852,11 @@ public class SearchCommandParser extends
nextIs(request, 'L', 'l');
}
+
+ private void nextIsV(ImapRequestLineReader request) throws DecodingException {
+ nextIs(request, 'V', 'v');
+ }
+
private void nextIs(ImapRequestLineReader request, final char upper, final char lower) throws DecodingException {
final char next = request.consume();
if (next != upper && next != lower) {
@@ -857,16 +864,16 @@ public class SearchCommandParser extends
}
}
- public SearchKey decode(ImapRequestLineReader request) throws DecodingException, IllegalCharsetNameException, UnsupportedCharsetException {
+ public SearchKey decode(ImapSession session, ImapRequestLineReader request) throws DecodingException, IllegalCharsetNameException, UnsupportedCharsetException {
request.nextWordChar();
- final SearchKey firstKey = searchKey(request, null, true);
+ final SearchKey firstKey = searchKey(session, request, null, true);
final SearchKey result;
if (request.nextChar() == ' ') {
List<SearchKey> keys = new ArrayList<SearchKey>();
keys.add(firstKey);
while (request.nextChar() == ' ') {
request.nextWordChar();
- final SearchKey key = searchKey(request, null, false);
+ final SearchKey key = searchKey(session, request, null, false);
keys.add(key);
}
result = SearchKey.buildAnd(keys);
@@ -935,6 +942,13 @@ public class SearchCommandParser extends
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
}
break;
+ // Check for SAVE options which is part of the SEARCHRES extension
+ case 'S':
+ nextIsA(reader);
+ nextIsV(reader);
+ nextIsE(reader);
+ options.add(SearchResultOption.SAVE);
+ break;
default:
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown search key");
}
@@ -987,7 +1001,7 @@ public class SearchCommandParser extends
}
// Parse the search term from the request
- final SearchKey key = decode(request);
+ final SearchKey key = decode(session, request);
final SearchKey finalKey;
if (recent != null) {
Modified: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StoreCommandParser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StoreCommandParser.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StoreCommandParser.java (original)
+++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/StoreCommandParser.java Mon May 30 18:01:06 2011
@@ -49,7 +49,7 @@ public class StoreCommandParser extends
* boolean, org.apache.james.imap.api.process.ImapSession)
*/
protected ImapMessage decode(ImapCommand command, ImapRequestLineReader request, String tag, boolean useUids, ImapSession session) throws DecodingException {
- final IdRange[] idSet = request.parseIdRange();
+ final IdRange[] idSet = request.parseIdRange(session);
final Boolean sign;
boolean silent = false;
Modified: james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserAndParenthesesTest.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserAndParenthesesTest.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserAndParenthesesTest.java (original)
+++ james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserAndParenthesesTest.java Mon May 30 18:01:06 2011
@@ -196,7 +196,7 @@ public class SearchCommandParserAndParen
new ByteArrayInputStream(input.getBytes("US-ASCII")),
new ByteArrayOutputStream());
- final SearchKey result = parser.decode(reader);
+ final SearchKey result = parser.decode(null, reader);
assertEquals(in.key, result);
}
Modified: james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserCharsetTest.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserCharsetTest.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserCharsetTest.java (original)
+++ james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserCharsetTest.java Mon May 30 18:01:06 2011
@@ -186,7 +186,7 @@ public class SearchCommandParserCharsetT
new ByteArrayInputStream(NioUtils.add(NioUtils.add(CHARSET,
term), BYTES_UTF8_NON_ASCII_SEARCH_TERM)),
new ByteArrayOutputStream());
- final SearchKey searchKey = parser.searchKey(reader, null, true);
+ final SearchKey searchKey = parser.searchKey(null, reader, null, true);
assertEquals(key, searchKey);
}
@@ -196,7 +196,7 @@ public class SearchCommandParserCharsetT
new ByteArrayInputStream(input.getBytes(charset)),
new ByteArrayOutputStream());
- final SearchKey searchKey = parser.searchKey(reader, null, isFirst);
+ final SearchKey searchKey = parser.searchKey(null, reader, null, isFirst);
assertEquals(key, searchKey);
}
Modified: james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserNotTest.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserNotTest.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserNotTest.java (original)
+++ james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserNotTest.java Mon May 30 18:01:06 2011
@@ -120,6 +120,6 @@ public class SearchCommandParserNotTest
new ByteArrayInputStream(input.getBytes("US-ASCII")),
new ByteArrayOutputStream());
- assertEquals(key, parser.searchKey(reader, null, false));
+ assertEquals(key, parser.searchKey(null, reader, null, false));
}
}
Modified: james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserOrTest.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserOrTest.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserOrTest.java (original)
+++ james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserOrTest.java Mon May 30 18:01:06 2011
@@ -180,7 +180,7 @@ public class SearchCommandParserOrTest {
new ByteArrayInputStream(input.getBytes("US-ASCII")),
new ByteArrayOutputStream());
- assertEquals(key, parser.searchKey(reader, null, false));
+ assertEquals(key, parser.searchKey(null, reader, null, false));
}
public class Input {
Modified: james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserQuotedCharsetTest.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserQuotedCharsetTest.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserQuotedCharsetTest.java (original)
+++ james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserQuotedCharsetTest.java Mon May 30 18:01:06 2011
@@ -164,7 +164,7 @@ public class SearchCommandParserQuotedCh
.getBytes("US-ASCII")),
BYTES_QUOTED_UTF8_LENGTHY_NON_ASCII_SEARCH_TERM)),
new ByteArrayOutputStream());
- final SearchKey searchKey = parser.searchKey(reader, null, true);
+ final SearchKey searchKey = parser.searchKey(null, reader, null, true);
assertEquals(key, searchKey);
}
@@ -176,7 +176,7 @@ public class SearchCommandParserQuotedCh
.getBytes("US-ASCII")),
BYTES_QUOTED_UTF8_NON_ASCII_SEARCH_TERM)),
new ByteArrayOutputStream());
- final SearchKey searchKey = parser.searchKey(reader, null, true);
+ final SearchKey searchKey = parser.searchKey(null, reader, null, true);
assertEquals(key, searchKey);
}
@@ -287,7 +287,7 @@ public class SearchCommandParserQuotedCh
new ByteArrayInputStream(add(add(CHARSET, term),
BYTES_UTF8_NON_ASCII_SEARCH_TERM)),
new ByteArrayOutputStream());
- final SearchKey searchKey = parser.searchKey(reader, null, true);
+ final SearchKey searchKey = parser.searchKey(null, reader, null, true);
assertEquals(key, searchKey);
}
@@ -297,7 +297,7 @@ public class SearchCommandParserQuotedCh
new ByteArrayInputStream(input.getBytes(charset)),
new ByteArrayOutputStream());
- final SearchKey searchKey = parser.searchKey(reader, null, isFirst);
+ final SearchKey searchKey = parser.searchKey(null, reader, null, isFirst);
assertEquals(key, searchKey);
}
Modified: james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserSearchKeySequenceSetTest.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserSearchKeySequenceSetTest.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserSearchKeySequenceSetTest.java (original)
+++ james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserSearchKeySequenceSetTest.java Mon May 30 18:01:06 2011
@@ -107,7 +107,7 @@ public class SearchCommandParserSearchKe
new ByteArrayInputStream(input.getBytes("US-ASCII")),
new ByteArrayOutputStream());
- final SearchKey searchKey = parser.searchKey(reader, null, false);
+ final SearchKey searchKey = parser.searchKey(null, reader, null, false);
assertEquals(key, searchKey);
}
}
Modified: james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserSearchKeyTest.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserSearchKeyTest.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserSearchKeyTest.java (original)
+++ james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserSearchKeyTest.java Mon May 30 18:01:06 2011
@@ -386,7 +386,7 @@ public class SearchCommandParserSearchKe
new ByteArrayInputStream(input.getBytes("US-ASCII")),
new ByteArrayOutputStream());
- assertEquals(key, parser.searchKey(reader, null, false));
+ assertEquals(key, parser.searchKey(null, reader, null, false));
}
@Test
@@ -740,7 +740,7 @@ public class SearchCommandParserSearchKe
new ByteArrayOutputStream());
try {
- parser.searchKey(reader, null, false);
+ parser.searchKey(null, reader, null, false);
fail("Expected protocol exception to be throw since input is invalid");
} catch (DecodingException e) {
// expected
Modified: james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserTopLevelAndTest.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserTopLevelAndTest.java?rev=1129279&r1=1129278&r2=1129279&view=diff
==============================================================================
--- james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserTopLevelAndTest.java (original)
+++ james/imap/trunk/message/src/test/java/org/apache/james/imap/decode/parser/SearchCommandParserTopLevelAndTest.java Mon May 30 18:01:06 2011
@@ -198,6 +198,6 @@ public class SearchCommandParserTopLevel
new ByteArrayInputStream(input.getBytes("US-ASCII")),
new ByteArrayOutputStream());
- assertEquals(input, key, parser.decode(reader));
+ assertEquals(input, key, parser.decode(null, reader));
}
}
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=1129279&r1=1129278&r2=1129279&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 May 30 18:01:06 2011
@@ -33,6 +33,7 @@ import org.apache.james.imap.api.message
import org.apache.james.imap.api.message.response.StatusResponseFactory;
import org.apache.james.imap.api.process.ImapProcessor;
import org.apache.james.imap.api.process.ImapSession;
+import org.apache.james.imap.api.process.SearchResUtil;
import org.apache.james.imap.api.process.SelectedMailbox;
import org.apache.james.imap.message.request.AbstractMailboxSelectionRequest;
import org.apache.james.imap.message.response.ExistsResponse;
@@ -84,6 +85,11 @@ abstract class AbstractSelectionProcesso
final MailboxPath fullMailboxPath = buildFullPath(session, mailboxName);
final MessageManager.MetaData metaData = selectMailbox(fullMailboxPath, session);
respond(tag, command, session, metaData, responder);
+
+ // Reset the saved sequence-set after successful SELECT / EXAMINE
+ // See RFC 5812 2.1. Normative Description of the SEARCHRES Extension
+ SearchResUtil.resetSavedSequenceSet(session);
+
} catch (MailboxNotFoundException e) {
session.getLog().debug("Select failed", e);
responder.respond(statusResponseFactory.taggedNo(tag, command, HumanReadableText.FAILURE_NO_SUCH_MAILBOX));
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=1129279&r1=1129278&r2=1129279&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 May 30 18:01:06 2011
@@ -42,6 +42,7 @@ import org.apache.james.imap.api.message
import org.apache.james.imap.api.message.response.StatusResponseFactory;
import org.apache.james.imap.api.process.ImapProcessor;
import org.apache.james.imap.api.process.ImapSession;
+import org.apache.james.imap.api.process.SearchResUtil;
import org.apache.james.imap.api.process.SelectedMailbox;
import org.apache.james.imap.message.request.SearchRequest;
import org.apache.james.imap.message.response.ESearchResponse;
@@ -73,10 +74,13 @@ public class SearchProcessor extends Abs
* org.apache.james.imap.api.process.ImapProcessor.Responder)
*/
protected void doProcess(SearchRequest request, ImapSession session, String tag, ImapCommand command, Responder responder) {
+ final SearchOperation operation = request.getSearchOperation();
+ final SearchKey searchKey = operation.getSearchKey();
+ final boolean useUids = request.isUseUids();
+ List<SearchResultOption> resultOptions = operation.getResultOptions();
+
try {
- final SearchOperation operation = request.getSearchOperation();
- final SearchKey searchKey = operation.getSearchKey();
- final boolean useUids = request.isUseUids();
+
final MessageManager mailbox = getSelectedMailbox(session);
final SearchQuery query = toQuery(searchKey, session);
@@ -84,20 +88,11 @@ public class SearchProcessor extends Abs
final Collection<Long> results = findIds(useUids, session, mailbox, query);
final long[] ids = toArray(results);
- List<SearchResultOption> resultOptions = operation.getResultOptions();
final ImapResponseMessage response;
if (resultOptions == null || resultOptions.isEmpty()) {
response = new SearchResponse(ids);
} else {
- long min = -1;
- long max = -1;
- long count = ids.length;
IdRange[] idRanges;
-
- if (ids.length > 0) {
- min = ids[0];
- max = ids[ids.length -1];
- }
List<Long> idList = new ArrayList<Long>(ids.length);
for ( int i = 0; i < ids.length; i++) {
idList.add(ids[i]);
@@ -108,10 +103,53 @@ public class SearchProcessor extends Abs
MessageRange range = ranges.get(i);
idRanges[i] = new IdRange(range.getUidFrom(), range.getUidTo());
}
+
+ boolean esearch = false;
+ for (int i = 0; i < resultOptions.size(); i++) {
+ if (SearchResultOption.SAVE != resultOptions.get(i)) {
+ esearch = true;
+ break;
+ }
+ }
+
+ if (esearch) {
+ long min = -1;
+ long max = -1;
+ long count = ids.length;
+
+ if (ids.length > 0) {
+ min = ids[0];
+ max = ids[ids.length -1];
+ }
+
+
+ // Save the sequence-set for later usage. This is part of SEARCHRES
+ if (resultOptions.contains(SearchResultOption.SAVE)) {
+ if (resultOptions.contains(SearchResultOption.ALL) || resultOptions.contains(SearchResultOption.COUNT)) {
+ // if the options contain ALL or COUNT we need to save the complete sequence-set
+ SearchResUtil.saveSequenceSet(session, idRanges);
+ } else {
+ List<IdRange> savedRanges = new ArrayList<IdRange>();
+ if (resultOptions.contains(SearchResultOption.MIN)) {
+ // Store the MIN
+ savedRanges.add(new IdRange(min));
+ }
+ if (resultOptions.contains(SearchResultOption.MAX)) {
+ // Store the MAX
+ savedRanges.add(new IdRange(max));
+ }
+ SearchResUtil.saveSequenceSet(session, savedRanges.toArray(new IdRange[0]));
+ }
+ }
+ response = new ESearchResponse(min, max, count, idRanges, tag, useUids, resultOptions);
+ } else {
+ // Just save the returned sequence-set as this is not SEARCHRES + ESEARCH
+ SearchResUtil.saveSequenceSet(session, idRanges);
+ response = new SearchResponse(ids);
- response = new ESearchResponse(min, max, count, idRanges, tag, useUids, resultOptions);
-
+ }
}
+
responder.respond(response);
boolean omitExpunged = (!useUids);
@@ -123,6 +161,13 @@ public class SearchProcessor extends Abs
} catch (MailboxException e) {
session.getLog().debug("Search failed", e);
no(command, tag, responder, HumanReadableText.SEARCH_FAILED);
+
+ if (resultOptions.contains(SearchResultOption.SAVE)) {
+ // Reset the saved sequence-set on a BAD response if the SAVE option was used.
+ //
+ // See RFC5182 2.1.Normative Description of the SEARCHRES Extension
+ SearchResUtil.resetSavedSequenceSet(session);
+ }
}
}
@@ -316,6 +361,6 @@ public class SearchProcessor extends Abs
* @see org.apache.james.imap.processor.CapabilityImplementingProcessor#getImplementedCapabilities(org.apache.james.imap.api.process.ImapSession)
*/
public List<String> getImplementedCapabilities(ImapSession session) {
- return Arrays.asList("WITHIN", "ESEARCH");
+ return Arrays.asList("WITHIN", "ESEARCH", "SEARCHRES");
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org