org.apache.hupa.server.InMemoryIMAPStoreCache.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hupa.server.InMemoryIMAPStoreCache.java

Source

/****************************************************************
 * 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 java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;

import org.apache.commons.logging.Log;
import org.apache.hupa.shared.domain.Settings;
import org.apache.hupa.shared.domain.User;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import com.sun.mail.iap.ProtocolException;
import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.imap.IMAPFolder.ProtocolCommand;
import com.sun.mail.imap.IMAPStore;
import com.sun.mail.imap.protocol.IMAPProtocol;
import com.sun.mail.imap.protocol.ListInfo;

@Singleton
public class InMemoryIMAPStoreCache implements IMAPStoreCache {

    private final Map<String, CachedIMAPStore> pool = new HashMap<String, CachedIMAPStore>();

    private Log logger;
    private int connectionPoolSize;
    private int timeout;
    private boolean debug;
    private boolean trustSSL;

    @Inject
    public InMemoryIMAPStoreCache(Log logger, @Named("IMAPConnectionPoolSize") int connectionPoolSize,
            @Named("IMAPConnectionPoolTimeout") int timeout, @Named("SessionDebug") boolean debug,
            @Named("TrustStore") String truststore, @Named("TrustStorePassword") String truststorePassword,
            @Named("TrustSSL") boolean trustSSL) {
        this.logger = logger;
        this.connectionPoolSize = connectionPoolSize;
        this.timeout = timeout;
        this.debug = debug;
        this.trustSSL = trustSSL;
        if (!truststore.isEmpty()) {
            System.setProperty("javax.net.ssl.trustStore", truststore);
        }
        if (!truststorePassword.isEmpty()) {
            System.setProperty("javax.net.ssl.trustStorePassword", truststorePassword);
        }
        System.setProperty("mail.mime.decodetext.strict", "false");
    }

    /*
     * (non-Javadoc)
     * @see org.apache.hupa.server.IMAPStoreCache#get(org.apache.hupa.shared.data.User)
     */
    public IMAPStore get(User user) throws MessagingException {
        // FIXME, there will be a NullPointerException thrown here when user session expired

        String id = user.getId();
        String username = user.getName();
        String password = user.getPassword();
        Settings settings = user.getSettings();

        CachedIMAPStore cstore = pool.get(username);
        if (cstore == null) {
            logger.debug("No cached store found for user " + username);
        } else {
            if (cstore.isExpired() == false) {
                try {
                    cstore.validate();
                } catch (MessagingException e) {
                }
            } else {
                pool.remove(username);
                try {
                    cstore.getStore().close();
                    cstore = null;
                } catch (MessagingException e) {
                }
            }
        }

        if (cstore == null) {
            cstore = createCachedIMAPStore(user);
        }

        if (cstore.getStore().isConnected() == false) {
            cstore.getStore().connect(settings.getImapServer(), settings.getImapPort(), id, password);
        }

        pool.put(username, cstore);
        IMAPStore ret = cstore.getStore();

        // TODO: this is a hack for gmail
        if (settings.getImapServer().contains("gmail.com")) {
            internationalizeGmailFolders(user, ret);
        }

        return ret;
    }

    public void internationalizeGmailFolders(User user, IMAPStore store) {
        // TODO: this is a hack, we should have a default domain suffix in configuration files
        if (!user.getName().contains("@")) {
            user.setName(user.getName() + "@gmail.com");
        }
        try {
            final IMAPFolder folder = (IMAPFolder) store.getDefaultFolder();
            final char c = folder.getSeparator();

            ListInfo[] li = (ListInfo[]) folder.doCommandIgnoreFailure(new ProtocolCommand() {
                public Object doCommand(IMAPProtocol p) throws ProtocolException {
                    String arg = folder.getFullName() + c + "*";
                    return p.lsub("", arg);
                }
            });

            for (ListInfo l : li) {
                if (l.attrs != null && l.attrs.length > 1) {
                    // * LIST (\HasNoChildren \Drafts) "/" "[Gmail]/Borradores"
                    String n = l.attrs[1];
                    if ("\\Drafts".equals(n)) {
                        user.getSettings().setDraftsFolderName(l.name);
                    } else if ("\\Sent".equals(n)) {
                        user.getSettings().setSentFolderName(l.name);
                    } else if ("\\Trash".equals(n)) {
                        user.getSettings().setTrashFolderName(l.name);
                    } else if ("\\Junk".equals(n)) {
                    }
                }
            }
        } catch (Exception e) {
        }
    }

    public CachedIMAPStore createCachedIMAPStore(User user) throws NoSuchProviderException {
        Session ses = createSession(user);
        IMAPStore store = (IMAPStore) ses.getStore(user.getSettings().getImapSecure() ? "imaps" : "imap");
        CachedIMAPStore ret = new CachedIMAPStore(store, 300);
        ret.setSession(ses);
        return ret;
    }

    /*
     * (non-Javadoc)
     * @see org.apache.hupa.server.IMAPStoreCache#delete(org.apache.hupa.shared.data.User)
     */
    public synchronized void delete(User user) {
        delete(user.getName());
    }

    /*
     * (non-Javadoc)
     * @see org.apache.hupa.server.IMAPStoreCache#delete(java.lang.String)
     */
    public synchronized void delete(String username) {
        CachedIMAPStore cstore = pool.get(username);
        if (cstore != null && cstore.getStore().isConnected()) {
            try {
                cstore.getStore().close();
            } catch (MessagingException e) {
                // Ignore on close
            }
        }
        pool.remove(username);
    }

    public void sendMessage(Message msg) throws MessagingException {
        Transport.send(msg);
    }

    public Session getMailSession(User user) {
        CachedIMAPStore cstore = pool.get(user.getName());
        return cstore.getSession();
    }

    private Session createSession(final User user) {
        Properties props = new Properties();
        Settings settings = user.getSettings();

        props.setProperty("mail.mime.decodetext.strict", "false");
        if (settings.getImapSecure()) {
            props.setProperty("mail.store.protocol", "imaps");
            props.setProperty("mail.imaps.connectionpoolsize", connectionPoolSize + "");
            props.setProperty("mail.imaps.connectionpooltimeout", timeout + "");
            if (trustSSL) {
                props.setProperty("mail.imaps.ssl.trust", settings.getImapServer());
            }
        } else {
            props.setProperty("mail.imap.connectionpoolsize", connectionPoolSize + "");
            props.setProperty("mail.imap.connectionpooltimeout", timeout + "");
        }

        if (settings.getSmtpSecure()) {
            if (settings.getSmtpPort() == 587) {
                props.setProperty("mail.smtp.starttls.enable", "true");
                props.setProperty("mail.transport.protocol.rfc822", "smtp");
            } else {
                props.setProperty("mail.transport.protocol.rfc822", "smtps");
                props.setProperty("mail.smtps.ssl.enable", "true");
                if (trustSSL) {
                    props.setProperty("mail.smtps.ssl.trust", settings.getSmtpServer());
                }
            }
        } else {
            props.setProperty("mail.transport.protocol.rfc822", "smtp");
        }

        props.setProperty("mail.smtp.host", settings.getSmtpServer());
        props.setProperty("mail.smtps.host", settings.getSmtpServer());
        props.setProperty("mail.smtp.port", settings.getSmtpPort() + "");
        props.setProperty("mail.smtps.port", settings.getSmtpPort() + "");

        Authenticator auth = null;
        if (settings.getSmtpAuth() && user.getPassword() != null && user.getName() != null) {
            props.setProperty("mail.smtp.auth", "true");
            props.setProperty("mail.smtps.auth", "true");
            auth = new javax.mail.Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    String userId = user.getId();
                    StackTraceElement[] sElms = Thread.currentThread().getStackTrace();
                    for (StackTraceElement e : sElms) {
                        if (e.getClassName().equals(InMemoryIMAPStoreCache.class.getName())
                                && e.getMethodName().equals("get")) {
                            // We try with the id part the second time (unix imap/smtp auth compatible)
                            if (userId.matches(".*@.*")) {
                                userId = userId.replaceFirst("@.*", "");
                                user.setId(userId);
                                break;
                            } else {
                                return null;
                            }
                        }
                    }
                    return new PasswordAuthentication(userId, user.getPassword());
                }
            };
        }

        Session ses = Session.getInstance(props, auth);
        ses.setDebug(debug && logger.isDebugEnabled());
        logger.debug("Created session " + user.getName() + "\n" + settings + "\n"
                + props.toString().replaceAll(",", ",\n "));
        return ses;
    }
}