Index: imap-api/src/main/java/org/apache/james/api/imap/imap4rev1/Imap4Rev1MessageFactory.java
===================================================================
--- imap-api/src/main/java/org/apache/james/api/imap/imap4rev1/Imap4Rev1MessageFactory.java	(revision 567160)
+++ imap-api/src/main/java/org/apache/james/api/imap/imap4rev1/Imap4Rev1MessageFactory.java	(working copy)
@@ -30,6 +30,7 @@
 import org.apache.james.api.imap.message.IdRange;
 import org.apache.james.api.imap.message.StatusDataItems;
 import org.apache.james.api.imap.message.StoreDirective;
+import org.apache.james.mailboxmanager.SearchParameters;
 
 /**
  * Creates messages.
@@ -80,7 +81,7 @@
     public ImapMessage createRenameMessage(final ImapCommand command, final String existingName, final String newName, 
             final String tag);
     
-    public ImapMessage createSearchImapMessage(final ImapCommand command, final SearchTerm searchTerm, final boolean useUids,
+    public ImapMessage createSearchImapMessage(final ImapCommand command, final SearchParameters searchTerm, final boolean useUids,
             final String tag);
     
     public ImapMessage createSelectMessage(final ImapCommand command, final String mailboxName, final String tag);
Index: core-library/src/main/java/org/apache/james/mailboxmanager/SearchParameters.java
===================================================================
--- core-library/src/main/java/org/apache/james/mailboxmanager/SearchParameters.java	(revision 0)
+++ core-library/src/main/java/org/apache/james/mailboxmanager/SearchParameters.java	(revision 0)
@@ -0,0 +1,218 @@
+package org.apache.james.mailboxmanager;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.james.imapserver.commands.IdRange;
+
+public class SearchParameters {
+
+	public final static Set BASE_SEARCH_TERMS = 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 = new HashSet(Arrays.asList(new String[] {
+        	"BCC", "BODY", "CC", "FROM", "KEYWORD", "SUBJECT", "TEXT", "TO", "UNKEYWORD"
+        }));
+    public final static Set DATE_SEARCH_TERMS = new HashSet(Arrays.asList(new String[] {
+        	"BEFORE", "ON", "SENTBEFORE", "SENTON", "SENTSINCE" , "SINCE"
+        }));
+    public final static Set NUMBER_SEARCH_TERMS = 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 {
+		IdRange[] idRanges;
+
+		public UIDSearchCriteria(IdRange[] idRanges) {
+			this.idRanges = idRanges;
+		}
+		public String getName() {
+			return "UID";
+		}
+		
+		public IdRange[] 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+"]";
+		}
+		
+	}
+
+	
+	
+}
Index: core-library/src/main/java/org/apache/james/mailboxmanager/mailbox/SearchableMailbox.java
===================================================================
--- core-library/src/main/java/org/apache/james/mailboxmanager/mailbox/SearchableMailbox.java	(revision 567160)
+++ core-library/src/main/java/org/apache/james/mailboxmanager/mailbox/SearchableMailbox.java	(working copy)
@@ -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;
 }
Index: core-library/src/main/java/org/apache/james/mailboxmanager/wrapper/ImapMailboxSessionWrapper.java
===================================================================
--- core-library/src/main/java/org/apache/james/mailboxmanager/wrapper/ImapMailboxSessionWrapper.java	(revision 567160)
+++ core-library/src/main/java/org/apache/james/mailboxmanager/wrapper/ImapMailboxSessionWrapper.java	(working copy)
@@ -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);
     }
 
Index: imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SearchProcessor.java
===================================================================
--- imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SearchProcessor.java	(revision 567160)
+++ imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/SearchProcessor.java	(working copy)
@@ -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;
 
@@ -64,14 +65,14 @@
     private ImapResponseMessage doProcess(SearchRequest request,
             ImapSession session, String tag, ImapCommand command)
             throws MailboxException, AuthorizationException, ProtocolException {
-        final SearchTerm searchTerm = request.getSearchTerm();
+        final SearchParameters searchTerm = request.getSearchTerm();
         final boolean useUids = request.isUseUids();
         final ImapResponseMessage result = doProcess(searchTerm, useUids,
                 session, tag, command);
         return result;
     }
 
-    private ImapResponseMessage doProcess(final SearchTerm searchTerm,
+    private ImapResponseMessage doProcess(final SearchParameters searchTerm,
             final boolean useUids, ImapSession session, String tag,
             ImapCommand command) throws MailboxException,
             AuthorizationException, ProtocolException {
Index: imapserver-function/src/main/java/org/apache/james/imapserver/commands/SearchCommand.java
===================================================================
--- imapserver-function/src/main/java/org/apache/james/imapserver/commands/SearchCommand.java	(revision 567160)
+++ imapserver-function/src/main/java/org/apache/james/imapserver/commands/SearchCommand.java	(working copy)
@@ -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,9 @@
 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.SearchCriteria;
 import org.apache.james.mailboxmanager.impl.GeneralMessageSetImpl;
 import org.apache.james.mailboxmanager.mailbox.ImapMailboxSession;
 
@@ -60,7 +66,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 +112,60 @@
         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(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!");
+			}
+		}
+
     }
+    
+    
 }
 /*
 6.4.4.  SEARCH Command
Index: imap-codec-library/src/main/java/org/apache/james/imap/message/request/imap4rev1/SearchRequest.java
===================================================================
--- imap-codec-library/src/main/java/org/apache/james/imap/message/request/imap4rev1/SearchRequest.java	(revision 567160)
+++ imap-codec-library/src/main/java/org/apache/james/imap/message/request/imap4rev1/SearchRequest.java	(working copy)
@@ -18,24 +18,23 @@
  ****************************************************************/
 package org.apache.james.imap.message.request.imap4rev1;
 
-import javax.mail.search.SearchTerm;
-
 import org.apache.james.api.imap.ImapCommand;
 import org.apache.james.imap.message.request.base.AbstractImapRequest;
+import org.apache.james.mailboxmanager.SearchParameters;
 
 public class SearchRequest extends AbstractImapRequest {
-    private final SearchTerm searchTerm;
+    private final SearchParameters searchTerm;
 
     private final boolean useUids;
 
     public SearchRequest(final ImapCommand command,
-            final SearchTerm searchTerm, final boolean useUids, final String tag) {
+            final SearchParameters searchTerm, final boolean useUids, final String tag) {
         super(tag, command);
         this.searchTerm = searchTerm;
         this.useUids = useUids;
     }
 
-    public final SearchTerm getSearchTerm() {
+    public final SearchParameters getSearchTerm() {
         return searchTerm;
     }
 
Index: imap-codec-library/src/main/java/org/apache/james/imap/message/request/base/BaseImap4Rev1MessageFactory.java
===================================================================
--- imap-codec-library/src/main/java/org/apache/james/imap/message/request/base/BaseImap4Rev1MessageFactory.java	(revision 567160)
+++ imap-codec-library/src/main/java/org/apache/james/imap/message/request/base/BaseImap4Rev1MessageFactory.java	(working copy)
@@ -56,6 +56,7 @@
 import org.apache.james.imap.message.request.imap4rev1.UnsubscribeRequest;
 import org.apache.james.imap.message.response.imap4rev1.legacy.BadResponse;
 import org.apache.james.imap.message.response.imap4rev1.legacy.ErrorResponse;
+import org.apache.james.mailboxmanager.SearchParameters;
 
 /**
  * Naive, factory creates unpooled instances.
@@ -131,7 +132,7 @@
         return new RenameRequest(command, existingName, newName, tag);
     }
 
-    public ImapMessage createSearchImapMessage(ImapCommand command, SearchTerm searchTerm, boolean useUids, String tag) {
+    public ImapMessage createSearchImapMessage(ImapCommand command, SearchParameters searchTerm, boolean useUids, String tag) {
         return new SearchRequest(command, searchTerm, useUids, tag);
     }
 
Index: imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParser.java
===================================================================
--- imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParser.java	(revision 567160)
+++ imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParser.java	(working copy)
@@ -27,6 +27,8 @@
 import org.apache.james.api.imap.imap4rev1.Imap4Rev1CommandFactory;
 import org.apache.james.imapserver.codec.decode.ImapRequestLineReader;
 import org.apache.james.imapserver.codec.decode.InitialisableCommandFactory;
+import org.apache.james.mailboxmanager.SearchParameters;
+import org.apache.james.mailboxmanager.SearchParameters.SearchCriteria;
 
 class SearchCommandParser extends AbstractUidCommandParser implements InitialisableCommandFactory
 {
@@ -44,35 +46,56 @@
     
     /**
      * 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)) {
+			// TODO : XXX there is 2 separate IdRange class !
+			// return new SearchParameters.UIDSearchCriteria(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!");
+		}
+	}
+
+    
     protected ImapMessage decode(ImapCommand command, ImapRequestLineReader request, String tag, boolean useUids) throws ProtocolException {
         // Parse the search term from the request
-        final SearchTerm searchTerm = searchTerm( request );
+        final SearchParameters searchTerm = searchTerm( request );
         endLine( request );
         final ImapMessage result = getMessageFactory().createSearchImapMessage(command, searchTerm, useUids, tag);
         return result;
