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 ma...@apache.org on 2010/02/09 12:00:49 UTC

svn commit: r908000 [1/2] - in /james/hupa/trunk: client/ client/src/main/java/org/apache/hupa/client/mvp/ client/war/ server/src/main/java/org/apache/hupa/server/ server/src/main/java/org/apache/hupa/server/guice/ server/src/main/java/org/apache/hupa/...

Author: manolo
Date: Tue Feb  9 11:00:47 2010
New Revision: 908000

URL: http://svn.apache.org/viewvc?rev=908000&view=rev
Log:
Added an implementation for storing user preferences in IMAP messages, right now, only contacts are stored.
When the user sends a message emails are added automatically to the contacts list.
Added new configuration parameters: DefaultDraftsFolder, and SessionDebug (SMTP, IMAP debugging).
A lot of work in test part in order to easily modify GuiceModule to be able to change classes implementations and run integration tests.
A couple of minor fixes.

Added:
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/InImapUserPreferencesStorage.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/HupaGuiceTestCase.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/HandlersTest.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/preferences/InImapUserPreferencesStorageTest.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/preferences/InSessionUserPreferencesStorageTest.java
      - copied, changed from r907633, james/hupa/trunk/server/src/test/java/org/apache/hupa/server/preferences/UserPreferencesStorageTest.java
Removed:
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/preferences/UserPreferencesStorageTest.java
Modified:
    james/hupa/trunk/client/pom.xml
    james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageView.java
    james/hupa/trunk/client/war/Hupa.css
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/InMemoryIMAPStoreCache.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/DefaultUserSettingsProvider.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/DemoModeConstants.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/GuiceServerModule.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractFetchMessagesHandler.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractSendMessageHandler.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CheckSessionHandler.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CreateFolderHandler.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchFoldersHandler.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchMessagesHandler.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ForwardMessageHandler.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/LoginUserHandler.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ReplyMessageHandler.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/SendMessageHandler.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/mock/MockIMAPFolder.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/mock/MockIMAPStore.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/InSessionUserPreferencesStorage.java
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/UserPreferencesStorage.java
    james/hupa/trunk/server/src/main/webapp/WEB-INF/conf/config.properties
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/DemoModeTest.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/HupaTestCase.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/guice/GuiceTestModule.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/AbstractHandlerTest.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/AbtractSendMessageHandlerTest.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/ContactsHandlerTest.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/FowardMessageHandlerTest.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/GetMessageDetailsHandlerTest.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/ReplyMessageHandlerTest.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/integration/StoreBugTest.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/mock/MockIMAPStoreCache.java
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/utils/TestUtils.java
    james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/data/Settings.java
    james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/rpc/LoginUser.java
    james/hupa/trunk/widgets/src/main/java/org/apache/hupa/widgets/WidgetsCSS.java

Modified: james/hupa/trunk/client/pom.xml
URL: http://svn.apache.org/viewvc/james/hupa/trunk/client/pom.xml?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/client/pom.xml (original)
+++ james/hupa/trunk/client/pom.xml Tue Feb  9 11:00:47 2010
@@ -92,10 +92,6 @@
             <artifactId>gwt-presenter</artifactId>
         </dependency>
         <dependency>
-            <groupId>com.google.gwt</groupId>
-            <artifactId>gwt-incubator</artifactId>
-        </dependency>
-        <dependency>
             <groupId>com.google.code.gwt-dnd</groupId>
             <artifactId>gwt-dnd</artifactId>
         </dependency>

Modified: james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageView.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageView.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageView.java (original)
+++ james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageView.java Tue Feb  9 11:00:47 2010
@@ -158,6 +158,7 @@
                     }
                 });
                 HorizontalPanel aPanel = new HorizontalPanel();
+                aPanel.addStyleName(HupaCSS.C_attachment);
                 aPanel.add(imageBundle.attachmentIcon().createImage());
                 aPanel.add(link);
                 attachments.add(aPanel);

Modified: james/hupa/trunk/client/war/Hupa.css
URL: http://svn.apache.org/viewvc/james/hupa/trunk/client/war/Hupa.css?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/client/war/Hupa.css (original)
+++ james/hupa/trunk/client/war/Hupa.css Tue Feb  9 11:00:47 2010
@@ -262,6 +262,14 @@
 	padding: 20px;
 }
 
+.hupa-attachment .hupa-hyperlink {
+	padding-left: 5px;
+	font-style: italic;
+	color: #0d0eb0;
+	text-decoration: underline;
+	cursor: pointer;
+}
+
 /************[ view: MessageSendView ]*******************/
 table.hupa-msgsend {
 	width: 100%;

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/InMemoryIMAPStoreCache.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/InMemoryIMAPStoreCache.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/InMemoryIMAPStoreCache.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/InMemoryIMAPStoreCache.java Tue Feb  9 11:00:47 2010
@@ -50,16 +50,17 @@
     private boolean useSSL = false;
     
     @Inject
-    public InMemoryIMAPStoreCache(Log logger,@Named("IMAPServerAddress") String address, @Named("IMAPServerPort") int port, @Named("IMAPS") boolean useSSL, @Named("IMAPConnectionPoolSize") int connectionPoolSize, @Named("IMAPConnectionPoolTimeout") int timeout, Provider<Session> sessionProvider) {
+    public InMemoryIMAPStoreCache(Log logger, @Named("IMAPServerAddress") String address, @Named("IMAPServerPort") int port, @Named("IMAPS") boolean useSSL, @Named("IMAPConnectionPoolSize") int connectionPoolSize, @Named("IMAPConnectionPoolTimeout") int timeout, @Named("SessionDebug") boolean debug, Provider<Session> sessionProvider) {
         this.logger = logger;
         this.address = address;
         this.port = port;
         this.useSSL = useSSL;
       
         session = sessionProvider.get();
-        if (logger.isDebugEnabled()) {
+        if (debug && logger.isDebugEnabled()) {
             session.setDebug(true);
         }
+        
         Properties props = session.getProperties();
         
         props.setProperty("mail.mime.decodetext.strict", "false");

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/DefaultUserSettingsProvider.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/DefaultUserSettingsProvider.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/DefaultUserSettingsProvider.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/DefaultUserSettingsProvider.java Tue Feb  9 11:00:47 2010
@@ -29,13 +29,15 @@
     private String inboxFolder;
     private String sentFolder;
     private String trashFolder;
+    private String draftFolder;
     private int postCount;
 
     @Inject
-    public DefaultUserSettingsProvider(@Named("DefaultInboxFolder") String inboxFolder, @Named("DefaultSentFolder") String sentFolder, @Named("DefaultTrashFolder") String trashFolder, @Named("PostFetchMessageCount") int postCount) {
+    public DefaultUserSettingsProvider(@Named("DefaultInboxFolder") String inboxFolder, @Named("DefaultSentFolder") String sentFolder, @Named("DefaultTrashFolder") String trashFolder, @Named("DefaultDraftsFolder") String draftFolder, @Named("PostFetchMessageCount") int postCount) {
         this.inboxFolder = inboxFolder;
         this.sentFolder = sentFolder;
         this.trashFolder = trashFolder;
+        this.draftFolder = draftFolder;
         this.postCount = postCount;
     }
     
@@ -48,6 +50,7 @@
         settings.setInboxFolderName(inboxFolder);
         settings.setSentFolderName(sentFolder);
         settings.setTrashFolderName(trashFolder);
+        settings.setDraftsFolderName(draftFolder);
         settings.setPostFetchMessageCount(postCount);
         return settings;
     }

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/DemoModeConstants.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/DemoModeConstants.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/DemoModeConstants.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/DemoModeConstants.java Tue Feb  9 11:00:47 2010
@@ -1,10 +1,10 @@
 package org.apache.hupa.server.guice;
 
-import java.util.Properties;
-
 import org.apache.hupa.shared.data.Settings;
 import org.apache.hupa.shared.data.User;
 
+import java.util.Properties;
+
 /**
  * Constants and properties used for demo mode
  */
@@ -18,6 +18,7 @@
     public static final String DEMO_MODE_SENT_FOLDER = "Demo-Sent";
     public static final String DEMO_MODE_TRASH_FOLDER = "Demo-Trash";
     public static final String DEMO_MODE_INBOX_FOLDER = "Demo-Inbox";
+    public static final String DEMO_MODE_DRAFTS_FOLDER = "Demo-Drafts";
     public static final String DEMO_MODE_DEFAULT_FOLDER = "";
     
     public static final String DEMO_MODE_MESSAGES_LOCATION = "mime/";
@@ -28,12 +29,16 @@
             setInboxFolderName(DEMO_MODE_INBOX_FOLDER);
             setSentFolderName(DEMO_MODE_SENT_FOLDER);
             setTrashFolderName(DEMO_MODE_TRASH_FOLDER);
+            setDraftsFolderName(DEMO_MODE_DRAFTS_FOLDER);
         }
     };
     
     public final static Properties demoProperties = new Properties() {
         private static final long serialVersionUID = 1L;
         {
+            put("Username",DEMO_LOGIN);
+            put("Password",DEMO_LOGIN);
+
             put("IMAPServerAddress", DEMO_MODE);
             put("IMAPServerPort", "143");
             put("IMAPS", "false");
@@ -43,14 +48,19 @@
             put("SMTPS", "false");
             put("SMTPAuth", "false");
             
+            put("SessionDebug", "false");
+            
             put("IMAPConnectionPoolSize", "4");
             put("IMAPConnectionPoolTimeout", "300000");
 
             put("DefaultInboxFolder", DEMO_MODE_INBOX_FOLDER);
             put("DefaultTrashFolder", DEMO_MODE_TRASH_FOLDER);
             put("DefaultSentFolder", DEMO_MODE_SENT_FOLDER);
+            put("DefaultDraftsFolder", DEMO_MODE_DRAFTS_FOLDER);
             
             put("PostFetchMessageCount", "0");
+            
+            put("DefaultUserSessionId", "just_an_id");
         }
     };
 
@@ -60,6 +70,7 @@
             setInboxFolderName(DEMO_MODE_INBOX_FOLDER);
             setSentFolderName(DEMO_MODE_SENT_FOLDER);
             setTrashFolderName(DEMO_MODE_TRASH_FOLDER);
+            setDraftsFolderName(DEMO_MODE_DRAFTS_FOLDER);
         }
     };
     

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/GuiceServerModule.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/GuiceServerModule.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/GuiceServerModule.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/guice/GuiceServerModule.java Tue Feb  9 11:00:47 2010
@@ -19,11 +19,8 @@
 
 package org.apache.hupa.server.guice;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.util.Properties;
-
-import javax.mail.Session;
+import com.google.inject.Singleton;
+import com.google.inject.name.Names;
 
 import net.customware.gwt.dispatch.server.guice.ActionHandlerModule;
 
@@ -50,15 +47,18 @@
 import org.apache.hupa.server.handler.SendMessageHandler;
 import org.apache.hupa.server.handler.SetFlagsHandler;
 import org.apache.hupa.server.handler.TagMessagesHandler;
-import org.apache.hupa.server.preferences.InSessionUserPreferencesStorage;
+import org.apache.hupa.server.preferences.InImapUserPreferencesStorage;
 import org.apache.hupa.server.preferences.UserPreferencesStorage;
 import org.apache.hupa.server.servlet.DownloadAttachmentServlet;
 import org.apache.hupa.server.servlet.MessageSourceServlet;
 import org.apache.hupa.server.servlet.UploadAttachmentServlet;
 import org.apache.hupa.shared.data.Settings;
 
-import com.google.inject.Singleton;
-import com.google.inject.name.Names;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Properties;
+
+import javax.mail.Session;
 
 /**
  * Module which binds the handlers and configurations
@@ -113,7 +113,7 @@
         bind(UploadAttachmentServlet.class).in(Singleton.class);
         bind(MessageSourceServlet.class).in(Singleton.class);
         bind(Session.class).toProvider(SessionProvider.class);
-        bind(UserPreferencesStorage.class).to(InSessionUserPreferencesStorage.class);
+        bind(UserPreferencesStorage.class).to(InImapUserPreferencesStorage.class);
 
         Properties properties;
         try {

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractFetchMessagesHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractFetchMessagesHandler.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractFetchMessagesHandler.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractFetchMessagesHandler.java Tue Feb  9 11:00:47 2010
@@ -68,29 +68,30 @@
             folder = new IMAPFolder(user.getSettings().getInboxFolderName());
         }
         com.sun.mail.imap.IMAPFolder f = null;
+        int start = action.getStart();
+        int offset = action.getOffset();
         try {
             IMAPStore store = cache.get(user);
-            int start = action.getStart();
-            int offset = action.getOffset();
             
             f =  (com.sun.mail.imap.IMAPFolder)store.getFolder(folder.getFullName());
 
-            // check if the folder is open, if not open it read only
-             if (f.isOpen() == false) {
-                 f.open(com.sun.mail.imap.IMAPFolder.READ_ONLY);
-             }
+             // check if the folder is open, if not open it read only
+            if (f.isOpen() == false) {
+                f.open(com.sun.mail.imap.IMAPFolder.READ_ONLY);
+            }
 
-            int exists = f.getMessageCount();
-            
             // if the folder is empty we have no need to process 
+            int exists = f.getMessageCount();
             if (exists == 0) {
-                return new FetchMessagesResult(new ArrayList<org.apache.hupa.shared.data.Message>(),start,offset,exists,0);
+                 return new FetchMessagesResult(new ArrayList<org.apache.hupa.shared.data.Message>(), start, offset, 0, 0);
             }        
             
             MessageConvertArray convArray = getMessagesToConvert(f,action);
-            
             return new FetchMessagesResult(convert(offset, f, convArray.getMesssages()),start, offset,convArray.getRealCount(),f.getUnreadMessageCount());
-            
+        } catch (MessagingException e) {
+            logger.info("Error fetching messages in folder: " + folder.getFullName() + " " + e.getMessage());
+            // Folder can not contain messages
+            return new FetchMessagesResult(new ArrayList<org.apache.hupa.shared.data.Message>(), start, offset, 0, 0);
         } catch (Exception e) {
             e.printStackTrace();
             logger.error("Error while fetching headers for user " + user.getName() + " in folder " + folder,e);
@@ -108,7 +109,7 @@
         }
     }
     
-    protected abstract MessageConvertArray getMessagesToConvert(com.sun.mail.imap.IMAPFolder f, A action) throws MessagingException;
+    protected abstract MessageConvertArray getMessagesToConvert(com.sun.mail.imap.IMAPFolder f, A action) throws MessagingException, ActionException;
     
     protected ArrayList<org.apache.hupa.shared.data.Message> convert(int offset, com.sun.mail.imap.IMAPFolder folder, Message[] messages) throws MessagingException {
         ArrayList<org.apache.hupa.shared.data.Message> mList = new ArrayList<org.apache.hupa.shared.data.Message>();

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractSendMessageHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractSendMessageHandler.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractSendMessageHandler.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractSendMessageHandler.java Tue Feb  9 11:00:47 2010
@@ -55,6 +55,7 @@
 import org.apache.hupa.server.IMAPStoreCache;
 import org.apache.hupa.server.guice.DemoModeConstants;
 import org.apache.hupa.server.mock.MockSMTPTransport;
+import org.apache.hupa.server.preferences.UserPreferencesStorage;
 import org.apache.hupa.server.utils.MessageUtils;
 import org.apache.hupa.server.utils.RegexPatterns;
 import org.apache.hupa.server.utils.SessionUtils;
@@ -82,9 +83,10 @@
     private final int port;
     private boolean useSSL = false;
     private Provider<HttpSession> httpSessionProvider;
+    UserPreferencesStorage userPreferences;
 
     @Inject
-    public AbstractSendMessageHandler(Log logger, IMAPStoreCache store, Provider<HttpSession> provider, @Named("SMTPServerAddress") String address, @Named("SMTPServerPort") int port, @Named("SMTPAuth") boolean auth, @Named("SMTPS") boolean useSSL) {
+    public AbstractSendMessageHandler(Log logger, IMAPStoreCache store, Provider<HttpSession> provider, UserPreferencesStorage preferences, @Named("SMTPServerAddress") String address, @Named("SMTPServerPort") int port, @Named("SMTPAuth") boolean auth, @Named("SMTPS") boolean useSSL) {
         super(store,logger,provider);
         this.auth = auth;
         this.address = address;
@@ -92,6 +94,7 @@
         this.useSSL  = useSSL;
         this.httpSessionProvider = provider;
         props.put("mail.smtp.auth", auth);
+        this.userPreferences = preferences;
     }
 
     @Override
@@ -109,7 +112,7 @@
         
             resetAttachments(action);
         
-            // TODO: notify the user more accurately where is the error
+            // TODO: notify the user more accurately where the error is
             // if the message was sent and the storage in the sent folder failed, etc.
         } catch (AddressException e) {
             result.setError("Error while parsing recipient: " + e.getMessage());
@@ -141,6 +144,11 @@
         MimeMessage message = new MimeMessage(session);
         SMTPMessage m = action.getMessage();
         message.setFrom(new InternetAddress(m.getFrom()));
+
+        userPreferences.addContact(m.getTo());
+        userPreferences.addContact(m.getCc());
+        userPreferences.addContact(m.getBcc());
+
         message.setRecipients(RecipientType.TO, MessageUtils.getRecipients(m.getTo()));
         message.setRecipients(RecipientType.CC, MessageUtils.getRecipients(m.getCc()));
         message.setRecipients(RecipientType.BCC, MessageUtils.getRecipients(m.getBcc()));
@@ -276,13 +284,7 @@
         IMAPStore iStore = cache.get(user);
         IMAPFolder folder = (IMAPFolder) iStore.getFolder(user.getSettings().getSentFolderName());
         
-        boolean exists = false;
-        if (folder.exists() == false) {
-            exists = folder.create(IMAPFolder.READ_WRITE);
-        } else {
-            exists = true;
-        }
-        if (exists) {
+        if (folder.exists() || folder.create(IMAPFolder.READ_WRITE)) {
             if (folder.isOpen() == false) {
                 folder.open(Folder.READ_WRITE);
             }
@@ -290,7 +292,8 @@
             // It is necessary to copy the message, before putting it
             // in the sent folder. If not, it is not guaranteed that it is 
             // stored in ascii and is not possible to get the attachments
-            // size.
+            // size. message.saveChanges() doesn't fix the problem.
+            // There are tests which demonstrate this.
             message = new MimeMessage((MimeMessage)message);
 
             message.setFlag(Flag.SEEN, true);

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CheckSessionHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CheckSessionHandler.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CheckSessionHandler.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CheckSessionHandler.java Tue Feb  9 11:00:47 2010
@@ -57,6 +57,7 @@
         } catch (Exception e) {
             e.printStackTrace();
         }
+        logger.debug("CheckSession returns: " + ret.isValid());
         return ret;
     }
 

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CreateFolderHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CreateFolderHandler.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CreateFolderHandler.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CreateFolderHandler.java Tue Feb  9 11:00:47 2010
@@ -69,7 +69,6 @@
         } catch (Exception e) {
             logger.error("Error while creating folder " + folder + " for user " + user, e);
             throw new ActionException("Error while creating folder " + folder + " for user " + user, e);
-
         }
     }
 

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchFoldersHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchFoldersHandler.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchFoldersHandler.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchFoldersHandler.java Tue Feb  9 11:00:47 2010
@@ -60,6 +60,7 @@
         User user = getUser();
         ArrayList<IMAPFolder> fList = new ArrayList<IMAPFolder>();
         try {
+
             // get the store for the user
             IMAPStore store = cache.get(user);
             com.sun.mail.imap.IMAPFolder folder = (com.sun.mail.imap.IMAPFolder) store.getDefaultFolder();
@@ -70,6 +71,7 @@
                 Folder f = folders[i];
                 createIMAPFolderTree(fList, createFolder(f), f.list());
             }
+            logger.debug("Fetching folders for user: " + user + " returns: " + fList.size() + " folders");
             return new FetchFoldersResult(fList);
         } catch (Exception e) {
             e.printStackTrace();
@@ -93,15 +95,17 @@
      * 
      * @param folder
      * @return imapFolder
+     * @throws ActionException 
      * @throws MessagingException
      */
-    private IMAPFolder createFolder(Folder folder) {
+    private IMAPFolder createFolder(Folder folder) throws ActionException {
 
         String fullName = folder.getFullName();
         String delimiter;
         IMAPFolder iFolder = null;
         
         try {
+            logger.debug("Creating folder: " + fullName + " for user: " + getUser());
             delimiter = String.valueOf(folder.getSeparator());
             iFolder = new IMAPFolder(fullName);
             iFolder.setDelimiter(delimiter);
@@ -110,7 +114,6 @@
             iFolder.setMessageCount(folder.getMessageCount());
             iFolder.setSubscribed(folder.isSubscribed());
             iFolder.setUnseenMessageCount(folder.getUnreadMessageCount());
-            
         } catch (MessagingException e) {
             logger.error("Unable to construct folder " + folder.getFullName(),e);
         }
@@ -128,7 +131,7 @@
      * @throws MessagingException
      */
     private void createIMAPFolderTree(List<IMAPFolder> fList,
-            IMAPFolder iFolder, Folder[] childFolders) throws MessagingException {
+            IMAPFolder iFolder, Folder[] childFolders) throws MessagingException, ActionException {
         
         for (int a = 0; a < childFolders.length; a++) {
             IMAPFolder folder = createFolder(childFolders[a]);

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchMessagesHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchMessagesHandler.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchMessagesHandler.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchMessagesHandler.java Tue Feb  9 11:00:47 2010
@@ -39,6 +39,8 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
+import net.customware.gwt.dispatch.shared.ActionException;
+
 /**
  * Fetch Messages for a user. The Messages don't contain any body, just some
  * fields of the headers are fetched for perfomance reasons
@@ -46,6 +48,7 @@
  */
 public class FetchMessagesHandler extends
         AbstractFetchMessagesHandler<FetchMessages> {
+    
 
     @Inject
     public FetchMessagesHandler(IMAPStoreCache cache, Log logger,
@@ -64,13 +67,11 @@
 
     @Override
     protected MessageConvertArray getMessagesToConvert(com.sun.mail.imap.IMAPFolder f,
-            FetchMessages action) throws MessagingException {
+            FetchMessages action) throws MessagingException, ActionException {
         String searchString = action.getSearchString();
         int start = action.getStart();
         int offset = action.getOffset();
         int end = start + offset;
-
-       
         Message[] messages;
         int exists;
         // check if a searchString was given, and if so use it
@@ -114,6 +115,8 @@
             }
           
         }
+        logger.debug("Fetching messages for user: " + getUser() + " returns: " + messages.length + " messages in " + f.getFullName());
+
         return new MessageConvertArray(exists, messages);
     }
 }

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ForwardMessageHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ForwardMessageHandler.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ForwardMessageHandler.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ForwardMessageHandler.java Tue Feb  9 11:00:47 2010
@@ -33,6 +33,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.server.preferences.UserPreferencesStorage;
 import org.apache.hupa.server.utils.MessageUtils;
 import org.apache.hupa.shared.rpc.ForwardMessage;
 
@@ -49,9 +50,9 @@
 public class ForwardMessageHandler extends AbstractSendMessageHandler<ForwardMessage> {
 
     @Inject
-    public ForwardMessageHandler(Log logger, IMAPStoreCache store, Provider<HttpSession> provider, @Named("SMTPServerAddress") String address, @Named("SMTPServerPort") int port,
+    public ForwardMessageHandler(Log logger, IMAPStoreCache store, Provider<HttpSession> provider, UserPreferencesStorage preferences, @Named("SMTPServerAddress") String address, @Named("SMTPServerPort") int port,
             @Named("SMTPAuth") boolean auth, @Named("SMTPS") boolean useSSL) {
-        super(logger, store, provider, address, port, auth, useSSL);
+        super(logger, store, provider, preferences, address, port, auth, useSSL);
     }
 
     @Override

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/LoginUserHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/LoginUserHandler.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/LoginUserHandler.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/LoginUserHandler.java Tue Feb  9 11:00:47 2010
@@ -78,10 +78,12 @@
             // store the session id for later usage
             HttpSession session = sessionProvider.get();
             session.setAttribute("user", user);
+            
+            logger.debug("Logged user: " + action);
             return new LoginUserResult(user);
 
         } catch (Exception e) {
-            logger.error("Unable to authenticate user " + username,e);
+            logger.error("Unable to authenticate user: " + action, e);
             throw new ActionException(e);
         }
     }

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ReplyMessageHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ReplyMessageHandler.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ReplyMessageHandler.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ReplyMessageHandler.java Tue Feb  9 11:00:47 2010
@@ -33,6 +33,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.server.preferences.UserPreferencesStorage;
 import org.apache.hupa.server.utils.MessageUtils;
 import org.apache.hupa.shared.rpc.ReplyMessage;
 
@@ -50,9 +51,9 @@
 public class ReplyMessageHandler extends AbstractSendMessageHandler<ReplyMessage> {
 
     @Inject
-    public ReplyMessageHandler(Log logger, IMAPStoreCache store, Provider<HttpSession> provider,
+    public ReplyMessageHandler(Log logger, IMAPStoreCache store, Provider<HttpSession> provider, UserPreferencesStorage preferences,
             @Named("SMTPServerAddress") String address, @Named("SMTPServerPort") int port, @Named("SMTPAuth") boolean auth, @Named("SMTPS") boolean useSSL) {
-        super(logger, store, provider, address, port, auth, useSSL);
+        super(logger, store, provider, preferences, address, port, auth, useSSL);
     }
 
     @Override

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/SendMessageHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/SendMessageHandler.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/SendMessageHandler.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/SendMessageHandler.java Tue Feb  9 11:00:47 2010
@@ -23,6 +23,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.server.preferences.UserPreferencesStorage;
 import org.apache.hupa.shared.rpc.SendMessage;
 
 import com.google.inject.Inject;
@@ -37,9 +38,9 @@
 public class SendMessageHandler extends AbstractSendMessageHandler<SendMessage> {
 
     @Inject
-    public SendMessageHandler(Log logger, IMAPStoreCache store, Provider<HttpSession> provider,
+    public SendMessageHandler(Log logger, IMAPStoreCache store, Provider<HttpSession> provider, UserPreferencesStorage preferences,
             @Named("SMTPServerAddress") String address, @Named("SMTPServerPort") int port, @Named("SMTPAuth") boolean auth, @Named("SMTPS") boolean useSSL) {
-        super(logger, store, provider, address, port, auth,useSSL);
+        super(logger, store, provider, preferences, address, port, auth,useSSL);
     }
 
     /*

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/mock/MockIMAPFolder.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/mock/MockIMAPFolder.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/mock/MockIMAPFolder.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/mock/MockIMAPFolder.java Tue Feb  9 11:00:47 2010
@@ -47,7 +47,7 @@
 
     public static final char SEPARATOR = '.';
     public List<Message> messages = new ArrayList<Message>();
-    private boolean closed;
+    private boolean closed = true;
     private boolean exists;
     
     public MockIMAPFolder(String fullName, IMAPStore store) {
@@ -87,7 +87,11 @@
 
     }
     
-    public void loadDemoMessages(Session session) {
+    public void loadDemoMessages(Session session) throws Exception{
+        if (!exists()) {
+            create(IMAPFolder.HOLDS_MESSAGES);
+            open(Folder.READ_WRITE);
+        }
         for(int i=0;;i++) {
             URL url = Thread.currentThread().getContextClassLoader().getResource(DemoModeConstants.DEMO_MODE_MESSAGES_LOCATION + i + ".msg");
             if (url == null) break;
@@ -126,7 +130,6 @@
     @Override
     public synchronized void fetch(Message[] msgs, FetchProfile fp)
             throws MessagingException {
-        // nothing todo
         checkExists();
     }
 
@@ -149,7 +152,7 @@
     public synchronized Message getMessage(int msgnum)
             throws MessagingException {
         checkExists();
-        if (messages.size() < msgnum) {
+        if (messages.size() <= msgnum) {
             throw new MessagingException();
         }
         return messages.get(msgnum);

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/mock/MockIMAPStore.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/mock/MockIMAPStore.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/mock/MockIMAPStore.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/mock/MockIMAPStore.java Tue Feb  9 11:00:47 2010
@@ -45,7 +45,7 @@
     static final URLName demoUrl = new URLName(null, DemoModeConstants.DEMO_MODE, 143, null, null, null);
     
     /**
-     * Demo mode constructor
+     * Default constructor, it creates the folder structure and loads messages for demo
      */
     @Inject
     public MockIMAPStore(Session session) {
@@ -53,17 +53,18 @@
     }
 
     /**
-     * Default constructor
+     * Customized constructor
      */
     public MockIMAPStore(Session session, URLName url) {
         super(session, url);
-        if (DemoModeConstants.DEMO_MODE.equals(url.getHost())) {
+        if (url != null && DemoModeConstants.DEMO_MODE.equals(url.getHost())) {
             validServers.put(DemoModeConstants.DEMO_MODE, 143);
             validLogins.put(DemoModeConstants.DEMO_LOGIN, DemoModeConstants.DEMO_LOGIN);
             try {
                 new MockIMAPFolder(DemoModeConstants.DEMO_MODE_INBOX_FOLDER, this).create(Folder.HOLDS_FOLDERS | Folder.HOLDS_MESSAGES);
                 new MockIMAPFolder(DemoModeConstants.DEMO_MODE_SENT_FOLDER, this).create(Folder.HOLDS_FOLDERS | Folder.HOLDS_MESSAGES);
                 new MockIMAPFolder(DemoModeConstants.DEMO_MODE_TRASH_FOLDER, this).create(Folder.HOLDS_FOLDERS | Folder.HOLDS_MESSAGES);
+                new MockIMAPFolder(DemoModeConstants.DEMO_MODE_DRAFTS_FOLDER, this).create(Folder.HOLDS_FOLDERS | Folder.HOLDS_MESSAGES);
                 ((MockIMAPFolder)getFolder(DemoModeConstants.DEMO_MODE_INBOX_FOLDER)).loadDemoMessages(session);
             } catch (Exception e) {
                 e.printStackTrace();

Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/InImapUserPreferencesStorage.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/InImapUserPreferencesStorage.java?rev=908000&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/InImapUserPreferencesStorage.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/InImapUserPreferencesStorage.java Tue Feb  9 11:00:47 2010
@@ -0,0 +1,273 @@
+package org.apache.hupa.server.preferences;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import com.sun.mail.imap.IMAPFolder;
+import com.sun.mail.imap.IMAPStore;
+
+import gwtupload.server.UploadServlet;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.server.utils.MessageUtils;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.rpc.ContactsResult.Contact;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import javax.mail.BodyPart;
+import javax.mail.Folder;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Multipart;
+import javax.mail.Session;
+import javax.mail.Flags.Flag;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+import javax.servlet.http.HttpSession;
+
+/**
+ * A user preferences storage which uses IMAP as repository data
+ * 
+ * @author manolo
+ */
+public class InImapUserPreferencesStorage extends UserPreferencesStorage {
+
+    // User preferences are saved in IMAP but there is a delay between a new
+    // contact is added an the save action. It saves number of operations in
+    // the IMAP server.
+    // It's not final in order to override in tests to make them run faster
+    protected static int IMAP_SAVE_DELAY = 10000;
+    
+    protected static final String MAGIC_SUBJECT_CONTACTS = "Hupa-Contacts";
+    
+    private static final String HUPA_DATA_MIME_TYPE = "application/hupa-data";
+
+    // TODO: centralize this constant
+    protected static final String USER_ATTR = "user";
+    
+    private static Hashtable<User, Thread> threads = new Hashtable<User, Thread>();
+    
+    /**
+     * Opens the IMAP folder and read messages until it founds the magic subject,
+     * then gets the attachment which contains the data and return the serialized object stored. 
+     */
+    protected static Object readUserPreferencesFromIMAP(Log logger, User user, IMAPStore iStore, String folderName, String magicType) 
+              throws MessagingException, IOException, ClassNotFoundException {
+        Folder folder = iStore.getFolder(folderName);
+        if (folder.exists()) {
+            if (!folder.isOpen()) {
+                folder.open(Folder.READ_WRITE);
+            }
+            Message message = null;
+            Message[] msgs = folder.getMessages();
+            for (Message msg : msgs) {
+                if (magicType.equals(msg.getSubject())) {
+                    message = msg;
+                    break;
+                }
+            }
+            if (message != null) {
+                Object con = message.getContent();
+                if (con instanceof Multipart) {
+                    Multipart mp = (Multipart) con;
+                    for(int i=0; i<mp.getCount(); i++) {
+                        BodyPart part = mp.getBodyPart(i);
+                        if (part.getContentType().toLowerCase().startsWith(HUPA_DATA_MIME_TYPE)) {
+                            ObjectInputStream ois = new ObjectInputStream(part.getInputStream());
+                            Object o = ois.readObject();
+                            ois.close();
+                            logger.info("Returning user preferences of type " + magicType + " from imap folder + " + folderName + " for user " + user);
+                            return o;
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * Opens the IMAP folder, deletes all messages which match the magic subject and
+     * creates a new message with an attachment which contains the object serialized
+     */
+    protected static void saveUserPreferencesInIMAP(Log logger, User user, Session session, IMAPStore iStore, String folderName, String subject, Object object) 
+              throws MessagingException, IOException, InterruptedException {
+        IMAPFolder folder = (IMAPFolder) iStore.getFolder(folderName);
+
+        if (folder.exists() || folder.create(IMAPFolder.HOLDS_MESSAGES)) {
+            if (!folder.isOpen()) {
+                folder.open(Folder.READ_WRITE);
+            }
+
+            // Serialize the object
+            ByteArrayOutputStream fout = new ByteArrayOutputStream();
+            ObjectOutputStream oos = new ObjectOutputStream(fout);
+            oos.writeObject(object);
+            oos.close();
+            ByteArrayInputStream is = new ByteArrayInputStream(fout.toByteArray());
+
+            // Create a new message with an attachment which has the serialized object
+            MimeMessage message = new MimeMessage(session);
+            message.setSubject(subject);
+            
+            Multipart multipart = new MimeMultipart();
+            MimeBodyPart txtPart = new MimeBodyPart();
+            txtPart.setContent("This message contains configuration used by Hupa, do not delete it", "text/plain");
+            multipart.addBodyPart(txtPart);
+            FileItem item = createPreferencesFileItem(is, subject, HUPA_DATA_MIME_TYPE);
+            multipart.addBodyPart(MessageUtils.fileitemToBodypart(item));
+            message.setContent(multipart);
+            message.saveChanges();
+
+            // It seems it's not possible to modify the content of an existing message using the API
+            // So I delete the previous message storing the preferences and I create a new one
+            Message[] msgs = folder.getMessages();
+            for (Message msg : msgs) {
+                if (subject.equals(msg.getSubject())) {
+                    msg.setFlag(Flag.DELETED, true);
+                    folder.expunge(new Message[] { msg });
+                }
+            }
+            
+            // It is necessary to copy the message before saving it (the same problem in AbstractSendMessageHandler)
+            message = new MimeMessage((MimeMessage)message);
+            message.setFlag(Flag.SEEN, true);
+            folder.appendMessages(new Message[] { message });
+            folder.close(true);
+            logger.info("Saved preferences " + subject + " in imap folder " + folderName + " for user " + user);
+        } else {
+            logger.error("Unable to save preferences " + subject + " in imap folder " + folderName + " for user " + user);
+        }
+    }
+    
+    /**
+     * Right now, using the same approach present in upload attachments to create the attachment
+     */
+    private static FileItem createPreferencesFileItem(InputStream is, String filename, String contentType) throws IOException {
+        FileItemFactory f = new DiskFileItemFactory();
+        FileItem item = f.createItem(filename, contentType, false, filename);
+        UploadServlet.copyFromInputStreamToOutputStream(is, item.getOutputStream());
+        return item;
+    }
+    
+    private Log logger;
+    
+    private Session session = Session.getDefaultInstance(new Properties());
+
+    private final IMAPStoreCache cache;
+
+    private final Provider<HttpSession> sessionProvider;
+ 
+    /**
+     * Constructor
+     */
+    @Inject
+    public InImapUserPreferencesStorage(IMAPStoreCache cache, Log logger, Provider<HttpSession> sessionProvider) {
+        this.sessionProvider = sessionProvider;
+        this.cache = cache;
+        this.logger = logger;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.hupa.server.preferences.UserPreferencesStorage#addContact(org.apache.hupa.shared.rpc.ContactsResult.Contact[])
+     */
+    @Override
+    public void addContact(Contact... contacts) {
+        HashMap<String, Contact> contactsHash = getContactsHash();
+
+        for (Contact contact : contacts) {
+            if (!contactsHash.containsKey(contact.toKey())) {
+                contactsHash.put(contact.toKey(), contact);
+                saveContactsAsync((User) sessionProvider.get().getAttribute(USER_ATTR));
+            }
+        }
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.hupa.server.preferences.UserPreferencesStorage#getContacts()
+     */
+    @Override
+    public Contact[] getContacts() {
+        HashMap<String, Contact> sessionContacts = getContactsHash();
+        return sessionContacts.values().toArray(new Contact[sessionContacts.size()]);
+    }
+
+    /**
+     * Returns the Hash of contacts getting it from the session if available, or from
+     * the IMAP repository if it is the first time.
+     */
+    @SuppressWarnings("unchecked")
+    private HashMap<String, Contact> getContactsHash() {
+        HttpSession session = sessionProvider.get();
+        HashMap<String, Contact> contactHash = (HashMap<String, Contact>) session.getAttribute(CONTACTS_ATTR);
+        if (contactHash == null) {
+            try {
+                User user = (User) sessionProvider.get().getAttribute("user");
+                IMAPStore iStore = cache.get(user);
+                Object o = readUserPreferencesFromIMAP(logger, user, iStore, user.getSettings().getDraftsFolderName(), MAGIC_SUBJECT_CONTACTS);
+                contactHash = o != null ? (HashMap<String, Contact>) o : new HashMap<String, Contact>();
+                session.setAttribute(CONTACTS_ATTR, contactHash);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return contactHash;
+    }
+
+    /**
+     * Saves the contacts list in IMAP asynchronously, It is so because of two reasons:
+     * 1.- User processes don't wait for it
+     * 2.- It saves number of save operations, because the method addContact
+     *  is called frequently when fetching a folder, so add these contacts are
+     *  added to the session list, and a thread is delayed to store
+     *  all the block. 
+     */
+    private void saveContactsAsync(User user) {
+        Thread thread = threads.get(user);
+        if (thread == null || !thread.isAlive()) {
+            thread = new SavePreferencesThread(user, MAGIC_SUBJECT_CONTACTS, getContactsHash());
+            threads.put(user, thread);
+            thread.start();
+        }
+    }
+
+    /**
+     * The thread class which saves asynchronously the user preferences 
+     */
+    private class SavePreferencesThread extends Thread {
+        private String folderName = null;
+        private Object object = null;
+        private String subject = null;
+        private User user = null;
+        
+        public SavePreferencesThread(User user, String subject, Object object) {
+            this.user = user;
+            this.folderName = user.getSettings().getDraftsFolderName();
+            this.subject = subject;
+            this.object = object;
+        }
+        
+        public void run(){
+            try {
+                sleep(IMAP_SAVE_DELAY);
+                saveUserPreferencesInIMAP(logger, user, session, cache.get(user), folderName, subject, object);
+            } catch (Exception e) {
+                logger.error("Error saving user's preferences: ", e);
+            }
+        }
+    }
+}

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/InSessionUserPreferencesStorage.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/InSessionUserPreferencesStorage.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/InSessionUserPreferencesStorage.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/InSessionUserPreferencesStorage.java Tue Feb  9 11:00:47 2010
@@ -14,7 +14,7 @@
 /**
  * A preferences storage which uses session as repository data
  */
-public class InSessionUserPreferencesStorage implements UserPreferencesStorage {
+public class InSessionUserPreferencesStorage extends UserPreferencesStorage {
 
     private final Provider<HttpSession> sessionProvider;
     
@@ -23,34 +23,29 @@
         this.sessionProvider = sessionProvider;
     }
 
-    public void addContact(Contact contact) {
-        
+    public void addContact(Contact... contacts) {
         HttpSession session = sessionProvider.get();
-        
+
         @SuppressWarnings("unchecked")
-        HashMap<String, Contact> sessionContacts = (HashMap<String, Contact>)session.getAttribute("contacts");
-        if (sessionContacts==null)
+        HashMap<String, Contact> sessionContacts = (HashMap<String, Contact>)session.getAttribute(CONTACTS_ATTR);
+        if (sessionContacts==null) {
             sessionContacts=new HashMap<String, Contact>();
+            session.setAttribute(CONTACTS_ATTR, sessionContacts);
+        }
         
-        if (!sessionContacts.containsKey(contact.toKey())) {
-            sessionContacts.put(contact.toKey(), contact);
-            session.setAttribute("contacts", sessionContacts);
+        for(Contact contact: contacts) {
+            if (!sessionContacts.containsKey(contact.toKey())) {
+                sessionContacts.put(contact.toKey(), contact);
+            }
         }
     }
 
-    public void addContact(String mail) {
-        Contact contact = new Contact(mail);
-        addContact(contact);
-    }
-
     public Contact[] getContacts() {
-        
         HttpSession session = sessionProvider.get();
         
         @SuppressWarnings("unchecked")
-        HashMap<String, Contact> sessionContacts = (HashMap<String, Contact>)session.getAttribute("contacts");
+        HashMap<String, Contact> sessionContacts = (HashMap<String, Contact>)session.getAttribute(CONTACTS_ATTR);
 
         return sessionContacts == null ? new Contact[]{} : sessionContacts.values().toArray(new Contact[sessionContacts.size()]);
     }
-    
 }

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/UserPreferencesStorage.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/UserPreferencesStorage.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/UserPreferencesStorage.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/preferences/UserPreferencesStorage.java Tue Feb  9 11:00:47 2010
@@ -2,29 +2,51 @@
 
 import org.apache.hupa.shared.rpc.ContactsResult.Contact;
 
+import java.util.Arrays;
+import java.util.List;
+
 /**
  *
- * Interface which defines storage operations related 
+ * Abstract class which defines storage operations related 
  * with user preferences
  *
  */
-public interface UserPreferencesStorage {
+public abstract class UserPreferencesStorage {
     
+    protected static final String CONTACTS_ATTR = "contacts";
+        
     /**
      * Add a new contact to the list.
      * The implementation has to check for duplicates 
      */
-    public void addContact(Contact c);
+    abstract public void addContact(Contact... c);
     
     /**
      * Add a new contact to the list.
      * The implementation has to check for duplicates 
      */
-    public void addContact(String s);
+    final public void addContact(String... mails) {
+        if (mails != null) {
+            addContact(Arrays.asList(mails));
+        }
+    }
+
+    /**
+     * Add a new contact to the list.
+     * The implementation has to check for duplicates 
+     */
+    final public void addContact(List<String> mails) {
+        if (mails != null) {
+            for (String mail: mails) {
+                Contact contact = new Contact(mail);
+                addContact(contact);
+            }
+        }
+    }
     
     /**
      * Get the list of contacts 
      */
-    public Contact[] getContacts();
+    abstract public Contact[] getContacts();
 
 }

Modified: james/hupa/trunk/server/src/main/webapp/WEB-INF/conf/config.properties
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/webapp/WEB-INF/conf/config.properties?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/webapp/WEB-INF/conf/config.properties (original)
+++ james/hupa/trunk/server/src/main/webapp/WEB-INF/conf/config.properties Tue Feb  9 11:00:47 2010
@@ -5,21 +5,22 @@
 # Set the connections amount which will get maximal opened per user for processing requests
 # Setting it higher can improve performance, but be sure that the IMAPServer will maybe have some limit
 IMAPConnectionPoolSize=4
-# Set the timout for connections in milliseconds
+# Set the timeout for connections in milliseconds
 IMAPConnectionPoolTimeout=300000
 # Use SSL/TLS to connect to the IMAP server
 IMAPS=true
 
-# For gmail change this to [GMail]\Sent
-DefaultSentFolder=Sent
-# For gmail change this to [GMail]\Trash
-DefaultTrashFolder=Trash
-
+DefaultSentFolder=[Gmail]\Sent
+DefaultTrashFolder=[Gmail]\Trash
+DefaultDraftsFolder=[Gmail]\Drafts
 DefaultInboxFolder=INBOX
 
 # Number of Messages to post fetch
 PostFetchMessageCount=0
 
+# Log IMAP and SMTP dialog, Logger has to be in debug mode
+SessionDebug=true
+
 # The IP or domainname of the SMTP server
 SMTPServerAddress=smtp.gmail.com
 # The port of the SMTP server

Modified: james/hupa/trunk/server/src/test/java/org/apache/hupa/server/DemoModeTest.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/test/java/org/apache/hupa/server/DemoModeTest.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/test/java/org/apache/hupa/server/DemoModeTest.java (original)
+++ james/hupa/trunk/server/src/test/java/org/apache/hupa/server/DemoModeTest.java Tue Feb  9 11:00:47 2010
@@ -27,7 +27,7 @@
 
     private LoginUser demoUser = new LoginUser("demo", "demo");
     
-    private InMemoryIMAPStoreCache memoryStore = new InMemoryIMAPStoreCache(logger, DemoModeConstants.DEMO_MODE, 143, false, 1, 300000, provider);
+    private InMemoryIMAPStoreCache memoryStore = new InMemoryIMAPStoreCache(logger, DemoModeConstants.DEMO_MODE, 143, false, 1, 300000, false, provider);
     
     private LoginUserHandler loginUserHandler = new LoginUserHandler(memoryStore, logger, httpSessionProvider, settingsProvider);
     
@@ -54,7 +54,7 @@
         try {
             loginUserHandler.execute(demoUser, null);
             FetchFoldersResult result = fetchFoldersHandler.execute(new FetchFolders(), null);
-            assertEquals("In demo mode should be 3 folders predefined", 3, result.getFolders().size());
+            assertEquals("In demo mode should be 4 folders predefined", 4, result.getFolders().size());
         } catch (ActionException e) {
             e.printStackTrace();
             fail("Shouldn't throw an exception");
@@ -67,7 +67,7 @@
     }
     
     public void testLoadMessageFiles() throws Exception {
-        MockIMAPStore store = new MockIMAPStore(session);
+        MockIMAPStore store = new MockIMAPStore(session, null);
         MockIMAPFolder folder = new MockIMAPFolder("WHATEVER", store);
         folder.create(Folder.HOLDS_MESSAGES);
         folder.loadDemoMessages(session);

Added: james/hupa/trunk/server/src/test/java/org/apache/hupa/server/HupaGuiceTestCase.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/test/java/org/apache/hupa/server/HupaGuiceTestCase.java?rev=908000&view=auto
==============================================================================
--- james/hupa/trunk/server/src/test/java/org/apache/hupa/server/HupaGuiceTestCase.java (added)
+++ james/hupa/trunk/server/src/test/java/org/apache/hupa/server/HupaGuiceTestCase.java Tue Feb  9 11:00:47 2010
@@ -0,0 +1,101 @@
+/****************************************************************
+ * 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.hupa.server;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+
+import com.sun.mail.imap.IMAPStore;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.guice.GuiceTestModule;
+import org.apache.hupa.server.handler.AbstractSendMessageHandler;
+import org.apache.hupa.server.handler.ContactsHandler;
+import org.apache.hupa.server.handler.CreateFolderHandler;
+import org.apache.hupa.server.handler.DeleteFolderHandler;
+import org.apache.hupa.server.handler.FetchFoldersHandler;
+import org.apache.hupa.server.handler.FetchMessagesHandler;
+import org.apache.hupa.server.handler.ForwardMessageHandler;
+import org.apache.hupa.server.handler.GetMessageDetailsHandler;
+import org.apache.hupa.server.handler.LoginUserHandler;
+import org.apache.hupa.server.handler.ReplyMessageHandler;
+import org.apache.hupa.server.handler.SendMessageHandler;
+import org.apache.hupa.server.preferences.UserPreferencesStorage;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.rpc.SendMessage;
+
+import javax.mail.Session;
+import javax.servlet.http.HttpSession;
+
+public abstract class HupaGuiceTestCase extends TestCase {
+
+    protected Injector injector = Guice.createInjector(getModule());
+
+    protected HttpSession httpSession = injector.getInstance(HttpSession.class);
+    
+    protected AbstractSendMessageHandler<SendMessage> abstSendMsgHndl = injector.getInstance(SendMessageHandler.class);
+    
+    protected ContactsHandler contactsHandler = injector.getInstance(ContactsHandler.class);
+
+    protected CreateFolderHandler createFHandler = injector.getInstance(CreateFolderHandler.class);
+    
+    protected DeleteFolderHandler deleteFHandler = injector.getInstance(DeleteFolderHandler.class);
+    
+    protected FetchFoldersHandler fetchFHandler = injector.getInstance(FetchFoldersHandler.class);
+    
+    protected FetchMessagesHandler fetchMessagesHandler = injector.getInstance(FetchMessagesHandler.class);
+    
+    protected ForwardMessageHandler fwdMsgHndl = injector.getInstance(ForwardMessageHandler.class);
+    
+    protected GetMessageDetailsHandler getDetailsMsgHndl = injector.getInstance(GetMessageDetailsHandler.class);
+    
+    protected Log logger = injector.getInstance(Log.class);
+    
+    protected LoginUserHandler loginUser = injector.getInstance(LoginUserHandler.class);
+    
+    protected ReplyMessageHandler reMsgHndl = injector.getInstance(ReplyMessageHandler.class);
+    
+    protected Session session = injector.getInstance(Session.class);
+    
+    protected IMAPStoreCache storeCache = injector.getInstance(IMAPStoreCache.class);
+    
+    protected  User testUser;
+    
+    protected UserPreferencesStorage userPreferences = injector.getInstance(UserPreferencesStorage.class);
+    
+    protected IMAPStore store;
+    
+    public HupaGuiceTestCase() {
+        try {
+            testUser = injector.getInstance(User.class);
+            store = storeCache.get(testUser);
+            httpSession.setAttribute("user", testUser);
+        } catch (Exception e) {
+        }
+    }
+    
+    protected Module getModule() {
+        return new GuiceTestModule();
+    }
+}

Modified: james/hupa/trunk/server/src/test/java/org/apache/hupa/server/HupaTestCase.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/test/java/org/apache/hupa/server/HupaTestCase.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/test/java/org/apache/hupa/server/HupaTestCase.java (original)
+++ james/hupa/trunk/server/src/test/java/org/apache/hupa/server/HupaTestCase.java Tue Feb  9 11:00:47 2010
@@ -20,7 +20,8 @@
 
 package org.apache.hupa.server;
 
-import javax.mail.Session;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
 
 import junit.framework.TestCase;
 
@@ -34,12 +35,11 @@
 import org.apache.hupa.server.preferences.UserPreferencesStorage;
 import org.apache.hupa.shared.rpc.SendMessage;
 
-import com.google.inject.Injector;
+import javax.mail.Session;
 
 public abstract class HupaTestCase extends TestCase{
 
-    protected GuiceTestModule module = new GuiceTestModule();
-    protected Injector injector = module.getInjector();
+    protected Injector injector = Guice.createInjector(new GuiceTestModule());
     
     protected Session session = injector.getInstance(Session.class);
     protected Log logger = injector.getInstance(Log.class);

Modified: james/hupa/trunk/server/src/test/java/org/apache/hupa/server/guice/GuiceTestModule.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/test/java/org/apache/hupa/server/guice/GuiceTestModule.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/test/java/org/apache/hupa/server/guice/GuiceTestModule.java (original)
+++ james/hupa/trunk/server/src/test/java/org/apache/hupa/server/guice/GuiceTestModule.java Tue Feb  9 11:00:47 2010
@@ -20,68 +20,186 @@
 package org.apache.hupa.server.guice;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.Guice;
-import com.google.inject.Injector;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
 import com.google.inject.Singleton;
+import com.google.inject.name.Named;
 import com.google.inject.name.Names;
 
 import com.sun.mail.imap.IMAPStore;
 
 import org.apache.commons.logging.Log;
 import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.server.InMemoryIMAPStoreCache;
 import org.apache.hupa.server.handler.AbstractSendMessageHandler;
 import org.apache.hupa.server.handler.ContactsHandler;
+import org.apache.hupa.server.handler.CreateFolderHandler;
+import org.apache.hupa.server.handler.DeleteFolderHandler;
 import org.apache.hupa.server.handler.FetchFoldersHandler;
 import org.apache.hupa.server.handler.FetchMessagesHandler;
 import org.apache.hupa.server.handler.ForwardMessageHandler;
 import org.apache.hupa.server.handler.GetMessageDetailsHandler;
+import org.apache.hupa.server.handler.LoginUserHandler;
 import org.apache.hupa.server.handler.ReplyMessageHandler;
 import org.apache.hupa.server.handler.SendMessageHandler;
 import org.apache.hupa.server.mock.MockHttpSession;
 import org.apache.hupa.server.mock.MockIMAPStore;
-import org.apache.hupa.server.mock.MockIMAPStoreCache;
 import org.apache.hupa.server.mock.MockLogProvider;
 import org.apache.hupa.server.preferences.InSessionUserPreferencesStorage;
 import org.apache.hupa.server.preferences.UserPreferencesStorage;
+import org.apache.hupa.shared.data.Settings;
+import org.apache.hupa.shared.data.User;
+
+import java.util.Properties;
 
 import javax.mail.Session;
 import javax.servlet.http.HttpSession;
 
+/**
+ * Guice module used in tests.
+ * 
+ * Extend this class with your own, and redefine protected attributes 
+ * if you need to change any of the class implementations in your test.
+ * 
+ * @author manolo
+ *
+ */
 public class GuiceTestModule extends AbstractModule {
+        
+    protected Class<? extends Provider<Session>> sessionClass = SessionProvider.class;
+    protected Class<? extends HttpSession> httpSessionClass = MockHttpSession.class;
+    protected Class<? extends Provider<Log>> logClass = MockLogProvider.class;
+    protected Class<? extends IMAPStore> imapStoreClass = MockIMAPStore.class; 
+    protected Class<? extends IMAPStoreCache> imapStoreCacheClass = InMemoryIMAPStoreCache.class; 
+    protected Class<? extends Provider<Settings>> settingsProviderClass = DefaultUserSettingsProvider.class;
+    protected Class<? extends UserPreferencesStorage> userPreferencesClass = InSessionUserPreferencesStorage.class;
+    protected Properties properties = DemoModeConstants.demoProperties;
 
     @Override
     protected void configure() {
+        Names.bindProperties(binder(), properties);
+        
+        bind(Session.class).toProvider(sessionClass);
+        bind(HttpSession.class).to(httpSessionClass).in(Singleton.class);
+        bind(Settings.class).toProvider(settingsProviderClass).in(Singleton.class);
+        bind(Log.class).toProvider(logClass).in(Singleton.class);
 
-        DemoModeConstants.demoProperties.put("DefaultUserSessionId", "just_an_id");
-        Names.bindProperties(binder(), DemoModeConstants.demoProperties);
-
-        bind(Log.class).toProvider(MockLogProvider.class).in(Singleton.class);
-        bind(Session.class).toProvider(SessionProvider.class);
-        bind(HttpSession.class).to(MockHttpSession.class).in(Singleton.class);
-
-        bind(IMAPStoreCache.class).to(MockIMAPStoreCache.class).in(Singleton.class);
-        bind(IMAPStore.class).to(MockIMAPStore.class);
+        bind(IMAPStore.class).to(imapStoreClass);
+        bind(IMAPStoreCache.class).to(imapStoreCacheClass).in(Singleton.class);
 
+        bind(LoginUserHandler.class);
+        bind(FetchFoldersHandler.class);
+        bind(CreateFolderHandler.class);
+        bind(DeleteFolderHandler.class);
+        bind(FetchMessagesHandler.class);
         bind(GetMessageDetailsHandler.class);
-        
         bind(AbstractSendMessageHandler.class).to(SendMessageHandler.class);
         bind(SendMessageHandler.class);
         bind(ReplyMessageHandler.class);
         bind(ForwardMessageHandler.class);
-        bind(FetchFoldersHandler.class);
-        bind(FetchMessagesHandler.class);
         bind(ContactsHandler.class);
         
-        bind(UserPreferencesStorage.class).to(InSessionUserPreferencesStorage.class);
-
+        bind(UserPreferencesStorage.class).to(userPreferencesClass);
+        
+        bind(User.class).to(TestUser.class).in(Singleton.class);
+        
     }
 
-    private Injector injector;
-    public Injector getInjector() {
-        if (injector == null)
-            injector = Guice.createInjector(this);
-        return injector;
+    static class TestUser extends User {
+        private static final long serialVersionUID = 1L;
+        @Inject
+        public TestUser(@Named("Username") String username, 
+                        @Named("Password") String password, 
+                        @Named("DefaultInboxFolder") final String inbox, 
+                        @Named("DefaultSentFolder") final String sent,
+                        @Named("DefaultTrashFolder") final String trash, 
+                        @Named("DefaultDraftsFolder") final String draft) {
+            setName(username);
+            setPassword(password);
+            setSettings(new Settings() {
+                private static final long serialVersionUID = 1L;
+                {
+                    setInboxFolderName(inbox);
+                    setSentFolderName(sent);
+                    setTrashFolderName(trash);
+                    setDraftsFolderName(draft);
+                }
+            });
+        }
     }
-
-
+    
+    
+    
+    /**
+     * Configuration of an IMAP server.
+     * Customize it for your integration tests.
+     */
+    public static final Properties courierProperties = new Properties() {
+        private static final long serialVersionUID = 1L;
+        {
+            /// SET THIS 
+            put("Username","user");
+            put("Password","password");
+            ///
+            
+            put("IMAPServerAddress", "localhost");
+            put("IMAPServerPort", "143");
+            put("IMAPS", "fase");
+            
+            put("IMAPConnectionPoolSize", "4");
+            put("IMAPConnectionPoolTimeout", "300000");
+            
+            put("DefaultInboxFolder", "INBOX");
+            put("DefaultTrashFolder", "INBOX.Trash");
+            put("DefaultSentFolder", "INBOX.Sent");
+            put("DefaultDraftsFolder", "INBOX.Drafts");
+            
+            put("PostFetchMessageCount", "0");
+
+            put("SMTPServerAddress", "mail.hotelsearch.com");
+            put("SMTPServerPort", "25");
+            put("SMTPS", "false");
+            put("SMTPAuth", "true");
+            
+            put("SessionDebug", "false");
+            
+            put("DefaultUserSessionId", "just_an_id");
+        }
+    };
+    
+    /**
+     * Configuration of GMail IMAP server.
+     */
+    public static final Properties gmailProperties = new Properties() {
+        private static final long serialVersionUID = 1L;
+        {
+            ///// Use a valid gmail account 
+            put("Username","doodootis@gmail.com");
+            put("Password","******");
+            /////
+            
+            put("IMAPServerAddress", "imap.gmail.com");
+            put("IMAPServerPort", "993");
+            put("IMAPS", "true");
+            
+            put("IMAPConnectionPoolSize", "4");
+            put("IMAPConnectionPoolTimeout", "300000");
+            
+            put("DefaultInboxFolder", "INBOX");
+            put("DefaultTrashFolder", "[Gmail]/Trash");
+            put("DefaultSentFolder", "[Gmail]/Sent Mail");
+            put("DefaultDraftsFolder", "[Gmail]/Drafts");
+            
+            put("PostFetchMessageCount", "0");
+
+            put("SMTPServerAddress", "smtp.gmail.com");
+            put("SMTPServerPort", "465");
+            put("SMTPS", "true");
+            put("SMTPAuth", "true");
+            
+            put("SessionDebug", "false");
+            
+            put("DefaultUserSessionId", "just_an_id");
+        }
+    };
 }

Modified: james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/AbstractHandlerTest.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/AbstractHandlerTest.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/AbstractHandlerTest.java (original)
+++ james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/AbstractHandlerTest.java Tue Feb  9 11:00:47 2010
@@ -27,7 +27,6 @@
 import org.apache.commons.logging.Log;
 import org.apache.hupa.server.guice.DemoModeConstants;
 import org.apache.hupa.server.mock.MockHttpSession;
-import org.apache.hupa.server.mock.MockIMAPStore;
 import org.apache.hupa.server.mock.MockIMAPStoreCache;
 import org.apache.hupa.server.mock.MockLog;
 import org.apache.hupa.server.preferences.UserPreferencesStorage;
@@ -69,19 +68,10 @@
         }
     };
     
-    protected MockIMAPStoreCache storeCache = new MockIMAPStoreCache( new Provider<Session>() {
-        public Session get() {
-            Session session = Session.getDefaultInstance(new Properties());
-            session.addProvider(MockIMAPStore.getProvider());
-            return session;
-        }
-    });
+    protected MockIMAPStoreCache storeCache = new MockIMAPStoreCache(user);
     
     protected UserPreferencesStorage preferences = new UserPreferencesStorage(){
-        public void addContact(Contact c) {
-        }
-
-        public void addContact(String s) {
+        public void addContact(Contact... c) {
         }
 
         public Contact[] getContacts() {

Modified: james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/AbtractSendMessageHandlerTest.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/AbtractSendMessageHandlerTest.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/AbtractSendMessageHandlerTest.java (original)
+++ james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/AbtractSendMessageHandlerTest.java Tue Feb  9 11:00:47 2010
@@ -20,15 +20,12 @@
 package org.apache.hupa.server.handler;
 
 
-import javax.mail.Message;
-import javax.mail.Part;
-import javax.servlet.http.HttpSession;
+import com.sun.mail.imap.IMAPStore;
 
 import org.apache.hupa.server.HupaTestCase;
 import org.apache.hupa.server.IMAPStoreCache;
 import org.apache.hupa.server.guice.DemoModeConstants;
 import org.apache.hupa.server.mock.MockIMAPFolder;
-import org.apache.hupa.server.mock.MockIMAPStoreCache;
 import org.apache.hupa.server.utils.MessageUtils;
 import org.apache.hupa.server.utils.SessionUtils;
 import org.apache.hupa.server.utils.TestUtils;
@@ -36,7 +33,9 @@
 import org.apache.hupa.shared.data.User;
 import org.apache.hupa.shared.rpc.SendMessage;
 
-import com.sun.mail.imap.IMAPStore;
+import javax.mail.Message;
+import javax.mail.Part;
+import javax.servlet.http.HttpSession;
 
 public class AbtractSendMessageHandlerTest extends HupaTestCase {
 
@@ -108,8 +107,7 @@
         httpSession.setAttribute("user", demouser);
 
         IMAPStoreCache storeCache = injector.getInstance(IMAPStoreCache.class);
-        IMAPStore store = injector.getInstance(IMAPStore.class);
-        ((MockIMAPStoreCache)storeCache).addValidUser(demouser, store);
+        IMAPStore store = storeCache.get(demouser);
         
         MockIMAPFolder sentbox = (MockIMAPFolder) store.getFolder(DemoModeConstants.DEMO_MODE_SENT_FOLDER);
         
@@ -147,8 +145,8 @@
         HttpSession httpSession = injector.getInstance(HttpSession.class);
         httpSession.setAttribute("user", demouser);
 
-        IMAPStore store = injector.getInstance(IMAPStore.class);
-        ((MockIMAPStoreCache)storeCache).addValidUser(demouser, store);
+        IMAPStoreCache storeCache = injector.getInstance(IMAPStoreCache.class);
+        IMAPStore store = storeCache.get(demouser);
         
         MockIMAPFolder sentbox = (MockIMAPFolder) store.getFolder(DemoModeConstants.DEMO_MODE_SENT_FOLDER);
         

Modified: james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/ContactsHandlerTest.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/ContactsHandlerTest.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/ContactsHandlerTest.java (original)
+++ james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/ContactsHandlerTest.java Tue Feb  9 11:00:47 2010
@@ -3,12 +3,20 @@
 import junit.framework.Assert;
 
 import org.apache.hupa.server.HupaTestCase;
+import org.apache.hupa.server.guice.DemoModeConstants;
+import org.apache.hupa.shared.data.User;
 import org.apache.hupa.shared.rpc.Contacts;
 
+import javax.servlet.http.HttpSession;
+
 
 public class ContactsHandlerTest extends HupaTestCase {
     
     public void testContactsHandler() throws Exception {
+        User demouser = DemoModeConstants.demoUser;
+        HttpSession httpSession = injector.getInstance(HttpSession.class);
+        httpSession.setAttribute("user", demouser);
+        
         Assert.assertEquals(0, contactsHandler.execute(new Contacts(), null).getContacts().length);
         userPreferences.addContact("Somebody <so...@foo.com>");
         userPreferences.addContact(" Some.body   <so...@foo.com>  ");

Modified: james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/FowardMessageHandlerTest.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/FowardMessageHandlerTest.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/FowardMessageHandlerTest.java (original)
+++ james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/FowardMessageHandlerTest.java Tue Feb  9 11:00:47 2010
@@ -19,22 +19,21 @@
 
 package org.apache.hupa.server.handler;
 
-import javax.mail.Message;
-import javax.servlet.http.HttpSession;
+import com.sun.mail.imap.IMAPStore;
 
 import org.apache.hupa.server.FileItemRegistry;
 import org.apache.hupa.server.HupaTestCase;
 import org.apache.hupa.server.IMAPStoreCache;
 import org.apache.hupa.server.guice.DemoModeConstants;
 import org.apache.hupa.server.mock.MockIMAPFolder;
-import org.apache.hupa.server.mock.MockIMAPStoreCache;
 import org.apache.hupa.server.utils.TestUtils;
 import org.apache.hupa.shared.data.IMAPFolder;
 import org.apache.hupa.shared.data.SMTPMessage;
 import org.apache.hupa.shared.data.User;
 import org.apache.hupa.shared.rpc.ForwardMessage;
 
-import com.sun.mail.imap.IMAPStore;
+import javax.mail.Message;
+import javax.servlet.http.HttpSession;
 
 public class FowardMessageHandlerTest extends HupaTestCase {
 
@@ -46,8 +45,7 @@
         httpSession.setAttribute("user", demouser);
 
         IMAPStoreCache storeCache = injector.getInstance(IMAPStoreCache.class);
-        IMAPStore store = injector.getInstance(IMAPStore.class);
-        ((MockIMAPStoreCache)storeCache).addValidUser(demouser, store);
+        IMAPStore store = storeCache.get(demouser);
         
         FileItemRegistry registry = injector.getInstance(FileItemRegistry.class);
         

Modified: james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/GetMessageDetailsHandlerTest.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/GetMessageDetailsHandlerTest.java?rev=908000&r1=907999&r2=908000&view=diff
==============================================================================
--- james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/GetMessageDetailsHandlerTest.java (original)
+++ james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/GetMessageDetailsHandlerTest.java Tue Feb  9 11:00:47 2010
@@ -19,21 +19,20 @@
 
 package org.apache.hupa.server.handler;
 
-import javax.mail.Folder;
-import javax.mail.Message;
-import javax.mail.internet.MimeMessage;
+import com.sun.mail.imap.IMAPFolder;
+import com.sun.mail.imap.IMAPStore;
 
 import org.apache.hupa.server.HupaTestCase;
 import org.apache.hupa.server.IMAPStoreCache;
 import org.apache.hupa.server.guice.DemoModeConstants;
-import org.apache.hupa.server.mock.MockIMAPStoreCache;
 import org.apache.hupa.server.utils.TestUtils;
 import org.apache.hupa.shared.SConsts;
 import org.apache.hupa.shared.data.MessageDetails;
 import org.apache.hupa.shared.data.User;
 
-import com.sun.mail.imap.IMAPFolder;
-import com.sun.mail.imap.IMAPStore;
+import javax.mail.Folder;
+import javax.mail.Message;
+import javax.mail.internet.MimeMessage;
 
 public class GetMessageDetailsHandlerTest extends HupaTestCase {
     
@@ -168,11 +167,10 @@
     
     public void testMessageDetails_html_with_inline_images() throws Exception {
 
-        IMAPStoreCache storeCache = injector.getInstance(IMAPStoreCache.class);
-        IMAPStore store = injector.getInstance(IMAPStore.class);
-
         User demouser = DemoModeConstants.demoUser;
-        ((MockIMAPStoreCache)storeCache).addValidUser(demouser, store);
+        
+        IMAPStoreCache storeCache = injector.getInstance(IMAPStoreCache.class);
+        IMAPStore store = storeCache.get(demouser);
         
         IMAPFolder serverfolder = (IMAPFolder)store.getFolder("WHATEVER"); 
         serverfolder.create(Folder.HOLDS_MESSAGES);

Added: james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/HandlersTest.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/HandlersTest.java?rev=908000&view=auto
==============================================================================
--- james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/HandlersTest.java (added)
+++ james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/HandlersTest.java Tue Feb  9 11:00:47 2010
@@ -0,0 +1,81 @@
+package org.apache.hupa.server.handler;
+
+import com.google.inject.Module;
+
+import com.sun.mail.imap.IMAPStore;
+
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.hupa.server.HupaGuiceTestCase;
+import org.apache.hupa.server.guice.GuiceTestModule;
+import org.apache.hupa.shared.data.IMAPFolder;
+import org.apache.hupa.shared.rpc.CreateFolder;
+import org.apache.hupa.shared.rpc.DeleteFolder;
+import org.apache.hupa.shared.rpc.FetchFolders;
+import org.apache.hupa.shared.rpc.FetchFoldersResult;
+
+import javax.mail.Folder;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+
+public class HandlersTest extends HupaGuiceTestCase {
+    
+    @Override
+    protected Module getModule() {
+        // These tests should work with Courier, Gmail and any other real IMAP implementations
+        // If you want to run these tests against your IMAP server do this:
+        //    1.- Change properties and classes to do integration tests and
+        //    2.- Be sure the user and password are set correctly
+        class MyModule extends GuiceTestModule {
+            public MyModule() {
+                // properties = courierProperties;
+                // properties = gmailProperties;
+                // logClass = LogProvider.class;
+            }
+        }
+        return new MyModule();
+    }
+
+    public void testLoginAndFetchFolders() {
+        try {
+            org.apache.hupa.shared.rpc.LoginUser l = new org.apache.hupa.shared.rpc.LoginUser(testUser.getName(),testUser.getPassword());
+            loginUser.execute(l, null);
+            FetchFoldersResult result = fetchFHandler.execute(new FetchFolders(), null);
+            assertNotNull(result);
+        } catch (ActionException e) {
+            e.printStackTrace();
+            fail("Shouldn't throw an exception");
+        }
+    }
+    
+    public void testCreateAndDeleteFolder() throws MessagingException {
+        IMAPStore store = storeCache.get(testUser);
+        
+        String folderName = testUser.getSettings().getInboxFolderName() + store.getDefaultFolder().getSeparator() + "newFolder";
+        IMAPFolder sFolder = new IMAPFolder();
+        sFolder.setFullName(folderName);
+        
+        Folder f1 = store.getFolder(sFolder.getFullName());
+        assertFalse("not exists", f1.exists());
+        
+        try {
+            createFHandler.execute(new CreateFolder(sFolder), null);
+            Folder f = store.getFolder(sFolder.getFullName());
+            assertTrue("exists", f.exists());
+            assertFalse("Not opened", f.isOpen());
+            f.open(Folder.READ_WRITE);
+            assertTrue("opened", f.isOpen());
+            
+            Message[] msgs = f.getMessages();
+            assertEquals(0, msgs.length);
+            
+            deleteFHandler.execute(new DeleteFolder(sFolder), null);
+            f = store.getFolder(sFolder.getFullName());
+            assertFalse("not exists",f.exists());
+
+        } catch (ActionException e) {
+            e.printStackTrace();
+            fail("Shouldn't throw an exception ");
+        }
+    }
+}



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