org.jahia.services.workflow.jbpm.JBPMMailProducer.java Source code

Java tutorial

Introduction

Here is the source code for org.jahia.services.workflow.jbpm.JBPMMailProducer.java

Source

/**
 * This file is part of Jahia, next-generation open source CMS:
 * Jahia's next-generation, open source CMS stems from a widely acknowledged vision
 * of enterprise application convergence - web, search, document, social and portal -
 * unified by the simplicity of web content management.
 *
 * For more information, please visit http://www.jahia.com.
 *
 * Copyright (C) 2002-2012 Jahia Solutions Group SA. All rights reserved.
 *
 * 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * As a special exception to the terms and conditions of version 2.0 of
 * the GPL (or any later version), you may redistribute this Program in connection
 * with Free/Libre and Open Source Software ("FLOSS") applications as described
 * in Jahia's FLOSS exception. You should have received a copy of the text
 * describing the FLOSS exception, and it is also available here:
 * http://www.jahia.com/license
 *
 * Commercial and Supported Versions of the program (dual licensing):
 * alternatively, commercial and supported versions of the program may be used
 * in accordance with the terms and conditions contained in a separate
 * written agreement between you and Jahia Solutions Group SA.
 *
 * If you are unsure which license is appropriate for your use,
 * please contact the sales department at sales@jahia.com.
 */

package org.jahia.services.workflow.jbpm;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.apache.velocity.tools.generic.DateTool;
import org.jahia.registries.ServicesRegistry;
import org.jahia.services.SpringContextSingleton;
import org.jahia.services.content.*;
import org.jahia.services.usermanager.JahiaUser;
import org.jahia.utils.ScriptEngineUtils;
import org.jahia.utils.i18n.JahiaResourceBundle;
import org.jbpm.api.Execution;
import org.jbpm.api.JbpmException;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.cmd.Environment;
import org.jbpm.api.identity.Group;
import org.jbpm.api.identity.User;
import org.jbpm.pvm.internal.email.impl.*;
import org.jbpm.pvm.internal.email.spi.AddressResolver;
import org.jbpm.pvm.internal.env.EnvironmentImpl;
import org.jbpm.pvm.internal.identity.spi.IdentitySession;
import org.jbpm.pvm.internal.model.ExecutionImpl;
import org.slf4j.Logger;

import javax.jcr.RepositoryException;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;
import javax.script.*;
import java.io.StringWriter;
import java.util.*;

/**
 * @author : rincevent
 * @since JAHIA 6.5
 *        Created : 14 sept. 2010
 */
public class JBPMMailProducer extends MailProducerImpl {
    private static final long serialVersionUID = -5084848266010688683L;
    private transient static Logger logger = org.slf4j.LoggerFactory.getLogger(JBPMMailProducer.class);
    ScriptEngine scriptEngine;
    private Bindings bindings;

    private String templateKey;

    public String getTemplateKey() {
        return templateKey;
    }

    public void setTemplateKey(String templateKey) {
        this.templateKey = templateKey;
    }

    public Collection<Message> produce(final Execution execution) {
        final Map<String, Object> vars = ((ExecutionImpl) execution).getVariables();
        Locale locale = (Locale) vars.get("locale");

        if (templateKey != null) {
            MailTemplate template = null;
            MailTemplateRegistry templateRegistry = ((ProcessEngine) SpringContextSingleton
                    .getBean("processEngine")).get(MailTemplateRegistry.class);
            if (locale != null) {
                template = (templateRegistry.getTemplate(templateKey + "." + locale.toString()));
                if (template == null) {
                    template = (templateRegistry.getTemplate(templateKey + "." + locale.getLanguage()));
                }
            }
            if (template == null) {
                template = templateRegistry.getTemplate(templateKey);
            }
            setTemplate(template);
        }

        if (ServicesRegistry.getInstance().getMailService().isEnabled() && getTemplate() != null) {
            try {
                return JCRTemplate.getInstance().doExecuteWithSystemSession(null, "default", locale,
                        new JCRCallback<Collection<Message>>() {
                            public Collection<Message> doInJCR(JCRSessionWrapper session)
                                    throws RepositoryException {
                                try {
                                    scriptEngine = ScriptEngineUtils.getInstance()
                                            .getEngineByName(getTemplate().getLanguage());
                                    bindings = null;
                                    Message email = instantiateEmail();
                                    fillFrom(email, execution, session);
                                    fillRecipients(email, execution, session);
                                    fillSubject(email, execution, session);
                                    fillContent(email, execution, session);
                                    Address[] addresses = email.getRecipients(Message.RecipientType.TO);
                                    if (addresses != null && addresses.length > 0) {
                                        return Collections.singleton(email);
                                    } else {
                                        return Collections.emptyList();
                                    }
                                } catch (MessagingException e) {
                                    logger.error(e.getMessage(), e);
                                } catch (ScriptException e) {
                                    logger.error(e.getMessage(), e);
                                }
                                return Collections.emptyList();
                            }
                        });
            } catch (RepositoryException e) {
                logger.error(e.getMessage(), e);
            }
        }
        return Collections.emptyList();
    }

    /**
       * Fills the <code>from</code> attribute of the given email. The sender addresses are an
       * optional element in the mail template. If absent, each mail server supplies the current
       * user's email address.
       *
       * @see {@link InternetAddress#getLocalAddress(Session)}
     */
    protected void fillFrom(Message email, Execution execution, JCRSessionWrapper session)
            throws MessagingException {
        try {
            AddressTemplate fromTemplate = getTemplate().getFrom();
            // "from" attribute is optional
            if (fromTemplate == null)
                return;

            // resolve and parse addresses
            String addresses = fromTemplate.getAddresses();
            if (addresses != null) {
                addresses = evaluateExpression(execution, addresses, session);
                // non-strict parsing applies to a list of mail addresses entered by a human
                email.addFrom(InternetAddress.parse(addresses, false));
            }

            EnvironmentImpl environment = EnvironmentImpl.getCurrent();
            IdentitySession identitySession = environment.get(IdentitySession.class);
            AddressResolver addressResolver = environment.get(AddressResolver.class);

            // resolve and tokenize users
            String userList = fromTemplate.getUsers();
            if (userList != null) {
                String[] userIds = tokenizeActors(userList, execution, session);
                List<User> users = identitySession.findUsersById(userIds);
                email.addFrom(resolveAddresses(users, addressResolver));
            }

            // resolve and tokenize groups
            String groupList = fromTemplate.getGroups();
            if (groupList != null) {
                for (String groupId : tokenizeActors(groupList, execution, session)) {
                    Group group = identitySession.findGroupById(groupId);
                    email.addFrom(addressResolver.resolveAddresses(group));
                }
            }
        } catch (ScriptException e) {
            logger.error(e.getMessage(), e);
        } catch (RepositoryException e) {
            logger.error(e.getMessage(), e);
        }
    }

    protected void fillRecipients(Message email, Execution execution, JCRSessionWrapper session)
            throws MessagingException {
        try {
            // to
            AddressTemplate to = getTemplate().getTo();
            if (to != null) {
                fillRecipients(to, email, Message.RecipientType.TO, execution, session);
            }

            // cc
            AddressTemplate cc = getTemplate().getCc();
            if (cc != null) {
                fillRecipients(cc, email, Message.RecipientType.CC, execution, session);
            }

            // bcc
            AddressTemplate bcc = getTemplate().getBcc();
            if (bcc != null) {
                fillRecipients(bcc, email, Message.RecipientType.BCC, execution, session);
            }
        } catch (ScriptException e) {
            logger.error(e.getMessage(), e);
        } catch (RepositoryException e) {
            logger.error(e.getMessage(), e);
        }
    }

    private void fillRecipients(AddressTemplate addressTemplate, Message email, Message.RecipientType recipientType,
            Execution execution, JCRSessionWrapper session)
            throws MessagingException, RepositoryException, ScriptException {
        // resolve and parse addresses
        String addresses = addressTemplate.getAddresses();
        if (addresses != null) {
            addresses = evaluateExpression(execution, addresses, session);
            // non-strict parsing applies to a list of mail addresses entered by a human
            email.addRecipients(recipientType, InternetAddress.parse(addresses, false));
        }

        EnvironmentImpl environment = EnvironmentImpl.getCurrent();
        IdentitySession identitySession = environment.get(IdentitySession.class);
        AddressResolver addressResolver = environment.get(AddressResolver.class);

        // resolve and tokenize users
        String userList = addressTemplate.getUsers();
        if (userList != null) {
            String[] userIds = tokenizeActors(userList, execution, session);
            List<User> users = identitySession.findUsersById(userIds);
            email.addRecipients(recipientType, resolveAddresses(users, addressResolver));
        }

        // resolve and tokenize groups
        String groupList = addressTemplate.getGroups();
        if (groupList != null) {
            for (String groupId : tokenizeActors(groupList, execution, session)) {
                Group group = identitySession.findGroupById(groupId);
                email.addRecipients(recipientType, addressResolver.resolveAddresses(group));
            }
        }
    }

    private String[] tokenizeActors(String recipients, Execution execution, JCRSessionWrapper session)
            throws RepositoryException, ScriptException {
        String[] actors = evaluateExpression(execution, recipients, session).split("[,;\\s]+");
        if (actors.length == 0)
            throw new JbpmException("recipient list is empty: " + recipients);
        return actors;
    }

    /** construct recipient addresses from user entities */
    private Address[] resolveAddresses(List<User> users, AddressResolver addressResolver) {
        int userCount = users.size();
        List<Address> addresses = new ArrayList<Address>();
        for (int i = 0; i < userCount; i++) {
            if (!StringUtils.isEmpty(users.get(i).getBusinessEmail())) {
                addresses.add(addressResolver.resolveAddress(users.get(i)));
            }
        }
        return addresses.toArray(new Address[addresses.size()]);
    }

    protected void fillSubject(Message email, Execution execution, JCRSessionWrapper session)
            throws MessagingException {
        String subject = getTemplate().getSubject();
        if (subject != null) {
            try {
                String evaluatedSubject = evaluateExpression(execution, subject, session).replaceAll("[\r\n]", "");
                email.setSubject(WordUtils.abbreviate(evaluatedSubject, 60, 74, "..."));
            } catch (RepositoryException e) {
                logger.error(e.getMessage(), e);
            } catch (ScriptException e) {
                logger.error(e.getMessage(), e);
            }
        }
    }

    protected void fillContent(Message email, Execution execution, JCRSessionWrapper session)
            throws MessagingException {
        String text = getTemplate().getText();
        String html = getTemplate().getHtml();
        List<AttachmentTemplate> attachmentTemplates = getTemplate().getAttachmentTemplates();

        try {
            if (html != null || !attachmentTemplates.isEmpty()) {
                // multipart
                MimeMultipart multipart = new MimeMultipart("related");

                BodyPart p = new MimeBodyPart();
                Multipart alternatives = new MimeMultipart("alternative");
                p.setContent(alternatives, "multipart/alternative");
                multipart.addBodyPart(p);

                // html
                if (html != null) {
                    BodyPart htmlPart = new MimeBodyPart();
                    html = evaluateExpression(execution, html, session);
                    htmlPart.setContent(html, "text/html; charset=UTF-8");
                    alternatives.addBodyPart(htmlPart);
                }

                // text
                if (text != null) {
                    BodyPart textPart = new MimeBodyPart();
                    text = evaluateExpression(execution, text, session);
                    textPart.setContent(text, "text/plain; charset=UTF-8");
                    alternatives.addBodyPart(textPart);
                }

                // attachments
                if (!attachmentTemplates.isEmpty()) {
                    addAttachments(execution, multipart);
                }

                email.setContent(multipart);
            } else if (text != null) {
                // unipart
                text = evaluateExpression(execution, text, session);
                email.setText(text);
            }
        } catch (RepositoryException e) {
            logger.error(e.getMessage(), e);
        } catch (ScriptException e) {
            logger.error(e.getMessage(), e);
        }
    }

    private String evaluateExpression(Execution execution, String scriptToExecute, JCRSessionWrapper session)
            throws RepositoryException, ScriptException {
        ScriptContext scriptContext = scriptEngine.getContext();
        if (bindings == null) {
            bindings = getBindings(execution, session);
        }
        scriptContext.setWriter(new StringWriter());
        scriptContext.setErrorWriter(new StringWriter());
        scriptEngine.eval(scriptToExecute, bindings);
        String error = scriptContext.getErrorWriter().toString();
        if (error.length() > 0) {
            logger.error("Scripting error : " + error);
        }
        return scriptContext.getWriter().toString().trim();
    }

    private Bindings getBindings(Execution execution, JCRSessionWrapper session) throws RepositoryException {
        EnvironmentImpl environment = EnvironmentImpl.getCurrent();
        final Map<String, Object> vars = ((ExecutionImpl) execution).getVariables();
        Locale locale = (Locale) vars.get("locale");
        final Bindings bindings = new MyBindings(environment);
        ResourceBundle resourceBundle = JahiaResourceBundle.lookupBundle(
                "org.jahia.services.workflow." + ((ExecutionImpl) execution).getProcessDefinition().getKey(),
                locale);
        bindings.put("bundle", resourceBundle);
        JahiaUser jahiaUser = ServicesRegistry.getInstance().getJahiaUserManagerService()
                .lookupUserByKey((String) vars.get("user"));
        bindings.put("user", jahiaUser);
        bindings.put("date", new DateTool());
        bindings.put("submissionDate", Calendar.getInstance());
        bindings.put("locale", locale);
        bindings.put("workspace", vars.get("workspace"));

        List<JCRNodeWrapper> nodes = new LinkedList<JCRNodeWrapper>();
        @SuppressWarnings("unchecked")
        List<String> stringList = (List<String>) vars.get("nodeIds");
        for (String s : stringList) {
            JCRNodeWrapper nodeByUUID = session.getNodeByUUID(s);
            if (!nodeByUUID.isNodeType("jnt:translation")) {
                nodes.add(nodeByUUID);
            }
        }
        bindings.put("nodes", nodes);
        return bindings;
    }

    public class MyBindings extends SimpleBindings {
        private final Environment environment;

        public MyBindings(Environment environment) {
            super();
            this.environment = environment;
        }

        @Override
        public boolean containsKey(Object key) {
            return super.containsKey(key) || environment.get((String) key) != null;
        }

        @Override
        public Object get(Object key) {
            return super.containsKey(key) ? super.get(key) : environment.get((String) key);
        }

    }

}