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 2008/03/09 09:24:47 UTC

svn commit: r635192 - in /james/server/trunk/torque-mailboxmanager-function/src: main/java/org/apache/james/mailboxmanager/torque/ main/java/org/apache/james/mailboxmanager/torque/om/ test/java/org/apache/james/mailboxmanager/torque/

Author: rdonkin
Date: Sun Mar  9 00:24:42 2008
New Revision: 635192

URL: http://svn.apache.org/viewvc?rev=635192&view=rev
Log:
Body and full mail search.

Added:
    james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageSearcher.java
    james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsMultipartMixedTest.java
    james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsRFC822Test.java
Modified:
    james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageRowUtils.java
    james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/SearchUtils.java
    james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/om/MessageBody.java
    james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/om/MessageHeader.java
    james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsTest.java

Modified: james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageRowUtils.java
URL: http://svn.apache.org/viewvc/james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageRowUtils.java?rev=635192&r1=635191&r2=635192&view=diff
==============================================================================
--- james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageRowUtils.java (original)
+++ james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageRowUtils.java Sun Mar  9 00:24:42 2008
@@ -102,7 +102,7 @@
         return result;
     }
 
-    public static Content createFullContent(final MessageRow messageRow, List headers) throws TorqueException, MailboxManagerException {
+    public static Content createFullContent(final MessageRow messageRow, List headers) throws TorqueException {
         if (headers == null) {
             headers = createHeaders(messageRow);
         }
@@ -217,6 +217,17 @@
     }
     
     private static PartContentBuilder build(int[] path, final MessageRow row) throws IOException, MimeException, TorqueException {
+        final InputStream stream = toInput(row);
+        PartContentBuilder result = new PartContentBuilder();
+        result.parse(stream);
+        for (int i = 0; i < path.length; i++) {
+            final int next = path[i];
+            result.to(next);
+        }
+        return result;
+    }
+
+    public static InputStream toInput(final MessageRow row) throws TorqueException {
         final List headers = getSortedHeaders(row);
         final StringBuffer headersToString = new StringBuffer(headers.size()*50);
         for (Iterator it = headers.iterator(); it.hasNext();) {
@@ -230,13 +241,7 @@
         
         byte[] bodyContent = row.getBodyContent();
         final MessageInputStream stream = new MessageInputStream(headersToString, bodyContent);
-        PartContentBuilder result = new PartContentBuilder();
-        result.parse(stream);
-        for (int i = 0; i < path.length; i++) {
-            final int next = path[i];
-            result.to(next);
-        }
-        return result;
+        return stream;
     }
     
     private static final class MessageInputStream extends InputStream {

Added: james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageSearcher.java
URL: http://svn.apache.org/viewvc/james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageSearcher.java?rev=635192&view=auto
==============================================================================
--- james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageSearcher.java (added)
+++ james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/MessageSearcher.java Sun Mar  9 00:24:42 2008
@@ -0,0 +1,252 @@
+/****************************************************************
+ * 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.torque;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.nio.CharBuffer;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.james.mime4j.MimeException;
+import org.apache.james.mime4j.MimeTokenStream;
+
+/**
+ * Searches an email for content.
+ * This class should be safe for use by concurrent threads.
+ */
+class MessageSearcher {
+    
+    private Log logger;
+    
+    private CharSequence searchContent = null;
+    private boolean isCaseInsensitive = false;
+    private boolean includeHeaders = false;
+    
+    public MessageSearcher() {}
+    
+    public MessageSearcher(CharSequence searchContent, boolean isCaseInsensitive, boolean includeHeaders) {
+        super();
+        this.searchContent = searchContent;
+        this.isCaseInsensitive = isCaseInsensitive;
+        this.includeHeaders = includeHeaders;
+    }
+
+    /**
+     * Is the search to include headers?
+     * @return true if header values are included,
+     * false otherwise
+     */
+    public boolean isIncludeHeaders() {
+        return includeHeaders;
+    }
+
+    /**
+     * Sets whether the search should include headers.
+     * @param true if header values are included,
+     * false otherwise
+     */
+    public synchronized void setIncludeHeaders(boolean includesHeaders) {
+        this.includeHeaders = includesHeaders;
+    }
+
+    /**
+     * Is this search case insensitive?
+     * @return true if the search should be case insensitive,
+     * false otherwise
+     */
+    public boolean isCaseInsensitive() {
+        return isCaseInsensitive;
+    }
+    
+    /**
+     * Sets whether the search should be case insensitive.
+     * @param isCaseInsensitive true for case insensitive searches,
+     * false otherwise
+     */
+    public synchronized void setCaseInsensitive(boolean isCaseInsensitive) {
+        this.isCaseInsensitive = isCaseInsensitive;
+    }
+    
+    /**
+     * Gets the content to be searched for.
+     * @return search content, initially null
+     */
+    public CharSequence getSearchContent() {
+        return searchContent;
+    }
+    
+    /**
+     * Sets the content sought.
+     * @param searchContent content sought
+     */
+    public synchronized void setSearchContent(CharSequence searchContent) {
+        this.searchContent = searchContent;
+    }
+    
+    /**
+     * Is {@link #getSearchContent()} found in the given input?
+     * @param input <code>InputStream</code> containing an email
+     * @return true if the content exists and the stream contains the content, 
+     * false otherwise
+     * @throws IOException
+     * @throws MimeException
+     */
+    public boolean isFoundIn(final InputStream input) throws IOException, MimeException {
+        final boolean includeHeaders;
+        final CharSequence searchContent;
+        final boolean isCaseInsensitive;
+        synchronized (this) {
+            includeHeaders = this.includeHeaders;
+            searchContent = this.searchContent;
+            isCaseInsensitive = this.isCaseInsensitive;
+        }
+        final boolean result;
+        if (searchContent == null || "".equals(searchContent)) {
+            final Log logger = getLogger();
+            logger.debug("Nothing to search for. ");
+            result = false;
+        } else {
+            final CharBuffer buffer = createBuffer(searchContent, isCaseInsensitive);
+            result = parse(input, isCaseInsensitive, includeHeaders, buffer); 
+        }
+        return result;
+    }
+
+    private boolean parse(final InputStream input, final boolean isCaseInsensitive, 
+            final boolean includeHeaders, final CharBuffer buffer) throws IOException, MimeException {
+        try {
+            boolean result = false;
+            MimeTokenStream parser = new MimeTokenStream();
+            parser.parse(input);
+            while (!result && parser.next() != MimeTokenStream.T_END_OF_STREAM) {
+                final int state = parser.getState();
+                System.out.println(MimeTokenStream.stateToString(state));
+                switch (state) {
+                    case MimeTokenStream.T_BODY:
+                    case MimeTokenStream.T_PREAMBLE:
+                    case MimeTokenStream.T_EPILOGUE:
+                        result = checkBody(isCaseInsensitive, buffer, result, parser);
+                        break;
+                    case MimeTokenStream.T_FIELD:
+                        if (includeHeaders) {
+                            result = checkHeader(isCaseInsensitive, buffer, result, parser);
+                        }
+                        break;
+                }
+            }
+            return result;
+        } catch (IllegalCharsetNameException e) {
+            handle(e);
+        } catch (UnsupportedCharsetException e) {
+            handle(e);
+        } catch (IllegalStateException e) {
+            handle(e);
+        }
+        return false;
+    }
+
+    private boolean checkHeader(final boolean isCaseInsensitive, final CharBuffer buffer, boolean result, MimeTokenStream parser) throws IOException {
+        final String value = parser.getFieldValue();
+        final StringReader reader = new StringReader(value);
+        if (isFoundIn(reader, buffer, isCaseInsensitive)) {
+            result = true;
+        }
+        return result;
+    }
+
+    private boolean checkBody(final boolean isCaseInsensitive, final CharBuffer buffer, boolean result, MimeTokenStream parser) throws IOException {
+        final Reader reader = parser.getReader();
+        if (isFoundIn(reader, buffer, isCaseInsensitive)) {
+            result = true;
+        }
+        return result;
+    }
+
+    private CharBuffer createBuffer(final CharSequence searchContent, final boolean isCaseInsensitive) {
+        final CharBuffer buffer;
+        if (isCaseInsensitive) {
+            final int length = searchContent.length();
+            buffer = CharBuffer.allocate(length);
+            for (int i=0;i<length;i++) {
+                final char next = searchContent.charAt(i);
+                final char upperCase = Character.toUpperCase(next);
+                buffer.put(upperCase);
+            }
+            buffer.flip();
+        } else {
+            buffer = CharBuffer.wrap(searchContent);
+        }
+        return buffer;
+    }
+    
+    protected void handle(Exception e) throws IOException, MimeException { 
+        final Log logger = getLogger();
+        logger.warn("Cannot read MIME body.");
+        logger.debug("Failed to read body.", e);
+    }
+    
+    private boolean isFoundIn(final Reader reader, final CharBuffer buffer, final boolean isCaseInsensitive) throws IOException {
+        boolean result = false;
+        int read;
+        while (!result && (read = reader.read()) != -1) {
+           final char next;
+           if (isCaseInsensitive) {
+               next = Character.toUpperCase((char) read);
+           } else {
+               next = (char) read;
+           }
+           result = matches(buffer, next);
+        }
+        return result;
+    }
+
+    private boolean matches(final CharBuffer buffer, final char next) {
+        boolean result = false;
+        if (buffer.hasRemaining()) {
+            final boolean partialMatch = (buffer.position() > 0); 
+            final char matching = buffer.get();
+            if (next != matching) {
+                buffer.rewind();
+                if (partialMatch) {
+                    result = matches(buffer, next);
+                }
+            } 
+        } else {
+            result = true;
+        }
+        return result;
+    }
+
+    public final Log getLogger() {
+        if (logger == null) {
+            logger = LogFactory.getLog(MessageSearcher.class);
+        }
+        return logger; 
+    }
+
+    public final void setLogger(Log logger) {
+        this.logger = logger;
+    }
+}

Modified: james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/SearchUtils.java
URL: http://svn.apache.org/viewvc/james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/SearchUtils.java?rev=635192&r1=635191&r2=635192&view=diff
==============================================================================
--- james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/SearchUtils.java (original)
+++ james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/SearchUtils.java Sun Mar  9 00:24:42 2008
@@ -19,6 +19,8 @@
 
 package org.apache.james.mailboxmanager.torque;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.io.StringReader;
 import java.util.Calendar;
 import java.util.Date;
@@ -34,6 +36,7 @@
 import org.apache.james.mailboxmanager.torque.om.MessageFlags;
 import org.apache.james.mailboxmanager.torque.om.MessageHeader;
 import org.apache.james.mailboxmanager.torque.om.MessageRow;
+import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.field.datetime.DateTime;
 import org.apache.james.mime4j.field.datetime.parser.DateTimeParser;
 import org.apache.james.mime4j.field.datetime.parser.ParseException;
@@ -56,6 +59,8 @@
             result = matches((SearchQuery.UidCriterion) criterion, row);
         } else if (criterion instanceof SearchQuery.FlagCriterion) {
             result = matches((SearchQuery.FlagCriterion) criterion, row);
+        } else if (criterion instanceof SearchQuery.TextCriterion) {
+            result = matches((SearchQuery.TextCriterion) criterion, row);
         } else if (criterion instanceof SearchQuery.AllCriterion) {
             result = true;
         } else if (criterion instanceof SearchQuery.ConjunctionCriterion) {
@@ -66,6 +71,38 @@
         return result;
     }
     
+    
+    private static boolean matches(SearchQuery.TextCriterion criterion, MessageRow row) throws TorqueException {
+        try {
+            final SearchQuery.ContainsOperator operator = criterion.getOperator();
+            final String value = operator.getValue();
+            final int type = criterion.getType();
+            switch (type) {
+                case SearchQuery.TextCriterion.BODY: return bodyContains(value, row);
+                case SearchQuery.TextCriterion.FULL_MESSAGE: return messageContains(value, row);
+                default: throw new UnsupportedSearchException();
+            }
+        } catch (IOException e) {
+            throw new TorqueException(e);
+        } catch (MimeException e) {
+            throw new TorqueException(e);
+        }
+    }
+    
+    private static boolean bodyContains(String value, MessageRow row) throws TorqueException, IOException, MimeException {
+        final InputStream input = MessageRowUtils.toInput(row);
+        final MessageSearcher searcher = new MessageSearcher(value, true, false);
+        final boolean result = searcher.isFoundIn(input);
+        return result;
+    }
+
+    private static boolean messageContains(String value, MessageRow row) throws TorqueException, IOException, MimeException {
+        final InputStream input = MessageRowUtils.toInput(row);
+        final MessageSearcher searcher = new MessageSearcher(value, true, true);
+        final boolean result = searcher.isFoundIn(input);
+        return result;
+    }
+
     private static boolean matches(SearchQuery.ConjunctionCriterion criterion, MessageRow row) throws TorqueException {
         final int type = criterion.getType();
         final List criteria = criterion.getCriteria();
@@ -187,7 +224,7 @@
     }
 
     private static boolean matches(final SearchQuery.ContainsOperator operator, final String headerName, final MessageRow row) throws TorqueException {
-        final String text = operator.getValue();
+        final String text = operator.getValue().toUpperCase();
         boolean result = false;
         final List headers = row.getMessageHeaders();
         for (Iterator it = headers.iterator(); it.hasNext();) {
@@ -195,9 +232,11 @@
             final String name = header.getField();
             if (headerName.equalsIgnoreCase(name)) {
                 final String value = header.getValue();
-                if (value.contains(text)) {
-                    result = true;
-                    break;
+                if (value != null) {
+                    if (value.toUpperCase().contains(text)) {
+                        result = true;
+                        break;
+                    }
                 }
             }
         }

Modified: james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/om/MessageBody.java
URL: http://svn.apache.org/viewvc/james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/om/MessageBody.java?rev=635192&r1=635191&r2=635192&view=diff
==============================================================================
--- james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/om/MessageBody.java (original)
+++ james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/om/MessageBody.java Sun Mar  9 00:24:42 2008
@@ -36,4 +36,14 @@
 {
 
     private static final long serialVersionUID = -1304530949913525943L;
+
+    public MessageBody() {
+        super();
+    }
+    
+    public MessageBody(byte[] content) {
+        super();
+        setBody(content);
+    }
+    
 }

Modified: james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/om/MessageHeader.java
URL: http://svn.apache.org/viewvc/james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/om/MessageHeader.java?rev=635192&r1=635191&r2=635192&view=diff
==============================================================================
--- james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/om/MessageHeader.java (original)
+++ james/server/trunk/torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/om/MessageHeader.java Sun Mar  9 00:24:42 2008
@@ -35,9 +35,16 @@
     extends org.apache.james.mailboxmanager.torque.om.BaseMessageHeader
     implements Persistent
 {
-
-    /**
-     * 
-     */
     private static final long serialVersionUID = -9191792349506771474L;
+
+    
+    public MessageHeader() {
+        super();
+    }
+    
+    public MessageHeader(final String field, final String value) {
+        super();
+        setField(field);
+        setValue(value);
+    }
 }

Added: james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsMultipartMixedTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsMultipartMixedTest.java?rev=635192&view=auto
==============================================================================
--- james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsMultipartMixedTest.java (added)
+++ james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsMultipartMixedTest.java Sun Mar  9 00:24:42 2008
@@ -0,0 +1,176 @@
+/****************************************************************
+ * 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.torque;
+
+import java.nio.charset.Charset;
+
+import junit.framework.TestCase;
+
+import org.apache.james.mailboxmanager.SearchQuery;
+import org.apache.james.mailboxmanager.torque.om.MessageBody;
+import org.apache.james.mailboxmanager.torque.om.MessageHeader;
+import org.apache.james.mailboxmanager.torque.om.MessageRow;
+import org.apache.mailet.RFC2822Headers;
+
+public class SearchUtilsMultipartMixedTest extends TestCase {
+
+    private static final String SAMPLE_INNER_MAIL_BODY_ONE = "far a modern quill doth come too";
+    private static final String SAMPLE_PART_ONE = "The better angel is a man right fair,\r\n";
+    private static final String SAMPLE_PART_TWO = "My bonds in thee are all determinate.";
+    private static final String SAMPLE_PART_TWO_FIELD = "948523475273457234952345";
+    private static final String SAMPLE_INNER_MAIL_FIELD = "Inner mail sample";
+    private static final String SAMPLE_INNER_MAIL_MIME_FIELD = "8347673450223534587232312221";
+    private static final String PREMABLE = "This is the premable.";
+    private static final String BODY = PREMABLE + 
+        "\r\n--1729\r\n" +
+        "Content-Type: text/plain; charset=US-ASCII\r\n\r\n" +
+        "Two loves I have of comfort and despair,\r\n" +
+        "Which like two spirits do suggest me still:\r\n" +
+        SAMPLE_PART_ONE +
+        "The worser spirit a woman colour'd ill.\r\n" +
+        "To win me soon to hell, my female evil,\r\n" +
+        "Tempteth my better angel from my side,\r\n" +
+        "And would corrupt my saint to be a devil,\r\n" +
+        "Wooing his purity with her foul pride.\r\n" +
+        "And whether that my angel be turn'd fiend,\r\n" +
+        "Suspect I may, yet not directly tell;\r\n" +
+        "But being both from me, both to each friend,\r\n" +
+        "I guess one angel in another's hell:\r\n" +
+        "  Yet this shall I ne'er know, but live in doubt,\r\n" +
+        "  Till my bad angel fire my good one out.\r\n" +
+        "r\n" +
+        "By William Shakespere\r\n" +
+        "\r\n--1729\r\n" +
+        "Content-Type: text/plain; charset=US-ASCII\r\n" +
+        "Content-Transfer-Encoding: 7bit\r\n" +
+        "Content-ID: 45" + SAMPLE_PART_TWO_FIELD +"\r\n\r\n" +
+        "Farewell! thou art too dear for my possessing,\r\n" +
+        "And like enough thou know'st thy estimate,\r\n" +
+        "The charter of thy worth gives thee releasing;\r\n" +
+        SAMPLE_PART_TWO + "\r\n" +
+        "For how do I hold thee but by thy granting?\r\n" +
+        "And for that riches where is my deserving?\r\n" +
+        "The cause of this fair gift in me is wanting,\r\n" +
+        "And so my patent back again is swerving.\r\n" +
+        "Thy self thou gav'st, thy own worth then not knowing,\r\n" +
+        "Or me to whom thou gav'st it, else mistaking;\r\n" +
+        "So thy great gift, upon misprision growing,\r\n" +
+        "Comes home again, on better judgement making.\r\n" +
+        "  Thus have I had thee, as a dream doth flatter,\r\n" +
+        "  In sleep a king, but waking no such matter.\r\n" + 
+        "r\n" +
+        "By William Shakespere\r\n" +
+        "\r\n--1729\r\n" +
+        "Content-Type: message/rfc822\r\n\r\n" +
+        "From: Timothy Tayler <ti...@example.org>\r\n" +
+        "To: John Smith <jo...@example.org>\r\n" +
+        "Date: Sat, 16 Feb 2008 12:00:00 +0000 (GMT)\r\n" +
+        "Subject: Custard " + SAMPLE_INNER_MAIL_FIELD + " \r\n" +
+        "Content-Type: multipart/mixed;boundary=2.50290787509\r\n\r\n" +
+        "--2.50290787509\r\n" +
+        "Content-Type: text/plain\r\n" +
+        "Content-ID: 4657" + SAMPLE_INNER_MAIL_MIME_FIELD + "\r\n\r\n" +
+        "I never saw that you did painting need,\r\n" +
+        "And therefore to your fair no painting set;\r\n" +
+        "I found, or thought I found, you did exceed\r\n" +
+        "That barren tender of a poet's debt:\r\n" +
+        "And therefore have I slept in your report,\r\n" +
+        "That you yourself, being extant, well might show\r\n" +
+        "How " + SAMPLE_INNER_MAIL_BODY_ONE + " short,\r\n" +
+        "Speaking of worth, what worth in you doth grow.\r\n" +
+        "This silence for my sin you did impute,\r\n" +
+        "Which shall be most my glory being dumb;\r\n" +
+        "For I impair not beauty being mute,\r\n" +
+        "When others would give life, and bring a tomb.\r\n" +
+        "  There lives more life in one of your fair eyes\r\n" +
+        "  Than both your poets can in praise devise.\r\n" +
+        "\r\n--2.50290787509--\r\n" +
+        "\r\n--1729--\r\n" ;
+    
+    
+    MessageRow row;
+    
+    protected void setUp() throws Exception {
+        super.setUp();
+        row = new MessageRow(); 
+        row.addMessageHeader(new MessageHeader(RFC2822Headers.FROM, "Alex <alex@example.org"));
+        row.addMessageHeader(new MessageHeader(RFC2822Headers.TO, "Harry <harry@example.org"));
+        row.addMessageHeader(new MessageHeader(RFC2822Headers.SUBJECT, "A Mixed Multipart Mail"));
+        row.addMessageHeader(new MessageHeader(RFC2822Headers.DATE, "Thu, 14 Feb 2008 12:00:00 +0000 (GMT)"));
+        row.addMessageHeader(new MessageHeader("Content-Type", "multipart/mixed;boundary=1729"));
+        row.addMessageBody(new MessageBody(Charset.forName("us-ascii").encode(BODY).array()));
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+    
+    public void testShouldNotFindWhatIsNotThere() throws Exception {
+        assertFalse(SearchUtils.matches(SearchQuery.bodyContains("BOGUS"), row));
+        assertFalse(SearchUtils.matches(SearchQuery.mailContains("BOGUS"), row));
+    }
+    
+    public void testBodyShouldFindTextInBody() throws Exception {
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(SAMPLE_INNER_MAIL_BODY_ONE), row));
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(SAMPLE_PART_ONE), row));
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(SAMPLE_PART_TWO), row));
+    }
+    
+    public void testBodyShouldFindTextInBodyCaseInsensitive() throws Exception {
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(SAMPLE_INNER_MAIL_BODY_ONE), row));
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(SAMPLE_PART_ONE), row));
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(SAMPLE_PART_TWO), row));
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(SAMPLE_INNER_MAIL_BODY_ONE.toLowerCase()), row));
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(SAMPLE_PART_ONE.toLowerCase()), row));
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(SAMPLE_PART_TWO.toLowerCase()), row));
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(SAMPLE_INNER_MAIL_BODY_ONE.toUpperCase()), row));
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(SAMPLE_PART_ONE.toUpperCase()), row));
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(SAMPLE_PART_TWO.toUpperCase()), row));
+    }
+    
+    public void testBodyShouldNotFindTextInHeaders() throws Exception {
+        assertFalse(SearchUtils.matches(SearchQuery.bodyContains(SAMPLE_INNER_MAIL_FIELD), row));
+        assertFalse(SearchUtils.matches(SearchQuery.bodyContains(SAMPLE_PART_TWO_FIELD), row));
+    }
+    
+    public void testTextShouldFindTextInBody() throws Exception {
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_INNER_MAIL_BODY_ONE), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_PART_ONE), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_PART_TWO), row));
+    }
+    
+    public void testTextShouldFindTextInBodyCaseInsensitive() throws Exception {
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_INNER_MAIL_BODY_ONE), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_PART_ONE), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_PART_TWO), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_INNER_MAIL_BODY_ONE.toLowerCase()), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_PART_ONE.toLowerCase()), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_PART_TWO.toLowerCase()), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_INNER_MAIL_BODY_ONE.toUpperCase()), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_PART_ONE.toUpperCase()), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_PART_TWO.toUpperCase()), row));
+    }
+    
+    public void testTextShouldFindTextInHeaders() throws Exception {
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_INNER_MAIL_FIELD), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_INNER_MAIL_BODY_ONE), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SAMPLE_PART_TWO_FIELD), row));
+    }
+}

Added: james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsRFC822Test.java
URL: http://svn.apache.org/viewvc/james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsRFC822Test.java?rev=635192&view=auto
==============================================================================
--- james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsRFC822Test.java (added)
+++ james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsRFC822Test.java Sun Mar  9 00:24:42 2008
@@ -0,0 +1,90 @@
+/****************************************************************
+ * 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.torque;
+
+import java.nio.charset.Charset;
+
+import junit.framework.TestCase;
+
+import org.apache.james.mailboxmanager.SearchQuery;
+import org.apache.james.mailboxmanager.torque.om.MessageBody;
+import org.apache.james.mailboxmanager.torque.om.MessageHeader;
+import org.apache.james.mailboxmanager.torque.om.MessageRow;
+import org.apache.mailet.RFC2822Headers;
+
+public class SearchUtilsRFC822Test extends TestCase {
+
+    private static final String FROM_ADDRESS = "Harry <harry@example.org";
+    private static final String SUBJECT_PART = "Mixed";
+    private static final String CUSTARD = "CUSTARD";
+    private static final String RHUBARD = "Rhubard";
+    private static final String BODY ="This is a simple email\r\n " +
+            "It has " + RHUBARD + ".\r\n" +
+            "It has " + CUSTARD + ".\r\n" +
+            "It needs naught else.\r\n";
+    
+    MessageRow row;
+    
+    protected void setUp() throws Exception {
+        super.setUp();
+        row = new MessageRow(); 
+        row.addMessageHeader(new MessageHeader(RFC2822Headers.FROM, "Alex <alex@example.org"));
+        row.addMessageHeader(new MessageHeader(RFC2822Headers.TO, FROM_ADDRESS));
+        row.addMessageHeader(new MessageHeader(RFC2822Headers.SUBJECT, "A " + SUBJECT_PART +" Multipart Mail"));
+        row.addMessageHeader(new MessageHeader(RFC2822Headers.DATE, "Thu, 14 Feb 2008 12:00:00 +0000 (GMT)"));
+        row.addMessageBody(new MessageBody(Charset.forName("us-ascii").encode(BODY).array()));
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+    
+    public void testBodyShouldMatchPhraseInBody() throws Exception {
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(CUSTARD), row));
+        assertFalse(SearchUtils.matches(SearchQuery.bodyContains(CUSTARD + CUSTARD), row));
+    }
+    
+    public void testBodyMatchShouldBeCaseInsensitive() throws Exception {
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(RHUBARD), row));
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(RHUBARD.toLowerCase()), row));
+        assertTrue(SearchUtils.matches(SearchQuery.bodyContains(RHUBARD.toLowerCase()), row));
+    }
+    
+    public void testBodyShouldNotMatchPhraseOnlyInHeader() throws Exception {
+        assertFalse(SearchUtils.matches(SearchQuery.bodyContains(FROM_ADDRESS), row));
+        assertFalse(SearchUtils.matches(SearchQuery.bodyContains(SUBJECT_PART), row));
+    }
+    
+    public void testTextShouldMatchPhraseInBody() throws Exception {
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(CUSTARD), row));
+        assertFalse(SearchUtils.matches(SearchQuery.mailContains(CUSTARD + CUSTARD), row));
+    }
+    
+    public void testTextMatchShouldBeCaseInsensitive() throws Exception {
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(RHUBARD), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(RHUBARD.toLowerCase()), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(RHUBARD.toLowerCase()), row));
+    }
+    
+    public void testBodyShouldMatchPhraseOnlyInHeader() throws Exception {
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(FROM_ADDRESS), row));
+        assertTrue(SearchUtils.matches(SearchQuery.mailContains(SUBJECT_PART), row));
+    }
+}

Modified: james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsTest.java?rev=635192&r1=635191&r2=635192&view=diff
==============================================================================
--- james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsTest.java (original)
+++ james/server/trunk/torque-mailboxmanager-function/src/test/java/org/apache/james/mailboxmanager/torque/SearchUtilsTest.java Sun Mar  9 00:24:42 2008
@@ -196,6 +196,24 @@
         assertFalse(SearchUtils.matches(SearchQuery.headerDateBefore("BOGUS",9, 9, 2001), row));
     }
     
+    public void testMatchHeaderContainsCaps() throws Exception {
+        addHeader(SUBJECT_FIELD, TEXT.toUpperCase());
+        assertFalse(SearchUtils.matches(SearchQuery.headerContains(DATE_FIELD, CUSTARD), row));
+        assertFalse(SearchUtils.matches(SearchQuery.headerContains(DATE_FIELD, TEXT), row));
+        assertTrue(SearchUtils.matches(SearchQuery.headerContains(SUBJECT_FIELD, TEXT), row));
+        assertTrue(SearchUtils.matches(SearchQuery.headerContains(SUBJECT_FIELD, RHUBARD), row));
+        assertFalse(SearchUtils.matches(SearchQuery.headerContains(SUBJECT_FIELD, CUSTARD), row)); 
+    }
+    
+    public void testMatchHeaderContainsLowers() throws Exception {
+        addHeader(SUBJECT_FIELD, TEXT.toLowerCase());
+        assertFalse(SearchUtils.matches(SearchQuery.headerContains(DATE_FIELD, CUSTARD), row));
+        assertFalse(SearchUtils.matches(SearchQuery.headerContains(DATE_FIELD, TEXT), row));
+        assertTrue(SearchUtils.matches(SearchQuery.headerContains(SUBJECT_FIELD, TEXT), row));
+        assertTrue(SearchUtils.matches(SearchQuery.headerContains(SUBJECT_FIELD, RHUBARD), row));
+        assertFalse(SearchUtils.matches(SearchQuery.headerContains(SUBJECT_FIELD, CUSTARD), row)); 
+    }
+    
     public void testMatchHeaderContains() throws Exception {
         addHeader(SUBJECT_FIELD, TEXT);
         assertFalse(SearchUtils.matches(SearchQuery.headerContains(DATE_FIELD, CUSTARD), row));



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