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

Java tutorial

Introduction

Here is the source code for com.celements.blog.plugin.BlogPlugin.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.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.VelocityContext;
import org.xwiki.model.reference.DocumentReference;

import com.celements.blog.service.IBlogServiceRole;
import com.celements.web.plugin.api.CelementsWebPluginApi;
import com.xpn.xwiki.XWiki;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.api.Api;
import com.xpn.xwiki.api.Document;
import com.xpn.xwiki.api.Property;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.objects.BaseObject;
import com.xpn.xwiki.plugin.XWikiDefaultPlugin;
import com.xpn.xwiki.plugin.XWikiPluginInterface;
import com.xpn.xwiki.web.Utils;

public class BlogPlugin extends XWikiDefaultPlugin {

    private static final String DEFAULT_RECEIVER_SPACE = "NewsletterReceivers";
    private static Log LOGGER = LogFactory.getFactory().getInstance(BlogPlugin.class);
    IBlogServiceRole injected_BlogService;

    public BlogPlugin(String name, String className, XWikiContext context) {
        super(name, className, context);
        init(context);
    }

    @Override
    public Api getPluginApi(XWikiPluginInterface plugin, XWikiContext context) {
        return new BlogPluginApi((BlogPlugin) plugin, context);
    }

    @Override
    public String getName() {
        LOGGER.debug("Entered method getName");
        return "celementsblog";
    }

    /**
     * @deprecated since 1.4 use BlogService.getBlogPageByBlogSpace instead
     */
    @Deprecated
    public XWikiDocument getBlogPageByBlogSpace(String blogSpaceName, XWikiContext context) throws XWikiException {
        return BlogUtils.getInstance().getBlogPageByBlogSpace(blogSpaceName, context);
    }

    /**
     * @param blogArticleSpace Space where the blog's articles are saved.
     * @param subscribedBlogsStr Comma separated String with all the blog article spaces 
     *        the blog has subscribed to.
     * @param language default language
     * @param archiveOnly Only get articles from the archive (archivedate < now)
     * @param futurOnly Only get articles that are not yet published (publishdate > now)
     * @param subscribableOnly Only get articles from subscribed blogs, but not the ones 
     *        from the blog the user is on.
     * @param withArchive Include archived articles in the answer. Has no effect if 
     *        archiveOnly = true.
     * @param withFutur Include not yet published articles. Only possible if the page has 
     *        been saved with programmingrights or the user has edit right on the article. Has no effect if futurOnly = true.
     * @param withSubscribable Include articles from subscribed blogs.
     * @param withSubscribed Include articles the blog has subscribed to.
     * @param withUnsubscribed Include articles the blog has unsubscribed from. Only works 
     *        with edit rights or programmingrights.
     * @param withUndecided Include articles the blog has not yet desided about a 
     *        subscription. Only works with edit rights or programmingrights.
     * @param checkAccessRights Do pay attention to the rights. Default = true if no 
     *        programmingrights.
     * @param context
     * @return
     * @throws XWikiException
     */
    public List<Article> getBlogArticles(String blogArticleSpace, String subscribedBlogsStr, String language,
            boolean archiveOnly, boolean futurOnly, boolean subscribableOnly, boolean withArchive,
            boolean withFutur, boolean withSubscribable, boolean withSubscribed, boolean withUnsubscribed,
            boolean withUndecided, boolean checkAccessRights, XWikiContext context) throws XWikiException {
        List<Article> articles = new ArrayList<Article>();
        List<String> subscribedBlogs = new ArrayList<String>();
        String[] subscribedBlogArray = subscribedBlogsStr.split(",");
        for (int i = 0; i < subscribedBlogArray.length; i++) {
            if ((subscribedBlogArray[i] != null) && (subscribedBlogArray[i].trim().length() > 0)) {
                LOGGER.info("Subscribed to Blog: '" + subscribedBlogArray[i] + "'");
                subscribedBlogs.add(subscribedBlogArray[i]);
            }
        }
        String hql = getHQL(blogArticleSpace, language, subscribedBlogs, withSubscribable, context);
        getArticlesFromDocs(articles, context.getWiki().search(hql, context), blogArticleSpace, context);
        LOGGER.info("Total articles found: '" + articles.size() + "'");
        filterTimespan(articles, language, withArchive, archiveOnly, withFutur, futurOnly, context);
        LOGGER.info("Total articles after Timespanfilter: '" + articles.size() + "'");
        filterRightsAndSubscription(articles, blogArticleSpace, language, withUnsubscribed, withUndecided,
                withSubscribed, subscribableOnly, checkAccessRights, context);
        LOGGER.info("Total articles returned: " + articles.size());
        return articles;
    }

    // checkRights = false braucht programmingrights auf blogdoc
    private void filterRightsAndSubscription(List<Article> articles, String blogArticleSpace, String language,
            boolean withUnsubscribed, boolean withUndecided, boolean withSubscribed, boolean subscribableOnly,
            boolean checkRights, XWikiContext context) throws XWikiException {
        List<Article> deleteArticles = new ArrayList<Article>();
        XWikiDocument spaceBlogDoc = getBlogService().getBlogPageByBlogSpace(blogArticleSpace);
        if (spaceBlogDoc == null) {
            LOGGER.debug("Missing Blog Configuration! (Blog space: '" + blogArticleSpace + "')");
            deleteArticles.addAll(articles);
        } else {
            Document origBlogDoc = spaceBlogDoc.newDocument(context);
            for (Iterator<Article> artIter = articles.iterator(); artIter.hasNext();) {
                Article article = (Article) artIter.next();
                try {
                    XWikiDocument articleDoc = context.getWiki().getDocument(article.getDocumentReference(),
                            context);
                    DocumentReference blogDocRef = getBlogService().getBlogDocRefByBlogSpace(
                            articleDoc.getDocumentReference().getLastSpaceReference().getName());
                    LOGGER.debug("articleDoc='" + articleDoc + "', " + blogDocRef);
                    Document blogDoc = context.getWiki().getDocument(blogDocRef, context).newDocument(context);
                    boolean hasRight = false;
                    boolean hasEditOnBlog = false;
                    if (checkRights || !blogDoc.hasProgrammingRights()) {
                        LOGGER.info("'" + article.getDocName() + "' - Checking rights. Reason: " + "checkRights='"
                                + checkRights + "' || !programming='" + !blogDoc.hasProgrammingRights() + "'");
                        Date publishdate = article.getPublishDate(language);
                        if ((publishdate != null) && (publishdate.after(new Date()))) {
                            if (blogDoc.hasAccessLevel("edit")) {
                                hasRight = true;
                            }
                        } else if (blogDoc.hasAccessLevel("view")) {
                            hasRight = true;
                        }
                        LOGGER.debug("'" + articleDoc.getSpace() + "' != '" + blogArticleSpace
                                + "' && origBlogDoc.hasAccessLevel('edit') => '"
                                + origBlogDoc.hasAccessLevel("edit") + "'");
                        if (!articleDoc.getSpace().equals(blogArticleSpace) && origBlogDoc.hasAccessLevel("edit")) {
                            hasEditOnBlog = true;
                        }
                    } else {
                        LOGGER.info("'" + article.getDocName() + "' - Saved with programming rights "
                                + "and not checking for rights.");
                        hasRight = true;
                        hasEditOnBlog = true;
                    }

                    LOGGER.info("'" + article.getDocName() + "' - hasRight: '" + hasRight + "' "
                            + "hasEditOnBlog: '" + hasEditOnBlog + "'");
                    if (hasRight) {
                        if (!articleDoc.getSpace().equals(blogArticleSpace)) {
                            Boolean isSubscribed = article.isSubscribed();

                            if (isSubscribed == null) {
                                if (!withUndecided || !hasEditOnBlog) {
                                    LOGGER.info("'" + article.getDocName() + "' - Removed reason: from "
                                            + "subscribed blog && isUndecided && (!withUndecided='" + !withUndecided
                                            + "' || !hasEditOnBlog='" + !hasEditOnBlog + "')");
                                    deleteArticles.add(article);
                                }
                            } else {
                                if (!isSubscribed && (!withUnsubscribed || !hasEditOnBlog)) {
                                    LOGGER.info("'" + article.getDocName() + "' - Removed reason: from "
                                            + "subscribed blog && isDecided && ((!isSubscribed='" + !isSubscribed
                                            + "' && !withUnsubscribed='" + !withUnsubscribed + "') || "
                                            + "!hasEditOnBlog='" + !hasEditOnBlog + "')");
                                    deleteArticles.add(article);
                                } else if (isSubscribed && !withSubscribed) {
                                    LOGGER.info("'" + article.getDocName() + "' - Removed reason: from "
                                            + "subscribed blog && isDecided && (isSubscribed='" + isSubscribed
                                            + "' && !withSubscribed='" + !withSubscribed + "')");
                                    deleteArticles.add(article);
                                }
                            }
                        } else if (subscribableOnly) {
                            LOGGER.info("'" + article.getDocName() + "' - Removed reason: from own "
                                    + "blog, but subscribableOnly='" + subscribableOnly + "'");
                            deleteArticles.add(article);
                        }
                    } else {
                        LOGGER.info("'" + article.getDocName() + "' - Removed reason: has no rights");
                        deleteArticles.add(article);
                    }
                } catch (XWikiException exp) {
                    LOGGER.error("filterRightsAndSubscription: Failed to check rights on: "
                            + article.getDocumentReference(), exp);
                }
            }
        }
        for (Iterator<Article> delIter = deleteArticles.iterator(); delIter.hasNext();) {
            articles.remove(delIter.next());
        }
    }

    private void filterTimespan(List<Article> articles, String language, boolean withArchive, boolean archiveOnly,
            boolean withFutur, boolean futurOnly, XWikiContext context) {
        Date now = new Date();
        List<Article> deleteArticles = new ArrayList<Article>();
        for (Iterator<Article> artIter = articles.iterator(); artIter.hasNext();) {
            Article article = (Article) artIter.next();
            Date archivedate = article.getArchiveDate(language);
            Date publishdate = article.getPublishDate(language);
            if (((archivedate != null) && archivedate.before(now))
                    && ((!withArchive && !archiveOnly) || futurOnly)) {
                deleteArticles.add(article);
            }
            if (((publishdate != null) && publishdate.after(now))
                    && ((!withFutur && !futurOnly) || (archiveOnly && (!withFutur || (archivedate == null)
                            || ((archivedate != null) && archivedate.after(now)))))) {
                deleteArticles.add(article);
            }
            if (((publishdate == null) || publishdate.before(now))
                    && ((archivedate == null) || archivedate.after(now)) && (archiveOnly || futurOnly)) {
                deleteArticles.add(article);
            }
        }
        for (Iterator<Article> delIter = deleteArticles.iterator(); delIter.hasNext();) {
            articles.remove(delIter.next());
        }
    }

    private void getArticlesFromDocs(List<Article> articles, List<Object> articleDocNames, String blogArticleSpace,
            XWikiContext context) throws XWikiException {
        LOGGER.debug("Matching articles found: " + articleDocNames.size());
        for (Object articleFullNameObj : articleDocNames) {
            String articleFullName = (String) articleFullNameObj.toString();
            XWikiDocument articleDoc = context.getWiki().getDocument(articleFullName, context);
            Article article = null;
            try {
                article = new Article(articleDoc.newDocument(context), context);
            } catch (EmptyArticleException e) {
                LOGGER.info(e);
            }
            if ((article != null) && (blogArticleSpace.equals(articleDoc.getSpace())
                    || (article.isSubscribable() == Boolean.TRUE))) {
                articles.add(article);
            }
        }
    }

    private String getHQL(String blogArticleSpace, String language, List<String> subscribedBlogs,
            boolean withSubscribable, XWikiContext context) throws XWikiException {
        String useInt = " ";
        String subscribableHQL = "";
        String subscribedBlogsStr = "";
        LOGGER.debug("if params: (" + subscribedBlogs + "!= null) ("
                + ((subscribedBlogs != null) ? subscribedBlogs.size() : "null") + " > 0) (withSubscribable = "
                + withSubscribable + ")");
        if ((subscribedBlogs != null) && (subscribedBlogs.size() > 0) && withSubscribable) {
            //useInt = ", IntegerProperty as int ";
            subscribableHQL = /*to slow with this query part "and (obj.id = int.id.id " +
                              "and int.id.name = 'isSubscribable' " +
                              "and int.value='1')*/ ")";

            for (Iterator<String> blogIter = subscribedBlogs.iterator(); blogIter.hasNext();) {
                String blogSpace = (String) blogIter.next();
                Document blogDoc = getBlogPageByBlogSpace(blogSpace, context).newDocument(context);
                com.xpn.xwiki.api.Object obj = blogDoc.getObject("Celements2.BlogConfigClass");
                Property prop = obj.getProperty("is_subscribable");
                LOGGER.debug("blogDoc is '" + blogDoc.getFullName() + "' and obj is '" + obj
                        + "' the is_subscribable property is '" + prop + "'");
                if (prop != null) {
                    int isSubscribable = Integer.parseInt(prop.getValue().toString());
                    LOGGER.debug("is_subscribable property exists and its value is: '" + isSubscribable + "'");
                    if (isSubscribable == 1) {
                        if (subscribedBlogsStr.length() > 0) {
                            subscribedBlogsStr += "or ";
                        } else {
                            subscribedBlogsStr = "or ((";
                        }
                        subscribedBlogsStr += "doc.space='" + blogSpace + "' ";
                    }
                }
            }

            if (subscribedBlogsStr.length() > 0) {
                subscribedBlogsStr += ") " + subscribableHQL;
            }

        }

        String hql = "select doc.fullName from XWikiDocument as doc, BaseObject as obj, "
                + "DateProperty as date, StringProperty as lang" + useInt;
        hql += "where obj.name=doc.fullName ";
        hql += "and obj.className='XWiki.ArticleClass' ";
        hql += "and (doc.space = '" + blogArticleSpace + "' " + subscribedBlogsStr + ") ";
        hql += "and lang.id.id=obj.id ";
        hql += "and lang.id.name='lang' ";
        hql += "and lang.value = '" + language + "' ";
        hql += "and obj.id = date.id.id ";
        hql += "and date.id.name='publishdate' ";
        hql += "order by date.value desc, doc.creationDate desc ";

        LOGGER.debug("hql built: " + hql);
        return hql;
    }

    @SuppressWarnings("unchecked")
    public String subscribeNewsletter(boolean inactiveWithoutMail, XWikiContext context) throws XWikiException {
        Map<String, String> request = new HashMap<String, String>();
        Map<String, String[]> req = context.getRequest().getParameterMap();
        for (String key : req.keySet()) {
            if ((req.get(key) != null) && (req.get(key).length > 0)) {
                request.put(key, req.get(key)[0]);
            }
        }
        return subscribeNewsletter(inactiveWithoutMail, request, context);
    }

    public Map<String, String> batchImportReceivers(boolean inactive, String importData, String newsletterFullName,
            XWikiContext context) {
        LOGGER.info("Starting batch newsletter receiver import.");
        Map<String, String> results = new TreeMap<String, String>();
        Map<String, String> data = new HashMap<String, String>();
        data.put("subsBlog", newsletterFullName);
        for (String emailCandidate : splitImportDataToEmailCandidates(importData)) {
            if (containsEmailAddress(emailCandidate)) {
                String email = extractEmailFromString(emailCandidate);
                email = email.toLowerCase();
                data.put("emailadresse", email);
                XWikiDocument userDoc = null;
                try {
                    String userDocName = subscribeNewsletter(inactive, data, context);
                    if ("".equals(userDocName)) {
                        userDocName = getSubscriberDoc(email, context);
                    }
                    userDoc = context.getWiki().getDocument(userDocName, context);
                } catch (XWikiException e) {
                    LOGGER.error(
                            "Exception while subscribing email '" + email + "' to '" + newsletterFullName + "'", e);
                }
                if (userDoc != null) {
                    BaseObject subsObj = userDoc.getObject("Celements.NewsletterReceiverClass", "subscribed",
                            newsletterFullName, false);
                    if ((subsObj != null) && (subsObj.getIntValue("isactive") == 1)) {
                        results.put(email, context.getMessageTool().get("cel_newsletter_subscriber_active"));
                    } else {
                        results.put(email, context.getMessageTool().get("cel_newsletter_subscriber_inactive"));
                    }
                } else {
                    results.put(email, context.getMessageTool().get("cel_newsletter_subscriber_invalid"));
                }
            } else {
                if (emailCandidate.trim().length() > 0) {
                    results.put(emailCandidate, context.getMessageTool().get("cel_newsletter_subscriber_invalid"));
                }
            }
        }
        return results;
    }

    String[] splitImportDataToEmailCandidates(String importData) {
        return importData.split("[,\r\n]+");
    }

    String extractEmailFromString(String emailCandidate) {
        return emailCandidate.replaceAll(getContainsEmailRegex(), "$1");
    }

    boolean containsEmailAddress(String email) {
        return email.matches(getContainsEmailRegex());
    }

    String getContainsEmailRegex() {
        return ".*?([\\w+\\.\\-\\_]+[@][\\w\\-\\_]+([.][\\w\\-\\_]+)+).*";
    }

    public String subscribeNewsletter(boolean inactiveWithoutMail, Map<String, String> request,
            XWikiContext context) throws XWikiException {
        XWiki wiki = context.getWiki();
        boolean subscribed = false;
        String email = request.get("emailadresse");
        email = email.toLowerCase();
        String docName = getSubscriberDocName(email, context);
        LOGGER.info("ReceiverDoc is " + docName);
        XWikiDocument receiverDoc = wiki.getDocument(docName, context);
        XWikiDocument blogDoc = getBlogDoc(request, context);
        BaseObject obj = receiverDoc.getObject("Celements.NewsletterReceiverClass", "subscribed",
                blogDoc.getFullName(), false);
        if ((email != null) && !"".equals(email.trim()) && (obj == null)) {
            obj = receiverDoc.newObject("Celements.NewsletterReceiverClass", context);
            obj.setStringValue("email", email);
            if (!"XWiki.XWikiGuest".equals(context.getUser()) && !inactiveWithoutMail) {
                obj.setIntValue("isactive", 1);
            } else {
                obj.setIntValue("isactive", 0);
            }
            obj.setStringValue("subscribed", blogDoc.getFullName());
            wiki.saveDocument(receiverDoc, context);
            LOGGER.info("new ReceiverObj is " + obj);
            subscribed = true;
        }
        if ((obj != null) && (obj.getIntValue("isactive") == 1) && inactiveWithoutMail) {
            obj.setIntValue("isactive", 0);
            wiki.saveDocument(receiverDoc, context);
        }
        LOGGER.trace("getStringValue: " + obj.getStringValue("subscribed"));
        if ((obj != null) && (obj.getIntValue("isactive") != 1) && "XWiki.XWikiGuest".equals(context.getUser())
                && !inactiveWithoutMail) {
            sendNewsletterActivationMail(obj, blogDoc, docName, request, context);
            subscribed = true;
        }
        if (!subscribed) {
            docName = "";
        }
        return docName;
    }

    void sendNewsletterActivationMail(BaseObject obj, XWikiDocument blogDoc, String docName,
            Map<String, String> request, XWikiContext context) throws XWikiException {
        String email = request.get("emailadresse");
        email = email.toLowerCase();
        if (context.getWiki().exists("Tools.NewsletterSubscriptionActivation", context)) {
            VelocityContext vcontext = ((VelocityContext) context.get("vcontext"));
            vcontext.put("activationKey", getActivationKey(obj, docName));
            vcontext.put("blog", blogDoc);
            vcontext.put("email", email);
            XWikiDocument emailContentDoc = context.getWiki().getDocument("Tools.NewsletterSubscriptionActivation",
                    context);
            String emailContent = emailContentDoc.getTranslatedContent(context);
            String htmlContent = context.getWiki().getRenderingEngine().interpretText(emailContent,
                    context.getDoc(), context);
            String emailTitle = emailContentDoc.getTranslatedDocument(context).getTitle();
            String renderedTitle = context.getWiki().getRenderingEngine().interpretText(emailTitle,
                    context.getDoc(), context);
            BaseObject blogConf = blogDoc.getObject("Celements2.BlogConfigClass");
            String from = "";
            String reply = "";
            if (blogConf != null) {
                from = blogConf.getStringValue("from_address");
                reply = blogConf.getStringValue("reply_to_address");
            }
            if ((from == null) || "".equals(from.trim())) {
                from = context.getWiki().getXWikiPreference("admin_email", context);
            }
            if ((reply == null) || "".equals(reply.trim())) {
                reply = from;
            }
            CelementsWebPluginApi celementsweb = (CelementsWebPluginApi) context.getWiki()
                    .getPluginApi("celementsweb", context);
            celementsweb.getPlugin().sendMail(from, reply, email, null, null, renderedTitle, htmlContent, "", null,
                    null, context);
        } else {
            LOGGER.error("No newsletter activation Mail sent for '" + email + "'. No "
                    + "Mailcontent found in Tools.NewsletterSubscriptionActivation");
        }
    }

    String getActivationKey(BaseObject obj, String docName) {
        String key = docName + "|" + obj.getNumber();
        MessageDigest digest = null;
        try {
            digest = MessageDigest.getInstance("SHA-1");
            digest.update(key.getBytes());
        } catch (NoSuchAlgorithmException e) {
            LOGGER.error("SHA-1 algorithm not available.");
        }
        String hash = "";
        if (digest != null) {
            hash = new String((new Hex()).encode(digest.digest()));
        }
        return hash;
    }

    private String getSubscriberDocName(String email, XWikiContext context) throws XWikiException {
        XWiki wiki = context.getWiki();
        String docName = getSubscriberDoc(email, context);
        if ("".equals(docName) || !wiki.exists(docName, context)) {
            while ("".equals(docName) || wiki.exists(docName, context)) {
                docName = DEFAULT_RECEIVER_SPACE + "." + wiki.generateRandomString(16);
            }
        }
        return docName;
    }

    public boolean unsubscribeNewsletter(XWikiContext context) throws XWikiException {
        boolean unsubscribed = false;
        String email = context.getRequest().get("emailadresse");
        email = email.toLowerCase();
        XWikiDocument blogDoc = getBlogDoc(null, context);
        String subsDocName = getSubscriberDoc(email, context);
        if (!"".equals(subsDocName) && context.getWiki().exists(subsDocName, context)) {
            XWikiDocument subscribedDoc = context.getWiki().getDocument(subsDocName, context);
            BaseObject subsObj = subscribedDoc.getObject("Celements.NewsletterReceiverClass", "subscribed",
                    blogDoc.getFullName(), false);
            if (subsObj != null) {
                subsObj.setIntValue("isactive", 0);
                context.getWiki().saveDocument(subscribedDoc, context);
                //TODO send email to notice unsubscription - necessary?
                unsubscribed = true;
            }
        }
        BaseObject obj = blogDoc.getObject("Celements2.ReceiverEMail", "email", email, false);
        if ((obj != null) && (email != "")) {
            obj.setIntValue("is_active", 0);
            context.getWiki().saveDocument(blogDoc, context);
            //TODO send email to notice unsubscription - necessary?
            unsubscribed = true;
        }

        return unsubscribed;
    }

    public String getSubscriberDoc(String email, XWikiContext context) throws XWikiException {
        email = email.toLowerCase();
        String hql = "select distinct doc.fullName " + "from XWikiDocument as doc, BaseObject as obj, "
                + "Celements.NewsletterReceiverClass as nr " + "where doc.fullName=obj.name " + "and obj.id=nr.id "
                + "and nr.email='" + email + "'";
        List<String> docs = context.getWiki().search(hql, context);
        String docName = "";
        if ((docs != null) && (docs.size() > 0)) {
            docName = docs.get(0);
        }
        return docName;
    }

    public boolean activateSubscriber(XWikiContext context) throws XWikiException {
        boolean activated = false;
        String email = context.getRequest().get("emailadresse");
        email = email.toLowerCase();
        String activationKey = context.getRequest().get("ak");
        String subscriberDocName = getSubscriberDoc(email, context);
        if (!"".equals(subscriberDocName.trim()) && context.getWiki().exists(subscriberDocName, context)) {
            XWikiDocument subscriberDoc = context.getWiki().getDocument(subscriberDocName, context);
            List<BaseObject> subscriptions = subscriberDoc.getObjects("Celements.NewsletterReceiverClass");
            if (subscriptions != null) {
                for (BaseObject subscription : subscriptions) {
                    if ((subscription != null) && (subscription.getIntValue("isactive") != 1)
                            && activationKey.equals(getActivationKey(subscription, subscriberDoc.getFullName()))) {
                        subscription.setIntValue("isactive", 1);
                        context.getWiki().saveDocument(subscriberDoc, context);
                        activated = true;
                    }
                }
            }
        }
        return activated;
    }

    public XWikiDocument getBlogDoc(Map<String, String> request, XWikiContext context) throws XWikiException {
        XWikiDocument doc = context.getDoc();
        if ((doc.getObject("Celements2.BlogConfigClass") == null)
                && (doc.getObject("XWiki.ArticleClass") != null)) {
            doc = getBlogPageByBlogSpace(doc.getSpace(), context);
        }
        if (request != null) {
            String subscribeBlog = request.get("subsBlog");
            if ((subscribeBlog != null) && !"".equals(subscribeBlog.trim())
                    && context.getWiki().exists(subscribeBlog, context)) {
                doc = context.getWiki().getDocument(subscribeBlog, context);
            }
        }
        LOGGER.info("BlogDoc is " + doc.getFullName());
        return doc;
    }

    /**
     * Get the previous or next article in the blog. Does not take into account subscribed 
     * blogs or archived articles.
     * @param article
     * @param next true gets the next, false the previous article
     * @return
     */
    public Article getNeighbourArticle(Article article, boolean next, XWikiContext context) {
        String aSpace = article.getDocName().substring(0, article.getDocName().indexOf('.'));
        List<Article> articles = null;
        try {
            articles = getBlogArticles(aSpace, "", context.getLanguage(), false, false, false, false, true, true,
                    true, false, true, true, context);
        } catch (XWikiException e) {
            LOGGER.error("could not get articles for blog");
        }
        Article nArticle = null;
        if (articles != null) {
            for (int i = 0; i < articles.size(); i++) {
                Article tmpArt = articles.get(i);
                if (article.getDocName().equals(tmpArt.getDocName())) {
                    if (next) {
                        if ((i + 1) == articles.size()) {
                            nArticle = articles.get(0);
                        } else {
                            nArticle = articles.get(i + 1);
                        }
                    } else {
                        if (i == 0) {
                            nArticle = articles.get(articles.size() - 1);
                        } else {
                            nArticle = articles.get(i - 1);
                        }
                    }
                }
            }
        }
        return nArticle;
    }

    private IBlogServiceRole getBlogService() {
        if (injected_BlogService != null) {
            return injected_BlogService;
        }
        return Utils.getComponent(IBlogServiceRole.class);
    }

}