ru.retbansk.utils.scheduled.impl.ReadEmailAndConvertToXmlSpringImpl.java Source code

Java tutorial

Introduction

Here is the source code for ru.retbansk.utils.scheduled.impl.ReadEmailAndConvertToXmlSpringImpl.java

Source

/*
 * Copyright 2012 the original author.
 *
 * 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 ru.retbansk.utils.scheduled.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;

import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.TimeZone;

import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import ru.retbansk.mail.domain.DayReport;
import ru.retbansk.mail.domain.Reply;

import ru.retbansk.mail.domain.TaskReport;
import ru.retbansk.utils.marshaller.Jaxb2Marshaller;
import ru.retbansk.utils.marshaller.Marshaller;

import ru.retbansk.utils.scheduled.ReadEmailAndConvertToXml;
import ru.retbansk.utils.scheduled.ReplyManager;

/**
 * 
 * @author Siarhei Yanusheuski
 * @since 25.10.2012
 */
public class ReadEmailAndConvertToXmlSpringImpl implements ReadEmailAndConvertToXml {
    protected static Logger logger = Logger.getLogger("service");
    private String path;
    private ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    private Marshaller marshaller = (Jaxb2Marshaller) context.getBean("marshaller");
    private List<Reply> replyList = new ArrayList<Reply>();

    /** Simple loading properties from email.properties file.
     * <p> At first, program will try to read external properties.
     * If nothing there - internal
     * <p> Implements user exit
     * 
     * @return email.properties from folder with jar, if nothing there - from classpath
     * @throws Exception
     */
    public Properties loadProperties() throws Exception {
        Properties prop = new Properties();
        InputStream inputStream = null;
        // At first, program will try to read external properties
        try {
            inputStream = new FileInputStream("email.properties");
            prop.load(inputStream);
        } catch (FileNotFoundException e) {
        }
        // If nothing there - internal
        if (inputStream == null)
            inputStream = prop.getClass().getResourceAsStream("/email.properties");

        prop.load(inputStream);
        if (inputStream != null)
            inputStream.close();
        // Implementing user exit
        try {
            if (prop.getProperty("continue").equals("no")) {
                logger.info("Program was stopped by the User");
                System.exit(0);
            }
        } catch (Exception e) {
            logger.info("Continue parameter is not defined");
        }
        return prop;
    }

    /**
     * Method execute actually does the entire job:
     * loads email properties, reads email, converts valid ones into xml files and send confirmation emails.
     * @see #readEmail()
     * @see #convertToXml(HashSet)
     * @see ru.retbansk.utils.scheduled.ReplyManager
     * 
     */
    @Override
    public void execute() throws Exception {
        convertToXml(readEmail());
        ReplyManager man = new ReplyManagerSimpleImpl();
        String info = replyList.size() > 0 ? "Sending confirmation emails" : "No reports detected";
        logger.info(info);
        for (Reply reply1 : replyList) {
            man.placeReply(reply1);
        }
        replyList.clear();

    }

    /**
     * Loads email properties, reads email messages, 
     * converts their multipart bodies into string,
     * send error emails if message doesn't contain valid report and at last returns a reversed Set of the Valid Reports
     * <p><b> deletes messages
     * @see #readEmail()
     * @see #convertToXml(HashSet)
     * @see ru.retbansk.utils.scheduled.ReplyManager
     * @return HashSet<DayReport> of the Valid Day Reports
     */
    @Override
    public HashSet<DayReport> readEmail() throws Exception {

        Properties prop = loadProperties();
        String host = prop.getProperty("host");
        String user = prop.getProperty("user");
        String password = prop.getProperty("password");
        path = prop.getProperty("path");

        // Get system properties
        Properties properties = System.getProperties();

        // Get the default Session object.
        Session session = Session.getDefaultInstance(properties);

        // Get a Store object that implements the specified protocol.
        Store store = session.getStore("pop3");

        // Connect to the current host using the specified username and
        // password.
        store.connect(host, user, password);

        // Create a Folder object corresponding to the given name.
        Folder folder = store.getFolder("inbox");

        // Open the Folder.
        folder.open(Folder.READ_WRITE);
        HashSet<DayReport> dayReportSet = new HashSet<DayReport>();
        try {

            // Getting messages from the folder
            Message[] message = folder.getMessages();
            // Reversing the order in the array with the use of Set to make the last one final
            Collections.reverse(Arrays.asList(message));

            // Reading messages.
            String body;
            for (int i = 0; i < message.length; i++) {
                DayReport dayReport = null;
                dayReport = new DayReport();
                dayReport.setPersonId(((InternetAddress) message[i].getFrom()[0]).getAddress());
                Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+3"));
                calendar.setTime(message[i].getSentDate());
                dayReport.setCalendar(calendar);
                dayReport.setSubject(message[i].getSubject());
                List<TaskReport> reportList = null;

                //Release the string from email message body
                body = "";
                Object content = message[i].getContent();
                if (content instanceof java.lang.String) {
                    body = (String) content;
                } else if (content instanceof Multipart) {
                    Multipart mp = (Multipart) content;

                    for (int j = 0; j < mp.getCount(); j++) {
                        Part part = mp.getBodyPart(j);

                        String disposition = part.getDisposition();

                        if (disposition == null) {
                            MimeBodyPart mbp = (MimeBodyPart) part;
                            if (mbp.isMimeType("text/plain")) {
                                body += (String) mbp.getContent();
                            }
                        } else if ((disposition != null)
                                && (disposition.equals(Part.ATTACHMENT) || disposition.equals(Part.INLINE))) {
                            MimeBodyPart mbp = (MimeBodyPart) part;
                            if (mbp.isMimeType("text/plain")) {
                                body += (String) mbp.getContent();
                            }
                        }
                    }
                }

                //Put the string (body of email message) and get list of valid reports else send error
                reportList = new ArrayList<TaskReport>();
                reportList = giveValidReports(body, message[i].getSentDate());
                //Check for valid day report. To be valid it should have size of reportList > 0.
                if (reportList.size() > 0) {
                    // adding valid ones to Set
                    dayReport.setReportList(reportList);
                    dayReportSet.add(dayReport);
                } else {
                    // This message doesn't have valid reports. Sending an error reply.
                    logger.info("Invalid Day Report detected. Sending an error reply");
                    ReplyManager man = new ReplyManagerSimpleImpl();
                    man.sendError(dayReport);
                }
                // Delete message
                message[i].setFlag(Flags.Flag.DELETED, true);
            }

        } finally {
            // true tells the mail server to expunge deleted messages.
            folder.close(true);
            store.close();
        }

        return dayReportSet;
    }

    /**
     * Converts a Set of the Valid Reports into xml and write into the files. 1 file per 1 DayReport
     * <p> Overwrites files with the same date from the same person
     * @param dayReportSet HashSet with the valid Day Reports only
     * @throws Exception
     */
    @Override
    public void convertToXml(HashSet<DayReport> dayReportSet) throws Exception {
        Properties prop = loadProperties();
        File dir;
        File file;
        String xml;

        // Writing file for every DayReport in Set
        for (DayReport dayReport : dayReportSet) {
            path = prop.getProperty("path");
            path += dayReport.getPersonId();
            dir = new File(path);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            String date = new SimpleDateFormat("dd.MM.YY").format(dayReport.getCalendar().getTime());
            file = new File(path + "/report.from." + date + ".xml");

            logger.info("Report created - " + path + "/report.from." + date + ".xml");

            xml = marshaller.marshal(dayReport, file);
            Reply reply = new Reply();
            reply.setXml(xml);
            reply.setEmailAddress(dayReport.getPersonId());
            reply.setValidNumber(dayReport.getReportList().size());
            reply.setSubject(dayReport.getSubject());
            replyList.add(reply);

        }
    }

    /**
     * Validation method. Patterns used:
     * <p>.+,.+,[\\d|\\s]{1,3}  
     * <p>.+[.].+[.][\\d|\\s]{1,3} 
     * <p>.+[/].+[/][\\d|\\s]{1,3}
     * @param body String released from email message body
     * @param reportDate Date from email message. All sub-reports will have the same Date as DayReport
     * @return Returns a List of valid sub-reports  
     */
    public List<TaskReport> giveValidReports(String body, Date reportDate) {
        List<TaskReport> reportList = new ArrayList<TaskReport>();
        TaskReport report;
        String lines[] = body.split("[\\r\\n]+");

        for (String string : lines) {
            if (string.matches(".+,.+,[\\d|\\s]{1,3}")) {
                String split[] = string.split(",");
                report = new TaskReport();
                report.setDate(reportDate);
                report.setWorkDescription(split[0].trim());
                report.setStatus(split[1].trim());
                report.setElapsedTime(Integer.valueOf(split[2].trim()).intValue());
                reportList.add(report);
            }
            if (string.matches(".+[.].+[.][\\d|\\s]{1,3}")) {
                String split[] = string.split("\\.");
                report = new TaskReport();
                report.setDate(reportDate);
                report.setWorkDescription(split[0].trim());
                report.setStatus(split[1].trim());
                report.setElapsedTime(Integer.valueOf(split[2].trim()).intValue());
                reportList.add(report);
            }
            if (string.matches(".+[/].+[/][\\d|\\s]{1,3}")) {
                String split[] = string.split("/");
                report = new TaskReport();
                report.setDate(reportDate);
                report.setWorkDescription(split[0].trim());
                report.setStatus(split[1].trim());
                report.setElapsedTime(Integer.valueOf(split[2].trim()).intValue());
                reportList.add(report);
            }
        }
        return reportList;
    }

}