com.riq.MailHandlerServlet.java Source code

Java tutorial

Introduction

Here is the source code for com.riq.MailHandlerServlet.java

Source

/* Copyright 2010 John L. Reilly
    
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 com.riq;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONArray;
import org.json.JSONObject;

import com.riq.entity.Alert;
import com.riq.entity.Department;
import com.riq.entity.Location;
import com.riq.entity.Member;
import com.riq.entity.Tracking;

public class MailHandlerServlet extends HttpServlet {

    private static final Logger log = Logger.getLogger(MailHandlerServlet.class.getName());
    private static final long serialVersionUID = 1L;
    private boolean textIsHtml = false;
    private String responseType = "";

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp)

            throws IOException {

        log.info("Inside MailServlet doPost");

        // TODO get path information to determine target Department for this email

        PersistenceManager pm = PMF.get().getPersistenceManager();
        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);

        try {

            MimeMessage msg = new MimeMessage(session, req.getInputStream());
            Address sender = msg.getFrom()[0];
            Address replyTo = msg.getReplyTo()[0];

            //      DEBUG
            //       log.info("Message Class: " + msg.getClass());
            //       log.info("Message Stream: " + msg.getInputStream());
            //       log.info("Message RawStream: " + msg.getRawInputStream());
            //       log.info("Message Flags: " + msg.getFlags());
            //       log.info("Message Content: " + msg.getContent().toString());
            //       log.info("Message ContentID: " + msg.getContentID());
            //       log.info("Message ContentMD: " + msg.getContentMD5());
            //       log.info("Message ContentType: " + msg.getContentType());
            //       log.info("Message Description: " + msg.getDescription());
            //       log.info("Message Disposition: " + msg.getDisposition());
            //       log.info("Message Encoding: " + msg.getEncoding());
            //       log.info("Message Filename: " + msg.getFileName());
            //       log.info("Message Line Count: " + msg.getLineCount());
            //       log.info("Message ID: " + msg.getMessageID());
            //       log.info("Message Number: " + msg.getMessageNumber());
            //       log.info("Message Size: " + msg.getSize());
            //       log.info("Message Subject: " + msg.getSubject());
            //       log.info("Message RawInputStream: " + msg.getRawInputStream().toString());
            //       log.info("Message ReplyTo: " + replyTo);
            //       log.info("Message Sender: " + sender.toString());
            //       log.info("Request URL TO: " +  getServletContext());      

            String alertMsgString = getText(msg);

            alertMsgString = alertMsgString.replaceAll("Begin forwarded message:", "");
            alertMsgString = alertMsgString.replaceAll("Forwarded message", "");
            alertMsgString = alertMsgString.replaceAll("Dispatch@co.morris.nj.us", "");
            alertMsgString = alertMsgString.replaceAll("Date:", "");
            alertMsgString = alertMsgString.replaceAll(">", "");
            alertMsgString = alertMsgString.replaceAll("::", "-");
            alertMsgString = alertMsgString.replaceAll("< ", "");
            alertMsgString = alertMsgString.replaceAll("----------", "");
            alertMsgString = alertMsgString.replaceAll("Subject:", "");
            alertMsgString = alertMsgString.replaceAll("To:", "");
            alertMsgString = alertMsgString.replaceAll("From:", "");

            //  Added to grab gmail confirmations
            //  alertMsgString = alertMsgString.substring(50, 300);

            try {

                String queryDept = "select from " + Department.class.getName() +
                // TODO: johnreilly workaround for getting allRecipients... 
                // " where dispatchId == '" + toAddressDigitsOnly + "' " + 
                        " where dispatchId == '2599' " + " && fromEmail == '" + sender + "' ";
                log.info("queryDept: " + queryDept);
                List<Department> depts = (List<Department>) pm.newQuery(queryDept).execute();

                if (depts.size() != 0) {

                    for (Department d : depts) {

                        // need to filter further e.g. last two hours
                        String queryAlert = "select from " + Alert.class.getName() + " where deptId == "
                                + depts.get(0).getid() + " && messageId == '" + msg.getMessageID() + "' ";
                        log.info("queryAlert: " + queryAlert);
                        List<Alert> alerts = (List<Alert>) pm.newQuery(queryAlert).execute();
                        log.info("queryAlert Result Qty: " + alerts.size());

                        if (alerts.size() == 0) {

                            riqGeocode(alertMsgString);

                            // geocode the address from the Alert
                            Map<String, String> geoResults = riqGeocode(alertMsgString);
                            log.info("lat print: " + geoResults.get("lat"));
                            log.info("lng print: " + geoResults.get("lng"));

                            // create the alert
                            Long deptId = depts.get(0).getid();
                            Long timeStamp = System.currentTimeMillis();
                            Alert a = new Alert(deptId, timeStamp, alertMsgString.trim(), sender.toString(),
                                    "Active", "", geoResults.get("lat"), geoResults.get("lng"), msg.getMessageID());
                            pm.makePersistent(a);

                            // query to get id of this alert
                            String queryThisAlert = "select from " + Alert.class.getName() + " where deptId == "
                                    + deptId + " " + " && timeStamp == " + timeStamp;
                            log.info("queryThisAlert: " + queryThisAlert);
                            List<Alert> thisAlert = (List<Alert>) pm.newQuery(queryThisAlert).execute();
                            log.info("queryCurrentAlert Result Qty: " + thisAlert.size());

                            // create Tracking records for "special" Locations
                            String querySpecialLocs = "select from " + Location.class.getName()
                                    + " where special == 'yes' && deptId == " + deptId;
                            log.info("querySpecialLocs: " + querySpecialLocs);
                            List<Location> specialLocs = (List<Location>) pm.newQuery(querySpecialLocs).execute();
                            log.info("querySpecialLocs qty: " + specialLocs.size());

                            for (Location specL : specialLocs) {
                                Tracking tSL = new Tracking(deptId, thisAlert.get(0).getid(), specL.getid(),
                                        System.currentTimeMillis(), null, // TODO: johnreilly authorId tbd
                                        "location", specL.getid(), null, "autoAddLocation");
                                pm.makePersistent(tSL);
                            }

                            // search Dept for Location where distant Members presumed not to be responding are set
                            String queryFarawayLocs = "select from " + Location.class.getName()
                                    + " where vru == '2' && deptId == " + deptId;
                            log.info("querySpecialLocs: " + queryFarawayLocs);
                            List<Location> farawayLoc = (List<Location>) pm.newQuery(queryFarawayLocs).execute();
                            log.info("queryFarawayLocs qty: " + farawayLoc.size());

                            // create Tracking records for Members presumed not to be responder due to fresh ETA
                            String queryFarAwayResponders = "select from " + Member.class.getName()
                                    + " where distGroup == '4' ";
                            log.info("queryFarAwayResponders: " + queryFarAwayResponders);
                            List<Member> farawayMembers = (List<Member>) pm.newQuery(queryFarAwayResponders)
                                    .execute();
                            log.info("queryFarAwayResponders qty: " + farawayMembers.size());

                            if (farawayMembers.size() != 0) {
                                for (Member far : farawayMembers) {
                                    Tracking tMFAR = new Tracking(deptId, thisAlert.get(0).getid(),
                                            farawayLoc.get(0).getid(), System.currentTimeMillis(), null, // TODO: johnreilly authorId tbd
                                            "farawayAddMember", far.getid(), null, responseType);
                                    pm.makePersistent(tMFAR);
                                }
                            }

                            // TODO: testing restriction HACKER - remove at launch
                            // send alert email
                            String queryMember = "select from " + Member.class.getName() + " where deptId == "
                                    + deptId + " && type == 'Hacker' ";
                            List<Member> members = (List<Member>) pm.newQuery(queryMember).execute();

                            //TODO Geocode address to insure easy navigation
                            //TODO johnreilly: add street and town fields to Alert
                            msg.setFrom(
                                    new InternetAddress("admin@responderiq05.appspotmail.com", "FirstResponder"));
                            msg.setSubject("Alert!");
                            msg.setText(" Y=" + d.getinboundVRU1() + "&N=" + d.getinboundVRU2() +
                            // "&3=" + d.getinboundVRU3() +  
                                    "&A=" + thisAlert.get(0).getalertMsgString());

                            // send message to all dept members who permit tracking (and sending email alerts)
                            for (Member m : members) {
                                msg.addRecipient(Message.RecipientType.TO, new InternetAddress(m.getsmsAddress(),
                                        m.getfirstName() + "" + m.getlastName()));
                                log.info("Member: " + m.getsmsAddress() + "|" + m.getlastName());
                            }
                        }
                        // only process for one department - should only be one department
                        break;
                    }
                }
            } catch (MessagingException me) {
                log.info("Error: Messaging");
            } catch (IndexOutOfBoundsException mi) {
                log.info("Error: Out of Bounds");
            }

            // Do not send alert notification if email is a Google Confirmation
            //      if (! sender.toString().contains("mail-noreply@google.com")) {
            //        Transport.send(msg);
            //      }

        } catch (MessagingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

        } finally {
            pm.close();
        }

    }

    private Map<String, String> riqGeocode(String alertMsgString) {

        Map<String, String> latlngmap = new HashMap();

        String alertStreet = alertMsgString.substring(0, alertMsgString.indexOf("[")).trim();
        alertStreet = alertStreet.replaceAll(" ", "+");
        log.info("inside riqGeocode street: " + alertStreet);

        String alertTown = alertMsgString.substring(alertMsgString.indexOf("[") + 1, alertMsgString.indexOf("]"))
                .trim();
        alertTown = alertTown.replaceAll(" ", "+");
        log.info("inside riqGeocode town: " + alertTown);

        // TODO johnreilly: get from dept record
        String alertState = "NJ";

        // TODO johnreilly: added region bias once geocode is in Alert record
        String geocodeURL = "http://maps.googleapis.com/maps/api/geocode/json?address=" + alertStreet + ",+"
                + alertTown + ",+" + alertState + "&sensor=false";

        try {

            URL url;
            String lat = "";
            String lng = "";
            url = new URL(geocodeURL);
            BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
            StringBuilder tempString = new StringBuilder();
            String line;

            while ((line = reader.readLine()) != null) {
                tempString.append(line);
            }

            JSONObject obj = new JSONObject(tempString.toString());

            if ("ok".equalsIgnoreCase(obj.getString("status"))) {
                JSONArray results = obj.getJSONArray("results");
                if (results.length() > 0) {
                    JSONObject result = results.getJSONObject(0);
                    JSONObject location = result.getJSONObject("geometry").getJSONObject("location");
                    lat = String.valueOf(location.getDouble("lat"));
                    lng = String.valueOf(location.getDouble("lng"));
                    log.info("Lat: " + lat);
                    log.info("Lng: " + lng);

                    latlngmap.put("lat", lat);
                    latlngmap.put("lng", lng);
                }
            }

            //      latlngmap.put("street", alertStreet);
            //      latlngmap.put("town", alertTown);
            //      latlngmap.put("state", alertState);

        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        return (latlngmap);
    }

    private String getText(Part p) throws MessagingException, IOException {
        //    log.info("Message S Zero");
        //    log.info("Inside MailServlet getText");

        if (p.isMimeType("text/*")) {
            String s = (String) p.getContent();
            log.info("Message S1: " + s);
            boolean textIsHtml = p.isMimeType("text/html");
            return s;
        }

        if (p.isMimeType("multipart/alternative")) {
            Multipart mp = (Multipart) p.getContent();
            String text = null;
            for (int i = 0; i < mp.getCount(); i++) {
                Part bp = mp.getBodyPart(i);
                if (bp.isMimeType("text/plain")) {
                    if (text == null)
                        text = getText(bp);
                    log.info("Message S2: " + text);
                    continue;
                } else if (bp.isMimeType("text/html")) {
                    String s = getText(bp);
                    if (s != null)
                        log.info("Message S3: " + s);
                    return s;
                } else if (bp.isMimeType("message/rfc822")) {
                    Object nestedObject = "";
                    nestedObject = bp.getContent();
                    Multipart nestedPart = (Multipart) nestedObject;
                    BodyPart nestedBodyPart = nestedPart.getBodyPart(0);
                    String s = getText(nestedBodyPart);
                    if (s != null)
                        log.info("Message Nested: " + s);
                    return s;
                } else {
                    log.info("Message nada");
                    return getText(bp);
                }
            }
            return text;

        } else if (p.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) p.getContent();
            for (int i = 0; i < mp.getCount(); i++) {
                String s = getText(mp.getBodyPart(i));
                if (s != null) {
                    log.info("Message S4: " + s);
                    return s;
                }
            }
        }
        return null;
    }

}