immf.ServerMain.java Source code

Java tutorial

Introduction

Here is the source code for immf.ServerMain.java

Source

/*
 * imoten - i mode.net mail tensou(forward)
 *
 * Copyright (C) 2010 shoozhoo (http://code.google.com/p/imoten/)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 */

package immf;

import immf.google.contact.GoogleContactsAccessor;
import immf.growl.GrowlNotifier;
import immf.growl.concrete.NMAClient;
import immf.growl.concrete.ProwlClient;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.cookie.Cookie;

public class ServerMain {
    public static final String Version = "imoten (imode.net mail tenson) ver. 1.1.37";
    private static final Log log = LogFactory.getLog(ServerMain.class);

    private ImodeNetClient client;
    private SendMailPicker spicker;
    private Config conf;
    private StatusManager status;
    private SkypeForwarder skypeForwarder;
    private ImKayacNotifier imKayacNotifier;
    private AppNotifications appNotifications;
    private GrowlNotifier prowlNotifier;
    private GrowlNotifier nmaNotifier;
    private int numForwardSite;
    private Map<Config, ForwardMailPicker> forwarders = new HashMap<Config, ForwardMailPicker>();
    private Map<Config, List<String>> ignoreDomainsMap = new HashMap<Config, List<String>>();

    public ServerMain(File conffile) {
        System.out.println("StartUp [" + Version + "]");
        log.info("StartUp [" + Version + "]");
        this.setShutdownHook();
        this.verCheck();
        try {
            log.info("Load Config file " + conffile.getAbsolutePath());
            FileInputStream is = new FileInputStream(conffile);
            this.conf = new Config(is);
            this.numForwardSite = conf.countForwardSite();
            if (numForwardSite > 1) {
                log.info("??????:" + numForwardSite);
            }

        } catch (Exception e) {
            log.fatal("Config Error. ??????", e);
            e.printStackTrace();
            System.exit(1);
        }

        // cookie?????ID
        File stFile = new File(conf.getStatusFile());
        log.info("Load Status file " + stFile.getAbsolutePath());
        this.status = new StatusManager(stFile);
        try {
            this.status.load();
        } catch (Exception e) {
            // ???
            log.info("Status File load error. " + e.getMessage());
            log.info("Status?????");
        }
        log.info("Loaded LastMailID=" + this.status.getLastMailId());

        this.client = new ImodeNetClient(this.conf.getDocomoId(), conf.getDocomoPasswd());
        this.client.setConnTimeout(this.conf.getHttpConnectTimeoutSec() * 1000);
        this.client.setSoTimeout(this.conf.getHttpSoTimeoutSec() * 1000);
        this.client.setMailAddrCharset(this.conf.getMailEncode());
        this.client.setCsvAddressBook(this.conf.getCsvAddressFile());
        //GoogleContactsAccesor??
        GoogleContactsAccessor.initialize(this.conf.getGmailId(), this.conf.getGmailPasswd());
        this.client.setVcAddressBook(this.conf.getVcAddressFile());

        CharacterConverter subjectCharConv = new CharacterConverter();
        for (String file : conf.getForwardSubjectCharConvertFile()) {
            try {
                subjectCharConv.load(new File(file));
            } catch (Exception e) {
                log.error("?(" + file + ")????????", e);
            }
        }
        ImodeForwardMail.setSubjectCharConv(subjectCharConv);

        if (conf.isForwardAddGoomojiSubject()) {
            CharacterConverter goomojiSubjectCharConv = new CharacterConverter();
            if (conf.getForwardGoogleCharConvertFile() != null) {
                try {
                    goomojiSubjectCharConv.load(new File(conf.getForwardGoogleCharConvertFile()));
                } catch (Exception e) {
                    log.error("?(" + conf.getForwardGoogleCharConvertFile()
                            + ")????????", e);
                }
            }
            ImodeForwardMail.setGoomojiSubjectCharConv(goomojiSubjectCharConv);
        }

        StringConverter strConv = new StringConverter();
        if (conf.getForwardStringConvertFile() != null) {
            try {
                strConv.load(new File(conf.getForwardStringConvertFile()));
            } catch (Exception e) {
                log.error("?(" + conf.getForwardStringConvertFile()
                        + ")????????", e);
            }
        }
        ImodeForwardMail.setStrConv(strConv);

        // ???
        this.loadIgnoreDomainList(this.conf, 1);

        try {
            // ??cookie
            if (this.conf.isSaveCookie()) {
                log.info("Load cookie");
                for (Cookie cookie : this.status.getCookies()) {
                    this.client.addCookie(cookie);
                }
            }
        } catch (Exception e) {
        }

        // ?
        spicker = new SendMailPicker(conf, this, this.client, this.status);
        new SendMailBridge(conf, this.client, this.spicker, this.status);

        // ?
        Config forwardConf = this.conf;
        ForwardMailPicker fpicker = new ForwardMailPicker(forwardConf, this);
        forwarders.put(forwardConf, fpicker);

        for (int i = 2; i <= numForwardSite; i++) {
            try {
                log.info("Load Config file[" + i + "] " + conffile.getAbsolutePath());
                FileInputStream is = new FileInputStream(conffile);
                is = new FileInputStream(conffile);
                forwardConf = new Config(is, i);
                fpicker = new ForwardMailPicker(forwardConf, this);
                forwarders.put(forwardConf, fpicker);

                // ???
                this.loadIgnoreDomainList(forwardConf, i);

            } catch (Exception e) {
                log.fatal("Config Error. ??????", e);
                e.printStackTrace();
                System.exit(1);
            }
        }

        // skype
        this.skypeForwarder = new SkypeForwarder(conf.getForwardSkypeChat(), conf.getForwardSkypeSms(), conf);

        // im.kayac.com
        this.imKayacNotifier = new ImKayacNotifier(this.conf);

        // appnotifications
        this.appNotifications = new AppNotifications(this.conf, this.status);

        // Growl APIs
        // for Prowl
        this.prowlNotifier = GrowlNotifier.getInstance(ProwlClient.getInstance(), this.conf);

        // for Notify My Android
        this.nmaNotifier = GrowlNotifier.getInstance(NMAClient.getInstance(), this.conf);

        Date lastUpdate = null;
        while (true) {
            if (lastUpdate != null) {
                // ????
                try {
                    this.status.load();
                } catch (Exception e) {
                }
                long diff = System.currentTimeMillis() - lastUpdate.getTime();
                if (diff < conf.getForceCheckIntervalSec() * 1000 && !this.status.needConnect()) {
                    //????????????
                    try {
                        Thread.sleep(conf.getCheckFileIntervalSec() * 1000);
                    } catch (Exception e) {
                    }
                    continue;
                }
            }

            Map<Integer, List<String>> mailIdListMap = null;
            try {
                // ID?(?)
                mailIdListMap = this.client.getMailIdList();
                this.client.checkAddressBook();

            } catch (LoginException e) {
                log.error("", e);
                if (lastUpdate == null) {
                    // ?cookie??????????
                    log.info("?5?????");
                    try {
                        Thread.sleep(1000 * 5);
                    } catch (Exception ex) {
                    }
                    lastUpdate = new Date();
                    continue;
                }
                try {
                    // ????
                    log.info("Wait " + this.conf.getLoginRetryIntervalSec() + " sec.");
                    Thread.sleep(this.conf.getLoginRetryIntervalSec() * 1000);
                } catch (Exception ex) {
                }
                continue;
            } catch (Exception e) {
                log.error("Get Mail ID List error.", e);
                try {
                    Thread.sleep(this.conf.getLoginRetryIntervalSec() * 1000);
                } catch (Exception ex) {
                }
                continue;
            }

            String newestId = "0"; // ?lastId?
            Iterator<Integer> folderIdIte = mailIdListMap.keySet().iterator();
            while (folderIdIte.hasNext()) {
                // ????
                Integer fid = folderIdIte.next();
                List<String> mailIdList = mailIdListMap.get(fid);

                folderProc(fid, mailIdList);

                if (!mailIdList.isEmpty()) {
                    String newestInFolder = mailIdList.get(0);
                    if (newestId.compareToIgnoreCase(newestInFolder) < 0) {
                        newestId = newestInFolder;
                    }
                }
            }

            // ?
            this.status.resetNeedConnect();

            // status.ini ?
            if (StringUtils.isBlank(this.status.getLastMailId())) {
                this.status.setLastMailId(newestId);
                log.info("LastMailId???????????");
            }
            String lastId = this.status.getLastMailId();
            if (lastId != null && !lastId.equals(newestId)) {
                this.status.setLastMailId(newestId);
                log.info("LastMailId(" + newestId + ")?????");
            }
            try {
                if (this.conf.isSaveCookie()) {
                    this.status.setCookies(client.getCookies());
                }
                this.status.save();
                log.info("status?????");
            } catch (Exception e) {
                log.error("Status File save Error.", e);
            }
            lastUpdate = new Date();

            // ?????
            try {
                Thread.sleep(conf.getCheckIntervalSec() * 1000);
            } catch (Exception e) {
            }
        }

    }

    private void folderProc(Integer fid, List<String> mailIdList) {
        String lastId = this.status.getLastMailId();
        log.info("FolderID " + fid + "  ?ID?:" + mailIdList.size() + "  lastId:" + lastId);

        String newestId = "";

        if (StringUtils.isBlank(lastId)) {
            if (!mailIdList.isEmpty()) {
                // ???????????
                if (newestId.compareToIgnoreCase(mailIdList.get(0)) < 0) {
                    return;
                }
            } else {
                // ???????
                return;
            }
        } else {
            List<String> forwardIdList = new LinkedList<String>();
            for (String id : mailIdList) {
                if (lastId.compareToIgnoreCase(id) < 0) {
                    // ?????
                    forwardIdList.add(0, id);
                }
            }
            log.info("??ID? " + forwardIdList.size());
            appNotifications.pushPrepare(fid, forwardIdList.size());
            for (String id : forwardIdList) {
                this.forward(fid, id);
            }
        }
    }

    private void verCheck() {
        String verndor = System.getProperty("java.vendor");
        String version = System.getProperty("java.version");
        log.info("Java vendor  " + verndor);
        log.info("Java version " + version);
        log.info("defaultCharset " + Charset.defaultCharset());
        try {
            String[] v = version.split("\\.");
            if (Integer.parseInt(v[0]) >= 2 || Integer.parseInt(v[1]) >= 6) {
                return;
            } else {
                log.warn("? ??Java ver 1.6 ??????");
            }
        } catch (Exception e) {
            log.warn(e.getMessage());
        }
    }

    /*
     * ???
     */
    private void forward(int folderId, String mailId) {
        if (folderId == ImodeNetClient.FolderIdSent && numForwardSite == 1 && !this.conf.isForwardSent()) {
            // ??????
            return;
        }
        ImodeMail mail = null;
        try {
            // download
            mail = this.client.getMail(folderId, mailId);
            if (log.isInfoEnabled()) {
                log.info("Downloaded Mail ########");
                log.info(mail.toLoggingString());
                log.info("########################");
            }
        } catch (Exception e) {
            log.warn("i mode.net mailId[" + mailId + "] download Error.", e);
            return;
        }

        String from = mail.getFromAddr().getAddress();
        List<String> ignoreDomains = new ArrayList<String>();
        try {
            // ?
            for (Map.Entry<Config, ForwardMailPicker> f : forwarders.entrySet()) {
                Config forwardConf = f.getKey();
                int id = forwardConf.getConfigId();

                if (folderId == ImodeNetClient.FolderIdSent && !forwardConf.isForwardSent()) {
                    // ??????
                    continue;
                }

                //  ???????
                boolean notForward = false;
                ignoreDomains = ignoreDomainsMap.get(forwardConf);
                for (String domain : ignoreDomains) {
                    if (from.endsWith(domain)) {
                        log.info("?:" + from + " ??[" + id + "]");
                        notForward = true;
                    }
                }
                if (notForward) {
                    continue;
                }

                ForwardMailPicker fpicker = f.getValue();
                if (forwardConf.isForwardAsync()) {
                    // (ForwardMailPicker)?????
                    fpicker.add(mail);
                } else {
                    ImodeForwardMail forwardMail = new ImodeForwardMail(mail, forwardConf);
                    forwardMail.send();
                    if (numForwardSite > 1) {
                        log.info("??[" + id + "]");
                    }
                }
            }

        } catch (Exception e) {
            log.error("mail[" + mailId + "] forward Error.", e);
            return;
        }

        //  ????Push???
        ignoreDomains = ignoreDomainsMap.get(this.conf);
        for (String domain : ignoreDomains) {
            if (from.endsWith(domain)) {
                this.appNotifications.pushError(folderId);
                return;
            }
        }

        try {
            this.skypeForwarder.forward(mail);
        } catch (Exception e) {
            log.error("mail[" + mailId + "] skype forward Error.", e);
            return;
        }

        try {
            this.imKayacNotifier.forward(mail);
        } catch (Exception e) {
            log.error("mail[" + mailId + "] im.kayac forward Error.", e);
            return;
        }

        try {
            this.prowlNotifier.forward(mail);
        } catch (Exception e) {
            log.error("mail[" + mailId + "] Prowl forward Error.", e);
            return;
        }

        try {
            this.nmaNotifier.forward(mail);
        } catch (Exception e) {
            log.error("mail[" + mailId + "] NMA forward Error.", e);
            return;
        }

        try {
            this.appNotifications.push(folderId, mail);
        } catch (Exception e) {
            this.appNotifications.pushError(folderId);
            log.error("mail[" + mailId + "] AppNotifications push Error.", e);
            return;
        }

        try {
            // ???????
            Thread.sleep(1000);
        } catch (Exception e) {
        }
    }

    /*
     * ???
     */
    public void notify(String message) {
        // XXX skypeForwarder?
        // XXX imKayacNotifier?
        this.appNotifications.push(message);
    }

    /*
     * ??
     */
    private void loadIgnoreDomainList(Config conf, int index) {
        List<String> ignoreDomains = new ArrayList<String>();
        String ignoreDomainTxt = conf.getIgnoreDomainFile();
        File ignoreDomainFile = new File(ignoreDomainTxt);
        if (!ignoreDomainFile.exists()) {
            log.info("# ?[" + index + "](" + ignoreDomainTxt
                    + ")????");
            this.ignoreDomainsMap.put(conf, ignoreDomains);
            return;
        }
        BufferedReader br = null;
        FileReader fr = null;
        try {
            fr = new FileReader(ignoreDomainFile);
            br = new BufferedReader(fr);
            //int id = 0;

            String line = null;
            while ((line = br.readLine()) != null) {
                //id++;
                try {
                    if (line.startsWith("#")) {
                        continue;
                    }
                    if (!line.contains(".")) {
                        continue;
                    }
                    ignoreDomains.add(line);

                } catch (Exception e) {
                    log.warn("loadIgnoreDomainList error.", e);
                }
            }
            br.close();
        } catch (Exception e) {
            log.warn("loadIgnoreDomainList " + ignoreDomainTxt + " error.", e);

        } finally {
            Util.safeclose(br);
            Util.safeclose(fr);
            String ignores = "";
            for (String domain : ignoreDomains) {
                ignores += domain + " ";
            }
            log.info("# ?[" + index + "]:" + ignores);
            this.ignoreDomainsMap.put(conf, ignoreDomains);
        }
    }

    /*
     * ??
     */
    private void setShutdownHook() {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                System.out.println("Shutdown [" + Version + "]");
                log.info("Shutdown [" + Version + "]");
            }
        });
        ;

    }

    public static void main(String[] args) {
        try {
            String confFile = Config.ConfFile;
            if (args.length > 0) {
                confFile = args[0];
            }
            new ServerMain(new File(confFile));
        } catch (Exception e) {
            e.printStackTrace();
            log.fatal("Startup Error.", e);
        }
    }
}