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 rd...@apache.org on 2007/10/27 12:13:33 UTC

svn commit: r589068 - in /james/server/trunk: core-library/src/main/java/org/apache/james/mailboxmanager/ core-library/src/main/java/org/apache/james/mailboxmanager/mailbox/ core-library/src/main/java/org/apache/james/mailboxmanager/wrapper/ imap-mailb...

Author: rdonkin
Date: Sat Oct 27 03:13:30 2007
New Revision: 589068

URL: http://svn.apache.org/viewvc?rev=589068&view=rev
Log:
JAMES-806 Search command implementation. Contributed by Zsombor Gegesy (https://issues.apache.org/jira/browse/JAMES-806). Only part of the proposed implementation has been committed.

Added:
    james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/SearchParameters.java
Modified:
    james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/mailbox/SearchableMailbox.java
    james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/wrapper/ImapMailboxSessionWrapper.java
    james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SearchProcessor.java
    james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/commands/SearchCommand.java
    james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailbox.java

Added: james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/SearchParameters.java
URL: http://svn.apache.org/viewvc/james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/SearchParameters.java?rev=589068&view=auto
==============================================================================
--- james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/SearchParameters.java (added)
+++ james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/SearchParameters.java Sat Oct 27 03:13:30 2007
@@ -0,0 +1,300 @@
+/****************************************************************
+ * 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.mailboxmanager;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class SearchParameters {
+
+	public static final String HEADER = "HEADER";
+    public static final String UID = "UID";
+    public static final String NOT = "NOT";
+    public static final String OR = "OR";
+    public static final String SMALLER = "SMALLER";
+    public static final String LARGER = "LARGER";
+    public static final String SINCE = "SINCE";
+    public static final String SENTSINCE = "SENTSINCE";
+    public static final String SENTON = "SENTON";
+    public static final String SENTBEFORE = "SENTBEFORE";
+    public static final String ON = "ON";
+    public static final String BEFORE = "BEFORE";
+    public static final String UNKEYWORD = "UNKEYWORD";
+    public static final String TO = "TO";
+    public static final String TEXT = "TEXT";
+    public static final String SUBJECT = "SUBJECT";
+    public static final String KEYWORD = "KEYWORD";
+    public static final String FROM = "FROM";
+    public static final String CC = "CC";
+    public static final String BODY = "BODY";
+    public static final String BCC = "BCC";
+    public static final String UNSEEN = "UNSEEN";
+    public static final String UNFLAGGED = "UNFLAGGED";
+    public static final String UNDRAFT = "UNDRAFT";
+    public static final String UNDELETED = "UNDELETED";
+    public static final String UNANSWERED = "UNANSWERED";
+    public static final String SEEN = "SEEN";
+    public static final String RECENT = "RECENT";
+    public static final String OLD = "OLD";
+    public static final String NEW = "NEW";
+    public static final String FLAGGED = "FLAGGED";
+    public static final String DRAFT = "DRAFT";
+    public static final String DELETED = "DELETED";
+    public static final String ANSWERED = "ANSWERED";
+    public static final String ALL = "ALL";
+    
+    public final static Set BASE_SEARCH_TERMS = Collections.unmodifiableSet(new HashSet(Arrays.asList(new String[] {
+        	ALL, ANSWERED, DELETED, DRAFT, FLAGGED, NEW, OLD, RECENT, SEEN,
+        	UNANSWERED, UNDELETED, UNDRAFT, UNFLAGGED, UNSEEN
+        })));
+    
+    public final static Set STRING_SEARCH_TERMS = Collections.unmodifiableSet(new HashSet(Arrays.asList(new String[] {
+        	BCC, BODY, CC, FROM, KEYWORD, SUBJECT, TEXT, TO, UNKEYWORD
+        })));
+    public final static Set DATE_SEARCH_TERMS = Collections.unmodifiableSet(new HashSet(Arrays.asList(new String[] {
+        	BEFORE, ON, SENTBEFORE, SENTON, SENTSINCE , SINCE
+        })));
+    public final static Set NUMBER_SEARCH_TERMS = Collections.unmodifiableSet(new HashSet(Arrays.asList(new String[] {
+        	LARGER, SMALLER
+        })));
+
+	public final static Set SPECIAL_SEARCH_TERMS = new HashSet(Arrays.asList(new String[] {
+        	OR, NOT,UID, HEADER
+    }));
+
+		
+	List criterias = new ArrayList();
+	
+	public void addCriteria(SearchCriteria crit) {
+		criterias.add(crit);
+	}
+	
+	public List getCriterias() {
+		return criterias;
+	}
+	
+	// @Override
+	public String toString() {
+		return "Search:"+criterias.toString();
+	}
+	
+	public static class SearchCriteria {
+		
+		
+		public String getName() {
+			return "search-criteria";
+		}
+		
+		// @Override
+		public String toString() {
+			return "['"+getName()+"']";
+		}
+	}
+
+	public static class NamedSearchCriteria extends SearchCriteria {
+		String name;
+		
+		public NamedSearchCriteria(String name) {
+			this.name = name;
+		}
+		
+		public String getName() {
+			return name;
+		}
+		
+		// @Override
+		public String toString() {
+			return "['"+name+"']";
+		}
+	}
+
+	public static class StringSearchCriteria extends NamedSearchCriteria {
+		String value;
+
+		public StringSearchCriteria(String name, String value) {
+			super(name);
+			this.value = value;
+		}
+		
+		public String getValue() {
+			return value;
+		}
+		public String toString() {
+			return "['"+name+"':'"+value+"']";
+		}
+	}
+	
+	public static class NumberSearchCriteria extends NamedSearchCriteria {
+		long value;
+
+		public NumberSearchCriteria(String name, long value) {
+			super(name);
+			this.value = value;
+		}
+		
+		public long getValue() {
+			return value;
+		}
+		public String toString() {
+			return "['"+name+"':'"+value+"']";
+		}
+	}
+	
+	
+
+	public static class DateSearchCriteria extends NamedSearchCriteria {
+		Date value;
+
+		public DateSearchCriteria(String name, Date value) {
+			super(name);
+			this.value = value;
+		}
+		
+		public Date getValue() {
+			return value;
+		}
+		public String toString() {
+			return "['"+name+"':'"+value+"']";
+		}
+		
+	}
+
+	public static class HeaderSearchCriteria extends SearchCriteria {
+		String fieldName;
+		String value;
+		
+		public HeaderSearchCriteria(String fieldName, String value) {
+			this.fieldName = fieldName;
+			this.value = value;
+		}
+		public String getName() {
+			return HEADER;
+		}
+
+		public String getFieldName() {
+			return fieldName;
+		}
+		
+		public String getValue() {
+			return value;
+		}
+		
+		public String toString() {
+			return "[header:'"+fieldName+"':'"+value+"']";
+		}
+
+	}
+	
+	public static class UIDSearchCriteria extends SearchCriteria {
+        NumericRange[] idRanges;
+
+		public UIDSearchCriteria(NumericRange[] idRanges) {
+			this.idRanges = idRanges;
+		}
+		public String getName() {
+			return UID;
+		}
+		
+		public NumericRange[] getIdRanges() {
+			return idRanges;
+		}
+	}
+	
+	public static class NotSearchCriteria extends SearchCriteria {
+		SearchCriteria inverse;
+		
+		public NotSearchCriteria(SearchCriteria inverse) {
+			this.inverse = inverse;
+		}
+		
+		public String getName() {
+			return NOT;
+		}
+
+		public SearchCriteria getInverse() {
+			return inverse;
+		}
+		
+		public String toString() {
+			return "[NOT "+inverse+"]";
+		}
+		
+	}
+	public static class OrSearchCriteria extends SearchCriteria {
+		SearchCriteria a,b;
+		
+		public OrSearchCriteria (SearchCriteria a, SearchCriteria b) {
+			this.a = a;
+			this.b = b;
+		}
+		
+		public String getName() {
+			return OR;
+		}
+
+
+		public SearchCriteria getFirst() {
+			return a;
+		}
+		
+		public SearchCriteria getSecond() {
+			return b;
+		}
+		public String toString() {
+			return "[OR "+a+' '+b+"]";
+		}
+		
+	}
+
+	
+	public static final class NumericRange {
+	    private final long lowValue;
+        private final long highValue;
+        
+        public NumericRange(final long value) {
+            super();
+            this.lowValue = value;
+            this.highValue = value;
+        }
+        
+        public NumericRange(final long lowValue, final long highValue) {
+            super();
+            this.lowValue = lowValue;
+            this.highValue = highValue;
+        }
+        
+        public final long getHighValue() {
+            return highValue;
+        }
+        
+        public final long getLowValue() {
+            return lowValue;
+        }
+        
+        public String toString() {
+            return "[" + lowValue + "->" + highValue + "]";
+        }
+    }
+}

Modified: james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/mailbox/SearchableMailbox.java
URL: http://svn.apache.org/viewvc/james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/mailbox/SearchableMailbox.java?rev=589068&r1=589067&r2=589068&view=diff
==============================================================================
--- james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/mailbox/SearchableMailbox.java (original)
+++ james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/mailbox/SearchableMailbox.java Sat Oct 27 03:13:30 2007
@@ -19,11 +19,10 @@
 
 package org.apache.james.mailboxmanager.mailbox;
 
-import javax.mail.search.SearchTerm;
-
 import org.apache.james.mailboxmanager.GeneralMessageSet;
 import org.apache.james.mailboxmanager.MailboxManagerException;
 import org.apache.james.mailboxmanager.MessageResult;
+import org.apache.james.mailboxmanager.SearchParameters;
 
 public interface SearchableMailbox {
     /**
@@ -37,5 +36,5 @@
      * @throws MailboxManagerException
      *             if anything went wrong
      */
-    MessageResult[] search(GeneralMessageSet set,SearchTerm searchTerm, int result) throws MailboxManagerException;
+    MessageResult[] search(GeneralMessageSet set,SearchParameters searchTerm, int result) throws MailboxManagerException;
 }

Modified: james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/wrapper/ImapMailboxSessionWrapper.java
URL: http://svn.apache.org/viewvc/james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/wrapper/ImapMailboxSessionWrapper.java?rev=589068&r1=589067&r2=589068&view=diff
==============================================================================
--- james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/wrapper/ImapMailboxSessionWrapper.java (original)
+++ james/server/trunk/core-library/src/main/java/org/apache/james/mailboxmanager/wrapper/ImapMailboxSessionWrapper.java Sat Oct 27 03:13:30 2007
@@ -25,6 +25,7 @@
 import org.apache.james.mailboxmanager.MailboxManagerException;
 import org.apache.james.mailboxmanager.MessageResult;
 import org.apache.james.mailboxmanager.Quota;
+import org.apache.james.mailboxmanager.SearchParameters;
 import org.apache.james.mailboxmanager.acl.MailboxRights;
 import org.apache.james.mailboxmanager.impl.MailboxEventDispatcher;
 import org.apache.james.mailboxmanager.mailbox.ImapMailbox;
@@ -65,7 +66,7 @@
         return ((ImapMailbox) mailbox).getUidNext();
     }
 
-    public MessageResult[] search(GeneralMessageSet set, SearchTerm searchTerm, int result) throws MailboxManagerException {
+    public MessageResult[] search(GeneralMessageSet set, SearchParameters searchTerm, int result) throws MailboxManagerException {
         return addMsnToResults(((SearchableMailbox)mailbox).search(set, searchTerm, noMsnResult(result)),result);
     }
 

Modified: james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SearchProcessor.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SearchProcessor.java?rev=589068&r1=589067&r2=589068&view=diff
==============================================================================
--- james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SearchProcessor.java (original)
+++ james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SearchProcessor.java Sat Oct 27 03:13:30 2007
@@ -39,6 +39,7 @@
 import org.apache.james.imapserver.store.MailboxException;
 import org.apache.james.mailboxmanager.MailboxManagerException;
 import org.apache.james.mailboxmanager.MessageResult;
+import org.apache.james.mailboxmanager.SearchParameters;
 import org.apache.james.mailboxmanager.impl.GeneralMessageSetImpl;
 import org.apache.james.mailboxmanager.mailbox.ImapMailboxSession;
 
@@ -84,8 +85,9 @@
         }
         MessageResult[] messageResults;
         try {
+            // TODO: implementation
             messageResults = mailbox.search(GeneralMessageSetImpl.all(),
-                    searchTerm, resultCode);
+                    new SearchParameters(), resultCode);
         } catch (MailboxManagerException e) {
             throw new MailboxException(e);
         }

Modified: james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/commands/SearchCommand.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/commands/SearchCommand.java?rev=589068&r1=589067&r2=589068&view=diff
==============================================================================
--- james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/commands/SearchCommand.java (original)
+++ james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/commands/SearchCommand.java Sat Oct 27 03:13:30 2007
@@ -19,7 +19,10 @@
 
 package org.apache.james.imapserver.commands;
 
-import javax.mail.Message;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
 import javax.mail.search.SearchTerm;
 
 import org.apache.james.imapserver.ImapRequestLineReader;
@@ -29,6 +32,10 @@
 import org.apache.james.imapserver.store.MailboxException;
 import org.apache.james.mailboxmanager.MailboxManagerException;
 import org.apache.james.mailboxmanager.MessageResult;
+import org.apache.james.mailboxmanager.SearchParameters;
+import org.apache.james.mailboxmanager.SearchParameters.NamedSearchCriteria;
+import org.apache.james.mailboxmanager.SearchParameters.NumericRange;
+import org.apache.james.mailboxmanager.SearchParameters.SearchCriteria;
 import org.apache.james.mailboxmanager.impl.GeneralMessageSetImpl;
 import org.apache.james.mailboxmanager.mailbox.ImapMailboxSession;
 
@@ -60,7 +67,7 @@
             throws ProtocolException, MailboxException
     {
         // Parse the search term from the request
-        SearchTerm searchTerm = parser.searchTerm( request );
+        SearchParameters searchTerm = parser.searchTerm( request );
         parser.endLine( request );
 
         ImapMailboxSession mailbox = session.getSelected().getMailbox();
@@ -106,37 +113,85 @@
         return ARGS;
     }
 
+    
+    
     private class SearchCommandParser extends CommandParser
     {
         /**
          * Parses the request argument into a valid search term.
-         * Not yet implemented - all searches will return everything for now.
-         * TODO implement search
          */
-        public SearchTerm searchTerm( ImapRequestLineReader request )
+        public SearchParameters searchTerm( ImapRequestLineReader request )
                 throws ProtocolException
         {
-            // Dummy implementation
-            // Consume to the end of the line.
-            char next = request.nextChar();
-            while ( next != '\n' ) {
-                request.consume();
+        	SearchParameters search = new SearchParameters();
+
+        	char next = request.nextChar();
+            while ( next != '\n' && next != '\r') {
+                
+            	SearchParameters.SearchCriteria crit = parseCriteria(request);
+            	search.addCriteria(crit);
                 next = request.nextChar();
+                while ( next == ' ' ) {
+                	request.consume();
+                    next = request.nextChar();
+                }
             }
 
-            // Return a search term that matches everything.
-            return new SearchTerm()
-            {
-                private static final long serialVersionUID = 5290284637903768771L;
-
-                public boolean match( Message message )
-                {
-                    return true;
+            return search;
+        }
+
+		private SearchCriteria parseCriteria(ImapRequestLineReader request) throws ProtocolException {
+            String term = atom(request).toUpperCase();
+
+			if (SearchParameters.BASE_SEARCH_TERMS.contains(term)) {
+				return new SearchParameters.NamedSearchCriteria(term);
+			} else if (SearchParameters.STRING_SEARCH_TERMS.contains(term)) {
+				return new SearchParameters.StringSearchCriteria(term, astring(request));
+			} else if (SearchParameters.NUMBER_SEARCH_TERMS.contains(term)) {
+				return new SearchParameters.NumberSearchCriteria(term, number(request));
+			} else if (SearchParameters.DATE_SEARCH_TERMS.contains(term)) {
+				return new SearchParameters.DateSearchCriteria(term, date(request));
+			} else if ("HEADER".equals(term)) {
+				return new SearchParameters.HeaderSearchCriteria(astring(request), astring(request));
+			} else if ("UID".equals(term)) {
+				return new SearchParameters.UIDSearchCriteria(toNumericRange(parseIdRange(request)));
+			} else if ("OR".equals(term)) {
+				return new SearchParameters.OrSearchCriteria(parseCriteria(request), parseCriteria(request));
+			} else if ("NOT".equals(term)) {
+				return new SearchParameters.NotSearchCriteria(parseCriteria(request));
+			} else {
+				throw new ProtocolException("Term '"+term+"' not supported in the current search implementation!");
+			}
+		}
+
+        private NumericRange[] toNumericRange(final IdRange[] ranges) {
+            final NumericRange[] result;
+            if (ranges == null) {
+                result = null;
+            } else {
+                final int length = ranges.length;
+                result = new NumericRange[length];
+                for (int i=0;i<length; i++) {
+                    result[i] = toNumericRange(ranges[i]);
                 }
-            };
+            }
+            
+            return result;
+        }
+
+        private NumericRange toNumericRange(IdRange range) {
+            final NumericRange result;
+            if (range == null) {
+                result = null;
+            } else {
+                result = new NumericRange(range.getLowVal(), range.getHighVal());
+            }
+            return result;
         }
 
     }
+    
+    
 }
 /*
 6.4.4.  SEARCH Command

Modified: james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailbox.java
URL: http://svn.apache.org/viewvc/james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailbox.java?rev=589068&r1=589067&r2=589068&view=diff
==============================================================================
--- james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailbox.java (original)
+++ james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailbox.java Sat Oct 27 03:13:30 2007
@@ -30,13 +30,13 @@
 import javax.mail.Flags;
 import javax.mail.MessagingException;
 import javax.mail.internet.MimeMessage;
-import javax.mail.search.SearchTerm;
 
 import org.apache.commons.logging.Log;
 import org.apache.james.mailboxmanager.GeneralMessageSet;
 import org.apache.james.mailboxmanager.MailboxListener;
 import org.apache.james.mailboxmanager.MailboxManagerException;
 import org.apache.james.mailboxmanager.MessageResult;
+import org.apache.james.mailboxmanager.SearchParameters;
 import org.apache.james.mailboxmanager.impl.GeneralMessageSetImpl;
 import org.apache.james.mailboxmanager.impl.MailboxEventDispatcher;
 import org.apache.james.mailboxmanager.impl.MessageResultImpl;
@@ -60,6 +60,7 @@
 import org.apache.torque.util.Criteria;
 
 import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
+
 import com.sun.mail.util.CRLFOutputStream;
 import com.workingdogs.village.DataSetException;
 
@@ -653,7 +654,7 @@
         this.mailboxRow = mailboxRow;
     }
 
-    public MessageResult[] search(GeneralMessageSet set, SearchTerm searchTerm,
+    public MessageResult[] search(GeneralMessageSet set, SearchParameters parameters,
             int result) throws MailboxManagerException {
         try {
             lock.readLock().acquire();



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