org.opensextant.xtext.collectors.mailbox.MailConfig.java Source code

Java tutorial

Introduction

Here is the source code for org.opensextant.xtext.collectors.mailbox.MailConfig.java

Source

/**
 *
 * Copyright 2013-2014 OpenSextant.org
 *
 * Licensed 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.opensextant.xtext.collectors.mailbox;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.Properties;

import org.apache.commons.lang3.StringUtils;

import com.sun.mail.util.MailSSLSocketFactory;
import org.opensextant.ConfigException;

/**
 * See reference property file at src/test/resources/collectors/imap-templ.cfg
 * This IMAP template documents the various parameters for configuring a Java mail client to use IMAP or IMAP/SSL
 *
 * @author ubaldino
 * @author b. o'neill
 *
 */
public class MailConfig extends Properties {

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    public static int READ_ALL = -1;
    public static String DEFAULT_IMAP_PORT = "143";
    public static String DEFAULT_IMAPS_PORT = "993";

    private boolean debug = false;

    // These must be provides
    private String host = null;
    private String keyStore = null;
    private String storePass = null;
    private String trustStore = null;
    private String username = null;
    private String password = null;

    private String mailFolder = "Inbox";

    private int maxMessagesToRead = READ_ALL;
    private boolean readOnly = false;
    private boolean readNewMessagesOnly = false;
    private boolean deleteOld = true;
    private boolean deleteOnRead = true;
    private int exchangeServer = -1;

    private boolean isSSL = false;

    /**
     * Default mail client configuration that inherits System/OS properties
     */
    public MailConfig() {
        super(System.getProperties());
    }

    /**
     * Configure from a file or classpath. Mail client configuration that
     * inherits System/OS properties, then overrides defaults from parameters in
     * given confg file.
     *
     * @param propsFilePath path to property sheet
     * @throws IOException on err, likely SSL 
     * @throws ConfigException on err
     */
    public MailConfig(String propsFilePath) throws IOException, ConfigException {
        super(System.getProperties());

        InputStream fileInputStream = null;
        fileInputStream = new FileInputStream(propsFilePath);

        this.load(fileInputStream);
        fileInputStream.close();
        setProperties();
    }

    public MailConfig(URL cfgUrl) throws IOException, ConfigException {
        super(System.getProperties());
        if (cfgUrl == null) {
            throw new ConfigException("Mail Configuration not found");
        }

        InputStream io = cfgUrl.openStream();
        this.load(io);
        io.close();

        setProperties();
    }

    /**
     * Given this configuration, determine if the messages read so far (curr) is
     * at the total available
     *
     * or if config specified a max read count, then if curr > max read, return
     * true.
     *
     * @param total  total available.
     * @param curr  current incrementor.
     * @return true if client/session is done reading available msgs
     */
    public boolean doneReading(int total, int curr) {
        if (this.getMaxMessagesToRead() < 0) {
            return curr >= total;
        }

        return curr >= getMaxMessagesToRead();
    }

    /**
     * Set default properties, interpreting System props and any props loaded
     * from config file. Various flags are set as a result of interpreting the
     * key/value pairs.
     *
     * @throws ConfigException on err
     */
    public void setProperties() throws ConfigException {
        setProperties(null);
    }

    /**
     * Set properties from existing Property sheet.
     *
     * @param props javamail props
     * @throws ConfigException  SSL or other property error
     */
    public void setProperties(Properties props) throws ConfigException {

        if (props != null) {
            for (Object o : props.keySet()) {
                setProperty(o.toString(), props.getProperty((String) o));
            }
        }
        validateBasicSettings();
        setConfiguration();

        isSSL = getFlagProperty(getProperty("mail.imap.ssl.enable"));

        if (isSSL) {
            validateCertificates();
        }
        try {
            setAdvancedSettings();
        } catch (Exception securityErr) {
            throw new ConfigException("Advanced settings failed", securityErr);

        }
    }

    /**
     *
     * @throws ConfigException SSL-related problem, e.g., keystore does not exist.
     */
    private void validateCertificates() throws ConfigException {
        if (StringUtils.isBlank(getKeyStore())) {
            return;
        }
        if (!new File(getKeyStore()).exists()) {
            throw new ConfigException("Keystore set, but is invalid file: " + getKeyStore());
        }
        System.setProperty("javax.net.ssl.keyStore", getKeyStore());

        if (StringUtils.isNotBlank(getStorepass())) {
            System.setProperty("javax.net.ssl.keyStorePassword", getStorepass());
        } else {
            throw new ConfigException("Keystore set, but no store pass provided");
        }

        // Trust Store is relatively unused. No references to it in code.
        // But may be used under the hood in java-mail API
        //
        if (StringUtils.isNotBlank(getTrustStore())) {
            System.setProperty("javax.net.ssl.trustStore", getTrustStore());
        }
    }

    private void validateBasicSettings() throws ConfigException {
        String proto = getProperty("mail.protocol");
        if (!("imap".equalsIgnoreCase(proto) || "imaps".equalsIgnoreCase(proto))) {
            throw new ConfigException("IMAP is only mailbox protocol supported currently");
        }
    }

    public boolean isSSLEnabled() {
        return isSSL;
    }

    /**
     * Parameters supported:
     *
     * <pre>
     * ## Mail client behavior
     * mail.read.count=10
     * mail.read.readonly=true
     * mail.read.newonly=true
     * mail.read.delete_after=false
     * mail.delete.purge_old=false
     * mail.debug=true
     *
     * ## Connection
     * #####################
     * mail.host=SERVERSERVER
     * mail.user=USER
     * mail.password=XXXXXXXX
     * mail.folder=Inbox
     * mail.protocol=imap
     *
     * # SSL, Certificates
     * #####################
     * keystore
     * storepass
     * truststore
     *
     * # Protocol: IMAP
     * #####################
     * mail.imap.starttls.enable=true
     * mail.imap.socketFactory.fallback=false
     * mail.imap.socketFactory.port
     * mail.imap.ssl.enable=true
     * mail.imap.socketFactory.class=javax.net.SocketFactory
     * mail.imaps.class=com.sun.mail.IMAPSSLStore
     *
     * mail.microsoft.exchange.version=2007
     * mail.imap.auth.ntlm.domain=xxxxxDOMAINxxxxx
     *
     *
     * Java Mail params:
     *     mail.imap.auth.ntlm.domain
     *     mail.imap.starttls.enable
     *     mail.imap.socketFactory.fallback
     *     mail.imap.socketFactory.port
     *     mail.imap.ssl.enable
     *     mail.imap.socketFactory.class
     *
     * </pre>
     * @return if relevant javamail properties were set.
     */
    protected boolean setConfiguration() {
        boolean foundParameters = false;

        for (Object key : keySet()) {

            String keyName = key.toString();
            String value = getProperty(keyName);

            if ("mail.host".equals(keyName)) {
                foundParameters = true; // Required.
                this.host = value;
            } else if ("keystore".equals(keyName)) {
                this.keyStore = value;
            } else if ("storepass".equals(keyName)) {
                this.storePass = value;
            } else if ("truststore".equals(keyName)) {
                this.trustStore = value;
            } else if ("mail.user".equals(keyName)) {
                this.username = value;
            } else if ("mail.password".equals(keyName)) {
                this.password = value;
            } else if ("mail.folder".equals(keyName)) {
                this.mailFolder = value;
            } else if ("mail.read.count".equals(keyName)) {
                this.maxMessagesToRead = getIntegerProperty(value);
            } else if ("mail.read.readonly".equals(keyName)) {
                this.readOnly = getFlagProperty(value);
            } else if ("mail.read.newonly".equals(keyName)) {
                this.readNewMessagesOnly = getFlagProperty(value);
            } else if ("mail.delete.purge_old".equals(keyName)) {
                this.deleteOld = getFlagProperty(value);
            } else if ("mail.debug".equals(keyName)) {
                this.debug = getFlagProperty(value);
            } else if ("mail.read.delete_after".equals(keyName)) {
                this.deleteOld = getFlagProperty(value);
            } else if ("mail.microsoft.exchange.version".equals(keyName)) {
                exchangeServer = getIntegerProperty(value);
            }
        }

        return foundParameters;
    }

    /**
     * A conveneince wrapper around setting the SSL socket factory and other parameters.
     * @throws GeneralSecurityException  error related to mail/socket factory or other issue
     */
    public void setAdvancedSettings() throws GeneralSecurityException {

        if (this.isSSLEnabled()) {
            MailSSLSocketFactory socketFactory = new MailSSLSocketFactory();
            socketFactory.setTrustAllHosts(true);
            this.put("mail.imaps.ssl.socketFactory", socketFactory);
            // Default?
            // setProperty("mail.imap.socketFactory.class",
            // "javax.net.ssl.SSLSocketFactory");
        }
    }

    public String getDefaultPort(boolean useSSL) {
        return (useSSL ? DEFAULT_IMAPS_PORT : DEFAULT_IMAP_PORT);
    }

    /**
     * Return -1 if unknown or if it does not matter. 2003, 2007, 2010
     *
     * @return  int representing year/version of MS Exchange
     */
    public int getExchangeServerVersion() {
        return exchangeServer;
    }

    /**
     * Defaults to -1 if no value found
     *
     * @param val property
     * @return parsed int
     */
    protected static int getIntegerProperty(Object val) {
        if (val == null) {
            return -1;
        }
        return Integer.parseInt(val.toString());
    }

    /**
     * get a flag. DEFAULT: false
     *
     * @param val property value
     * @return parsed boolean
     */
    protected static boolean getFlagProperty(Object val) {
        if (val == null) {
            return false;
        }
        return Boolean.parseBoolean(val.toString());
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getKeyStore() {
        return keyStore;
    }

    public void setKeyStore(String keyStore) {
        this.keyStore = keyStore;
    }

    public String getStorepass() {
        return storePass;
    }

    public void setStorepass(String keyStoreKey) {
        this.storePass = keyStoreKey;
    }

    public String getTrustStore() {
        return trustStore;
    }

    public void setTrustStore(String trustStore) {
        this.trustStore = trustStore;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String userName) {
        this.username = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String userKey) {
        this.password = userKey;
    }

    public String getMailFolder() {
        return mailFolder;
    }

    public void setMailFolder(String mailFolder) {
        this.mailFolder = mailFolder;
    }

    public int getMaxMessagesToRead() {
        return maxMessagesToRead;
    }

    public void setMaxMessagesToRead(int maxMessagesToRead) {
        if (maxMessagesToRead <= READ_ALL) {
            this.maxMessagesToRead = READ_ALL;
        } else {
            this.maxMessagesToRead = maxMessagesToRead;
        }
    }

    public boolean isReadOnly() {
        return readOnly;
    }

    public void setReadOnly(boolean readOnly) {
        this.readOnly = readOnly;
    }

    public boolean isReadNewMessagesOnly() {
        return readNewMessagesOnly;
    }

    public void setReadNewMessagesOnly(boolean readNewMessagesOnly) {
        this.readNewMessagesOnly = readNewMessagesOnly;
    }

    public boolean isDeleteOld() {
        return deleteOld;
    }

    public void setDeleteOld(boolean deleteOld) {
        this.deleteOld = deleteOld;
    }

    public boolean isDebug() {
        return debug;
    }

    public void setDebug(boolean debug) {
        this.debug = debug;
    }

    public boolean isDeleteOnRead() {
        return deleteOnRead;
    }

    public void setDeleteOnRead(boolean deleteOnRead) {
        this.deleteOnRead = deleteOnRead;
    }

}