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/05/12 18:50:27 UTC

svn commit: r943579 [1/2] - in /james/imap/trunk: deployment/src/test/java/org/apache/james/imap/functional/jcr/ jcr/src/main/java/org/apache/james/imap/jcr/ jcr/src/main/java/org/apache/james/imap/jcr/mail/ jcr/src/main/java/org/apache/james/imap/jcr/...

Author: norman
Date: Wed May 12 16:50:26 2010
New Revision: 943579

URL: http://svn.apache.org/viewvc?rev=943579&view=rev
Log:
* Introduce a UidConsumer which take care of consume/reserve the next uid for the message to append. Every implementation need to write a specific implementation
* Refactor the implementations to use the UidConsumer
* Now the JCRStressTest passes
* Relayout the JCR Tree (still work in progress) to make it more usable when using webdav etc

Added:
    james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRUidConsumer.java
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAUidConsumer.java
    james/imap/trunk/store/src/main/java/org/apache/james/imap/store/UidConsumer.java
Removed:
    james/imap/trunk/jcr/src/test/java/org/apache/james/imap/jcr/JCRUtilsTest.java
Modified:
    james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jcr/JCRHostSystem.java
    james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jcr/JCRStressTest.java
    james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/AbstractJCRMapper.java
    james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailbox.java
    james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailboxManager.java
    james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRSubscriptionManager.java
    james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRUtils.java
    james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/JCRMailboxMapper.java
    james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/JCRMessageMapper.java
    james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMailbox.java
    james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMessage.java
    james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/user/JCRSubscriptionMapper.java
    james/imap/trunk/jcr/src/main/resources/org/apache/james/imap/jcr/imap.cnd
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java
    james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.java
    james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java
    james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java
    james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java

Modified: james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jcr/JCRHostSystem.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jcr/JCRHostSystem.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jcr/JCRHostSystem.java (original)
+++ james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jcr/JCRHostSystem.java Wed May 12 16:50:26 2010
@@ -28,7 +28,6 @@ import org.apache.james.imap.encode.main
 import org.apache.james.imap.functional.ImapHostSystem;
 import org.apache.james.imap.functional.InMemoryUserManager;
 import org.apache.james.imap.jcr.GlobalMailboxSessionJCRRepository;
-import org.apache.james.imap.jcr.JCRImapConstants;
 import org.apache.james.imap.jcr.JCRMailboxManager;
 import org.apache.james.imap.jcr.JCRSubscriptionManager;
 import org.apache.james.imap.jcr.JCRUtils;
@@ -70,7 +69,7 @@ public class JCRHostSystem extends ImapH
             userManager = new InMemoryUserManager();
 
             //TODO: Fix the scaling stuff so the tests will pass with max scaling too
-            mailboxManager = new JCRMailboxManager(userManager, new JCRSubscriptionManager(sessionRepos, JCRImapConstants.MIN_SCALING), sessionRepos, JCRImapConstants.MIN_SCALING);
+            mailboxManager = new JCRMailboxManager(userManager, new JCRSubscriptionManager(sessionRepos), sessionRepos);
 
             final DefaultImapProcessorFactory defaultImapProcessorFactory = new DefaultImapProcessorFactory();
             resetUserMetaData();

Modified: james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jcr/JCRStressTest.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jcr/JCRStressTest.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jcr/JCRStressTest.java (original)
+++ james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jcr/JCRStressTest.java Wed May 12 16:50:26 2010
@@ -26,10 +26,11 @@ import org.apache.commons.logging.impl.S
 import org.apache.jackrabbit.core.RepositoryImpl;
 import org.apache.jackrabbit.core.config.RepositoryConfig;
 import org.apache.james.imap.functional.AbstractStressTest;
-import org.apache.james.imap.jcr.JCRImapConstants;
+import org.apache.james.imap.jcr.GlobalMailboxSessionJCRRepository;
 import org.apache.james.imap.jcr.JCRMailboxManager;
+import org.apache.james.imap.jcr.JCRSubscriptionManager;
 import org.apache.james.imap.jcr.JCRUtils;
-import org.apache.james.imap.mailbox.MailboxException;
+import org.apache.james.imap.jcr.MailboxSessionJCRRepository;
 import org.apache.james.imap.mailbox.MailboxSession;
 import org.apache.james.imap.store.StoreMailboxManager;
 import org.junit.After;
@@ -64,35 +65,35 @@ public class JCRStressTest extends Abstr
         // Register imap cnd file
         JCRUtils.registerCnd(repository, workspace, user, pass);
 
+        MailboxSessionJCRRepository sessionRepos = new GlobalMailboxSessionJCRRepository(repository, workspace, user, pass);
         // TODO: Fix the scaling stuff so the tests will pass with max scaling
         // too
-        //mailboxManager = new JCRGlobalUserMailboxManager(null, new JCRGlobalUserSubscriptionManager(repository, workspace, user, pass, JCRImapConstants.MIN_SCALING), repository, workspace, user, pass, JCRImapConstants.MIN_SCALING);
+        mailboxManager = new JCRMailboxManager(null, new JCRSubscriptionManager(sessionRepos), sessionRepos);
 
     }
     
-    /*
+    
     @After
     
     public void tearDown() {
         MailboxSession session = mailboxManager.createSystemSession("test", new SimpleLog("Test"));
+        /*
         try {
             //mailboxManager.deleteEverything(session);
         } catch (MailboxException e) {
             e.printStackTrace();
         }
+        */
         session.close();
         new File(JACKRABBIT_HOME).delete();
 
     }
-*/
+
     
     @Override
     protected StoreMailboxManager<?> getMailboxManager() {
         return mailboxManager;
     }
 
-    @Override
-    public void testStessTest() throws InterruptedException, MailboxException {
-        //
-    }
+ 
 }

Modified: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/AbstractJCRMapper.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/AbstractJCRMapper.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/AbstractJCRMapper.java (original)
+++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/AbstractJCRMapper.java Wed May 12 16:50:26 2010
@@ -21,6 +21,7 @@ package org.apache.james.imap.jcr;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
+import org.apache.commons.logging.Log;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.mailbox.MailboxException;
 import org.apache.james.imap.store.transaction.AbstractTransactionalMapper;
@@ -30,21 +31,29 @@ import org.apache.james.imap.store.trans
 /**
  * Abstract Mapper base class for Level 1 Implementations of JCR. So no real transaction management is used. 
  * 
- * The Session.save() will get called on commit() method
+ * The Session.save() will get called on commit() method,  session.refresh(false) on rollback, and session.refresh(true) on begin()
  *
  */
 public abstract class AbstractJCRMapper extends AbstractTransactionalMapper implements JCRImapConstants{
+    public final static String MAILBOXES_PATH =  "mailboxes";
+    public final static String SUBSCRIPTIONS_PATH =  "subscriptions";
 
     private final Session session;
-    private final int scaling;
+    private final Log logger;
 
-    public AbstractJCRMapper(final Session session, final int scaling) {
+    public AbstractJCRMapper(final Session session, Log logger) {
         this.session = session;
-        this.scaling = scaling;
+        this.logger = logger;
     }
     
-    protected int getScaling() {
-        return scaling;
+
+    /**
+     * Return the logger
+     * 
+     * @return logger
+     */
+    protected Log getLogger() {
+        return logger;
     }
     
     /**
@@ -56,19 +65,18 @@ public abstract class AbstractJCRMapper 
         return session;
     }
 
-    /*
-     * (non-Javadoc)
-     * @see org.apache.james.imap.store.transaction.TransactionalMapper#destroy()
-     */
-    public void destroy() {
-        // Do nothing
-    }
 
     /**
-     * Begin is not supported by level 1 JCR implementations, so just do nothing
+     * Begin is not supported by level 1 JCR implementations, however we refresh the session
      */
-    protected void begin() throws MailboxException {    
+    protected void begin() throws MailboxException {  
+        try {
+            session.refresh(true);
+        } catch (RepositoryException e) {
+            // do nothin on refresh
+        }
         // Do nothing
+        
     }
 
     /**
@@ -80,8 +88,7 @@ public abstract class AbstractJCRMapper 
                 session.save();
             }
         } catch (RepositoryException e) {
-            e.printStackTrace();
-            throw new MailboxException(HumanReadableText.SAVE_FAILED, e);
+            throw new MailboxException(HumanReadableText.COMMIT_TRANSACTION_FAILED, e);
         }
 
     }
@@ -90,12 +97,12 @@ public abstract class AbstractJCRMapper 
      * Rollback is not supported by level 1 JCR implementations, so just do nothing
      */
     protected void rollback() throws MailboxException {
-        // no rollback supported by level 1 jcr
-    }
-
-    public void dispose() {
-        session.logout();
+        try {
+            // just refresh session and discard all pending changes
+            session.refresh(false);
+        } catch (RepositoryException e) {
+            // just catch on rollback by now
+        }
     }
-    
-    
+        
 }

Modified: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailbox.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailbox.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailbox.java (original)
+++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailbox.java Wed May 12 16:50:26 2010
@@ -35,13 +35,11 @@ import org.apache.james.imap.mailbox.Mai
 import org.apache.james.imap.mailbox.MailboxSession;
 import org.apache.james.imap.mailbox.util.MailboxEventDispatcher;
 import org.apache.james.imap.store.StoreMailbox;
-import org.apache.james.imap.store.mail.MailboxMapper;
+import org.apache.james.imap.store.UidConsumer;
 import org.apache.james.imap.store.mail.MessageMapper;
 import org.apache.james.imap.store.mail.model.Header;
-import org.apache.james.imap.store.mail.model.Mailbox;
 import org.apache.james.imap.store.mail.model.MailboxMembership;
 import org.apache.james.imap.store.mail.model.PropertyBuilder;
-import org.apache.james.imap.store.transaction.TransactionalMapper;
 
 /**
  * JCR implementation of a {@link StoreMailbox}
@@ -51,27 +49,15 @@ public class JCRMailbox extends StoreMai
 
     private final Session jcrSession;
     private final Log log;
-    private final int scaling;
 
-    public JCRMailbox(final MailboxEventDispatcher dispatcher, final org.apache.james.imap.jcr.mail.model.JCRMailbox mailbox, final Session jcrSession, final int scaling, final Log log) {
-        super(dispatcher, mailbox);
+    public JCRMailbox(final MailboxEventDispatcher dispatcher, UidConsumer<String> consumer, final org.apache.james.imap.jcr.mail.model.JCRMailbox mailbox, final Session jcrSession, final Log log) {
+        super(dispatcher, consumer, mailbox);
         this.log = log;
-        this.scaling = scaling;
         this.jcrSession = jcrSession;
         
     }
 
-    /**
-     * Return the scaling depth
-     * 
-     * @return scaling
-     */
-    protected int getScaling() {
-        return scaling;
-    }
-    
 
-    
     @Override
     protected MailboxMembership<String> copyMessage(MailboxMembership<String> originalMessage, long uid, MailboxSession session) throws MailboxException {
         MailboxMembership<String> newRow = new JCRMailboxMembership(getMailboxId(), uid, (JCRMailboxMembership) originalMessage, log);
@@ -97,7 +83,7 @@ public class JCRMailbox extends StoreMai
 
     @Override
     protected MessageMapper<String> createMessageMapper(MailboxSession session) throws MailboxException {
-        JCRMessageMapper messageMapper = new JCRMessageMapper(jcrSession, getMailboxId(), getScaling(), log);
+        JCRMessageMapper messageMapper = new JCRMessageMapper(jcrSession, getMailboxId(), log);
         
         return messageMapper;
 
@@ -112,22 +98,8 @@ public class JCRMailbox extends StoreMai
      * @throws MailboxException
      */
     protected JCRMailboxMapper createMailboxMapper(MailboxSession session) throws MailboxException {
-        JCRMailboxMapper mapper = new JCRMailboxMapper(jcrSession, getScaling(), log);
+        JCRMailboxMapper mapper = new JCRMailboxMapper(jcrSession, log);
         return mapper;
 
     }
-
-    @Override
-    protected Mailbox<String> reserveNextUid(MailboxSession session) throws MailboxException {
-        final MailboxMapper<String> mapper = createMailboxMapper(session);
-        final org.apache.james.imap.jcr.mail.model.JCRMailbox mailbox = (org.apache.james.imap.jcr.mail.model.JCRMailbox) mapper.findMailboxById(getMailboxId());
-        mapper.execute(new TransactionalMapper.Transaction() {
-
-            public void run() throws MailboxException {
-                mailbox.consumeUid();
-            }
-            
-        });
-        return mailbox;
-    }
 }

Modified: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailboxManager.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailboxManager.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailboxManager.java (original)
+++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRMailboxManager.java Wed May 12 16:50:26 2010
@@ -37,6 +37,7 @@ import org.apache.james.imap.store.Passw
 import org.apache.james.imap.store.StoreMailbox;
 import org.apache.james.imap.store.StoreMailboxManager;
 import org.apache.james.imap.store.Subscriber;
+import org.apache.james.imap.store.UidConsumer;
 import org.apache.james.imap.store.mail.MailboxMapper;
 import org.apache.james.imap.store.mail.model.Mailbox;
 import org.apache.james.imap.store.transaction.TransactionalMapper;
@@ -50,32 +51,17 @@ public class JCRMailboxManager extends S
 
     private final MailboxSessionJCRRepository repository;
     private final Log logger = LogFactory.getLog(JCRMailboxManager.class);
-    private final int scaling;
     
-    public JCRMailboxManager(final Authenticator authenticator, final Subscriber subscriber, final MailboxSessionJCRRepository repository, final int scaling) {
-        super(authenticator, subscriber);
+    public JCRMailboxManager(final Authenticator authenticator, final Subscriber subscriber, final MailboxSessionJCRRepository repository) {
+        super(authenticator, subscriber, new JCRUidConsumer(repository));
         this.repository = repository;
-        this.scaling = scaling;
     }
 
-    
-    public JCRMailboxManager(final Authenticator authenticator, final Subscriber subscriber, final MailboxSessionJCRRepository repository) {
-        this(authenticator, subscriber, repository, MIN_SCALING);
-    }
-    
-    /**
-     * Return the scaling depth
-     * 
-     * @return scaling
-     */
-    protected int getScaling() {
-        return scaling;
-    }
-    
+
     @Override
-    protected StoreMailbox<String> createMailbox(MailboxEventDispatcher dispatcher, Mailbox<String> mailboxRow, MailboxSession session) throws MailboxException{
+    protected StoreMailbox<String> createMailbox(MailboxEventDispatcher dispatcher, UidConsumer<String> consumer,Mailbox<String> mailboxRow, MailboxSession session) throws MailboxException{
         try {
-            return new JCRMailbox(dispatcher, (org.apache.james.imap.jcr.mail.model.JCRMailbox) mailboxRow, repository.login(session), getScaling(), getLog());
+            return new JCRMailbox(dispatcher, consumer, (org.apache.james.imap.jcr.mail.model.JCRMailbox) mailboxRow, repository.login(session), getLog());
         } catch (RepositoryException e) {
             throw new MailboxException(HumanReadableText.GENERIC_FAILURE_DURING_PROCESSING, e);
         }
@@ -86,7 +72,7 @@ public class JCRMailboxManager extends S
 
         try {
             Session jcrSession = repository.login(session);
-            JCRMailboxMapper mapper = new JCRMailboxMapper(jcrSession, getScaling(), getLog());
+            JCRMailboxMapper mapper = new JCRMailboxMapper(jcrSession, getLog());
             return mapper;
         } catch (RepositoryException e) {
             throw new MailboxException(HumanReadableText.GENERIC_FAILURE_DURING_PROCESSING, e);

Modified: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRSubscriptionManager.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRSubscriptionManager.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRSubscriptionManager.java (original)
+++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRSubscriptionManager.java Wed May 12 16:50:26 2010
@@ -40,34 +40,19 @@ import org.apache.james.imap.store.user.
 public class JCRSubscriptionManager extends StoreSubscriptionManager implements JCRImapConstants{
     private final Log logger = LogFactory.getLog(JCRSubscriptionManager.class);
     private final MailboxSessionJCRRepository repository;
-    private final int scaling;
 
-    public JCRSubscriptionManager(final MailboxSessionJCRRepository repository, final int scaling) {
+    public JCRSubscriptionManager(final MailboxSessionJCRRepository repository ) {
         super();
-        this.scaling = scaling;
         this.repository = repository;
     }
 
 
-    public JCRSubscriptionManager(final MailboxSessionJCRRepository repository ) {
-        this(repository, MIN_SCALING);
-    }
-    
-
-    /**
-     * Return the scaling depth
-     * 
-     * @return scaling
-     */
-    protected int getScaling() {
-        return scaling;
-    }
     
     @Override
     protected SubscriptionMapper createMapper(MailboxSession session) throws SubscriptionException {
         try {
             Session jcrSession = repository.login(session);
-            JCRSubscriptionMapper mapper = new JCRSubscriptionMapper(jcrSession, getScaling(), logger);
+            JCRSubscriptionMapper mapper = new JCRSubscriptionMapper(jcrSession, logger);
 
             return mapper;
         } catch (RepositoryException e) {

Added: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRUidConsumer.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRUidConsumer.java?rev=943579&view=auto
==============================================================================
--- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRUidConsumer.java (added)
+++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRUidConsumer.java Wed May 12 16:50:26 2010
@@ -0,0 +1,79 @@
+/****************************************************************
+ * 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.jcr;
+
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.util.Locked;
+import org.apache.james.imap.api.display.HumanReadableText;
+import org.apache.james.imap.jcr.mail.model.JCRMailbox;
+import org.apache.james.imap.mailbox.MailboxException;
+import org.apache.james.imap.mailbox.MailboxSession;
+import org.apache.james.imap.store.UidConsumer;
+import org.apache.james.imap.store.mail.model.Mailbox;
+
+/**
+ * {@link UidConsumer} implementation for JCR. It use the {@link Locked} class to lock the Mailbox Node while
+ * consume the next uid. So we can be sure that its really unique
+ * 
+ *
+ */
+public class JCRUidConsumer implements UidConsumer<String>{
+
+    private MailboxSessionJCRRepository repos;
+    
+    public JCRUidConsumer(MailboxSessionJCRRepository repos) {
+        this.repos = repos;
+    }
+    
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.imap.store.UidConsumer#reserveNextUid(org.apache.james.imap.store.mail.model.Mailbox, org.apache.james.imap.mailbox.MailboxSession)
+     */
+    public long reserveNextUid(Mailbox<String> mailbox, MailboxSession session) throws MailboxException {
+        try {
+            Session jcrSession = repos.login(session);
+            Node node = jcrSession.getNodeByIdentifier(mailbox.getMailboxId());
+            return (Long) new Locked() {
+                
+                @Override
+                protected Object run(Node node) throws RepositoryException {
+                    Property uidProp = node.getProperty(JCRMailbox.LASTUID_PROPERTY);
+                    long uid = uidProp.getLong();
+                    uid++;
+                    uidProp.setValue(uid);
+                    uidProp.getSession().save();
+                    return uid;
+                }
+            }.with(node, false);
+            
+         
+        } catch (RepositoryException e) {
+            throw new MailboxException(HumanReadableText.COMSUME_UID_FAILED, e);
+        } catch (InterruptedException e) {
+            throw new MailboxException(HumanReadableText.COMSUME_UID_FAILED, e);
+        }
+
+    }
+
+}

Modified: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRUtils.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRUtils.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRUtils.java (original)
+++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRUtils.java Wed May 12 16:50:26 2010
@@ -21,19 +21,11 @@ package org.apache.james.imap.jcr;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 
-import javax.jcr.ItemExistsException;
-import javax.jcr.Node;
-import javax.jcr.PathNotFoundException;
 import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.SimpleCredentials;
-import javax.jcr.lock.LockException;
-import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.version.VersionException;
 
 import org.apache.jackrabbit.commons.cnd.CndImporter;
-import org.apache.jackrabbit.util.Text;
 
 /**
  * Utilities used for JCR 
@@ -41,140 +33,6 @@ import org.apache.jackrabbit.util.Text;
  */
 public class JCRUtils implements JCRImapConstants{
 
-
-    
-    /**
-     * Create a scaled path for the given path, where scaling is the nesting mode. 
-     * There will be no escaping of illegal chars at this point
-     * 
-     * With scaling -1 it will create a sub-path for every  char in the path. 
-     * 
-     * So for example:
-     * 
-     * scaling  = -1 
-     * user/test:
-     *     u/us/use/user/t/te/tes/test
-     *   
-     * scaling = 2
-     * user/test:
-     *     u/us/user/t/te/test
-     *     
-     * scaling = 0
-     * user/test:
-     *     user/test
-     *     
-     *     
-     * @param path
-     * @param scaling
-     * @return scaledPath
-     */
-    public static String createScaledPath(String path, int scaling) {
-        if (scaling == MIN_SCALING) {
-            return path;
-        } else {
-            StringBuffer buffer = new StringBuffer();
-            String[] pathParts = path.split(NODE_DELIMITER);
-            
-            for (int a = 0; a < pathParts.length; a++) {
-                String subPath =escape(pathParts[a]);
-                
-                for (int i = 0; i < subPath.length(); i++) {
-                    
-                    if ( scaling != MAX_SCALING && i == scaling) {                       
-                        buffer.append(subPath);
-                        
-                        if (a +1 != pathParts.length) {
-                            buffer.append(NODE_DELIMITER);
-                        }
-                        break;
-                    } else {
-                        buffer.append(subPath.substring(0,i +1));
-
-                        if (i +1 != subPath.length() || a +1 != pathParts.length) {
-                            buffer.append(NODE_DELIMITER);
-                        }
-                    }
-                }
-            }
-            return buffer.toString();
-        }
-    }
-  
-    public static String escape(String string) {
-        return Text.escapeIllegalJcrChars(string);
-    }
-    
-    public static String createScaledPath(String[] paths, int scaling) {
-        StringBuffer sb = new StringBuffer();
-        for (int i = 0; i < paths.length; i++) {
-            String path = paths[i];
-            sb.append(path);
-            if (i + 1 != path.length()) {
-                sb.append(NODE_DELIMITER);
-            }
-        }
-        return createScaledPath(sb.toString(), scaling);
-    }
-
-    
-    
-    /**
-     * Create a node path recursive from the given root {@link Node}. This includes
-     * to create all subnodes
-     * 
-     * @param rootNode
-     * @param nodePath
-     * @return lastNode
-     * @throws PathNotFoundException
-     * @throws ItemExistsException
-     * @throws VersionException
-     * @throws ConstraintViolationException
-     * @throws LockException
-     * @throws RepositoryException
-     */
-    public static Node createNodeRecursive(Node rootNode, String nodePath) throws PathNotFoundException, ItemExistsException, VersionException, ConstraintViolationException, LockException, RepositoryException {
-        return createNodeRecursive(rootNode, nodePath, null);
-    }
-    
-    public static Node createNodeRecursive(Node rootNode, String nodePath, String primaryNodeTypeName) throws PathNotFoundException, ItemExistsException, VersionException, ConstraintViolationException, LockException, RepositoryException {
-        Node parent = rootNode;
-        String nodeNames[] = nodePath.split(NODE_DELIMITER);
-        for (int i = 0; i < nodeNames.length; i++) {
-            String nodeName = escape(nodeNames[i]);
-            if (parent.hasNode(nodeName)) {
-                parent = parent.getNode(nodeName);
-            } else {
-                if (i +1 == nodeNames.length && primaryNodeTypeName != null) {
-                    parent = parent.addNode(nodeName, primaryNodeTypeName);
-                } else {
-                    parent = parent.addNode(nodeName);
-                }
-            }
-        }
-        return parent;
-    }
-    /**
-     * Create a path which can be used for nodes. It handles the escaping etc
-     * 
-     * @param subNodes
-     * @return completePath
-     */
-    public static String escapePath(String... subNodes) {
-        StringBuffer pathBuf = new StringBuffer();
-
-        for (int i = 0; i < subNodes.length; i++) {
-            String path = subNodes[i];
-            pathBuf.append(escape(path));
-
-            if (i + 1 != subNodes.length) {
-                pathBuf.append(NODE_DELIMITER);
-            }
-        }
-        return pathBuf.toString();
-    }
-
-    
-
     /**
      * Register the imap CND file in the workspace
      * 

Modified: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/JCRMailboxMapper.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/JCRMailboxMapper.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/JCRMailboxMapper.java (original)
+++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/JCRMailboxMapper.java Wed May 12 16:50:26 2010
@@ -31,12 +31,10 @@ import javax.jcr.query.QueryManager;
 import javax.jcr.query.QueryResult;
 
 import org.apache.commons.logging.Log;
-import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.commons.JcrUtils;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.jcr.AbstractJCRMapper;
-import org.apache.james.imap.jcr.JCRUtils;
 import org.apache.james.imap.jcr.mail.model.JCRMailbox;
-import org.apache.james.imap.mailbox.MailboxException;
 import org.apache.james.imap.mailbox.MailboxNotFoundException;
 import org.apache.james.imap.mailbox.StorageException;
 import org.apache.james.imap.store.mail.MailboxMapper;
@@ -49,12 +47,8 @@ import org.apache.james.imap.store.mail.
  */
 public class JCRMailboxMapper extends AbstractJCRMapper implements MailboxMapper<String> {
 
-    public final String PATH =  "mailboxes";
-    private final Log logger;
-
-    public JCRMailboxMapper(final Session session, final int scaling,final Log logger) {
-        super(session, scaling);
-        this.logger = logger;
+    public JCRMailboxMapper(final Session session, final Log logger) {
+        super(session, logger);
     }
 
     /*
@@ -65,21 +59,21 @@ public class JCRMailboxMapper extends Ab
      * (java.lang.String)
      */
     public long countMailboxesWithName(String name) throws StorageException {
-       
+
         try {
-        	QueryManager manager = getSession().getWorkspace().getQueryManager();
-        	String queryString =  "//" + PATH + "//element(*,imap:mailbox)[@" + JCRMailbox.NAME_PROPERTY + "='" + name + "']";
-        	QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
-        	NodeIterator it = result.getNodes();
-        	long resultSize = it.getSize();
-        	if (resultSize == -1) {
-        	    resultSize = 0;
-        	    while (it.hasNext()) {
-        	        it.nextNode();
-        	        resultSize++;
-        	    }
-        	}
-        	return resultSize;
+            QueryManager manager = getSession().getWorkspace().getQueryManager();
+            String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailbox)[@" + JCRMailbox.NAME_PROPERTY + "='" + name + "'] order by @"+ JCRMailbox.NAME_PROPERTY;
+            QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
+            NodeIterator it = result.getNodes();
+            long resultSize = it.getSize();
+            if (resultSize == -1) {
+                resultSize = 0;
+                while (it.hasNext()) {
+                    it.nextNode();
+                    resultSize++;
+                }
+            }
+            return resultSize;
         } catch (PathNotFoundException e) {
             // not found
         } catch (RepositoryException e) {
@@ -113,7 +107,7 @@ public class JCRMailboxMapper extends Ab
      */
     public void deleteAll() throws StorageException {
         try {
-            getSession().getRootNode().getNode(PATH).remove();
+            getSession().getRootNode().getNode(MAILBOXES_PATH).remove();
 
         } catch (PathNotFoundException e) {
             // nothing todo
@@ -134,7 +128,7 @@ public class JCRMailboxMapper extends Ab
     public boolean existsMailboxStartingWith(String mailboxName) throws StorageException {
         try {
         	QueryManager manager = getSession().getWorkspace().getQueryManager();
-        	String queryString = "//" + PATH + "//element(*,imap:mailbox)[jcr:like(@" + JCRMailbox.NAME_PROPERTY + ",'" +mailboxName+"%')]";
+        	String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailbox)[jcr:like(@" + JCRMailbox.NAME_PROPERTY + ",'" +mailboxName+"%')]";
         	QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
         	NodeIterator it = result.getNodes();
         	return it.hasNext();
@@ -150,7 +144,7 @@ public class JCRMailboxMapper extends Ab
      */
     public Mailbox<String> findMailboxById(String mailboxId) throws StorageException, MailboxNotFoundException {
         try {
-            return new JCRMailbox(getSession().getNodeByUUID(mailboxId),logger);
+            return new JCRMailbox(getSession().getNodeByUUID(mailboxId), getLogger());
         } catch (PathNotFoundException e) {
             throw new MailboxNotFoundException(mailboxId);
         } catch (RepositoryException e) {
@@ -168,11 +162,11 @@ public class JCRMailboxMapper extends Ab
     public Mailbox<String> findMailboxByName(String name) throws StorageException, MailboxNotFoundException {
         try {
         	QueryManager manager = getSession().getWorkspace().getQueryManager();
-        	String queryString = "//" + PATH + "//element(*,imap:mailbox)[@" + JCRMailbox.NAME_PROPERTY + "='" + name + "']";
+        	String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailbox)[@" + JCRMailbox.NAME_PROPERTY + "='" + name + "']";
         	QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
         	NodeIterator it = result.getNodes();
         	if (it.hasNext()) {
-                return new JCRMailbox(it.nextNode(), logger);
+                return new JCRMailbox(it.nextNode(), getLogger());
         	}
             throw new MailboxNotFoundException(name);
         } catch (PathNotFoundException e) {
@@ -194,11 +188,11 @@ public class JCRMailboxMapper extends Ab
         List<Mailbox<String>> mailboxList = new ArrayList<Mailbox<String>>();
         try {       
         	QueryManager manager = getSession().getWorkspace().getQueryManager();
-        	String queryString = "//" + PATH + "//element(*,imap:mailbox)[jcr:like(@" + JCRMailbox.NAME_PROPERTY + ",'%" + name + "%')]";
+        	String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailbox)[jcr:like(@" + JCRMailbox.NAME_PROPERTY + ",'%" + name + "%')]";
         	QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
         	NodeIterator it = result.getNodes();
         	while (it.hasNext()) {
-                mailboxList.add(new JCRMailbox(it.nextNode(), logger));
+                mailboxList.add(new JCRMailbox(it.nextNode(), getLogger()));
             }            
         } catch (PathNotFoundException e) {
             // nothing todo
@@ -225,10 +219,8 @@ public class JCRMailboxMapper extends Ab
                 node = getSession().getNodeByUUID(jcrMailbox.getMailboxId());
             }
             if (node == null) {
-                String nodePath =   PATH + NODE_DELIMITER + JCRUtils.createScaledPath(mailbox.getName(), getScaling());
-
-                node = JCRUtils.createNodeRecursive(getSession().getRootNode(), nodePath, "imap:mailbox");
-                node.addMixin(JcrConstants.MIX_REFERENCEABLE);
+                Node mailboxNode = JcrUtils.getOrAddNode(getSession().getRootNode(), MAILBOXES_PATH);
+                node = JcrUtils.getOrAddNode(mailboxNode, mailbox.getName(), "imap:mailbox");
            } 
             
             jcrMailbox.merge(node);

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=943579&r1=943578&r2=943579&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 Wed May 12 16:50:26 2010
@@ -20,6 +20,8 @@ package org.apache.james.imap.jcr.mail;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
 import java.util.List;
 
 import javax.jcr.Node;
@@ -32,9 +34,10 @@ import javax.jcr.query.QueryResult;
 
 import org.apache.commons.logging.Log;
 import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.commons.JcrUtils;
+import org.apache.jackrabbit.util.Locked;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.jcr.AbstractJCRMapper;
-import org.apache.james.imap.jcr.JCRUtils;
 import org.apache.james.imap.jcr.mail.model.JCRMailboxMembership;
 import org.apache.james.imap.mailbox.MessageRange;
 import org.apache.james.imap.mailbox.SearchQuery;
@@ -47,13 +50,10 @@ import org.apache.james.imap.store.mail.
 
 public class JCRMessageMapper extends AbstractJCRMapper implements MessageMapper<String> {
 
-    private final static String PATH =  "mailboxes";
-    private final Log logger;
     private final String uuid;
 
-    public JCRMessageMapper(final Session session, final String uuid, final int scaling, final Log logger) {
-        super(session,scaling);
-        this.logger = logger;
+    public JCRMessageMapper(final Session session, final String uuid, final Log logger) {
+        super(session, logger);
         this.uuid = uuid;
     }
 
@@ -65,7 +65,8 @@ public class JCRMessageMapper extends Ab
      */
     public long countMessagesInMailbox() throws StorageException {
         try {
-            String queryString = "//" + PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY +"='" + uuid +"']";
+            // we use order by because without it count will always be 0 in jackrabbit
+            String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY +"='" + uuid +"'] order by @" + JCRMailboxMembership.UID_PROPERTY;
             QueryManager manager = getSession().getWorkspace().getQueryManager();
             QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
             NodeIterator nodes = result.getNodes();
@@ -95,7 +96,8 @@ public class JCRMessageMapper extends Ab
     public long countUnseenMessagesInMailbox() throws StorageException {
         
         try {
-            String queryString = "//" + PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY +"='" + uuid +"'] AND [@" + JCRMailboxMembership.SEEN_PROPERTY +"='false']";
+            // we use order by because without it count will always be 0 in jackrabbit
+            String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY +"='" + uuid +"'] AND [@" + JCRMailboxMembership.SEEN_PROPERTY +"='false'] order by @" + JCRMailboxMembership.UID_PROPERTY;
             QueryManager manager = getSession().getWorkspace().getQueryManager();
             QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
             NodeIterator nodes = result.getNodes();
@@ -173,42 +175,42 @@ public class JCRMessageMapper extends Ab
 
     private List<MailboxMembership<String>> findMessagesInMailboxAfterUID(String uuid, long uid) throws RepositoryException {
         List<MailboxMembership<String>> list = new ArrayList<MailboxMembership<String>>();
-        String queryString = "//" + PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY + "='" + uuid + "'] AND [@" + JCRMailboxMembership.UID_PROPERTY + ">=" + uid + "] order by @" + JCRMailboxMembership.UID_PROPERTY;
+        String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY + "='" + uuid + "'] AND [@" + JCRMailboxMembership.UID_PROPERTY + ">=" + uid + "] order by @" + JCRMailboxMembership.UID_PROPERTY;
 
         QueryManager manager = getSession().getWorkspace().getQueryManager();
         QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
 
         NodeIterator iterator = result.getNodes();
         while (iterator.hasNext()) {
-            list.add(new JCRMailboxMembership(iterator.nextNode(), logger));
+            list.add(new JCRMailboxMembership(iterator.nextNode(), getLogger()));
         }
         return list;
     }
 
     private List<MailboxMembership<String>> findMessagesInMailboxWithUID(String uuid, long uid) throws RepositoryException  {
         List<MailboxMembership<String>> list = new ArrayList<MailboxMembership<String>>();
-        String queryString = "//" + PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY + "='" + uuid + "'] AND [@" + JCRMailboxMembership.UID_PROPERTY + "=" + uid + "] order by @" + JCRMailboxMembership.UID_PROPERTY;
+        String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY + "='" + uuid + "'] AND [@" + JCRMailboxMembership.UID_PROPERTY + "=" + uid + "] order by @" + JCRMailboxMembership.UID_PROPERTY;
 
         QueryManager manager = getSession().getWorkspace().getQueryManager();
         QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
 
         NodeIterator iterator = result.getNodes();
         while (iterator.hasNext()) {
-            list.add(new JCRMailboxMembership(iterator.nextNode(), logger));
+            list.add(new JCRMailboxMembership(iterator.nextNode(), getLogger()));
         }
         return list;
     }
 
     private List<MailboxMembership<String>> findMessagesInMailboxBetweenUIDs(String uuid, long from, long to) throws RepositoryException {
         List<MailboxMembership<String>> list = new ArrayList<MailboxMembership<String>>();
-        String queryString = "//" + PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY + "='" + uuid + "'] AND [@" + JCRMailboxMembership.UID_PROPERTY + ">=" + from + "] AND [@" + JCRMailboxMembership.UID_PROPERTY + "<=" + to + "] order by @" + JCRMailboxMembership.UID_PROPERTY;
+        String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY + "='" + uuid + "'] AND [@" + JCRMailboxMembership.UID_PROPERTY + ">=" + from + "] AND [@" + JCRMailboxMembership.UID_PROPERTY + "<=" + to + "] order by @" + JCRMailboxMembership.UID_PROPERTY;
         
         QueryManager manager = getSession().getWorkspace().getQueryManager();
         QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
 
         NodeIterator iterator = result.getNodes();
         while (iterator.hasNext()) {
-            list.add(new JCRMailboxMembership(iterator.nextNode(), logger));
+            list.add(new JCRMailboxMembership(iterator.nextNode(), getLogger()));
         }
         return list;
     }
@@ -216,14 +218,13 @@ public class JCRMessageMapper extends Ab
     private List<MailboxMembership<String>> findMessagesInMailbox(String uuid) throws RepositoryException {        
         List<MailboxMembership<String>> list = new ArrayList<MailboxMembership<String>>();
         
-        String queryString = "//" + PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY +"='" + uuid +"'] order by @" + JCRMailboxMembership.UID_PROPERTY;
-        getSession().refresh(true);
+        String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY +"='" + uuid +"'] order by @" + JCRMailboxMembership.UID_PROPERTY;
         QueryManager manager = getSession().getWorkspace().getQueryManager();
         QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
 
         NodeIterator iterator = result.getNodes();
         while (iterator.hasNext()) {
-            list.add(new JCRMailboxMembership(iterator.nextNode(), logger));
+            list.add(new JCRMailboxMembership(iterator.nextNode(), getLogger()));
         }
         return list;
     }
@@ -232,27 +233,27 @@ public class JCRMessageMapper extends Ab
     
     private List<MailboxMembership<String>> findDeletedMessagesInMailboxAfterUID(String uuid, long uid) throws RepositoryException {
         List<MailboxMembership<String>> list = new ArrayList<MailboxMembership<String>>();
-        String queryString = "//" + PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY + "='" + uuid + "'] AND [@" + JCRMailboxMembership.UID_PROPERTY + ">=" + uid + "] AND [@" + JCRMailboxMembership.DELETED_PROPERTY+ "='true'] order by @" + JCRMailboxMembership.UID_PROPERTY;
+        String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY + "='" + uuid + "'] AND [@" + JCRMailboxMembership.UID_PROPERTY + ">=" + uid + "] AND [@" + JCRMailboxMembership.DELETED_PROPERTY+ "='true'] order by @" + JCRMailboxMembership.UID_PROPERTY;
  
         QueryManager manager = getSession().getWorkspace().getQueryManager();
         QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
 
         NodeIterator iterator = result.getNodes();
         while (iterator.hasNext()) {
-            list.add(new JCRMailboxMembership(iterator.nextNode(), logger));
+            list.add(new JCRMailboxMembership(iterator.nextNode(), getLogger()));
         }
         return list;
     }
 
     private List<MailboxMembership<String>> findDeletedMessagesInMailboxWithUID(String uuid, long uid) throws RepositoryException  {
         List<MailboxMembership<String>> list = new ArrayList<MailboxMembership<String>>();
-        String queryString = "//" + PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY + "='" + uuid + "'] AND [@" + JCRMailboxMembership.UID_PROPERTY + "=" + uid + "] AND [@" + JCRMailboxMembership.DELETED_PROPERTY+ "='true']  order by @" + JCRMailboxMembership.UID_PROPERTY;
+        String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY + "='" + uuid + "'] AND [@" + JCRMailboxMembership.UID_PROPERTY + "=" + uid + "] AND [@" + JCRMailboxMembership.DELETED_PROPERTY+ "='true']  order by @" + JCRMailboxMembership.UID_PROPERTY;
         QueryManager manager = getSession().getWorkspace().getQueryManager();
         QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
 
         NodeIterator iterator = result.getNodes();
         while (iterator.hasNext()) {
-            JCRMailboxMembership member = new JCRMailboxMembership(iterator.nextNode(), logger);
+            JCRMailboxMembership member = new JCRMailboxMembership(iterator.nextNode(), getLogger());
             list.add(member);
         }
         return list;
@@ -260,14 +261,14 @@ public class JCRMessageMapper extends Ab
 
     private List<MailboxMembership<String>> findDeletedMessagesInMailboxBetweenUIDs(String uuid, long from, long to) throws RepositoryException {
         List<MailboxMembership<String>> list = new ArrayList<MailboxMembership<String>>();
-        String queryString = "//" + PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY + "='" + uuid + "'] AND [@" + JCRMailboxMembership.UID_PROPERTY + ">=" + from + "] AND [@" + JCRMailboxMembership.UID_PROPERTY + "<=" + to + "] AND [@" + JCRMailboxMembership.DELETED_PROPERTY+ "='true'] order by @" + JCRMailboxMembership.UID_PROPERTY;
+        String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY + "='" + uuid + "'] AND [@" + JCRMailboxMembership.UID_PROPERTY + ">=" + from + "] AND [@" + JCRMailboxMembership.UID_PROPERTY + "<=" + to + "] AND [@" + JCRMailboxMembership.DELETED_PROPERTY+ "='true'] order by @" + JCRMailboxMembership.UID_PROPERTY;
        
         QueryManager manager = getSession().getWorkspace().getQueryManager();
         QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
 
         NodeIterator iterator = result.getNodes();
         while (iterator.hasNext()) {
-            list.add(new JCRMailboxMembership(iterator.nextNode(), logger));
+            list.add(new JCRMailboxMembership(iterator.nextNode(), getLogger()));
         }
         return list;
     }
@@ -275,14 +276,14 @@ public class JCRMessageMapper extends Ab
     private List<MailboxMembership<String>> findDeletedMessagesInMailbox(String uuid) throws RepositoryException {
         
         List<MailboxMembership<String>> list = new ArrayList<MailboxMembership<String>>();
-        String queryString = "//" + PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY +"='" + uuid +"'] AND [@" + JCRMailboxMembership.DELETED_PROPERTY+ "='true'] order by @" + JCRMailboxMembership.UID_PROPERTY;
+        String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY +"='" + uuid +"'] AND [@" + JCRMailboxMembership.DELETED_PROPERTY+ "='true'] order by @" + JCRMailboxMembership.UID_PROPERTY;
         
         QueryManager manager = getSession().getWorkspace().getQueryManager();
         QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
 
         NodeIterator iterator = result.getNodes();
         while (iterator.hasNext()) {
-            JCRMailboxMembership member = new JCRMailboxMembership(iterator.nextNode(), logger);
+            JCRMailboxMembership member = new JCRMailboxMembership(iterator.nextNode(), getLogger());
             list.add(member);
         }
         return list;
@@ -334,14 +335,14 @@ public class JCRMessageMapper extends Ab
         
         try {
             List<MailboxMembership<String>> list = new ArrayList<MailboxMembership<String>>();
-            String queryString = "//" + PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY +"='" + uuid +"'] AND [@" + JCRMailboxMembership.RECENT_PROPERTY +"='true'] order by @" + JCRMailboxMembership.UID_PROPERTY;
+            String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY +"='" + uuid +"'] AND [@" + JCRMailboxMembership.RECENT_PROPERTY +"='true'] order by @" + JCRMailboxMembership.UID_PROPERTY;
             
             QueryManager manager = getSession().getWorkspace().getQueryManager();
             QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
             
             NodeIterator iterator = result.getNodes();
             while(iterator.hasNext()) {
-                list.add(new JCRMailboxMembership(iterator.nextNode(), logger));
+                list.add(new JCRMailboxMembership(iterator.nextNode(), getLogger()));
             }
             return list;
         } catch (RepositoryException e) {
@@ -358,14 +359,14 @@ public class JCRMessageMapper extends Ab
     public List<MailboxMembership<String>> findUnseenMessagesInMailbox() throws StorageException {
         try {
             List<MailboxMembership<String>> list = new ArrayList<MailboxMembership<String>>();
-            String queryString = "//" + PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY +"='" + uuid +"'] AND [@" + JCRMailboxMembership.SEEN_PROPERTY +"='false'] order by @" + JCRMailboxMembership.UID_PROPERTY;
+            String queryString = "//" + MAILBOXES_PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY +"='" + uuid +"'] AND [@" + JCRMailboxMembership.SEEN_PROPERTY +"='false'] order by @" + JCRMailboxMembership.UID_PROPERTY;
           
             QueryManager manager = getSession().getWorkspace().getQueryManager();
             QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
             
             NodeIterator iterator = result.getNodes();
             while(iterator.hasNext()) {
-                list.add(new JCRMailboxMembership(iterator.nextNode(), logger));
+                list.add(new JCRMailboxMembership(iterator.nextNode(), getLogger()));
             }
             return list;
         } catch (RepositoryException e) {
@@ -382,7 +383,7 @@ public class JCRMessageMapper extends Ab
      * imap.store.mail.model.MailboxMembership)
      */
     public void save(MailboxMembership<String> message) throws StorageException {
-        JCRMailboxMembership membership = (JCRMailboxMembership) message;
+        final JCRMailboxMembership membership = (JCRMailboxMembership) message;
         try {
             //JCRUtils.createNodeRecursive(getSession().getRootNode(), mailboxN);
             Node messageNode = null;
@@ -392,30 +393,81 @@ public class JCRMessageMapper extends Ab
             }
 
             if (messageNode == null) {
+                Date date = message.getInternalDate();
+                if (date == null) {
+                    date = new Date();
+                }
+                
+                // extracte the date from the message to create node structure later
+                Calendar cal = Calendar.getInstance();
+                cal.setTime(date);
+                final String year = String.valueOf(cal.get(Calendar.YEAR));
+                final String month = String.valueOf(cal.get(Calendar.MONTH +1));
+                final String day = String.valueOf(cal.get(Calendar.DAY_OF_MONTH));
+               
+                Node dayNode = null;
                 Node mailboxNode = getSession().getNodeByUUID(uuid);
-                Node membershipsNode;
+                String dayNodePath = year + NODE_DELIMITER + month + NODE_DELIMITER + day;
+                boolean found = mailboxNode.hasNode(dayNodePath);
                 
-                if (mailboxNode.hasNode("mailboxMemberships")) {
-                    membershipsNode = mailboxNode.getNode("mailboxMemberships");
+                // check if the node for the day already exists. if not we need to create the structure
+                if (found == false) {
+                    // we lock the whole mailbox with all its childs while
+                    // adding the folder structure for the date
+                    // TODO: Maybe we should just lock the last child folder
+                    dayNode = (Node) new Locked() {
+
+                        @Override
+                        protected Object run(Node mailboxNode) throws RepositoryException {
+
+                            Node yearNode = JcrUtils.getOrAddFolder(mailboxNode, String.valueOf(year));
+                            yearNode.addMixin(JcrConstants.MIX_LOCKABLE);
+
+                            Node monthNode = JcrUtils.getOrAddFolder(yearNode, String.valueOf(month));
+                            monthNode.addMixin(JcrConstants.MIX_LOCKABLE);
+
+                            Node dayNode = JcrUtils.getOrAddFolder(monthNode, String.valueOf(day));
+                            dayNode.addMixin(JcrConstants.MIX_LOCKABLE);
+                            // save the folders for now
+                            getSession().save();
+                            return dayNode;
+                        }
+                    }.with(mailboxNode, true);
                 } else {
-                    membershipsNode = mailboxNode.addNode("mailboxMemberships","imap:mailboxMemberships");
+                    
+                    dayNode = mailboxNode.getNode(dayNodePath);
                 }
                 
-                // TODO: Maybe we should use some kind of hashes for scaling here
-                String path = membershipsNode.getPath() + NODE_DELIMITER + JCRUtils.escapePath(String.valueOf(membership.getUid()));
                 
-                // strip leading /
-                path = path.substring(1, path.length());
+                // lock the day node and add the message
+                new Locked() {
+
+                    @Override
+                    protected Object run(Node dayNode) throws RepositoryException {
+                        Node messageNode = dayNode.addNode("message-"+String.valueOf(membership.getUid()),"imap:mailboxMembership");
+                        try {
+                            membership.merge(messageNode);
+                        } catch (IOException e) {
+                            throw new RepositoryException("Unable to merge message in to tree", e);
+                        }
+                        // save the message 
+                        getSession().save();
+
+                        return null;
+                    }
+                    
+                }.with(dayNode,false);
                 
-                messageNode = getSession().getRootNode().addNode(path,"imap:mailboxMembership");
-                messageNode.addMixin(JcrConstants.MIX_REFERENCEABLE);
+              
+            } else {
+                membership.merge(messageNode);
             }
-            membership.merge(messageNode);
         } catch (RepositoryException e) {
-            e.printStackTrace();
             throw new StorageException(HumanReadableText.SAVE_FAILED, e);
         } catch (IOException e) {
             throw new StorageException(HumanReadableText.SAVE_FAILED, e);
+        } catch (InterruptedException e) {
+            throw new StorageException(HumanReadableText.SAVE_FAILED, e);
         }
 
     }
@@ -437,7 +489,7 @@ public class JCRMessageMapper extends Ab
             
             NodeIterator it = result.getNodes();
             while (it.hasNext()) {
-                list.add(new JCRMailboxMembership(it.nextNode(), logger));
+                list.add(new JCRMailboxMembership(it.nextNode(), getLogger()));
             }
             return list;
         } catch (RepositoryException e) {
@@ -455,7 +507,7 @@ public class JCRMessageMapper extends Ab
      */
     private String formulateXPath(String uuid, SearchQuery query) {
         final StringBuilder queryBuilder = new StringBuilder(50);
-        queryBuilder.append("//" + PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY +"='" + uuid +"'] ");
+        queryBuilder.append("//" + MAILBOXES_PATH + "//element(*,imap:mailboxMembership)[@" + JCRMailboxMembership.MAILBOX_UUID_PROPERTY +"='" + uuid +"'] ");
         final List<Criterion> criteria = query.getCriterias();
         if (criteria.size() == 1) {
             final Criterion firstCriterion = criteria.get(0);

Modified: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMailbox.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMailbox.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMailbox.java (original)
+++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMailbox.java Wed May 12 16:50:26 2010
@@ -64,6 +64,9 @@ public class JCRMailbox implements Mailb
         this.logger = logger;
     }
     
+    public Log getLog() {
+        return logger;
+    }
     
     /*
      * (non-Javadoc)

Modified: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMessage.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMessage.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMessage.java (original)
+++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/mail/model/JCRMessage.java Wed May 12 16:50:26 2010
@@ -30,8 +30,8 @@ import javax.jcr.RepositoryException;
 
 import org.apache.commons.logging.Log;
 import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.util.Text;
 import org.apache.james.imap.jcr.JCRImapConstants;
-import org.apache.james.imap.jcr.JCRUtils;
 import org.apache.james.imap.jcr.Persistent;
 import org.apache.james.imap.store.StreamUtils;
 import org.apache.james.imap.store.mail.model.AbstractDocument;
@@ -333,7 +333,7 @@ public class JCRMessage extends Abstract
         // store new properties
         for (int i = 0; i < newProperites.size(); i++) {
             JCRProperty prop = (JCRProperty)newProperites.get(i);
-            Node propNode = propertiesNode.addNode(JCRUtils.escapePath(String.valueOf(prop.getOrder())), "imap:messageProperty");
+            Node propNode = propertiesNode.addNode(Text.escapeIllegalJcrChars(String.valueOf(prop.getOrder())), "imap:messageProperty");
             prop.merge(propNode);
         }
       

Modified: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/user/JCRSubscriptionMapper.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/user/JCRSubscriptionMapper.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/user/JCRSubscriptionMapper.java (original)
+++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/user/JCRSubscriptionMapper.java Wed May 12 16:50:26 2010
@@ -31,9 +31,9 @@ import javax.jcr.query.QueryManager;
 import javax.jcr.query.QueryResult;
 
 import org.apache.commons.logging.Log;
+import org.apache.jackrabbit.commons.JcrUtils;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.jcr.AbstractJCRMapper;
-import org.apache.james.imap.jcr.JCRUtils;
 import org.apache.james.imap.jcr.user.model.JCRSubscription;
 import org.apache.james.imap.mailbox.SubscriptionException;
 import org.apache.james.imap.store.user.SubscriptionMapper;
@@ -45,12 +45,8 @@ import org.apache.james.imap.store.user.
  */
 public class JCRSubscriptionMapper extends AbstractJCRMapper implements SubscriptionMapper {
 
-    private final Log log;
-    private final static String PATH =  "subscriptions";
-
-    public JCRSubscriptionMapper(final Session session, final int scaling,final Log log) {
-        super(session, scaling);
-        this.log = log;
+    public JCRSubscriptionMapper(final Session session, final Log log) {
+        super(session, log);
     }
 
     /*
@@ -85,14 +81,14 @@ public class JCRSubscriptionMapper exten
      */
     public Subscription findFindMailboxSubscriptionForUser(String user, String mailbox) throws SubscriptionException {
         try {
-            String queryString = "//" + PATH + "//element(*,imap:subscription)[@" + JCRSubscription.USERNAME_PROPERTY + "='" + user + "'] AND [@" + JCRSubscription.MAILBOX_PROPERTY +"='" + mailbox + "']";
+            String queryString = "//" + SUBSCRIPTIONS_PATH + "//element(*,imap:subscription)[@" + JCRSubscription.USERNAME_PROPERTY + "='" + user + "'] AND [@" + JCRSubscription.MAILBOX_PROPERTY +"='" + mailbox + "']";
 
             QueryManager manager = getSession().getWorkspace().getQueryManager();
             QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
             
             NodeIterator nodeIt = result.getNodes();
             if (nodeIt.hasNext()) {
-                JCRSubscription sub = new JCRSubscription(nodeIt.nextNode(), log);
+                JCRSubscription sub = new JCRSubscription(nodeIt.nextNode(), getLogger());
                 return sub;
             }
             
@@ -115,14 +111,14 @@ public class JCRSubscriptionMapper exten
     public List<Subscription> findSubscriptionsForUser(String user) throws SubscriptionException {
         List<Subscription> subList = new ArrayList<Subscription>();
         try {
-            String queryString = "//" + PATH + "//element(*,imap:subscription)[@" + JCRSubscription.USERNAME_PROPERTY + "='" + user + "']";
+            String queryString = "//" + SUBSCRIPTIONS_PATH + "//element(*,imap:subscription)[@" + JCRSubscription.USERNAME_PROPERTY + "='" + user + "']";
 
             QueryManager manager = getSession().getWorkspace().getQueryManager();
             QueryResult result = manager.createQuery(queryString, Query.XPATH).execute();
             
             NodeIterator nodeIt = result.getNodes();
             while (nodeIt.hasNext()) {
-                subList.add(new JCRSubscription(nodeIt.nextNode(), log));
+                subList.add(new JCRSubscription(nodeIt.nextNode(), getLogger()));
             }
         } catch (PathNotFoundException e) {
             // Do nothing just return the empty list later
@@ -153,9 +149,10 @@ public class JCRSubscriptionMapper exten
             
             // its a new subscription
             if (sub == null) {
-                String nodePath = PATH + NODE_DELIMITER + JCRUtils.createScaledPath(new String[] {username, mailbox}, getScaling());
+                Node subscriptionsNode = JcrUtils.getOrAddNode(getSession().getRootNode(), SUBSCRIPTIONS_PATH);
                 
-                node = JCRUtils.createNodeRecursive(getSession().getRootNode(), nodePath, "imap:subscription");
+                Node userNode = JcrUtils.getOrAddNode(subscriptionsNode, username);
+                node = JcrUtils.getOrAddNode(userNode, mailbox, "imap:subscription");
             } else {
                 node = sub.getNode();
             }

Modified: james/imap/trunk/jcr/src/main/resources/org/apache/james/imap/jcr/imap.cnd
URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/resources/org/apache/james/imap/jcr/imap.cnd?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/jcr/src/main/resources/org/apache/james/imap/jcr/imap.cnd (original)
+++ james/imap/trunk/jcr/src/main/resources/org/apache/james/imap/jcr/imap.cnd Wed May 12 16:50:26 2010
@@ -32,14 +32,13 @@
     - imap:propertyValue(STRING) mandatory
     - imap:propertyOrder (Long) mandatory
    
-[imap:message] >  mix:referenceable, nt:base
+[imap:message] >  mix:referenceable, nt:file
     - imap:messageBodyStartOctet (LONG) mandatory
     - imap:messageFullContentOctets (LONG) mandatory
     - imap:messageTextualLineCount (LONG)
     - imap:messageSubType (String) mandatory
     + messageHeaders (imap:messageHeaders) 
     + messageProperties (imap:messageProperties)
-    + jcr:content (nt:resource) mandatory 
     
 [imap:messageHeaders] > nt:unstructured
     + imap:messageHeader multiple
@@ -51,9 +50,10 @@
     - imap:mailboxUidValidity (LONG) mandatory
     - imap:mailboxName (STRING) mandatory
     - imap:mailboxLastUid (LONG) mandatory
-    + mailboxMemberships (imap:mailboxMemberships) 
+    + *
+
  
-[imap:mailboxMembership] >  mix:referenceable, nt:base
+[imap:mailboxMembership] >  mix:referenceable, nt:hierarchyNode
     - imap:mailboxUUID (String) mandatory
     - imap:uid (LONG) mandatory
     - imap:size (LONG) mandatory
@@ -65,7 +65,3 @@
     - imap:seen (BOOLEAN) mandatory
     - imap:internalDate (DATE) mandatory
     + message (imap:message) mandatory
-
- [imap:mailboxMemberships] > nt:unstructured
-    + imap:mailboxMembership multiple   
-   

Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java (original)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java Wed May 12 16:50:26 2010
@@ -25,8 +25,6 @@ import java.util.List;
 
 import javax.mail.Flags;
 import javax.persistence.EntityManager;
-import javax.persistence.EntityTransaction;
-import javax.persistence.LockModeType;
 
 import org.apache.james.imap.jpa.mail.JPAMailboxMapper;
 import org.apache.james.imap.jpa.mail.JPAMessageMapper;
@@ -37,6 +35,7 @@ import org.apache.james.imap.mailbox.Mai
 import org.apache.james.imap.mailbox.MailboxSession;
 import org.apache.james.imap.mailbox.util.MailboxEventDispatcher;
 import org.apache.james.imap.store.StoreMailbox;
+import org.apache.james.imap.store.UidConsumer;
 import org.apache.james.imap.store.mail.MailboxMapper;
 import org.apache.james.imap.store.mail.MessageMapper;
 import org.apache.james.imap.store.mail.model.Header;
@@ -54,8 +53,8 @@ public class JPAMailbox extends StoreMai
 
     protected final EntityManager manager;
     
-    public JPAMailbox(final MailboxEventDispatcher dispatcher, final Mailbox<Long> mailbox, final EntityManager manager) {
-        super(dispatcher, mailbox);
+    public JPAMailbox(final MailboxEventDispatcher dispatcher, final UidConsumer<Long> consumer,final Mailbox<Long> mailbox, final EntityManager manager) {
+        super(dispatcher, consumer, mailbox);
         this.manager = manager;        
     }  
 
@@ -88,26 +87,6 @@ public class JPAMailbox extends StoreMai
         return newRow;
     }
     
-    /**
-     * Reserve next Uid in mailbox and return the mailbox. We use a PESSIMISTIC_WRITE lock here to be sure we don't see any duplicates here when
-     * accessing the database with many different threads / connections
-     * 
-     */
-    protected Mailbox<Long> reserveNextUid(MailboxSession session) throws MailboxException {
-
-        EntityTransaction transaction = manager.getTransaction();
-        transaction.begin();
-
-        // we need to set a persimistic write lock to be sure we don't get any problems with dirty reads etc
-        org.apache.james.imap.jpa.mail.model.JPAMailbox mailbox = manager.find(org.apache.james.imap.jpa.mail.model.JPAMailbox.class, getMailboxId(), LockModeType.PESSIMISTIC_WRITE);
-        manager.refresh(mailbox);
-        mailbox.consumeUid();
-        manager.persist(mailbox);
-        manager.flush();
-        transaction.commit();
-        return mailbox;
-
-    }
     
     @Override
     protected Header createHeader(int lineNumber, String name, String value) {

Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java (original)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java Wed May 12 16:50:26 2010
@@ -40,7 +40,7 @@ public abstract class JPAMailboxManager 
     protected final MailboxSessionEntityManagerFactory entityManagerFactory;
     public JPAMailboxManager(final Authenticator authenticator, final Subscriber subscriber, 
             final MailboxSessionEntityManagerFactory entityManagerFactory) {
-        super(authenticator, subscriber);
+        super(authenticator, subscriber,new JPAUidConsumer(entityManagerFactory));
         this.entityManagerFactory = entityManagerFactory;
     }
     

Added: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAUidConsumer.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAUidConsumer.java?rev=943579&view=auto
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAUidConsumer.java (added)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAUidConsumer.java Wed May 12 16:50:26 2010
@@ -0,0 +1,59 @@
+/****************************************************************
+ * 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.jpa;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+import javax.persistence.LockModeType;
+
+import org.apache.james.imap.mailbox.MailboxSession;
+import org.apache.james.imap.store.UidConsumer;
+import org.apache.james.imap.store.mail.model.Mailbox;
+
+public class JPAUidConsumer implements UidConsumer<Long>{
+
+    private MailboxSessionEntityManagerFactory factory;
+
+    public JPAUidConsumer(MailboxSessionEntityManagerFactory factory) {
+        this.factory = factory;
+    }
+    
+    /**
+     * 
+     * Reserve next Uid in mailbox and return the mailbox. We use a PESSIMISTIC_WRITE lock here to be sure we don't see any duplicates here when
+     * accessing the database with many different threads / connections
+     * 
+     * @see org.apache.james.imap.store.UidConsumer#reserveNextUid(org.apache.james.imap.store.mail.model.Mailbox, org.apache.james.imap.mailbox.MailboxSession)
+     */
+    public long reserveNextUid(Mailbox<Long> mailbox, MailboxSession session) {
+        EntityManager manager = factory.createEntityManager(session);
+        EntityTransaction transaction = manager.getTransaction();
+        transaction.begin();
+
+        // we need to set a persimistic write lock to be sure we don't get any problems with dirty reads etc
+        org.apache.james.imap.jpa.mail.model.JPAMailbox m = manager.find(org.apache.james.imap.jpa.mail.model.JPAMailbox.class, mailbox.getMailboxId(), LockModeType.PESSIMISTIC_WRITE);
+        manager.refresh(m);
+        m.consumeUid();
+        manager.persist(m);
+        manager.flush();
+        transaction.commit();
+        return m.getLastUid();
+    }
+
+}

Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java (original)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java Wed May 12 16:50:26 2010
@@ -34,6 +34,7 @@ import org.apache.james.imap.jpa.mail.mo
 import org.apache.james.imap.mailbox.MailboxException;
 import org.apache.james.imap.mailbox.MailboxSession;
 import org.apache.james.imap.mailbox.util.MailboxEventDispatcher;
+import org.apache.james.imap.store.UidConsumer;
 import org.apache.james.imap.store.mail.model.Header;
 import org.apache.james.imap.store.mail.model.Mailbox;
 import org.apache.james.imap.store.mail.model.MailboxMembership;
@@ -47,12 +48,12 @@ public class OpenJPAMailbox extends JPAM
 
     private final boolean useStreaming;
 
-    public OpenJPAMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long> mailbox, EntityManager entityManager) {
-        this(dispatcher, mailbox, entityManager, false);
+    public OpenJPAMailbox(MailboxEventDispatcher dispatcher, UidConsumer<Long> consumer, Mailbox<Long> mailbox, EntityManager entityManager) {
+        this(dispatcher, consumer, mailbox, entityManager, false);
     }
 
-    public OpenJPAMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long> mailbox, EntityManager entityManager, final boolean useStreaming) {
-        super(dispatcher, mailbox, entityManager);
+    public OpenJPAMailbox(MailboxEventDispatcher dispatcher, UidConsumer<Long> consumer, Mailbox<Long> mailbox, EntityManager entityManager, final boolean useStreaming) {
+        super(dispatcher, consumer, mailbox, entityManager);
         this.useStreaming = useStreaming;
     }
 

Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java (original)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java Wed May 12 16:50:26 2010
@@ -27,6 +27,7 @@ import org.apache.james.imap.mailbox.uti
 import org.apache.james.imap.store.Authenticator;
 import org.apache.james.imap.store.StoreMailbox;
 import org.apache.james.imap.store.Subscriber;
+import org.apache.james.imap.store.UidConsumer;
 import org.apache.james.imap.store.mail.model.Mailbox;
 
 /**
@@ -46,8 +47,8 @@ public class OpenJPAMailboxManager exten
         this(authenticator, subscriber, entityManagerFactory, false);
     }
 
-    protected StoreMailbox<Long> createMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long> mailboxRow, MailboxSession session) {
-        StoreMailbox<Long> result =  new OpenJPAMailbox(dispatcher,mailboxRow, entityManagerFactory.createEntityManager(session), useStreaming);
+    protected StoreMailbox<Long> createMailbox(MailboxEventDispatcher dispatcher, UidConsumer<Long> consumer, Mailbox<Long> mailboxRow, MailboxSession session) {
+        StoreMailbox<Long> result =  new OpenJPAMailbox(dispatcher, consumer, mailboxRow,entityManagerFactory.createEntityManager(session), useStreaming);
         return result;
     }
 }

Modified: james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.java (original)
+++ james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.java Wed May 12 16:50:26 2010
@@ -33,11 +33,12 @@ import org.apache.james.imap.store.Authe
 import org.apache.james.imap.store.StoreMailbox;
 import org.apache.james.imap.store.StoreMailboxManager;
 import org.apache.james.imap.store.Subscriber;
+import org.apache.james.imap.store.UidConsumer;
 import org.apache.james.imap.store.mail.MailboxMapper;
 import org.apache.james.imap.store.mail.model.Mailbox;
 import org.apache.james.imap.store.transaction.TransactionalMapper;
 
-public class InMemoryMailboxManager extends StoreMailboxManager<Long> implements MailboxMapper<Long> {
+public class InMemoryMailboxManager extends StoreMailboxManager<Long> implements MailboxMapper<Long>{
 
     private static final int INITIAL_SIZE = 128;
     private Map<Long, InMemoryMailbox> mailboxesById;
@@ -46,17 +47,23 @@ public class InMemoryMailboxManager exte
     private MailboxSession session;
 
     public InMemoryMailboxManager(Authenticator authenticator, Subscriber subscriber) {
-        super(authenticator, subscriber);
+        super(authenticator, subscriber, new UidConsumer<Long>() {
+
+            public long reserveNextUid(Mailbox<Long> mailbox, MailboxSession session) throws MailboxException {
+                mailbox.consumeUid();
+                return mailbox.getLastUid();
+            }
+        });
         mailboxesById = new ConcurrentHashMap<Long, InMemoryMailbox>(INITIAL_SIZE);
         storeMailboxByName = new ConcurrentHashMap<String, InMemoryStoreMailbox>(INITIAL_SIZE);
         idNameMap = new ConcurrentHashMap<Long, String>(INITIAL_SIZE);
     }
 
     @Override
-    protected StoreMailbox<Long> createMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long> mailboxRow, MailboxSession session) {
+    protected StoreMailbox<Long> createMailbox(MailboxEventDispatcher dispatcher, UidConsumer<Long> consumer, Mailbox<Long> mailboxRow, MailboxSession session) {
         InMemoryStoreMailbox storeMailbox = storeMailboxByName.get(mailboxRow.getName());
         if (storeMailbox == null) {
-            storeMailbox = new InMemoryStoreMailbox(dispatcher, (InMemoryMailbox)mailboxRow);
+            storeMailbox = new InMemoryStoreMailbox(dispatcher, consumer, (InMemoryMailbox)mailboxRow);
             storeMailboxByName.put(mailboxRow.getName(), storeMailbox);
         }
         
@@ -209,5 +216,10 @@ public class InMemoryMailboxManager exte
         idNameMap.clear();
     }
 
+    public long reserveNextUid(Mailbox<Long> mailbox, MailboxSession session) throws MailboxException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
     
 }

Modified: james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java (original)
+++ james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java Wed May 12 16:50:26 2010
@@ -39,6 +39,7 @@ import org.apache.james.imap.mailbox.Sto
 import org.apache.james.imap.mailbox.util.MailboxEventDispatcher;
 import org.apache.james.imap.store.MailboxMembershipComparator;
 import org.apache.james.imap.store.StoreMailbox;
+import org.apache.james.imap.store.UidConsumer;
 import org.apache.james.imap.store.mail.MailboxMapper;
 import org.apache.james.imap.store.mail.MessageMapper;
 import org.apache.james.imap.store.mail.model.Header;
@@ -52,8 +53,8 @@ public class InMemoryStoreMailbox extend
     private Map<Long, MailboxMembership<Long>> membershipByUid;
     private InMemoryMailbox mailbox;
 
-    public InMemoryStoreMailbox(MailboxEventDispatcher dispatcher, InMemoryMailbox mailbox) {
-        super(dispatcher, mailbox);
+    public InMemoryStoreMailbox(MailboxEventDispatcher dispatcher, UidConsumer<Long> consumer, InMemoryMailbox mailbox) {
+        super(dispatcher, consumer, mailbox);
         this.mailbox = mailbox;
         this.membershipByUid = new ConcurrentHashMap<Long, MailboxMembership<Long>>(INITIAL_SIZE);
     }
@@ -97,14 +98,6 @@ public class InMemoryStoreMailbox extend
     protected MessageMapper<Long> createMessageMapper(MailboxSession session) {
         return this;
     }
-
-
-    @Override
-    protected Mailbox<Long> reserveNextUid(MailboxSession session) throws MailboxException {
-        mailbox.consumeUid();
-        return mailbox;
-    }
-
     /*
      * (non-Javadoc)
      * @see org.apache.james.imap.store.mail.MessageMapper#countMessagesInMailbox()

Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java?rev=943579&r1=943578&r2=943579&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java Wed May 12 16:50:26 2010
@@ -83,11 +83,14 @@ public abstract class StoreMailbox<Id> i
     private final Id mailboxId;
     
     private MailboxEventDispatcher dispatcher;
+
+    private UidConsumer<Id> consumer;
     
     
-    public StoreMailbox(final MailboxEventDispatcher dispatcher, final Mailbox<Id> mailbox) {
+    public StoreMailbox(final MailboxEventDispatcher dispatcher, UidConsumer<Id> consumer, final Mailbox<Id> mailbox) {
         this.mailboxId = mailbox.getMailboxId();
         this.dispatcher = dispatcher;
+        this.consumer = consumer;
     }
 
     /**
@@ -157,8 +160,7 @@ public abstract class StoreMailbox<Id> i
         // this will hold the uid after the transaction was complete
         final MessageMapper<Id> mapper = createMessageMapper(mailboxSession);
         
-        final Mailbox<Id> mailbox = reserveNextUid(mailboxSession);
-        final long uid = mailbox.getLastUid();
+        final long uid = consumer.reserveNextUid(getMailboxRow(mailboxSession), mailboxSession);
         
         
         File file = null;
@@ -379,16 +381,6 @@ public abstract class StoreMailbox<Id> i
     protected abstract Header createHeader(int lineNumber, String name, String value);
 
 
-    /**
-     * Reserve the next Uid on the underlying {@link Mailbox}. Its important that the implementation guaranteer a thread-safe/atomic calculation of the 
-     * next uid. So be sure you don't use any caching etc.
-     * 
-     * 
-     * @return mailbox
-     * @throws MailboxException
-     */
-    protected abstract Mailbox<Id> reserveNextUid(MailboxSession session) throws  MailboxException;
-
     /*
      * (non-Javadoc)
      * @see org.apache.james.imap.mailbox.Mailbox#getMessages(org.apache.james.imap.mailbox.MessageRange, org.apache.james.imap.mailbox.MessageResult.FetchGroup, org.apache.james.imap.mailbox.MailboxSession)
@@ -623,8 +615,7 @@ public abstract class StoreMailbox<Id> i
             
 
             for (final MailboxMembership<Id> originalMessage:originalRows) {
-                final Mailbox<Id> mailbox = reserveNextUid(session );
-                final long uid = mailbox.getLastUid();
+                final long uid = consumer.reserveNextUid(getMailboxRow(session),session);
                 
                 mapper.execute(new TransactionalMapper.Transaction() {
 



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