pt.ist.fenix.api.SupportFormResource.java Source code

Java tutorial

Introduction

Here is the source code for pt.ist.fenix.api.SupportFormResource.java

Source

/**
 * Copyright  ${project.inceptionYear} Instituto Superior Tcnico
 *
 * This file is part of Fenix IST.
 *
 * Fenix IST is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Fenix IST 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Fenix IST.  If not, see <http://www.gnu.org/licenses/>.
 */
package pt.ist.fenix.api;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Base64;
import java.util.Properties;
import java.util.stream.Collectors;

import javax.activation.DataHandler;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.commons.validator.EmailValidator;
import org.fenixedu.academic.FenixEduAcademicConfiguration;
import org.fenixedu.academic.domain.Person;
import org.fenixedu.academic.predicate.AccessControl;
import org.fenixedu.academic.util.Bundle;
import org.fenixedu.bennu.core.i18n.BundleUtil;
import org.fenixedu.bennu.core.rest.BennuRestResource;
import org.fenixedu.bennu.core.security.Authenticate;
import org.fenixedu.bennu.core.util.CoreConfiguration;
import org.fenixedu.bennu.portal.domain.MenuFunctionality;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import pt.ist.fenixedu.contracts.domain.LegacyRoleUtils;
import pt.ist.fenixframework.FenixFramework;

import com.google.common.base.Objects;
import com.google.common.base.Strings;
import com.google.gson.Gson;

@Path("/fenix-ist/support-form")
public class SupportFormResource extends BennuRestResource {

    private static final Logger logger = LoggerFactory.getLogger(SupportFormResource.class);

    private static final String SEPARATOR = "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n";

    private static final String hostname = getHostName();

    private static String getHostName() {
        try {
            return InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
            return "<Host name unknown>";
        }
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response sendSupportForm(String jsonStr, @Context HttpServletRequest request) {
        SupportBean bean = new Gson().fromJson(jsonStr, SupportBean.class);

        String email = bean.getEmail();

        String mailSubject = generateEmailSubject(bean);
        String mailBody = generateEmailBody(bean);

        if (CoreConfiguration.getConfiguration().developmentMode()) {
            logger.warn("Submitted error form from {}: '{}'\n{}", email, mailSubject, mailBody);
        } else {
            sendEmail(
                    EmailValidator.getInstance().isValid(email) ? email
                            : CoreConfiguration.getConfiguration().defaultSupportEmailAddress(),
                    mailSubject, mailBody, bean);
        }
        return Response.ok().build();
    }

    private String generateEmailSubject(SupportBean bean) {
        StringBuilder builder = new StringBuilder();
        MenuFunctionality functionality = bean.getFunctionality();
        builder.append("[Fenix] [");
        builder.append(functionality != null ? functionality.getPathFromRoot().get(0).getTitle().getContent() : "")
                .append("] ");
        builder.append('[').append(str("label.support.form.type." + bean.type)).append("] ");
        builder.append(bean.subject);
        return builder.toString();
    }

    private String generateEmailBody(SupportBean bean) {
        StringBuilder builder = new StringBuilder();
        builder.append(SEPARATOR);
        appendHeader(builder, bean);
        appendBody(builder, bean);
        return builder.toString();
    }

    private void appendBody(StringBuilder builder, SupportBean bean) {
        builder.append(SEPARATOR).append("\n");
        builder.append(bean.description).append("\n\n\n\n");
        if (!Strings.isNullOrEmpty(bean.exceptionInfo)) {
            builder.append(SEPARATOR).append(bean.exceptionInfo);
        }
    }

    private void appendHeader(StringBuilder builder, SupportBean bean) {
        generateLabel(builder, "Roles").append('[');
        Person person = AccessControl.getPerson();
        if (person != null) {
            builder.append(LegacyRoleUtils.mainRolesStr(person.getUser()));
        }
        builder.append("]\n");

        generateLabel(builder, BundleUtil.getString(Bundle.APPLICATION, "label.name"));
        if (person != null) {
            builder.append("[").append(person.getName()).append("]\n");
            generateLabel(builder, "Username");
            builder.append("[").append(person.getUsername()).append("]\n");
        } else {
            builder.append(BundleUtil.getString(Bundle.APPLICATION, "support.mail.session.error")).append('\n');
        }

        generateLabel(builder, "Email").append("[").append(bean.getEmail()).append("]\n");

        // Portal
        MenuFunctionality functionality = bean.getFunctionality();
        generateLabel(builder, "Portal").append("[");
        if (functionality != null) {
            builder.append(functionality.getPathFromRoot().stream().map(item -> item.getTitle().getContent())
                    .collect(Collectors.joining(" > ")));
        }
        builder.append("]\n");

        generateLabel(builder, "Referer").append('[').append(bean.referer).append("]\n");
        generateLabel(builder, "Browser/OS").append("[").append(bean.userAgent).append("]\n");

        generateLabel(builder, str("label.support.form.type")).append('[')
                .append(str("label.support.form.type." + bean.type)).append("]\n");

        // Extra Info
        generateLabel(builder, "When").append('[').append(DateTime.now()).append("]\n");
        generateLabel(builder, "Host").append('[').append(hostname).append("]\n");
    }

    private static String str(String key) {
        return BundleUtil.getString("resources.FenixIstResources", key);
    }

    private StringBuilder generateLabel(StringBuilder builder, String label) {
        builder.append(label);
        for (int i = label.length(); i <= 15; i++) {
            builder.append('_');
        }
        return builder;
    }

    private void sendEmail(String from, String subject, String body, SupportBean bean) {
        Properties props = new Properties();
        props.put("mail.smtp.host", Objects
                .firstNonNull(FenixEduAcademicConfiguration.getConfiguration().getMailSmtpHost(), "localhost"));
        Session session = Session.getDefaultInstance(props, null);
        MimeMessage message = new MimeMessage(session);
        try {
            message.setFrom(new InternetAddress(from));
            message.addRecipient(Message.RecipientType.TO,
                    new InternetAddress(CoreConfiguration.getConfiguration().defaultSupportEmailAddress()));
            message.setSubject(subject);
            message.setText(body);

            Multipart multipart = new MimeMultipart();
            {
                BodyPart messageBodyPart = new MimeBodyPart();
                messageBodyPart.setText(body);
                multipart.addBodyPart(messageBodyPart);
            }

            if (!Strings.isNullOrEmpty(bean.attachment)) {
                BodyPart messageBodyPart = new MimeBodyPart();
                messageBodyPart.setDataHandler(new DataHandler(
                        new ByteArrayDataSource(Base64.getDecoder().decode(bean.attachment), bean.mimeType)));
                messageBodyPart.setFileName(bean.fileName);
                multipart.addBodyPart(messageBodyPart);
            }

            message.setContent(multipart);

            Transport.send(message);
        } catch (Exception e) {
            logger.error("Could not send support email! Original message was: " + body, e);
        }
    }

    private static class SupportBean {
        public String mimeType;
        public String userAgent;
        public String exceptionInfo;
        public String description;
        private String functionality;
        private String email;
        public String subject;
        public String type = "exception";
        public String referer;
        public String attachment;
        public String fileName;

        public String getEmail() {
            if (!Strings.isNullOrEmpty(email)) {
                return email;
            } else if (Authenticate.isLogged()) {
                return Authenticate.getUser().getEmail();
            } else {
                return "noreply@fenixedu.org";
            }
        }

        public MenuFunctionality getFunctionality() {
            return Strings.isNullOrEmpty(functionality) ? null : FenixFramework.getDomainObject(functionality);
        }
    }

}