eu.uqasar.message.UQasarMessage.java Source code

Java tutorial

Introduction

Here is the source code for eu.uqasar.message.UQasarMessage.java

Source

package eu.uqasar.message;

/*
 * #%L
 * U-QASAR
 * %%
 * Copyright (C) 2012 - 2015 U-QASAR Consortium
 * %%
 * 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.
 * #L%
 */

import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.apache.wicket.Application;
import org.jboss.solder.logging.Logger;

import eu.uqasar.model.user.User;
import eu.uqasar.util.resources.XMLResourceBundleControl;
import eu.uqasar.web.UQasar;
import eu.uqasar.web.pages.BasePage;
import eu.uqasar.web.provider.UrlProvider;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;

/**
 *
 *
 */
public class UQasarMessage extends MimeMessage {

    private static final Logger logger = Logger.getLogger(UQasarMessage.class);
    private static final Configuration templateConfig;
    private static final String CHARSET = "UTF-8";
    private Locale locale = new Locale("");

    // TODO get this from the user preferences!
    private MessageType messageType = MessageType.HTML;
    private User recipient;
    private Address from;

    static {
        templateConfig = new Configuration();
        templateConfig.setClassForTemplateLoading(UQasarMessage.class, "");
        templateConfig.setDefaultEncoding("UTF-8");
    }

    protected UQasarMessage(Session session, final String recipientAddress, final String fromAddress)
            throws MessagingException {
        super(session);
        setRecipient(Message.RecipientType.TO, convertStringToAddress(recipientAddress));
        setFrom(fromAddress);
        this.recipient = createDummyRecipient(recipientAddress);
    }

    protected UQasarMessage(Session session, final String recipientAddress, Address fromAddress)
            throws MessagingException {
        super(session);
        setRecipient(Message.RecipientType.TO, convertStringToAddress(recipientAddress));
        setFrom(fromAddress);
        this.recipient = createDummyRecipient(recipientAddress);
        this.from = fromAddress;
    }

    protected UQasarMessage(Session session, User recipient, Address from) throws MessagingException {
        super(session);
        setRecipient(Message.RecipientType.TO, recipient);
        setFrom(from);
        this.from = from;
    }

    protected UQasarMessage(Session session, User recipient, User from) throws MessagingException {
        super(session);
        setRecipient(Message.RecipientType.TO, recipient);
        setFrom(from);
    }

    protected UQasarMessage(Session session, User recipient, final String fromAddress) throws MessagingException {
        super(session);
        setRecipient(Message.RecipientType.TO, recipient);
        setFrom(fromAddress);
    }

    private User createDummyRecipient(final String address) {
        User user = new User();
        user.setFirstName(address);
        user.setMail(address);
        return user;
    }

    protected User getRecipient() {
        return this.recipient;
    }

    private void validate() throws MessagingException {
        if (getFrom() == null) {
            throw new MessagingException("Sender cannot be null!");
        }
        if (getRecipient() == null || getRecipients(Message.RecipientType.TO).length == 0) {
            throw new MessagingException("Recipient(s) cannot be null or empty!");
        }
        if (getSubject() == null) {
            throw new MessagingException("Subject cannot be null!");
        }
        try {
            getContent();
        } catch (IOException ex) {
            throw new MessagingException(ex.getMessage(), ex);
        }
    }

    public void send() throws MessagingException, IOException {
        adjustLocale();
        prepareHeaders();
        generateContentFromTemplate();
        validate();
        Transport.send(this);
    }

    private String getContentTemplateFileName() {
        return this.getClass().getSimpleName() + ".ftl";
    }

    private String getContentTemplatePath() {
        // assume that all message templates reside below UQasarMessage class path
        // base path therefor is UQasarMessage classpath without UQasarMessage name 
        // (i.e. eu.uqasar.message.UQasarMessage -> eu.uqasar.message)
        final String baseMessagePath = UQasarMessage.class.getCanonicalName()
                .replace("." + UQasarMessage.class.getSimpleName(), "");

        // build the difference from current inherting class to base path
        // (i.e. eu.uqasar.message.auth.register.RegistrationConfirmationMessage -> auth.register)
        // (by stripping eu.uqasar.message and RegistrationConfirmationMessage)
        final String diffPath = this.getClass().getCanonicalName().replace(baseMessagePath, "")
                .replace("." + this.getClass().getSimpleName(), "");

        // build final template path by combining diffPath, type of template (txt or html) and name of this class

        return String.format("%s/%s/%s", diffPath.replace(".", "/"), getMessageType().getTemplateSourceType(),
                getContentTemplateFileName());
    }

    private Configuration updateTemplatingConfiguration() {
        // adjust execption handling based on message type
        TemplateExceptionHandler handler = getMessageType() == MessageType.HTML
                ? TemplateExceptionHandler.HTML_DEBUG_HANDLER
                : TemplateExceptionHandler.DEBUG_HANDLER;
        templateConfig.setTemplateExceptionHandler(handler);
        return templateConfig;
    }

    protected Map<String, Object> getDefaultModel() {
        Map<String, Object> defaultModel = new HashMap<>();
        defaultModel.put("homepage", getHomepageLink());
        defaultModel.put("logo", getLogoLink());
        defaultModel.put("from", from.toString());
        return defaultModel;
    }

    protected Object getDataModel() {
        return getDefaultModel();
    }

    private UQasarMessage generateContentFromTemplate() throws MessagingException {
        try {
            Configuration cfg = updateTemplatingConfiguration();
            final String templatePath = getContentTemplatePath();
            logger.infof("Trying to load template at %s", templatePath);
            Template template = cfg.getTemplate(templatePath, getLocale());
            StringWriter writer = new StringWriter();
            template.process(getDataModel(), writer);
            final String processedTemplate = writer.toString();
            setContent(processedTemplate, getMessageType().getMimeType());
        } catch (IOException | TemplateException ex) {
            logger.error(ex.getMessage(), ex);
        }
        return this;
    }

    protected UrlProvider getUrlProvider() {
        if (Application.exists()) {
            return UQasar.get().getUrlProvider();
        } else {
            return null;
        }
    }

    private static String getBaseURL() {
        return "http://" + BasePage.SERVERNAMEANDPORT + "/uqasar";
    }

    private static String getAssetURL(final String assetPath) {
        return String.format("http://" + BasePage.SERVERNAMEANDPORT + "/uqasar/%s", assetPath);
    }

    private String getHomepageLink() {
        if (Application.exists()) {
            return UQasar.get().getHomePageUrl();
        } else {
            return getBaseURL();
        }
    }

    private String getLogoLink() {
        if (Application.exists()) {
            return UQasar.get().getHomePageUrl() + "/assets/img/uqasar-logo.png";
        } else {
            return getAssetURL("assets/img/uqasar-logo.png");
        }
    }

    private String getLocalizedSubject() {
        final String KEY_SUBJECT = "subject";
        ResourceBundle bundle = getMyOrMyParentsResourceBundle();
        if (bundle != null && bundle.containsKey(KEY_SUBJECT)) {
            return bundle.getString(KEY_SUBJECT);
        }
        return null;
    }

    private ResourceBundle getMyOrMyParentsResourceBundle() {
        Class<?> clazzes[] = new Class<?>[] { this.getClass(), this.getClass().getSuperclass() };
        Locale[] locales = new Locale[] { locale, new Locale("") };
        ResourceBundle bundle = null;
        ResourceBundle.Control xmlLocator = new XMLResourceBundleControl();
        for (Class<?> clazz : clazzes) {
            for (Locale localeT : locales) {
                try {
                    bundle = ResourceBundle.getBundle(clazz.getCanonicalName(), localeT, clazz.getClassLoader(),
                            xmlLocator);
                    return bundle;
                } catch (MissingResourceException ex) {
                    try {
                        bundle = ResourceBundle.getBundle(clazz.getCanonicalName(), localeT,
                                clazz.getClassLoader());
                        return bundle;
                    } catch (MissingResourceException ignored) {
                    }
                }
            }
        }
        if (bundle == null) {
            logger.warn("Could not find any resource bundle!");
        }
        return bundle;
    }

    private void adjustLocale() {
        if (recipient != null && recipient.getPreferredLocale() != null) {
            this.locale = recipient.getPreferredLocale();
        } else if (UQasar.exists()) {
            this.locale = UQasar.getSession().getLocale();
        }
        templateConfig.setLocale(this.locale);
    }

    private UQasarMessage prepareHeaders() {
        try {
            if (this.getSubject() == null) {
                // TODO add "U-QASAR" in front of every subject?
                setSubject(getLocalizedSubject(), CHARSET.toLowerCase());
            }
        } catch (MessagingException ex) {
            logger.warn(ex.getMessage(), ex);
        }
        return this;
    }

    private MessageType getMessageType() {
        return this.messageType;
    }

    private void setMessageType(MessageType type) {
        this.messageType = type;
    }

    private Locale getLocale() {
        return this.locale;
    }

    public void setLocale(Locale locale) {
        this.locale = locale;
    }

    private void setFrom(User user) throws MessagingException {
        Address address = convertStringToAddress(user.getMail(), user.getFullName());
        setFrom(address);
        this.from = address;
    }

    private void setFrom(final String mailAddress) throws MessagingException {
        Address address = convertStringToAddress(mailAddress, mailAddress);
        setFrom(address);
        this.from = address;
    }

    private void setRecipient(Message.RecipientType type, User user) throws MessagingException {
        Address address = convertStringToAddress(user.getMail(), user.getFullName());
        this.recipient = user;
        setRecipient(type, address);
        setMessageType(user.getPreferredMessageType());
    }

    public final void setRecipient(Message.RecipientType type, final String mailAddress) throws MessagingException {
        Address address = convertStringToAddress(mailAddress);
        setRecipient(type, address);
    }

    public static Address convertStringToAddress(final String address) {
        try {
            return new InternetAddress(address, CHARSET);
        } catch (UnsupportedEncodingException ex) {
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    public static Address convertStringToAddress(final String address, final String name) {
        try {
            return new InternetAddress(address, name, CHARSET);
        } catch (UnsupportedEncodingException ex) {
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    public enum MessageType {

        TEXT("text/plain; charset=UTF-8", "txt"), HTML("text/html; charset=UTF-8", "html"),;

        private final String templateMimeType;
        private final String templateType;

        MessageType(final String templateMimeType, final String templateType) {
            this.templateMimeType = templateMimeType;
            this.templateType = templateType;
        }

        public String getTemplateSourceType() {
            return this.templateType;
        }

        public String getMimeType() {
            return this.templateMimeType;
        }
    }
}