it.geosolutions.opensdi2.userexpiring.ExpiringTask.java Source code

Java tutorial

Introduction

Here is the source code for it.geosolutions.opensdi2.userexpiring.ExpiringTask.java

Source

/*
 *  OpenSDI Manager
 *  Copyright (C) 2014 GeoSolutions S.A.S.
 *  http://www.geo-solutions.it
 *
 *  GPLv3 + Classpath exception
 *
 *  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 it.geosolutions.opensdi2.userexpiring;

import freemarker.template.TemplateException;
import it.geosolutions.geostore.core.model.User;
import it.geosolutions.geostore.core.model.UserAttribute;
import it.geosolutions.geostore.services.rest.AdministratorGeoStoreClient;
import it.geosolutions.geostore.services.rest.model.RESTUser;
import it.geosolutions.opensdi2.email.OpenSDIMailer;
import it.geosolutions.opensdi2.userexpiring.model.ExecutionState;
import it.geosolutions.opensdi2.userexpiring.model.ExpireLogElement;
import it.geosolutions.opensdi2.userexpiring.model.NotificationLogElement;
import it.geosolutions.opensdi2.userexpiring.model.TaskState;
import it.geosolutions.opensdi2.userexpiring.model.UserExpiringStatus;
import it.geosolutions.opensdi2.utils.email.EmailUtil;

import java.io.IOException;
import java.net.ConnectException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.mail.MailException;

/**
 * Class that wraps the method execution for expiring users check. Send email if
 * configured to do it
 * 
 * @author Lorenzo Natali (lorenzo.natali at geo-solutions.it)
 * 
 */
public class ExpiringTask {
    private final static Logger LOGGER = Logger.getLogger(ExpiringTask.class);

    private UserExpiringStatus userExpiringTaskStatus;

    private AdministratorGeoStoreClient administratorGeoStoreClient;

    OpenSDIMailer notificationService;

    /**
     * email subject
     */
    private String userSubject;
    /**
     * email subject
     */
    private String checksumSubject;

    /**
     * email from address (note: gmail or other services could not allow to use
     * an address different from the account)
     * 
     */
    private String mailFrom;

    /**
     * email address for notification
     */
    private String notifyTo;

    /**
     * Date Format for parsing
     */
    private String dateFormat;

    /**
     * Attribute name for expiring date
     */
    private String expiringDateAttribute;
    /**
     * email attribute
     */
    private String emailAttribute;

    private boolean notifyUsers;

    private boolean autoExpireUsers;

    /**
     * this method check if the program is configured to expire users and then
     * run the process. Can be schedule
     */
    public void execute() {
        if (autoExpireUsers) {
            LOGGER.info("User Expiring task started");
            runExpiringUsers();
            LOGGER.info("User Expiring task ended");
        }
    }

    /**
     * This method check user expiring and notify the administrator
     */
    public void runExpiringUsers() {
        Date executionStart = new Date();
        // check executing
        synchronized (userExpiringTaskStatus) {
            if (userExpiringTaskStatus.getStatus() == TaskState.Running) {
                userExpiringTaskStatus.setMessage(
                        "task was running at " + new Date() + " while trying to execute the process again");
                return;
            } // TODO syncronize on the status object

            // Log Start
            userExpiringTaskStatus.setStatus(TaskState.Running);
            userExpiringTaskStatus.setLastRun(executionStart.toString());
        }
        // check connection to geostore
        if (!pingGeoStore()) {

            synchronized (userExpiringTaskStatus) {
                userExpiringTaskStatus.setStatus(TaskState.Stopped);
                userExpiringTaskStatus.setLastExecutionOutCome((ExecutionState.Error));
                userExpiringTaskStatus.setMessage(
                        "GeoStore is unreachable at:" + administratorGeoStoreClient.getGeostoreRestUrl());

            }

            return;
        } else if (userExpiringTaskStatus.getMessage() != null) {
            // Remove the message if GeoStore is reachable again
            // TODO improve this check
            if (userExpiringTaskStatus.getMessage().contains("GeoStore is unreachable")) {
                userExpiringTaskStatus.setMessage(null);
            }
        }

        // Setup
        ExpiringUpdater updater = new ExpiringUpdater();
        updater.setClient(administratorGeoStoreClient);
        updater.setDateFormat(dateFormat);
        updater.setAttributeName(expiringDateAttribute);

        // instantiate log element
        ExpireLogElement e = null;
        List<User> expired = null;
        // run
        try {

            // Check users and expire accounts
            expired = updater.checkUserList();

            // add log entry to the execution log
            // only if some account expired
            boolean mailSuccess = true;
            if (expired != null && expired.size() > 0) {
                e = new ExpireLogElement();
                // set users in log
                e.setExpiredUsers(getRestUsers(expired));
                e.setDate(executionStart.toString());
                // send checksum
                if (notifyTo != null) {
                    mailSuccess = notifyAdminUserExpiring(expired, e);
                }

                if (notifyUsers && emailAttribute != null) {
                    if (notifyUsersAccountExpiring(expired, e) && mailSuccess) {
                        e.setEmailNotificationStatusSummary(ExecutionState.Success);
                    } else {
                        e.setEmailNotificationStatusSummary(ExecutionState.Error);
                        mailSuccess = false;
                    }
                }
            }

            synchronized (userExpiringTaskStatus) {
                userExpiringTaskStatus.setLastExecutionOutCome((ExecutionState.Success));
                if (e != null) {
                    e.setStatus(userExpiringTaskStatus.getLastExecutionOutCome());
                }
                userExpiringTaskStatus.setStatus(TaskState.Stopped);

            }
        } catch (Exception ee) {
            synchronized (userExpiringTaskStatus) {
                userExpiringTaskStatus.setStatus(TaskState.Stopped);
                userExpiringTaskStatus.setLastExecutionOutCome((ExecutionState.Error));
                userExpiringTaskStatus.setMessage(ee.getMessage());
                if (e != null) {
                    e.setStatus(userExpiringTaskStatus.getLastExecutionOutCome());
                }
            }
            LOGGER.error("error during user expiring task execution", ee);

        } finally {
            // if the log element is initialized
            // an expiration occurred.
            userExpiringTaskStatus.setStatus(TaskState.Stopped);
            if (e != null) {
                userExpiringTaskStatus.addLog(e);
            }
        }

    }

    /**
     * utility method for to get a rest user from a user TODO move it into a
     * Utility class
     */
    private List<RESTUser> getRestUsers(List<User> users) {
        List<RESTUser> restus = new ArrayList<RESTUser>();
        if (users == null) {
            return restus;
        }
        for (User u : users) {
            RESTUser ret = new RESTUser();
            ret.setName(u.getName());
            ret.setId(u.getId());
            ret.setRole(u.getRole());
            restus.add(ret);
        }
        return restus;

    }

    /**
     * Notify expiring of the users
     * 
     * @param expired
     *            the list of expired users
     * @param logEl
     *            the log element to fill
     * @return false if some error occurred, true otherwise
     */
    private boolean notifyAdminUserExpiring(List<User> expired, ExpireLogElement logEl) {
        Map<String, Object> model = new HashMap<String, Object>();
        model.put("users", expired);
        NotificationLogElement notification = new NotificationLogElement();
        notification.setAddress(notifyTo);
        notification.setReceiver("*Administrator*");

        try {
            // create message
            String message = notificationService.applyTemplate("adminExpireNotification.ftl", model);
            LOGGER.info("Sending email to:" + notifyTo);
            // sending email
            notificationService.sendMail(mailFrom, notifyTo, checksumSubject, message);
            LOGGER.info("Message sent to:" + notifyTo + ":\n" + message);
            notification.setStatus(ExecutionState.Success);
            logEl.getEmailNotificationLog().add(notification);
        } catch (IOException e) {
            // log error for template and return error message
            LOGGER.error("Error getting email template", e);
            notification.setStatus(ExecutionState.Error);
            notification.setMessage("Error getting the email template");
            logEl.getEmailNotificationLog().add(notification);
            return false;
        } catch (TemplateException e) {
            // log error for template and return error message
            LOGGER.error("error during generation of email body", e);
            notification.setStatus(ExecutionState.Error);
            notification.setMessage("Error during generation of email body");
            logEl.getEmailNotificationLog().add(notification);
            return false;
        } catch (MailException e) {
            // log error for email return error message
            LOGGER.error("error sending expire checksum email to" + notifyTo, e);
            notification.setStatus(ExecutionState.Error);
            notification.setMessage("Error sending expire checksum email to " + notifyTo);
            logEl.getEmailNotificationLog().add(notification);
            return false;
        }
        return true;

    }

    /**
     * Notify expiring of the users. Users must include email as attribute
     * 
     * @param expired
     *            the list of expired users
     * @param logEl
     *            the log element to fill
     * @return false if some error occurred, true otherwise
     */
    private boolean notifyUsersAccountExpiring(List<User> expired, ExpireLogElement logEl) {
        boolean ret = true;
        for (User user : expired) {
            if (!sendMailToUser(user, "userExpireNotification.ftl", logEl)) {
                ret = false;
            }
        }
        return ret;

    }

    /**
     * Send email to the user. The user must have a field defined as email
     * 
     * @param user
     *            the user to notify
     * @param the
     *            template to use
     * @param logEl
     *            the log element to fill
     * @return false if some error occurred, true otherwise
     */
    private boolean sendMailToUser(User user, String template, ExpireLogElement logEl) {
        Map<String, Object> model = new HashMap<String, Object>();
        NotificationLogElement notification = new NotificationLogElement();
        notification.setReceiver(user.getName());
        model.put("user", user);
        if (user.getAttribute() == null) {
            notification.setStatus(ExecutionState.Error);
            LOGGER.warn("Error getting user email for user: " + user.getName());
            notification.setMessage("Error getting user email");
            logEl.getEmailNotificationLog().add(notification);
        }
        String email = null;

        for (UserAttribute ua : user.getAttribute()) {
            if (emailAttribute.equals(ua.getName()))
                email = ua.getValue();
        }

        if (email == null || "".equals(email)) {
            LOGGER.warn("Error getting user email for user: " + user.getName());
            notification.setMessage("Couldn't find user email");
            notification.setStatus(ExecutionState.Error);
            logEl.getEmailNotificationLog().add(notification);
            return false;
        }
        if (!EmailUtil.validateEmail(email)) {
            LOGGER.warn("The user email is not valid for user: " + user.getName());
            notification.setMessage("the user email is not valid");
            notification.setStatus(ExecutionState.Error);
            logEl.getEmailNotificationLog().add(notification);
            return false;
        }
        ;
        notification.setAddress(email);
        try {
            // create message
            String message = notificationService.applyTemplate(template, model);
            LOGGER.info("Sending email to:" + email);
            // sending email
            notificationService.sendMail(mailFrom, email, userSubject, message);
            LOGGER.info("Message sent to " + email + ":\n" + message);
            notification.setStatus(ExecutionState.Success);
            logEl.getEmailNotificationLog().add(notification);
        } catch (IOException e) {
            // log error for template and return error message
            LOGGER.error("Error getting email template", e);
            notification.setStatus(ExecutionState.Error);
            notification.setMessage("Error getting email template");
            logEl.getEmailNotificationLog().add(notification);
            return false;
        } catch (TemplateException e) {
            // log error for template and return error message
            LOGGER.error("error during generation of email body", e);
            notification.setStatus(ExecutionState.Error);
            notification.setMessage("Error getting email template");
            logEl.getEmailNotificationLog().add(notification);
            return false;
        } catch (MailException e) {
            // log error for email return error message
            LOGGER.error("error sending expire checksum email to" + notifyTo, e);
            notification.setStatus(ExecutionState.Error);
            notification.setMessage("Error sending email message");
            logEl.getEmailNotificationLog().add(notification);
            return false;
        }
        return true;
    }

    /**
     * Check GeoStore Connection
     * 
     * @param client
     * @return
     */
    protected boolean pingGeoStore() {
        try {
            administratorGeoStoreClient.getCategories();
            return true;
        } catch (Exception ex) {

            // ... and now for an awful example of heuristic.....
            Throwable t = ex;
            while (t != null) {
                if (t instanceof ConnectException) {
                    LOGGER.warn("Testing GeoStore is offline");
                    return false;
                }
                t = t.getCause();
            }
            return false;
        }
    }

    // GETTERS AND SETTERS
    public UserExpiringStatus getUserExpiringTaskStatus() {
        return userExpiringTaskStatus;
    }

    public void setUserExpiringTaskStatus(UserExpiringStatus userExpiringTaskStatus) {
        this.userExpiringTaskStatus = userExpiringTaskStatus;
    }

    public AdministratorGeoStoreClient getAdministratorGeoStoreClient() {
        return administratorGeoStoreClient;
    }

    public void setAdministratorGeoStoreClient(AdministratorGeoStoreClient administratorGeoStoreClient) {
        this.administratorGeoStoreClient = administratorGeoStoreClient;
    }

    public OpenSDIMailer getNotificationService() {
        return notificationService;
    }

    public void setNotificationService(OpenSDIMailer notificationService) {
        this.notificationService = notificationService;
    }

    public String getMailFrom() {
        return mailFrom;
    }

    public void setMailFrom(String mailFrom) {
        this.mailFrom = mailFrom;
    }

    public String getNotifyTo() {
        return notifyTo;
    }

    public void setNotifyTo(String notifyTo) {
        this.notifyTo = notifyTo;
    }

    public String getDateFormat() {
        return dateFormat;
    }

    public void setDateFormat(String dateFormat) {
        this.dateFormat = dateFormat;
    }

    public String getUserSubject() {
        return userSubject;
    }

    public void setUserSubject(String userSubject) {
        this.userSubject = userSubject;
    }

    public String getChecksumSubject() {
        return checksumSubject;
    }

    public void setChecksumSubject(String checksumSubject) {
        this.checksumSubject = checksumSubject;
    }

    public String getExpiringDateAttribute() {
        return expiringDateAttribute;
    }

    public void setExpiringDateAttribute(String expiringDateAttribute) {
        this.expiringDateAttribute = expiringDateAttribute;
    }

    public String getEmailAttribute() {
        return emailAttribute;
    }

    public void setEmailAttribute(String emailAttribute) {
        this.emailAttribute = emailAttribute;
    }

    public boolean isNotifyUsers() {
        return notifyUsers;
    }

    public void setNotifyUsers(boolean notifyUsers) {
        this.notifyUsers = notifyUsers;
    }

    public boolean isAutoExpireUsers() {
        return autoExpireUsers;
    }

    public void setAutoExpireUsers(boolean autoExpireUsers) {
        this.autoExpireUsers = autoExpireUsers;
    }

}