com.celements.blog.plugin.NewsletterReceivers.java Source code

Java tutorial

Introduction

Here is the source code for com.celements.blog.plugin.NewsletterReceivers.java

Source

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This 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 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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 this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package com.celements.blog.plugin;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.VelocityContext;
import org.xwiki.context.Execution;
import org.xwiki.model.reference.DocumentReference;

import com.celements.rendering.RenderCommand;
import com.celements.web.plugin.cmd.CelSendMail;
import com.celements.web.plugin.cmd.UserNameForUserDataCommand;
import com.celements.web.service.IWebUtilsService;
import com.celements.web.utils.WebUtils;
import com.xpn.xwiki.XWiki;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.objects.BaseObject;
import com.xpn.xwiki.web.Utils;
import com.xpn.xwiki.web.XWikiMessageTool;
import com.xpn.xwiki.web.XWikiRequest;

public class NewsletterReceivers {

    private static Log LOGGER = LogFactory.getFactory().getInstance(NewsletterReceivers.class);
    private UserNameForUserDataCommand userNameForUserDataCmd = new UserNameForUserDataCommand();
    private RenderCommand renderCommand = new RenderCommand();

    private List<String> allAddresses = new ArrayList<String>();
    private List<String[]> groups = new ArrayList<String[]>();
    private List<String[]> groupUsers = new ArrayList<String[]>();
    private List<String[]> users = new ArrayList<String[]>();
    private List<String> addresses = new ArrayList<String>();

    //TODO ADD UNIT TESTS!!!
    public NewsletterReceivers(XWikiDocument blogDoc, XWikiContext context) throws XWikiException {
        List<BaseObject> objs = blogDoc.getObjects("Celements2.ReceiverEMail");
        LOGGER.debug("objs.size = " + (objs != null ? objs.size() : 0));
        if (objs != null) {
            for (BaseObject obj : objs) {
                LOGGER.debug("obj: " + obj);
                if (obj != null) {
                    String receiverAdr = obj.getStringValue("email");
                    String address = receiverAdr.toLowerCase();
                    boolean active = (obj.getIntValue("is_active") == 1);
                    boolean isMail = address.matches("[\\w\\.]{1,}[@][\\w\\-\\.]{1,}([.]([\\w\\-\\.]{1,})){1,3}$");
                    String type = obj.getStringValue("address_type");
                    if (isMail && active && (!allAddresses.contains(address))) {
                        addresses.add(address);
                        allAddresses.add(address);
                        LOGGER.info("reveiver added: " + address);
                    } else {
                        if (context.getWiki().exists(receiverAdr, context)) {
                            parseDocument(receiverAdr, type, context);
                        }
                    }
                }
            }
        }
        String hql = "select nr.email from Celements.NewsletterReceiverClass as nr " + "where nr.isactive='1' "
                + "and subscribed='" + blogDoc.getFullName() + "'";
        List<String> nlRegAddresses = context.getWiki().search(hql, context);
        if (nlRegAddresses != null) {
            LOGGER.info("Found " + nlRegAddresses.size() + " Celements.NewsletterReceiverClass"
                    + " object-subscriptions for blog " + blogDoc.getFullName());
            for (String address : nlRegAddresses) {
                address = address.toLowerCase();
                if (!allAddresses.contains(address)) {
                    addresses.add(address);
                    allAddresses.add(address);
                    LOGGER.info("reveiver added: " + address);
                }
            }
        }
    }

    private void parseDocument(String address, String type, XWikiContext context) throws XWikiException {
        XWikiDocument recDoc = context.getWiki().getDocument(address, context);
        BaseObject userObj = recDoc.getObject("XWiki.XWikiUsers");
        List<BaseObject> groupObjs = recDoc.getObjects("XWiki.XWikiGroups");
        if (userObj != null) {
            String email = userObj.getStringValue("email").toLowerCase();
            String language = userObj.getStringValue("admin_language");
            if ((email.trim().length() > 0) && (!allAddresses.contains(email))) {
                users.add(new String[] { recDoc.getFullName(), email, language });
                allAddresses.add(email);
            }
        } else if ((groupObjs != null) && (groupObjs.size() > 0)) {
            int usersInGroup = parseGroupMembers(groupObjs, type, context);
            groups.add(new String[] { recDoc.getFullName(), Integer.toString(usersInGroup) });
        }
    }

    private int parseGroupMembers(List<BaseObject> groupObjs, String type, XWikiContext context)
            throws XWikiException {
        int usersInGroup = 0;
        for (BaseObject groupObj : groupObjs) {
            if ((groupObj != null) && (groupObj.getStringValue("member") != null)) {
                String userDocName = groupObj.getStringValue("member");
                if ((userDocName.trim().length() > 0) && context.getWiki().exists(userDocName, context)) {
                    XWikiDocument userDoc = context.getWiki().getDocument(userDocName, context);
                    BaseObject groupUserObj = userDoc.getObject("XWiki.XWikiUsers");
                    if (groupUserObj != null) {
                        String email = groupUserObj.getStringValue("email").toLowerCase();
                        String language = groupUserObj.getStringValue("admin_language");
                        if ((email.trim().length() > 0) && (!allAddresses.contains(email))) {
                            usersInGroup++;
                            allAddresses.add(email);
                            groupUsers.add(new String[] { userDocName, email, language });
                        }
                    }
                }
            }
        }
        return usersInGroup;
    }

    public List<String[]> sendArticleByMail(XWikiContext context) throws XWikiException {
        XWikiRequest request = context.getRequest();
        String articleName = request.get("sendarticle");
        String from = request.get("from");
        String replyTo = request.get("reply_to");
        String subject = request.get("subject");
        String testSend = request.get("testSend");

        boolean isTest = false;
        if ((testSend != null) && testSend.equals("1")) {
            isTest = true;
        }

        XWiki wiki = context.getWiki();
        List<String[]> result = new ArrayList<String[]>();
        int successfullySent = 0;

        LOGGER.debug("articleName = " + articleName);
        LOGGER.debug("article exists = " + wiki.exists(articleName, context));
        if ((articleName != null) && (!"".equals(articleName.trim())) && (wiki.exists(articleName, context))) {
            XWikiDocument doc = wiki.getDocument(articleName, context);
            String baseURL = doc.getExternalURL("view", context);

            List<String[]> allUserMailPairs = null;
            LOGGER.debug("is test send: " + isTest);
            if (isTest) {
                String user = context.getUser();
                XWikiDocument userDoc = context.getWiki().getDocument(user, context);
                BaseObject userObj = userDoc.getObject("XWiki.XWikiUsers");
                if (userObj != null) {
                    String email = userObj.getStringValue("email");
                    if (email.trim().length() > 0) {
                        allUserMailPairs = new ArrayList<String[]>();
                        String language = getUserAdminLanguage(user, getDefaultLanguage());
                        allUserMailPairs.add(new String[] { user, email, language });
                    }
                }
            } else {
                allUserMailPairs = getNewsletterReceiversList();
            }

            String origUser = context.getUser();
            String origLanguage = context.getLanguage();
            VelocityContext vcontext = (VelocityContext) context.get("vcontext");
            Object origAdminLanguage = vcontext.get("admin_language");
            Object origMsgTool = vcontext.get("msg");
            Object origAdminMsgTool = vcontext.get("adminMsg");
            for (String[] userMailPair : allUserMailPairs) {
                context.setUser(userMailPair[0]);
                String language = userMailPair[2];
                context.setLanguage(language);
                vcontext.put("language", language);
                vcontext.put("admin_language", language);
                XWikiMessageTool msgTool = WebUtils.getInstance().getMessageTool(language, getContext());
                vcontext.put("msg", msgTool);
                vcontext.put("adminMsg", msgTool);

                if (wiki.checkAccess("view", doc, context)) {
                    String htmlContent = getHtmlContent(doc, baseURL, context);
                    htmlContent += getUnsubscribeFooter(userMailPair[1], doc, context);

                    String textContent = context.getMessageTool().get("cel_newsletter_text_only_message",
                            Arrays.asList("_NEWSLETTEREMAILADRESSKEY_"));
                    textContent = textContent.replaceAll("_NEWSLETTEREMAILADRESSKEY_",
                            doc.getExternalURL("view", context));
                    textContent += getUnsubscribeFooter(userMailPair[1], doc, context);

                    int singleResult = sendMail(from, replyTo, userMailPair[1], subject, baseURL, htmlContent,
                            textContent, context);
                    result.add(new String[] { userMailPair[1], Integer.toString(singleResult) });
                    if (singleResult == 0) {
                        successfullySent++;
                    }
                } else {
                    LOGGER.warn("Tried to send " + doc + " to user " + userMailPair[0] + " which"
                            + " has no view rights on this Document.");
                    List<String> params = new ArrayList<String>();
                    params.add(doc.toString());
                    result.add(new String[] { userMailPair[1],
                            context.getMessageTool().get("cel_blog_newsletter_receiver_no_rights", params) });
                }

            }
            context.setUser(origUser);
            context.setLanguage(origLanguage);
            vcontext.put("language", origLanguage);
            vcontext.put("admin_language", origAdminLanguage);
            vcontext.put("msg", origMsgTool);
            vcontext.put("adminMsg", origAdminMsgTool);

            setNewsletterSentObject(doc, from, replyTo, subject, successfullySent, isTest, context);
        }

        return result;
    }

    List<String[]> getNewsletterReceiversList() {
        ArrayList<String[]> allUserMailPairs = new ArrayList<String[]>();
        allUserMailPairs.addAll(groupUsers);
        allUserMailPairs.addAll(users);
        //TODO use webUtilsServices as soon as available
        String defaultLanguage = getDefaultLanguage();
        for (String address : addresses) {
            String mailUser = "XWiki.XWikiGuest";
            String language = defaultLanguage;
            String addrUser = null;
            try {
                addrUser = userNameForUserDataCmd.getUsernameForUserData(address, "email", getContext());
            } catch (XWikiException e) {
                LOGGER.error("Exception getting username for user email '" + address + "'.", e);
            }
            if ((addrUser != null) && (addrUser.length() > 0)) {
                mailUser = addrUser;
                language = getUserAdminLanguage(mailUser, defaultLanguage);
            }
            allUserMailPairs.add(new String[] { mailUser, address, language });
        }
        return allUserMailPairs;
    }

    private String getDefaultLanguage() {
        return getContext().getWiki().getSpacePreference("default_language", getContext());
    }

    private String getUserAdminLanguage(String mailUser, String defaultLanguage) {
        String userLanguage = defaultLanguage;
        try {
            DocumentReference userDocRef = getWebUtilsService().resolveDocumentReference(mailUser);
            XWikiDocument mailUserDoc = getContext().getWiki().getDocument(userDocRef, getContext());
            BaseObject mailUserObj = mailUserDoc.getXObject(
                    new DocumentReference(userDocRef.getWikiReference().getName(), "XWiki", "XWikiUsers"));
            String userAdminLanguage = mailUserObj.getStringValue("admin_language");
            if ((userAdminLanguage != null) && !"".equals(userAdminLanguage)) {
                userLanguage = userAdminLanguage;
            }
        } catch (XWikiException exp) {
            LOGGER.error("Exception getting userdoc to find admin-language ['" + mailUser + "]'.", exp);
        }
        return userLanguage;
    }

    private String getUnsubscribeFooter(String emailAddress, XWikiDocument blogDocument, XWikiContext context)
            throws XWikiException {
        String unsubscribeFooter = "";
        if (!"".equals(getUnsubscribeLink(blogDocument.getSpace(), emailAddress, context))) {
            unsubscribeFooter = context.getMessageTool().get("cel_newsletter_unsubscribe_footer",
                    Arrays.asList("_NEWSLETTEREMAILADRESSKEY_"));
            unsubscribeFooter = unsubscribeFooter.replaceAll("_NEWSLETTEREMAILADRESSKEY_",
                    getUnsubscribeLink(blogDocument.getSpace(), emailAddress, context));
        }
        return unsubscribeFooter;
    }

    private String getUnsubscribeLink(String blogSpace, String emailAddresse, XWikiContext context)
            throws XWikiException {
        String unsubscribeLink = "";
        XWikiDocument blogDocument = BlogUtils.getInstance().getBlogPageByBlogSpace(blogSpace, context);
        BaseObject blogObj = blogDocument.getObject("Celements2.BlogConfigClass", false, context);
        if ((blogObj != null) && (blogObj.getIntValue("unsubscribe_info") == 1)) {
            unsubscribeLink = blogDocument.getExternalURL("view",
                    "xpage=celements_ajax&ajax_mode=BlogAjax&doaction=unsubscribe" + "&emailadresse="
                            + emailAddresse,
                    context);
        }
        return unsubscribeLink;
    }

    private String getHtmlContent(XWikiDocument doc, String baseURL, XWikiContext context) throws XWikiException {
        String header = "";
        if ((baseURL != null) && !"".equals(baseURL.trim())) {
            header = "<base href='" + baseURL + "' />\n";
        }

        renderCommand.setDefaultPageType("RichText");
        String content = renderCommand.renderCelementsDocument(doc.getDocumentReference(), "view");
        content = Utils.replacePlaceholders(content, context);

        String footer = context.getMessageTool().get("cel_newsletter_html_footer_message",
                Arrays.asList("_NEWSLETTEREMAILADRESSKEY_"));
        footer = footer.replaceAll("_NEWSLETTEREMAILADRESSKEY_", doc.getExternalURL("view", context));

        return header + content + footer;
    }

    private int sendMail(String from, String replyTo, String to, String subject, String baseURL, String htmlContent,
            String textContent, XWikiContext context) throws XWikiException {
        if ((to != null) && (to.trim().length() == 0)) {
            to = null;
        }
        Map<String, String> otherHeader = new HashMap<String, String>();
        otherHeader.put("Content-Location", baseURL);

        CelSendMail sender = new CelSendMail(getContext());
        sender.setFrom(from);
        sender.setReplyTo(replyTo);
        sender.setTo(to);
        sender.setSubject(subject);
        sender.setHtmlContent(htmlContent, false);
        sender.setTextContent(textContent);
        sender.setOthers(otherHeader);
        return sender.sendMail();
    }

    private void setNewsletterSentObject(XWikiDocument doc, String from, String replyTo, String subject,
            int nrOfSent, boolean isTest, XWikiContext context) throws XWikiException {
        BaseObject configObj = doc.getObject("Classes.NewsletterConfigClass");
        if (configObj == null) {
            configObj = doc.newObject("Classes.NewsletterConfigClass", context);
        }

        configObj.set("from_address", from, context);
        configObj.set("reply_to_address", replyTo, context);
        configObj.set("subject", subject, context);

        if ((nrOfSent > 0) && !isTest) {
            setNewsletterHistory(configObj, nrOfSent, context);
        }

        context.getWiki().saveDocument(doc, context);
    }

    private void setNewsletterHistory(BaseObject configObj, int nrOfSent, XWikiContext context) {
        int timesSent = configObj.getIntValue("times_sent");
        configObj.set("times_sent", timesSent + 1, context);
        configObj.set("last_sent_date", new Date(), context);
        configObj.set("last_sender", context.getUser(), context);
        configObj.set("last_sent_recipients", nrOfSent, context);
    }

    public boolean hasReceivers() {
        return getAllAddresses().size() > 0;
    }

    public boolean hasReceiverGroups() {
        return getGroups().size() > 0;
    }

    public boolean hasSingleReceivers() {
        return (getUsers().size() > 0) || (getAddresses().size() > 0);
    }

    public boolean hasUsers() {
        return getUsers().size() > 0;
    }

    public boolean hasAdresses() {
        return getAddresses().size() > 0;
    }

    public List<String> getAllAddresses() {
        return allAddresses;
    }

    public List<String[]> getGroups() {
        return groups;
    }

    public List<String[]> getUsers() {
        return users;
    }

    public List<String> getAddresses() {
        return addresses;
    }

    public int getNrOfReceivers() {
        return allAddresses.size();
    }

    private IWebUtilsService getWebUtilsService() {
        return Utils.getComponent(IWebUtilsService.class);
    }

    private XWikiContext getContext() {
        return (XWikiContext) Utils.getComponent(Execution.class).getContext().getProperty("xwikicontext");
    }

}