Author: eric
Date: Sat Apr 27 06:33:50 2013
New Revision: 1476501

URL: http://svn.apache.org/r1476501
Log:
Readd first implementation of mailox-caching (IMAP-373)

Added:
    
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CacheInvalidatingMailboxListener.java
    
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CacheLoaderFromUnderlying.java
    
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMailboxMapper.java
    
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMailboxSessionMapperFactory.java
    
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMessageMapper.java
    
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/MailboxByPathCache.java
    
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/MailboxMetadataCache.java
    
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/AbstractGuavaCache.java
    
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaCacheWrapper.java
    
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaMailboxByPathCache.java
    
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaMailboxMetadataCache.java

Added: 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CacheInvalidatingMailboxListener.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CacheInvalidatingMailboxListener.java?rev=1476501&view=auto
==============================================================================
--- 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CacheInvalidatingMailboxListener.java
 (added)
+++ 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CacheInvalidatingMailboxListener.java
 Sat Apr 27 06:33:50 2013
@@ -0,0 +1,47 @@
+package org.apache.mailbox.caching;
+
+import org.apache.james.mailbox.MailboxListener;
+import org.apache.james.mailbox.MailboxListenerSupport;
+import org.apache.james.mailbox.exception.MailboxException;
+
+public class CacheInvalidatingMailboxListener<Id> implements MailboxListener {
+
+       private MailboxByPathCache<Id> mailboxCacheByPath;
+       private MailboxMetadataCache<Id> mailboxMetadataCache;
+
+       public CacheInvalidatingMailboxListener(MailboxByPathCache<Id> 
mailboxCacheByPath, MailboxMetadataCache<Id> mailboxMetadataCache) {
+               this.mailboxCacheByPath = mailboxCacheByPath;
+               this.mailboxMetadataCache = mailboxMetadataCache;
+       }
+       
+       public void register(MailboxListenerSupport listener) throws 
MailboxException {
+               listener.addGlobalListener(this, null);
+       }
+       
+       @Override
+       public void event(Event event) {
+               // TODO this needs for sure to be smarter
+               try {
+                       if (event instanceof MessageEvent) {
+                               // invalidate the metadata caches
+                                       invalidateMetadata(event);
+                       }
+                       invalidateMailbox(event);
+               } catch (MailboxException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               }
+
+       }
+
+       private void invalidateMetadata(Event event) throws MailboxException {
+               //HMM, race conditions welcome?
+               
mailboxMetadataCache.invalidate(mailboxCacheByPath.findMailboxByPath(event.getMailboxPath(),
 null));
+               
+       }
+
+       private void invalidateMailbox(Event event) {
+               mailboxCacheByPath.invalidate(event.getMailboxPath());          
+       }
+
+}

Added: 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CacheLoaderFromUnderlying.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CacheLoaderFromUnderlying.java?rev=1476501&view=auto
==============================================================================
--- 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CacheLoaderFromUnderlying.java
 (added)
+++ 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CacheLoaderFromUnderlying.java
 Sat Apr 27 06:33:50 2013
@@ -0,0 +1,5 @@
+package org.apache.mailbox.caching;
+
+public interface CacheLoaderFromUnderlying<Key, Value, Underlying, Except 
extends Throwable> {
+       Value load(Key key, Underlying underlying) throws Except;
+}

Added: 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMailboxMapper.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMailboxMapper.java?rev=1476501&view=auto
==============================================================================
--- 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMailboxMapper.java
 (added)
+++ 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMailboxMapper.java
 Sat Apr 27 06:33:50 2013
@@ -0,0 +1,79 @@
+package org.apache.mailbox.caching;
+import java.util.List;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.exception.MailboxNotFoundException;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.MailboxMapper;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+
+
+public class CachingMailboxMapper<Id> implements MailboxMapper<Id> {
+
+       private MailboxMapper<Id> underlying;
+       private MailboxByPathCache<Id> cache;
+
+       public CachingMailboxMapper(MailboxMapper<Id> underlying, 
MailboxByPathCache<Id> cache) {
+               this.underlying = underlying;
+               this.cache = cache;
+       }
+       
+       @Override
+       public void endRequest() {
+               underlying.endRequest();                
+       }
+
+       @Override
+       public <T> T execute(Transaction<T> transaction) throws 
MailboxException {
+               return underlying.execute(transaction);
+       }
+
+       @Override
+       public void save(Mailbox<Id> mailbox) throws MailboxException {
+               invalidate(mailbox);
+               underlying.save(mailbox);
+       }
+
+       @Override
+       public void delete(Mailbox<Id> mailbox) throws MailboxException {
+               cache.invalidate(mailbox);
+               underlying.delete(mailbox);
+       }
+
+       @Override
+       public Mailbox<Id> findMailboxByPath(MailboxPath mailboxName)
+                       throws MailboxException, MailboxNotFoundException {
+               try {
+                       return cache.findMailboxByPath(mailboxName, underlying);
+               } catch (MailboxNotFoundException e) {
+                       cache.invalidate(mailboxName);
+                       throw e;
+               }
+       }
+
+       @Override
+       public List<Mailbox<Id>> findMailboxWithPathLike(MailboxPath 
mailboxPath)
+                       throws MailboxException {
+               // TODO possible to meaningfully cache it?
+               return underlying.findMailboxWithPathLike(mailboxPath);
+       }
+
+       @Override
+       public boolean hasChildren(Mailbox<Id> mailbox, char delimiter)
+                       throws MailboxException, MailboxNotFoundException {
+               // TODO possible to meaningfully cache it?
+               return hasChildren(mailbox, delimiter);
+       }
+
+       @Override
+       public List<Mailbox<Id>> list() throws MailboxException {
+               // TODO possible to meaningfully cache it? is it used at all?
+               return underlying.list();
+       }
+
+       private void invalidate(Mailbox<Id> mailbox) {
+               cache.invalidate(mailbox);
+       }
+
+
+}

Added: 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMailboxSessionMapperFactory.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMailboxSessionMapperFactory.java?rev=1476501&view=auto
==============================================================================
--- 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMailboxSessionMapperFactory.java
 (added)
+++ 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMailboxSessionMapperFactory.java
 Sat Apr 27 06:33:50 2013
@@ -0,0 +1,43 @@
+package org.apache.mailbox.caching;
+
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.exception.SubscriptionException;
+import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
+import org.apache.james.mailbox.store.mail.MailboxMapper;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.user.SubscriptionMapper;
+
+public class CachingMailboxSessionMapperFactory<Id> extends
+               MailboxSessionMapperFactory<Id> {
+
+       private MailboxSessionMapperFactory<Id> underlying;
+       private MailboxByPathCache<Id> mailboxByPathCache;
+       private MailboxMetadataCache<Id> mailboxMetadataCache;
+
+       public 
CachingMailboxSessionMapperFactory(MailboxSessionMapperFactory<Id> underlying, 
MailboxByPathCache<Id> mailboxByPathCache, MailboxMetadataCache<Id> 
mailboxMetadataCache) {
+               this.underlying = underlying;
+               this.mailboxByPathCache = mailboxByPathCache;
+               this.mailboxMetadataCache = mailboxMetadataCache;
+       }
+       
+       @Override
+       public MessageMapper<Id> createMessageMapper(MailboxSession session)
+                       throws MailboxException {
+               return new 
CachingMessageMapper<Id>(underlying.createMessageMapper(session), 
mailboxByPathCache);
+       }
+
+       @Override
+       public MailboxMapper<Id> createMailboxMapper(MailboxSession session)
+                       throws MailboxException {
+           //TODO(eric) this cast will not work!!! Temporary adding it to 
compile the project...
+               return (MailboxMapper<Id>) new 
CachingMessageMapper<Id>(underlying.createMailboxMapper(session), 
mailboxMetadataCache);
+       }
+
+       @Override
+       public SubscriptionMapper createSubscriptionMapper(MailboxSession 
session)
+                       throws SubscriptionException {
+               return underlying.createSubscriptionMapper(session);
+       }
+
+}

Added: 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMessageMapper.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMessageMapper.java?rev=1476501&view=auto
==============================================================================
--- 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMessageMapper.java
 (added)
+++ 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/CachingMessageMapper.java
 Sat Apr 27 06:33:50 2013
@@ -0,0 +1,138 @@
+package org.apache.mailbox.caching;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.mail.Flags;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MessageMetaData;
+import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.model.UpdatedFlags;
+import org.apache.james.mailbox.store.mail.MailboxMapper;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.james.mailbox.store.mail.model.Message;
+
+public class CachingMessageMapper<Id> implements MessageMapper<Id> {
+       
+       private MessageMapper<Id> underlying;
+       private MailboxMetadataCache<Id> cache;
+
+       public CachingMessageMapper(MessageMapper<Id> underlying, 
MailboxMetadataCache<Id> cache) {
+               this.underlying = underlying;
+               this.cache = cache;
+       }
+       
+    public CachingMessageMapper(MessageMapper<Id> createMessageMapper, 
MailboxByPathCache<Id> mailboxByPathCache) {
+        // TODO(eric) Auto-generated constructor stub
+    }
+
+    public CachingMessageMapper(MailboxMapper<Id> mailboxMapper, 
MailboxMetadataCache<Id> mailboxMetadataCache) {
+        // TODO(eric) Auto-generated constructor stub
+    }
+
+    @Override
+       public void endRequest() {
+               underlying.endRequest();
+       }
+
+       @Override
+       public <T> T execute(Transaction<T> transaction) throws 
MailboxException {
+               return underlying.execute(transaction);
+       }
+
+       @Override
+       public Iterator<Message<Id>> findInMailbox(Mailbox<Id> mailbox,
+                       MessageRange set,
+                       
org.apache.james.mailbox.store.mail.MessageMapper.FetchType type,
+                       int limit) throws MailboxException {
+               return underlying.findInMailbox(mailbox, set, type, limit);
+       }
+
+       @Override
+       public Map<Long, MessageMetaData> expungeMarkedForDeletionInMailbox(
+                       Mailbox<Id> mailbox, MessageRange set) throws 
MailboxException {
+               invalidateMetadata(mailbox);
+               return underlying.expungeMarkedForDeletionInMailbox(mailbox, 
set);
+       }
+
+       @Override
+       public long countMessagesInMailbox(Mailbox<Id> mailbox)
+                       throws MailboxException {
+               return cache.countMessagesInMailbox(mailbox, underlying);
+       }
+
+       @Override
+       public long countUnseenMessagesInMailbox(Mailbox<Id> mailbox)
+                       throws MailboxException {
+               return cache.countUnseenMessagesInMailbox(mailbox, underlying);
+       }
+
+       @Override
+       public void delete(Mailbox<Id> mailbox, Message<Id> message)
+                       throws MailboxException {
+               invalidateMetadata(mailbox);
+               underlying.delete(mailbox, message);
+               
+       }
+
+       @Override
+       public Long findFirstUnseenMessageUid(Mailbox<Id> mailbox)
+                       throws MailboxException {
+               return cache.findFirstUnseenMessageUid(mailbox, underlying);
+       }
+
+       @Override
+       public List<Long> findRecentMessageUidsInMailbox(Mailbox<Id> mailbox)
+                       throws MailboxException {
+               // TODO can be meaningfully cached?
+               return underlying.findRecentMessageUidsInMailbox(mailbox);
+       }
+
+       @Override
+       public MessageMetaData add(Mailbox<Id> mailbox, Message<Id> message)
+                       throws MailboxException {
+               invalidateMetadata(mailbox);
+               return underlying.add(mailbox, message);
+       }
+
+       @Override
+       public Iterator<UpdatedFlags> updateFlags(Mailbox<Id> mailbox, Flags 
flags,
+                       boolean value, boolean replace, MessageRange set)
+                       throws MailboxException {
+               //check if there are in fact any updates
+               if (set.iterator().hasNext())
+                       invalidateMetadata(mailbox);
+               return underlying.updateFlags(mailbox, flags, value, replace, 
set);
+       }
+
+
+       @Override
+       public MessageMetaData copy(Mailbox<Id> mailbox, Message<Id> original)
+                       throws MailboxException {
+               invalidateMetadata(mailbox);
+               return underlying.copy(mailbox, original);
+       }
+
+       @Override
+       public long getLastUid(Mailbox<Id> mailbox) throws MailboxException {
+               return cache.getLastUid(mailbox, underlying);
+       }
+
+       @Override
+       public long getHighestModSeq(Mailbox<Id> mailbox) throws 
MailboxException {
+               return cache.getHighestModSeq(mailbox, underlying);
+       }
+
+       private void invalidateMetadata(Mailbox<Id> mailbox) {
+               cache.invalidate(mailbox);
+               
+       }
+
+    @Override
+    public MessageMetaData move(Mailbox<Id> mailbox, Message<Id> original) 
throws MailboxException {
+        throw new UnsupportedOperationException("Move is not yet supported");
+    }
+
+}

Added: 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/MailboxByPathCache.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/MailboxByPathCache.java?rev=1476501&view=auto
==============================================================================
--- 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/MailboxByPathCache.java
 (added)
+++ 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/MailboxByPathCache.java
 Sat Apr 27 06:33:50 2013
@@ -0,0 +1,22 @@
+package org.apache.mailbox.caching;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.exception.MailboxNotFoundException;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.MailboxMapper;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+
+public interface MailboxByPathCache<Id> {
+
+       public abstract Mailbox<Id> findMailboxByPath(MailboxPath mailboxName,
+                       MailboxMapper<Id> underlying) throws 
MailboxNotFoundException,
+                       MailboxException;
+
+       public abstract void invalidate(Mailbox<Id> mailbox);
+       
+       public abstract void invalidate(MailboxPath mailboxPath);
+
+       // for the purpose of cascading the invalidations; does it make sense? 
+       //public void connectTo(MailboxMetadataCache<Id> mailboxMetadataCache);
+
+}

Added: 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/MailboxMetadataCache.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/MailboxMetadataCache.java?rev=1476501&view=auto
==============================================================================
--- 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/MailboxMetadataCache.java
 (added)
+++ 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/MailboxMetadataCache.java
 Sat Apr 27 06:33:50 2013
@@ -0,0 +1,28 @@
+package org.apache.mailbox.caching;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+
+public interface MailboxMetadataCache<Id> {
+
+       public abstract long countMessagesInMailbox(Mailbox<Id> mailbox,
+                       MessageMapper<Id> underlying) throws MailboxException;
+
+       public abstract long countUnseenMessagesInMailbox(Mailbox<Id> mailbox,
+                       MessageMapper<Id> underlying) throws MailboxException;
+
+       public abstract Long findFirstUnseenMessageUid(Mailbox<Id> mailbox,
+                       MessageMapper<Id> underlying) throws MailboxException;
+
+       public abstract long getLastUid(Mailbox<Id> mailbox,
+                       MessageMapper<Id> underlying) throws MailboxException;
+
+       public abstract long getHighestModSeq(Mailbox<Id> mailbox,
+                       MessageMapper<Id> underlying) throws MailboxException;
+
+       public abstract void invalidate(Mailbox<Id> mailbox);
+
+//     public abstract void invalidate(MailboxPath mailboxPath);
+
+}
\ No newline at end of file

Added: 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/AbstractGuavaCache.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/AbstractGuavaCache.java?rev=1476501&view=auto
==============================================================================
--- 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/AbstractGuavaCache.java
 (added)
+++ 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/AbstractGuavaCache.java
 Sat Apr 27 06:33:50 2013
@@ -0,0 +1,15 @@
+package org.apache.mailbox.caching.guava;
+
+import java.util.concurrent.TimeUnit;
+
+import com.google.common.cache.CacheBuilder;
+
+public class AbstractGuavaCache {
+
+       // TODO this can probably be instantiated more elegant way
+       protected static final CacheBuilder<Object, Object> BUILDER = 
+                       CacheBuilder.newBuilder()                       
+                       .maximumSize(100000)
+                       .expireAfterWrite(15, TimeUnit.MINUTES);
+
+}

Added: 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaCacheWrapper.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaCacheWrapper.java?rev=1476501&view=auto
==============================================================================
--- 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaCacheWrapper.java
 (added)
+++ 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaCacheWrapper.java
 Sat Apr 27 06:33:50 2013
@@ -0,0 +1,37 @@
+package org.apache.mailbox.caching.guava;
+
+import org.apache.mailbox.caching.CacheLoaderFromUnderlying;
+
+import com.google.common.cache.Cache;
+
+public abstract class GuavaCacheWrapper<Key, Value, Underlying, 
KeyRepresentation, Except extends Throwable>
+       implements CacheLoaderFromUnderlying<Key, Value, Underlying, Except> {
+
+       private final Cache<KeyRepresentation, Value> cache;
+//     private final CacheLoaderFromUnderlying<Key, Value, Underlying, Except> 
loader;
+
+       public GuavaCacheWrapper(Cache<KeyRepresentation, Value> cache/*, 
CacheLoaderFromUnderlying<Key, Value, Underlying, Except> loader*/) {
+               this.cache = cache;
+//             this.loader = loader;
+       }
+       
+       public Value get(Key key, Underlying underlying) throws Except {
+               Value value = cache.getIfPresent(getKeyRepresentation(key));
+               if (value != null)
+                       return value;
+               else {
+                       value = load(key, underlying);
+                       cache.put(getKeyRepresentation(key), value);
+                       return value;
+               }
+
+       }
+       
+       public void invalidate(Key key) {
+               if (key != null) //needed?
+                       cache.invalidate(getKeyRepresentation(key));
+       }
+
+       public abstract KeyRepresentation getKeyRepresentation(Key key);
+
+}

Added: 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaMailboxByPathCache.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaMailboxByPathCache.java?rev=1476501&view=auto
==============================================================================
--- 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaMailboxByPathCache.java
 (added)
+++ 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaMailboxByPathCache.java
 Sat Apr 27 06:33:50 2013
@@ -0,0 +1,80 @@
+package org.apache.mailbox.caching.guava;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.exception.MailboxNotFoundException;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.MailboxMapper;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.mailbox.caching.MailboxByPathCache;
+
+import com.google.common.cache.Cache;
+
+public class GuavaMailboxByPathCache<Id> extends AbstractGuavaCache implements 
MailboxByPathCache<Id> {
+       
+       private final Cache<String, Mailbox<Id>> findMailboxByPathCache = 
BUILDER.build();
+
+       private final MailboxByPathCacheWrapper wrapper;
+
+       public GuavaMailboxByPathCache() {
+               this.wrapper = new 
MailboxByPathCacheWrapper(findMailboxByPathCache);
+       }
+       
+       @Override
+       public Mailbox<Id> findMailboxByPath(MailboxPath mailboxName, 
MailboxMapper<Id> underlying) throws MailboxNotFoundException, MailboxException 
{
+               
+               return wrapper.get(mailboxName, underlying);
+       }
+       
+//     alternative plain implementation - review and choose the better
+//     public Mailbox<Id> findMailboxByPath(MailboxPath mailboxName, 
MailboxMapper<Id> underlying) throws MailboxNotFoundException, MailboxException 
{
+//             Mailbox<Id> mailbox = 
findMailboxByPathCache.getIfPresent(mailboxName.toString());
+//             if (mailbox != null)
+//                     return mailbox;
+//             else {
+//                     mailbox = new 
MailboxByPathCacheLoaderFromUnderlying().load(mailboxName, underlying);
+//                     findMailboxByPathCache.put(mailboxName.toString(), 
mailbox);
+//                     return mailbox;
+//             }
+//     }
+
+       
+
+       @Override
+       public void invalidate(Mailbox<Id> mailbox) {
+               invalidate(new MailboxPath(mailbox.getNamespace(), 
mailbox.getUser(), mailbox.getName()));
+       }
+       
+       @Override
+       public void invalidate(MailboxPath mailboxPath) {
+               wrapper.invalidate(mailboxPath);
+       }
+
+
+       //Does it make sense to define such loaders as separate classes for 
reuse?
+//     class MailboxByPathCacheLoaderFromUnderlying implements 
CacheLoaderFromUnderlying<MailboxPath, Mailbox<Id>, MailboxMapper<Id>, 
MailboxException> {
+//             @Override
+//             public Mailbox<Id> load(MailboxPath mailboxName, 
MailboxMapper<Id> underlying) throws MailboxException {
+//                     return underlying.findMailboxByPath(mailboxName);
+//             }
+//     }
+
+       class MailboxByPathCacheWrapper extends GuavaCacheWrapper<MailboxPath, 
Mailbox<Id>, MailboxMapper<Id>, String, MailboxException> {
+
+               public MailboxByPathCacheWrapper(
+                               Cache<String, Mailbox<Id>> cache/*,
+                               MailboxByPathCacheLoaderFromUnderlying 
loader*/) {
+                       super(cache);
+               }
+
+               @Override
+               public Mailbox<Id> load(MailboxPath mailboxName, 
MailboxMapper<Id> underlying) throws MailboxException {
+                       return underlying.findMailboxByPath(mailboxName);
+               }
+
+               @Override
+               public String getKeyRepresentation(MailboxPath key) {
+                       return key.toString();
+               }
+               
+       }
+}

Added: 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaMailboxMetadataCache.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaMailboxMetadataCache.java?rev=1476501&view=auto
==============================================================================
--- 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaMailboxMetadataCache.java
 (added)
+++ 
james/mailbox/trunk/caching/src/main/java/org/apache/mailbox/caching/guava/GuavaMailboxMetadataCache.java
 Sat Apr 27 06:33:50 2013
@@ -0,0 +1,135 @@
+package org.apache.mailbox.caching.guava;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.mailbox.caching.MailboxMetadataCache;
+
+import com.google.common.cache.Cache;
+
+public class GuavaMailboxMetadataCache<Id> extends AbstractGuavaCache 
implements MailboxMetadataCache<Id> {
+
+       // TODO these can probably be instantiated more elegant way
+       private final Cache<Id, Long> cacheCountMessagesInMailbox = 
BUILDER.build();
+       private final Cache<Id, Long> cacheCountUnseenMessagesInMailbox = 
BUILDER.build();
+       private final Cache<Id, Long> cacheFindFirstUnseenMessageUid = 
BUILDER.build();
+       private final Cache<Id, Long> cacheGetLastUid = BUILDER.build();
+       private final Cache<Id, Long> cacheGetHighestModSeq = BUILDER.build();
+
+       private final MetadataCacheWrapper countMessagesInMailboxWrapper = new 
CountMessagesInMailboxWrapper(cacheCountMessagesInMailbox);
+       private final MetadataCacheWrapper countUnseenMessagesInMailboxWrapper 
= new CountUnseenMessagesInMailboxWrapper(cacheCountUnseenMessagesInMailbox);
+       private final MetadataCacheWrapper findFirstUnseenMessageUid = new 
FindFirstUnseenMessageUidWrapper(cacheFindFirstUnseenMessageUid);
+       private final MetadataCacheWrapper highestModSeqWrapper = new 
HighestModseqCacheWrapper(cacheGetHighestModSeq);
+       private final MetadataCacheWrapper lastUidWrapper = new 
LastUidCacheWrapper(cacheGetLastUid);
+       
+       @Override
+       public long countMessagesInMailbox(Mailbox<Id> mailbox, 
MessageMapper<Id> underlying) throws MailboxException {
+               return countMessagesInMailboxWrapper.get(mailbox, underlying);
+       }
+       
+       @Override
+       public long countUnseenMessagesInMailbox(Mailbox<Id> mailbox, 
MessageMapper<Id> underlying)
+                       throws MailboxException {
+               return countUnseenMessagesInMailboxWrapper.get(mailbox, 
underlying);
+       }
+       
+       @Override
+       public Long findFirstUnseenMessageUid(Mailbox<Id> mailbox, 
MessageMapper<Id> underlying)
+                       throws MailboxException {
+               return findFirstUnseenMessageUid.get(mailbox, underlying);
+       }
+       
+       @Override
+       public long getLastUid(Mailbox<Id> mailbox, MessageMapper<Id> 
underlying) throws MailboxException {
+               return lastUidWrapper.get(mailbox, underlying);
+
+       }
+       
+       @Override
+       public long getHighestModSeq(Mailbox<Id> mailbox, MessageMapper<Id> 
underlying) throws MailboxException {
+               return highestModSeqWrapper.get(mailbox, underlying);
+       }
+       
+       @Override
+       public void invalidate(Mailbox<Id> mailbox) {
+               cacheCountMessagesInMailbox.invalidate(mailbox);
+               cacheCountUnseenMessagesInMailbox.invalidate(mailbox);
+               cacheFindFirstUnseenMessageUid.invalidate(mailbox);
+               lastUidWrapper.invalidate(mailbox);
+               highestModSeqWrapper.invalidate(mailbox);
+       }
+
+       
+       abstract class MetadataCacheWrapper extends 
GuavaCacheWrapper<Mailbox<Id>, Long, MessageMapper<Id>, Id, MailboxException> {
+
+               public MetadataCacheWrapper(Cache<Id, Long> cache) {
+                       super(cache);
+               }
+
+               @Override
+               public Id getKeyRepresentation(Mailbox<Id> key) {
+                       return key.getMailboxId();
+               }               
+               
+       }
+
+       class CountMessagesInMailboxWrapper extends MetadataCacheWrapper {
+
+               public CountMessagesInMailboxWrapper(Cache<Id, Long> cache) {
+                       super(cache);
+               }
+               @Override
+               public Long load(Mailbox<Id> mailbox, MessageMapper<Id> 
underlying)
+                               throws MailboxException {
+                       return underlying.countMessagesInMailbox(mailbox);
+               }
+
+       }
+       
+       class CountUnseenMessagesInMailboxWrapper extends MetadataCacheWrapper {
+
+               public CountUnseenMessagesInMailboxWrapper(Cache<Id, Long> 
cache) {
+                       super(cache);
+               }
+               @Override
+               public Long load(Mailbox<Id> mailbox, MessageMapper<Id> 
underlying)
+                               throws MailboxException {
+                       return underlying.countUnseenMessagesInMailbox(mailbox);
+               }
+
+       }
+
+       class FindFirstUnseenMessageUidWrapper extends MetadataCacheWrapper {
+
+               public FindFirstUnseenMessageUidWrapper(Cache<Id, Long> cache) {
+                       super(cache);
+               }
+               @Override
+               public Long load(Mailbox<Id> mailbox, MessageMapper<Id> 
underlying)
+                               throws MailboxException {
+                       return underlying.findFirstUnseenMessageUid(mailbox);
+               }
+
+       }
+
+       class LastUidCacheWrapper extends MetadataCacheWrapper {
+               public LastUidCacheWrapper(Cache<Id, Long> cache) {
+                       super(cache);
+               }
+               @Override
+               public Long load(Mailbox<Id> mailbox, MessageMapper<Id> 
underlying) throws MailboxException {
+                       return underlying.getLastUid(mailbox);
+               }
+       }
+
+       class HighestModseqCacheWrapper extends MetadataCacheWrapper {
+               public HighestModseqCacheWrapper(Cache<Id, Long> cache) {
+                       super(cache);
+               }
+               @Override
+               public Long load(Mailbox<Id> mailbox, MessageMapper<Id> 
underlying) throws MailboxException {
+                       return underlying.getHighestModSeq(mailbox);
+               }
+       }
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to