001 /* 002 * Copyright 2010 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package com.hs.mail.imap.message.builder; 017 018 import java.io.UnsupportedEncodingException; 019 import java.util.LinkedList; 020 021 import javax.mail.Flags; 022 import javax.mail.Message; 023 import javax.mail.internet.MimeUtility; 024 import javax.mail.search.ComparisonTerm; 025 026 import com.hs.mail.imap.message.SequenceRange; 027 import com.hs.mail.imap.message.request.ImapRequest; 028 import com.hs.mail.imap.message.request.SearchRequest; 029 import com.hs.mail.imap.message.search.AllKey; 030 import com.hs.mail.imap.message.search.AndKey; 031 import com.hs.mail.imap.message.search.FlagKey; 032 import com.hs.mail.imap.message.search.FromStringKey; 033 import com.hs.mail.imap.message.search.HeaderKey; 034 import com.hs.mail.imap.message.search.InternalDateKey; 035 import com.hs.mail.imap.message.search.KeywordKey; 036 import com.hs.mail.imap.message.search.NotKey; 037 import com.hs.mail.imap.message.search.OrKey; 038 import com.hs.mail.imap.message.search.RecipientStringKey; 039 import com.hs.mail.imap.message.search.SearchKey; 040 import com.hs.mail.imap.message.search.SearchKeyList; 041 import com.hs.mail.imap.message.search.SentDateKey; 042 import com.hs.mail.imap.message.search.SequenceKey; 043 import com.hs.mail.imap.message.search.SizeKey; 044 import com.hs.mail.imap.message.search.SubjectKey; 045 import com.hs.mail.imap.message.search.TextKey; 046 import com.hs.mail.imap.parser.ParseException; 047 import com.hs.mail.imap.parser.Token; 048 import com.hs.mail.imap.server.codec.DecoderUtils; 049 import com.hs.mail.imap.server.codec.ImapMessage; 050 import com.hs.mail.util.MailUtils; 051 052 /** 053 * 054 * @author Won Chul Doh 055 * @since 30 Jan, 2010 056 * 057 */ 058 public class SearchRequestBuilder extends AbstractUidRequestBuilder { 059 060 @Override 061 public ImapRequest createRequest(String tag, String command, 062 ImapMessage message, boolean useUID) { 063 LinkedList<Token> tokens = message.getTokens(); 064 String charset = parseCharset(tokens); 065 SearchKey searchKey = createSearchKey(tag, tokens, charset); 066 return new SearchRequest(tag, command, charset, searchKey, useUID); 067 } 068 069 protected SearchKey createSearchKey(String tag, LinkedList<Token> tokens, 070 String charset) { 071 try { 072 SearchKeyList searchKey = new AndKey(); 073 do { 074 searchKey.addKey(decodeSearchKey(tokens, charset)); 075 } while (tokens.peek() != null); 076 removeAllKey(searchKey); 077 if (searchKey.size() == 1) { 078 return searchKey.getSearchKeys().get(0); 079 } else { 080 return searchKey; 081 } 082 } catch (Exception e) { 083 throw new ParseException(tag, "Error while parsing command"); 084 } 085 } 086 087 private void removeAllKey(SearchKeyList searchKey) { 088 if (searchKey.size() > 1) { 089 searchKey.getSearchKeys().remove(new AllKey()); 090 } 091 } 092 093 protected String parseCharset(LinkedList<Token> tokens) { 094 Token token = tokens.peek(); 095 if ("CHARSET".equals(token.value.toUpperCase())) { 096 tokens.remove(); 097 return MimeUtility.javaCharset(tokens.remove().value); 098 } else { 099 return null; 100 } 101 } 102 103 private SearchKey decodeSearchKey(LinkedList<Token> tokens, String charset) 104 throws Exception { 105 Token token = tokens.peek(); 106 SearchKey key = null; 107 if (token.type == Token.Type.KEYWORD) { 108 tokens.remove(); 109 String value = token.value.toUpperCase(); 110 if ("ALL".equals(value)) { 111 key = new AllKey(); 112 } else if ("ANSWERED".equals(value)) { 113 key = new FlagKey(Flags.Flag.ANSWERED, true); 114 } else if ("BCC".equals(value)) { 115 key = new RecipientStringKey(Message.RecipientType.BCC, decode( 116 (token = tokens.remove()).value, charset)); 117 } else if ("BEFORE".equals(value)) { 118 key = new InternalDateKey(ComparisonTerm.LT, DecoderUtils 119 .parseDate((token = tokens.remove()).value)); 120 } else if ("BODY".equals(value)) { 121 key = new TextKey(decode((token = tokens.remove()).value, 122 charset), false); 123 } else if ("CC".equals(value)) { 124 key = new RecipientStringKey(Message.RecipientType.CC, decode( 125 (token = tokens.remove()).value, charset)); 126 } else if ("DELETED".equals(value)) { 127 key = new FlagKey(Flags.Flag.DELETED, true); 128 } else if ("FLAGGED".equals(value)) { 129 key = new FlagKey(Flags.Flag.FLAGGED, true); 130 } else if ("FROM".equals(value)) { 131 key = new FromStringKey(decode((token = tokens.remove()).value, 132 charset)); 133 } else if ("KEYWORD".equals(value)) { 134 key = new KeywordKey(decode((token = tokens.remove()).value, 135 charset), true); 136 } else if ("NEW".equals(value)) { 137 key = new AndKey(new FlagKey(Flags.Flag.RECENT, true), 138 new FlagKey(Flags.Flag.SEEN, false)); 139 } else if ("OLD".equals(value)) { 140 key = new FlagKey(Flags.Flag.RECENT, false); 141 } else if ("ON".equals(value)) { 142 key = new InternalDateKey(ComparisonTerm.EQ, DecoderUtils 143 .parseDate((token = tokens.remove()).value)); 144 } else if ("RECENT".equals(value)) { 145 key = new FlagKey(Flags.Flag.RECENT, true); 146 } else if ("SEEN".equals(value)) { 147 key = new FlagKey(Flags.Flag.SEEN, true); 148 } else if ("SINCE".equals(value)) { 149 key = new InternalDateKey(ComparisonTerm.GE, DecoderUtils 150 .parseDate((token = tokens.remove()).value)); 151 } else if ("SUBJECT".equals(value)) { 152 key = new SubjectKey(decode((token = tokens.remove()).value, 153 charset)); 154 } else if ("TEXT".equals(value)) { 155 key = new TextKey((token = tokens.remove()).value); 156 } else if ("TO".equals(value)) { 157 key = new RecipientStringKey(Message.RecipientType.TO, decode( 158 (token = tokens.remove()).value, charset)); 159 } else if ("UNANSWERED".equals(value)) { 160 key = new FlagKey(Flags.Flag.ANSWERED, false); 161 } else if ("UNDELETED".equals(value)) { 162 key = new FlagKey(Flags.Flag.DELETED, false); 163 } else if ("UNFLAGGED".equals(value)) { 164 key = new FlagKey(Flags.Flag.FLAGGED, false); 165 } else if ("UNKEYWORD".equals(value)) { 166 key = new KeywordKey((token = tokens.remove()).value, false); 167 } else if ("UNSEEN".equals(value)) { 168 key = new FlagKey(Flags.Flag.SEEN, false); 169 } else if ("DRAFT".equals(value)) { 170 key = new FlagKey(Flags.Flag.DRAFT, true); 171 } else if ("HEADER".equals(value)) { 172 String headerName = tokens.remove().value; 173 key = new HeaderKey(headerName, (token = tokens.remove()).value); 174 } else if ("LARGER".equals(value)) { 175 key = new SizeKey(ComparisonTerm.GT, Integer 176 .parseInt((token = tokens.remove()).value)); 177 } else if ("NOT".equals(value)) { 178 key = new NotKey(decodeSearchKey(tokens, charset)); 179 } else if ("OR".equals(value)) { 180 SearchKey k1 = decodeSearchKey(tokens, charset); 181 SearchKey k2 = decodeSearchKey(tokens, charset); 182 key = new OrKey(k1, k2); 183 } else if ("SENTBEFORE".equals(value)) { 184 key = new SentDateKey(ComparisonTerm.LT, DecoderUtils 185 .parseDate((token = tokens.remove()).value)); 186 } else if ("SENTON".equals(value)) { 187 key = new SentDateKey(ComparisonTerm.EQ, DecoderUtils 188 .parseDate((token = tokens.remove()).value)); 189 } else if ("SENTSINCE".equals(value)) { 190 key = new SentDateKey(ComparisonTerm.GE, DecoderUtils 191 .parseDate((token = tokens.remove()).value)); 192 } else if ("SMALLER".equals(value)) { 193 key = new SizeKey(ComparisonTerm.LT, Integer 194 .parseInt((token = tokens.remove()).value)); 195 } else if ("UID".equals(value)) { 196 SequenceRange[] sequenceSet = parseSequenceSet(tokens); 197 key = new SequenceKey(sequenceSet, true); 198 } else if ("UNDRAFT".equals(value)) { 199 key = new FlagKey(Flags.Flag.DRAFT, false); 200 } 201 } else if (token.type == Token.Type.SEQ_NUMBER 202 || token.type == Token.Type.SEQ_RANGE) { 203 SequenceRange[] sequenceSet = parseSequenceSet(tokens); 204 key = new SequenceKey(sequenceSet); 205 } else if (token.type == Token.Type.LPAREN) { 206 tokens.remove(); 207 key = new AndKey(); 208 do { 209 if (token.type == Token.Type.RPAREN) { 210 tokens.remove(); 211 break; 212 } 213 ((AndKey) key).addKey(decodeSearchKey(tokens, charset)); 214 token = tokens.peek(); 215 } while (true); 216 } else { 217 throw new Exception("Unexpected token: " + token); 218 } 219 return key; 220 } 221 222 private static String decode(String s, String charset) { 223 if (charset != null) { 224 try { 225 if (!MailUtils.isAscii(s) && !"ISO8859_1".equals(charset)) { 226 return new String(s.getBytes("ISO8859_1"), charset); 227 } 228 } catch (UnsupportedEncodingException e) { 229 } 230 } 231 return s; 232 } 233 234 }