You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2010/08/12 12:10:56 UTC
svn commit: r984711 - in /james/imap/trunk:
jcr/src/main/java/org/apache/james/imap/jcr/mail/
jpa/src/main/java/org/apache/james/imap/jpa/mail/
memory/src/main/java/org/apache/james/imap/inmemory/mail/
store/src/main/java/org/apache/james/imap/store/ s...
Author: norman
Date: Thu Aug 12 10:10:56 2010
New Revision: 984711
URL: http://svn.apache.org/viewvc?rev=984711&view=rev
Log:
Introduce a SearchQueryIterator which can handle the SearchQuery matching lazy. I also changed the Mapper to return only an Iterator with the uids of the found messages so its easier to write an implementation specific implementation whith an optimized performance (IMAP-190)
Added:
james/imap/trunk/store/src/main/java/org/apache/james/imap/store/SearchQueryIterator.java
Modified:
james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/JCRMessageMapper.java
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMessageMapper.java
james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/mail/InMemoryMessageMapper.java
james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMessageManager.java
james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/MessageMapper.java
Modified: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/JCRMessageMapper.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/JCRMessageMapper.java?rev=984711&r1=984710&r2=984711&view=diff
==============================================================================
--- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/JCRMessageMapper.java (original)
+++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/JCRMessageMapper.java Thu Aug 12 10:10:56 2010
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
+import java.util.Iterator;
import java.util.List;
import javax.jcr.ItemNotFoundException;
@@ -51,6 +52,7 @@ import org.apache.james.imap.mailbox.Sto
import org.apache.james.imap.mailbox.MessageRange.Type;
import org.apache.james.imap.mailbox.SearchQuery.Criterion;
import org.apache.james.imap.mailbox.SearchQuery.NumericRange;
+import org.apache.james.imap.store.SearchQueryIterator;
import org.apache.james.imap.store.mail.MessageMapper;
import org.apache.james.imap.store.mail.model.Mailbox;
import org.apache.james.imap.store.mail.model.MailboxMembership;
@@ -604,25 +606,37 @@ public class JCRMessageMapper extends Ab
return String.valueOf(value);
}
}
+
/*
* (non-Javadoc)
- *
- * @see
- * org.apache.james.imap.store.mail.MessageMapper#searchMailbox(org.apache
- * .james.imap.mailbox.SearchQuery)
+ * @see org.apache.james.imap.store.mail.MessageMapper#searchMailbox(org.apache.james.imap.store.mail.model.Mailbox, org.apache.james.imap.mailbox.SearchQuery)
*/
- public List<MailboxMembership<String>> searchMailbox(Mailbox<String> mailbox, SearchQuery query) throws StorageException {
+ public Iterator<Long> searchMailbox(Mailbox<String> mailbox, SearchQuery query) throws StorageException {
try {
- List<MailboxMembership<String>> list = new ArrayList<MailboxMembership<String>>();
final Query xQuery = formulateXPath(mailbox, query);
QueryResult result = xQuery.execute();
- NodeIterator it = result.getNodes();
- while (it.hasNext()) {
- list.add(new JCRMessage(it.nextNode(), getLogger()));
- }
- return list;
+ final NodeIterator it = result.getNodes();
+
+
+ // Lazy build the JCRMessage instances
+ return new SearchQueryIterator(new Iterator<MailboxMembership<?>>() {
+
+ public boolean hasNext() {
+ return it.hasNext();
+ }
+
+ public MailboxMembership<?> next() {
+ return new JCRMessage(it.nextNode(), getLogger());
+
+ }
+
+ public void remove() {
+ it.remove();
+ }
+
+ }, query, getLogger());
} catch (RepositoryException e) {
throw new StorageException(HumanReadableText.SEARCH_FAILED, e);
}
Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMessageMapper.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMessageMapper.java?rev=984711&r1=984710&r2=984711&view=diff
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMessageMapper.java (original)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMessageMapper.java Thu Aug 12 10:10:56 2010
@@ -18,6 +18,7 @@
****************************************************************/
package org.apache.james.imap.jpa.mail;
+import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityManager;
@@ -39,6 +40,7 @@ import org.apache.james.imap.mailbox.Sto
import org.apache.james.imap.mailbox.MessageRange.Type;
import org.apache.james.imap.mailbox.SearchQuery.Criterion;
import org.apache.james.imap.mailbox.SearchQuery.NumericRange;
+import org.apache.james.imap.store.SearchQueryIterator;
import org.apache.james.imap.store.mail.MessageMapper;
import org.apache.james.imap.store.mail.model.Mailbox;
import org.apache.james.imap.store.mail.model.MailboxMembership;
@@ -189,61 +191,61 @@ public class JPAMessageMapper extends JP
}
}
- /**
- * @see org.apache.james.imap.store.mail.MessageMapper#searchMailbox(org.apache.james.imap.mailbox.SearchQuery)
+
+
+ /*
+ *
+ * (non-Javadoc)
+ * @see org.apache.james.imap.store.mail.MessageMapper#searchMailbox(org.apache.james.imap.store.mail.model.Mailbox, org.apache.james.imap.mailbox.SearchQuery)
*/
@SuppressWarnings("unchecked")
- public List<MailboxMembership<Long>> searchMailbox(Mailbox<Long> mailbox, SearchQuery query) throws StorageException {
+ public Iterator<Long> searchMailbox(Mailbox<Long> mailbox, SearchQuery query) throws StorageException {
try {
- final Query jQuery = formulateJQL(mailbox.getMailboxId(), query);
- return jQuery.getResultList();
- } catch (PersistenceException e) {
- throw new StorageException(HumanReadableText.SEARCH_FAILED, e);
- }
- }
-
- private Query formulateJQL(Long mailboxId, SearchQuery query) {
- final StringBuilder queryBuilder = new StringBuilder(50);
- queryBuilder.append("SELECT membership FROM Membership membership WHERE membership.mailboxId = ").append(mailboxId);
- final List<Criterion> criteria = query.getCriterias();
- boolean range = false;
- int rangeLength = -1;
-
- if (criteria.size() == 1) {
- final Criterion firstCriterion = criteria.get(0);
- if (firstCriterion instanceof SearchQuery.UidCriterion) {
- final SearchQuery.UidCriterion uidCriterion = (SearchQuery.UidCriterion) firstCriterion;
- final NumericRange[] ranges = uidCriterion.getOperator().getRange();
- rangeLength = ranges.length;
-
- for (int i = 0; i < ranges.length; i++) {
- final long low = ranges[i].getLowValue();
- final long high = ranges[i].getHighValue();
-
- if (low == Long.MAX_VALUE) {
- queryBuilder.append(" AND membership.uid<=").append(high);
- range = true;
- } else if (low == high) {
- queryBuilder.append(" AND membership.uid=").append(low);
- range = false;
- } else {
- queryBuilder.append(" AND membership.uid BETWEEN ").append(low).append(" AND ").append(high);
- range = true;
+ final StringBuilder queryBuilder = new StringBuilder(50);
+ queryBuilder.append("SELECT membership FROM Membership membership WHERE membership.mailboxId = ").append(mailbox.getMailboxId());
+ final List<Criterion> criteria = query.getCriterias();
+ boolean range = false;
+ int rangeLength = -1;
+
+ if (criteria.size() == 1) {
+ final Criterion firstCriterion = criteria.get(0);
+ if (firstCriterion instanceof SearchQuery.UidCriterion) {
+ final SearchQuery.UidCriterion uidCriterion = (SearchQuery.UidCriterion) firstCriterion;
+ final NumericRange[] ranges = uidCriterion.getOperator().getRange();
+ rangeLength = ranges.length;
+
+ for (int i = 0; i < ranges.length; i++) {
+ final long low = ranges[i].getLowValue();
+ final long high = ranges[i].getHighValue();
+
+ if (low == Long.MAX_VALUE) {
+ queryBuilder.append(" AND membership.uid<=").append(high);
+ range = true;
+ } else if (low == high) {
+ queryBuilder.append(" AND membership.uid=").append(low);
+ range = false;
+ } else {
+ queryBuilder.append(" AND membership.uid BETWEEN ").append(low).append(" AND ").append(high);
+ range = true;
+ }
}
}
+ }
+ if (rangeLength != 0 || range) {
+ queryBuilder.append(" order by membership.uid");
}
- }
- if (rangeLength != 0 || range) {
- queryBuilder.append(" order by membership.uid");
- }
-
- Query jQuery = getEntityManager().createQuery(queryBuilder.toString());
+
+ Query jQuery = getEntityManager().createQuery(queryBuilder.toString());
- // Check if we only need to fetch 1 message, if so we can set a limit to speed up things
- if (rangeLength == 1 && range == false) {
- jQuery.setMaxResults(1);
+ // Check if we only need to fetch 1 message, if so we can set a limit to speed up things
+ if (rangeLength == 1 && range == false) {
+ jQuery.setMaxResults(1);
+ }
+ return new SearchQueryIterator(jQuery.getResultList().iterator(), query);
+
+ } catch (PersistenceException e) {
+ throw new StorageException(HumanReadableText.SEARCH_FAILED, e);
}
- return jQuery;
}
/*
Modified: james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/mail/InMemoryMessageMapper.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/mail/InMemoryMessageMapper.java?rev=984711&r1=984710&r2=984711&view=diff
==============================================================================
--- james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/mail/InMemoryMessageMapper.java (original)
+++ james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/mail/InMemoryMessageMapper.java Thu Aug 12 10:10:56 2010
@@ -14,6 +14,7 @@ import org.apache.james.imap.mailbox.Mes
import org.apache.james.imap.mailbox.SearchQuery;
import org.apache.james.imap.mailbox.StorageException;
import org.apache.james.imap.store.MailboxMembershipComparator;
+import org.apache.james.imap.store.SearchQueryIterator;
import org.apache.james.imap.store.mail.MessageMapper;
import org.apache.james.imap.store.mail.model.Mailbox;
import org.apache.james.imap.store.mail.model.MailboxMembership;
@@ -169,12 +170,13 @@ public class InMemoryMessageMapper imple
return message.getUid();
}
+
/*
* (non-Javadoc)
- * @see org.apache.james.imap.store.mail.MessageMapper#searchMailbox(org.apache.james.imap.mailbox.SearchQuery)
+ * @see org.apache.james.imap.store.mail.MessageMapper#searchMailbox(org.apache.james.imap.store.mail.model.Mailbox, org.apache.james.imap.mailbox.SearchQuery)
*/
- public List<MailboxMembership<Long>> searchMailbox(Mailbox<Long> mailbox, SearchQuery query) throws StorageException {
- return new ArrayList<MailboxMembership<Long>>(getMembershipByUidForMailbox(mailbox).values());
+ public Iterator<Long> searchMailbox(Mailbox<Long> mailbox, SearchQuery query) throws StorageException {
+ return new SearchQueryIterator(new ArrayList<MailboxMembership<?>>(getMembershipByUidForMailbox(mailbox).values()).iterator(), query);
}
/**
Added: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/SearchQueryIterator.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/SearchQueryIterator.java?rev=984711&view=auto
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/SearchQueryIterator.java (added)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/SearchQueryIterator.java Thu Aug 12 10:10:56 2010
@@ -0,0 +1,110 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+package org.apache.james.imap.store;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.apache.commons.logging.Log;
+import org.apache.james.imap.mailbox.MailboxException;
+import org.apache.james.imap.mailbox.SearchQuery;
+import org.apache.james.imap.store.mail.model.MailboxMembership;
+
+/**
+ * {@link Iterator} implementation which use a {@link MessageSearches} instance to lazy
+ * match the elements of a wrapped {@link Iterator} against a {@link SearchQuery}. This class should be used
+ * if the store implementation can not filter the {@link Iterator} fore-hand against the {@link SearchQuery}
+ *
+ *
+ */
+public final class SearchQueryIterator implements Iterator<Long>{
+
+ private final MessageSearches searches = new MessageSearches();
+ private Iterator<MailboxMembership<?>> it;
+ private SearchQuery query;
+ private Long next;
+
+ public SearchQueryIterator(Iterator<MailboxMembership<?>> it, SearchQuery query) {
+ this(it, query, null);
+ }
+
+ public SearchQueryIterator(Iterator<MailboxMembership<?>> it, SearchQuery query, Log log) {
+ this.it = it;
+ this.query = query;
+ if (log != null) {
+ searches.setLog(log);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ // check if we already did the lazy loading
+ if (next == null) {
+ while (it.hasNext()) {
+ MailboxMembership<?> nextMembership = it.next();
+ try {
+ if (searches.isMatch(query, nextMembership)) {
+ next = nextMembership.getUid();
+ return true;
+ } else {
+ next = null;
+ }
+ } catch (MailboxException e) {
+ searches.getLog().info("Cannot test message against search criteria. Will continue to test other messages.", e);
+ if (searches.getLog().isDebugEnabled())
+ searches.getLog().debug("UID: " + nextMembership.getUid());
+ }
+ }
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+
+ /**
+ * Return the next Uid of the {@link MailboxMembership} which matched the
+ * {@link SearchQuery}
+ *
+ * @return uid
+ */
+ public Long next() {
+ if (hasNext()) {
+ Long copy = next;
+ next = null;
+ return copy;
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+
+ /**
+ * Not supported.
+ *
+ * @throws UnsupportedOperationException
+ */
+ public void remove() {
+ throw new UnsupportedOperationException("Read-only Iterator");
+ }
+
+}
Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMessageManager.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMessageManager.java?rev=984711&r1=984710&r2=984711&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMessageManager.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMessageManager.java Thu Aug 12 10:10:56 2010
@@ -32,7 +32,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
@@ -506,23 +505,7 @@ public abstract class StoreMessageManage
* @see org.apache.james.imap.mailbox.Mailbox#search(org.apache.james.imap.mailbox.SearchQuery, org.apache.james.imap.mailbox.MailboxSession)
*/
public Iterator<Long> search(SearchQuery query, MailboxSession mailboxSession) throws MailboxException {
- final List<MailboxMembership<Id>> members = messageMapper.searchMailbox(mailbox, query);
- final Set<Long> uids = new TreeSet<Long>();
- for (MailboxMembership<Id> member:members) {
- try {
- final MessageSearches searches = new MessageSearches();
- searches.setLog(mailboxSession.getLog());
- if (searches.isMatch(query, member)) {
- uids.add(member.getUid());
- }
- } catch (MailboxException e) {
- mailboxSession.getLog().info("Cannot test message against search criteria. Will continue to test other messages.", e);
- if (mailboxSession.getLog().isDebugEnabled())
- mailboxSession.getLog().debug("UID: " + member.getUid());
- }
- }
-
- return uids.iterator();
+ return messageMapper.searchMailbox(mailbox, query);
}
/**
Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/MessageMapper.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/MessageMapper.java?rev=984711&r1=984710&r2=984711&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/MessageMapper.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/MessageMapper.java Thu Aug 12 10:10:56 2010
@@ -18,6 +18,7 @@
****************************************************************/
package org.apache.james.imap.store.mail;
+import java.util.Iterator;
import java.util.List;
import org.apache.james.imap.mailbox.MessageRange;
@@ -79,14 +80,14 @@ public interface MessageMapper<Id> exten
throws StorageException;
/**
- * Return a List of {@link MailboxMembership} which matched the {@link SearchQuery}
+ * Return a List of uids which matched the {@link SearchQuery}
* The list must be ordered by the {@link Document} uid
* @param mailbox
* @param query
* @return
* @throws StorageException
*/
- public abstract List<MailboxMembership<Id>> searchMailbox(Mailbox<Id> mailbox, SearchQuery query) throws StorageException;
+ public abstract Iterator<Long> searchMailbox(Mailbox<Id> mailbox, SearchQuery query) throws StorageException;
/**
* Delete the given {@link MailboxMembership}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org