org.agnitas.web.MailingBaseAction.java Source code

Java tutorial

Introduction

Here is the source code for org.agnitas.web.MailingBaseAction.java

Source

/*********************************************************************************
 * The contents of this file are subject to the Common Public Attribution
 * License Version 1.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.openemm.org/cpal1.html. The License is based on the Mozilla
 * Public License Version 1.1 but Sections 14 and 15 have been added to cover
 * use of software over a computer network and provide for limited attribution
 * for the Original Developer. In addition, Exhibit A has been modified to be
 * consistent with Exhibit B.
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 * 
 * The Original Code is OpenEMM.
 * The Original Developer is the Initial Developer.
 * The Initial Developer of the Original Code is AGNITAS AG. All portions of
 * the code written by AGNITAS AG are Copyright (c) 2007 AGNITAS AG. All Rights
 * Reserved.
 * 
 * Contributor(s): AGNITAS AG. 
 ********************************************************************************/

package org.agnitas.web;

import org.agnitas.beans.Mailing;
import org.agnitas.beans.MailingBase;
import org.agnitas.beans.MailingComponent;
import org.agnitas.beans.MediatypeEmail;
import org.agnitas.beans.factory.MailingFactory;
import org.agnitas.cms.utils.CmsUtils;
import org.agnitas.dao.CampaignDao;
import org.agnitas.dao.MailingDao;
import org.agnitas.dao.MailinglistDao;
import org.agnitas.dao.TargetDao;
import org.agnitas.exceptions.CharacterEncodingValidationException;
import org.agnitas.preview.AgnTagException;
import org.agnitas.preview.PreviewHelper;
import org.agnitas.preview.TAGCheck;
import org.agnitas.preview.TAGCheckFactory;
import org.agnitas.service.MailingsQueryWorker;
import org.agnitas.util.AgnUtils;
import org.agnitas.util.CharacterEncodingValidator;
import org.agnitas.util.SafeString;
import org.agnitas.web.forms.MailingBaseForm;
import org.apache.commons.lang.StringUtils;
import org.apache.struts.Globals;
import org.apache.struts.action.*;
import org.springframework.context.ApplicationContext;
import org.springframework.dao.TransientDataAccessResourceException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.mail.internet.InternetAddress;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * Implementation of <strong>Action</strong> that handles Mailings
 *
 * @author Martin Helff
 */

public class MailingBaseAction extends StrutsActionBase {

    public static final String FUTURE_TASK = "GET_MAILING_LIST";

    public static final int ACTION_SELECT_TEMPLATE = ACTION_LAST + 1;

    public static final int ACTION_REMOVE_TARGET = ACTION_LAST + 2;

    public static final int ACTION_VIEW_WITHOUT_LOAD = ACTION_LAST + 3;

    public static final int ACTION_CLONE_AS_MAILING = ACTION_LAST + 4;

    public static final int ACTION_USED_ACTIONS = ACTION_LAST + 5;

    public static final int ACTION_VIEW_TABLE_ONLY = ACTION_LAST + 6;

    public static final int ACTION_MAILING_BASE_LAST = ACTION_LAST + 6;

    protected MailinglistDao mailinglistDao;

    protected MailingDao mailingDao;

    protected AbstractMap<String, Future> futureHolder;

    protected TargetDao targetDao;

    protected TAGCheckFactory tagCheckFactory;

    protected ExecutorService executorService;

    protected CampaignDao campaignDao;

    protected CharacterEncodingValidator characterEncodingValidator;

    protected MailingFactory mailingFactory;

    // --------------------------------------------------------- Public Methods

    /**
     * Process the specified HTTP request, and create the corresponding HTTP
     * response (or forward to another web component that will create it).
     * Return an <code>ActionForward</code> instance describing where and how
     * control should be forwarded, or <code>null</code> if the response has
     * already been completed.
     * <br>
    * ACTION_LIST: Initializes columns width list for the mailings-list-table, forwards to "list"
    * <br><br>
    * ACTION_SAVE: validates character encoding in mailing subject, mailing components and content blocks;
     *     saves mailing in database;
     *     if the current mailing is template - updates all mailings using this template with dynamic-template
     *     property set and saves these mailings to database;
     *     loads saved mailing into form;
     *     if the mailing was cloned and the original mailing has cms data, clones cms data for the saved mailing;
     *     forwards to "view".
    * <br><br>
     * ACTION_VIEW: loads mailing data from database into a form, forwards to "view". Also resets showTemplate property
     *     of form which indicates if new need to show the template-section of a mailing.
     * <br><br>
     * ACTION_NEW: checks if there is at least one mailinglist in database: shows error message if no mailing list was found,
     *     if the mailinglist exists - clears the form and forwards to "view".
     * <br><br>
     * ACTION_REMOVE_TARGET: removes given target group from the list of chosen target groups; forwards to "view".
     * <br><br>
     * ACTION_SELECT_TEMPLATE: loads the settings of chosen template into current form (mailing type, mailinglist,
     *     target-groups etc.); doesn't save mailing to database; forwards to "view".
     * <br><br>
     * ACTION_CLONE_AS_MAILING: clears the form; sets the properties of original mailing to form (original mailing
     *     is mailing used as source for cloning); names the new mailing as "Copy of " + name of original; stores
     *     the id of original mailing in form as templateID; forwards to mailing view page.
     * <br><br>
     * ACTION_USED_ACTIONS: loads map of emm actions used by current mailing into form; forwards to mailing actions
     *     page (forward is "action").
     * <br><br>
     * ACTION_VIEW_WITHOUT_LOAD: just forwards to "view" without reloading form data (is used after failing form
     *     validation).
     * <br><br>
    * ACTION_CONFIRM_DELETE: loads mailing into form; forwards to jsp with question to confirm deletion (forward
     *     is "delete").
    * <br><br>
    * ACITON_DELETE: marks the mailing as deleted in database; forwards to "list".
    * <br><br>
    * Any other ACTION_* would cause a forward to "list"
     * <br><br>
     * If destination is "list" - calls a FutureHolder to get the list of mailings/templates according to selected
     * mailing types and isTemplate form-property (indicates if we we work with templates or mailings). <br>
     * If the Future object is not ready, increases the page refresh time by 50ms until it reaches 1 second.
     * (The page refresh time - is the wait-time before calling the action again while the FutureHolder is
     * running; the initial value is 250ms). While the FutureHolder is running - destination is "loading".<br>
     * When the FutureHolder is finished - the list of mailings/templates is set to request, the destination is "list".
     * <br><br>
     * If destination is "view": updates oldMailFormat property with the current value;<br>
     * loads list of templates and template name to form;<br>
     * loads mailinglists, campaigns, target groups and selected target groups into form.
     * <br><br>
     * If destination is null and there are errors found - forwards to "list"
     * @param form  ActionForm object
     * @param req   request
     * @param res   response
     * @param mapping The ActionMapping used to select this instance
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet exception occurs
     * @return destination
     */
    @Override
    public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest req,
            HttpServletResponse res) throws IOException, ServletException {

        // Validate the request parameters specified by the user
        MailingBaseForm aForm = null;
        ActionMessages errors = new ActionMessages();
        ActionMessages messages = new ActionMessages();
        ActionForward destination = null;
        boolean showTemplates = false;
        ApplicationContext aContext = WebApplicationContextUtils
                .getRequiredWebApplicationContext(req.getSession().getServletContext());

        if (!AgnUtils.isUserLoggedIn(req)) {
            return mapping.findForward("logon");
        }

        aForm = (MailingBaseForm) form;

        AgnUtils.logger().info("execute: action " + aForm.getAction());

        boolean hasAnyPermission = true;

        if (aForm.isIsTemplate()) {
            if (!allowed("template.show", req)) {
                errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied"));
                saveErrors(req, errors);
                hasAnyPermission = false;
                //return null;
            }
        } else {
            if (!allowed("mailing.show", req)) {
                errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied"));
                saveErrors(req, errors);
                hasAnyPermission = false;
                //return null;
            }
        }

        req.setAttribute("hasPermission", hasAnyPermission);

        if (hasAnyPermission) {

            if (aForm.getAction() != MailingBaseAction.ACTION_SAVE) {
                aForm.setOriginalMailingId(0);
            }

            try {
                switch (aForm.getAction()) {
                case MailingBaseAction.ACTION_LIST:
                    if (aForm.getColumnwidthsList() == null) {
                        aForm.setColumnwidthsList(getInitializedColumnWidthList(5));
                    }
                    destination = mapping.findForward("list");
                    break;
                case MailingBaseAction.ACTION_NEW:
                    if (allowed("mailing.new", req)) {
                        List mlists = mailinglistDao.getMailinglists(getCompanyID(req));

                        if (mlists.size() > 0) {
                            aForm.setAction(MailingBaseAction.ACTION_SAVE);
                            int campaignID = aForm.getCampaignID();
                            aForm.clearData(getCompanyID(req), getDefaultMediaType(req));
                            aForm.setMailingID(0);
                            aForm.setCampaignID(campaignID);
                            destination = mapping.findForward("view");
                        } else {
                            errors.add(ActionErrors.GLOBAL_MESSAGE,
                                    new ActionMessage("error.mailing.noMailinglist"));
                        }
                    } else {
                        errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied"));
                    }
                    break;

                case MailingBaseAction.ACTION_VIEW:
                    aForm.setAction(MailingBaseAction.ACTION_SAVE);
                    resetShowTemplate(req, aForm);
                    loadMailing(aForm, req);
                    destination = mapping.findForward("view");
                    break;

                case MailingBaseAction.ACTION_VIEW_WITHOUT_LOAD:
                    aForm.setAction(MailingBaseAction.ACTION_SAVE);
                    destination = mapping.findForward("view");
                    break;

                case MailingBaseAction.ACTION_REMOVE_TARGET:
                    removeTarget(aForm, req);
                    aForm.setAction(MailingBaseAction.ACTION_SAVE);
                    destination = mapping.findForward("view");
                    break;

                case MailingBaseAction.ACTION_SAVE:
                    if (allowed("mailing.change", req)) {
                        destination = mapping.findForward("view");

                        try {
                            validateMailing(aForm, req);
                        } catch (CharacterEncodingValidationException e) {
                            if (!e.isSubjectValid())
                                errors.add(ActionMessages.GLOBAL_MESSAGE,
                                        new ActionMessage("error.charset.subject"));
                            for (String mailingComponent : e.getFailedMailingComponents())
                                errors.add(ActionMessages.GLOBAL_MESSAGE,
                                        new ActionMessage("error.charset.component", mailingComponent));
                            for (String dynTag : e.getFailedDynamicTags())
                                errors.add(ActionMessages.GLOBAL_MESSAGE,
                                        new ActionMessage("error.charset.content", dynTag));
                        }

                        try {
                            saveMailing(aForm, req, messages);
                            loadMailing(aForm, req);
                            // Show "changes saved"
                            messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("default.changes_saved"));
                        } catch (AgnTagException e) {
                            req.setAttribute("errorReport", e.getReport());
                            errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.template.dyntags"));
                        } catch (TransientDataAccessResourceException e) {
                            AgnUtils.logger().error("execute: " + e + "\n" + AgnUtils.getStackTrace(e));
                            errors.add(ActionMessages.GLOBAL_MESSAGE,
                                    new ActionMessage("error.hibernate.attachmentTooLarge"));
                        }

                        showTemplates = aForm.isShowTemplate();
                        aForm.setShowTemplate(showTemplates);

                        // copy CMS data of cloned mailing if the original
                        // mailing included CMS content
                        if (aForm.getOriginalMailingId() != 0) {
                            if (CmsUtils.mailingHasCmsData(aForm.getOriginalMailingId(), aContext)) {
                                CmsUtils.cloneMailingCmsData(aForm.getOriginalMailingId(), aForm.getMailingID(),
                                        aContext);
                            }
                            aForm.setOriginalMailingId(0);
                        }

                    } else {
                        errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied"));
                    }
                    break;

                case MailingBaseAction.ACTION_SELECT_TEMPLATE:
                    loadTemplateSettings(aForm, req);
                    aForm.setAction(MailingBaseAction.ACTION_SAVE);
                    destination = mapping.findForward("view");
                    break;

                case MailingBaseAction.ACTION_CLONE_AS_MAILING:
                    if (allowed("mailing.copy", req)) {
                        aForm.setOriginalMailingId(aForm.getMailingID());
                        int tmpTemplateID = aForm.getMailingID();
                        int tmpMlId = aForm.getMailinglistID();
                        String sname = aForm.getShortname();
                        int tmpFormat = aForm.getMediaEmail().getMailFormat();
                        boolean tmpl = aForm.isIsTemplate();
                        String tempDescription = aForm.getDescription();
                        aForm.clearData(this.getCompanyID(req), this.getDefaultMediaType(req));
                        aForm.setTemplateID(tmpTemplateID);
                        aForm.setIsTemplate(tmpl);
                        loadTemplateSettings(aForm, req);
                        aForm.setMailinglistID(tmpMlId);
                        aForm.getMediaEmail().setMailFormat(tmpFormat);
                        aForm.setMailingID(0);
                        aForm.setAction(MailingBaseAction.ACTION_SAVE);
                        aForm.setShortname(SafeString.getLocaleString("mailing.CopyOf",
                                (Locale) req.getSession().getAttribute(Globals.LOCALE_KEY)) + " " + sname);
                        //                        aForm.setDescription(SafeString.getLocaleString("default.description", (Locale)req.getSession().getAttribute(Globals.LOCALE_KEY)));
                        aForm.setDescription(tempDescription);
                        aForm.setCopyFlag(true);
                        destination = mapping.findForward("view");
                    } else {
                        errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied"));
                    }
                    break;

                case MailingBaseAction.ACTION_CONFIRM_DELETE:
                    if (allowed("mailing.delete", req)) {
                        aForm.setAction(MailingBaseAction.ACTION_DELETE);
                        loadMailing(aForm, req);
                        destination = mapping.findForward("delete");
                    } else {
                        errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied"));
                    }
                    break;

                case MailingBaseAction.ACTION_DELETE:
                    if (allowed("mailing.delete", req)) {
                        aForm.setAction(MailingBaseAction.ACTION_LIST);
                        deleteMailing(aForm, req);
                        destination = mapping.findForward("list");

                        messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("default.changes_saved"));
                        aForm.setMessages(messages);
                    } else {
                        errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied"));
                    }
                    break;

                case MailingBaseAction.ACTION_USED_ACTIONS:
                    loadActions(aForm, req);
                    destination = mapping.findForward("action");
                    break;

                default:
                    aForm.setAction(MailingBaseAction.ACTION_LIST);
                    destination = mapping.findForward("list");
                }

            } catch (Exception e) {
                AgnUtils.logger().error("execute: " + e + "\n" + AgnUtils.getStackTrace(e));
                errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage("error.exception"));
            }

            if (destination != null && "list".equals(destination.getName())) {
                try {
                    setNumberOfRows(req, aForm);
                    destination = mapping.findForward("loading");
                    String key = FUTURE_TASK + "@" + req.getSession(false).getId();

                    if (!futureHolder.containsKey(key)) {
                        Future mailingListFuture = getMailingListFuture(req, aForm.getTypes(), aForm.isIsTemplate(),
                                aForm);
                        futureHolder.put(key, mailingListFuture);
                    }

                    if (futureHolder.containsKey(key) && futureHolder.get(key).isDone()) {
                        req.setAttribute("mailinglist", futureHolder.get(key).get());
                        destination = mapping.findForward("list");
                        futureHolder.remove(key);
                        aForm.setRefreshMillis(RecipientForm.DEFAULT_REFRESH_MILLIS);
                        saveMessages(req, aForm.getMessages());
                        saveErrors(req, aForm.getErrors());
                        aForm.setMessages(null);
                        aForm.setErrors(null);
                    } else {
                        if (aForm.getRefreshMillis() < 1000) { // raise the refresh time
                            aForm.setRefreshMillis(aForm.getRefreshMillis() + 50);
                        }
                        aForm.setError(false);
                    }

                } catch (Exception e) {
                    AgnUtils.logger().error("getMailingList: " + e + "\n" + AgnUtils.getStackTrace(e));
                    errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage("error.exception"));
                    aForm.setError(true); // do not refresh when an error has been occurred
                }
            }

            checkShowDynamicTemplateCheckbox(aForm, req);

            if (destination != null && "view".equals(destination.getName())) {
                if (aForm.getMediaEmail() != null) {
                    aForm.setOldMailFormat(aForm.getMediaEmail().getMailFormat());
                }
                aForm.setTemplateMailingBases(mailingDao.getTemplateMailingsByCompanyID(getCompanyID(req)));
                if (aForm.getTemplateID() != 0) {
                    MailingBase mb = mailingDao.getMailingForTemplateID(aForm.getTemplateID(), getCompanyID(req));
                    aForm.setTemplateShortname(mb.getShortname().compareTo("") != 0 ? mb.getShortname()
                            : SafeString.getLocaleString("mailing.No_Template",
                                    (Locale) req.getSession().getAttribute(Globals.LOCALE_KEY)));
                } else
                    aForm.setTemplateShortname(SafeString.getLocaleString("mailing.No_Template",
                            (Locale) req.getSession().getAttribute(Globals.LOCALE_KEY)));

                aForm.setMailingLists(mailinglistDao.getMailinglists(getCompanyID(req)));
                aForm.setCampaigns(campaignDao.getCampaignList(getCompanyID(req), "lower(shortname)", 1));
                aForm.setTargetGroupsList(targetDao.getTargetGroup(getCompanyID(req), aForm.getTargetGroups()));
                aForm.setTargets(targetDao.getUnchoosenTargets(getCompanyID(req), aForm.getTargetGroups()));
            }
        }

        // Report any errors we have discovered back to the original form
        if (!errors.isEmpty()) {
            saveErrors(req, errors);
            if (destination == null) {
                destination = mapping.findForward("list");
            }
        }

        // Report any message (non-errors) we have discovered
        if (!messages.isEmpty()) {
            saveMessages(req, messages);
        }

        return destination;
    }

    /**
     * Validates mailing subject, mailing components and dynamic tags
     *
     * @param form MailingBaseForm object
     * @param req  request
     * @throws CharacterEncodingValidationException contains numbers of line and position of wrong character
     */
    protected void validateMailing(MailingBaseForm form, HttpServletRequest req)
            throws CharacterEncodingValidationException {
        Mailing mailing = mailingDao.getMailing(form.getMailingID(), getCompanyID(req));
        characterEncodingValidator.validate(form, mailing);
    }

    protected void resetShowTemplate(HttpServletRequest req, MailingBaseForm aForm) {
        String showTemplate = req.getParameter("showTemplate");
        if (showTemplate == null || !showTemplate.equals("true")) {
            aForm.setShowTemplate(false);
        }
    }

    /**
     * Loads mailing data from db.
     *
     * @param aForm  MailingBaseForm object
     * @param req request
     * @throws Exception
     */
    protected void loadMailing(MailingBaseForm aForm, HttpServletRequest req) throws Exception {
        MediatypeEmail type = null;
        MailingComponent comp = null;
        Mailing aMailing = mailingDao.getMailing(aForm.getMailingID(), getCompanyID(req));
        ApplicationContext aContext = WebApplicationContextUtils
                .getRequiredWebApplicationContext(req.getSession().getServletContext());
        if (aMailing == null) {
            aMailing = mailingFactory.newMailing();
            aMailing.init(getCompanyID(req), aContext);
            aMailing.setId(0);
            aForm.setMailingID(0);
        }

        aForm.setShortname(aMailing.getShortname());
        aForm.setDescription(aMailing.getDescription());
        aForm.setMailingType(aMailing.getMailingType());
        aForm.setMailinglistID(aMailing.getMailinglistID());
        aForm.setTemplateID(aMailing.getMailTemplateID());
        aForm.setTargetGroups(aMailing.getTargetGroups());
        aForm.setMediatypes(aMailing.getMediatypes());
        aForm.setArchived(aMailing.getArchived() != 0);
        aForm.setCampaignID(aMailing.getCampaignID());
        aForm.setTargetMode(aMailing.getTargetMode());
        aForm.setWorldMailingSend(aMailing.isWorldMailingSend());
        aForm.setUseDynamicTemplate(aMailing.getUseDynamicTemplate());

        type = aMailing.getEmailParam();
        if (type != null) {
            aForm.setEmailSubject(type.getSubject());
            aForm.setEmailOnepixel(type.getOnepixel());
            try {
                aForm.setEmailReplytoEmail(new InternetAddress(type.getReplyAdr()).getAddress());
            } catch (Exception e) {
                // do nothing
            }
            try {
                aForm.setEmailReplytoFullname(new InternetAddress(type.getReplyAdr()).getPersonal());
            } catch (Exception e) {
                // do nothing
            }
            aForm.setEmailLinefeed(type.getLinefeed());
            aForm.setEmailCharset(type.getCharset());
        }

        comp = aMailing.getTextTemplate();
        if (comp != null) {
            aForm.setTextTemplate(comp.getEmmBlock());
        }

        comp = aMailing.getHtmlTemplate();
        if (comp != null) {
            aForm.setHtmlTemplate(comp.getEmmBlock());
        }

        String entityName = aMailing.isIsTemplate() ? "template" : "mailing";
        AgnUtils.userlogger().info(
                AgnUtils.getAdmin(req).getUsername() + ": do load " + entityName + " " + aMailing.getShortname());

        AgnUtils.logger().info("loadMailing: mailing loaded");
    }

    /**
     * Removes target group from the list of chosen targets.
     *
     * @param aForm  MailingBaseForm object
     * @param req request
     * @throws Exception
     */
    protected void removeTarget(MailingBaseForm aForm, HttpServletRequest req) throws Exception {
        Collection<Integer> allTargets = aForm.getTargetGroups();
        Integer tmpInt = null;

        if (allTargets != null) {
            Iterator<Integer> aIt = allTargets.iterator();
            while (aIt.hasNext()) {
                tmpInt = aIt.next();
                if (aForm.getTargetID() == tmpInt.intValue()) {
                    allTargets.remove(tmpInt);
                    break;
                }
            }
        }

        if (allTargets.isEmpty()) {
            aForm.setTargetGroups(null);
        }
    }

    /**
     * Gets mailing template data from db and calls method for loading the data into form.
     *
     * @param aForm  MailingBaseForm object
     * @param req  request
     * @throws Exception
     */
    protected void loadTemplateSettings(MailingBaseForm aForm, HttpServletRequest req) throws Exception {
        Mailing aTemplate = null;

        if (aForm.getTemplateID() != 0) {

            aTemplate = mailingDao.getMailing(aForm.getTemplateID(), this.getCompanyID(req));
            if (aTemplate != null) {
                copyTemplateSettingsToMailingForm(aTemplate, aForm);
            }
        }
    }

    /**
     * Loads chosen mailing template data into form.
     *
     * @param template  Mailing bean object, contains mailing template data
     * @param mailingBaseForm  MailingBaseForm object
     */
    protected void copyTemplateSettingsToMailingForm(Mailing template, MailingBaseForm mailingBaseForm) {
        MailingComponent tmpComp = null;

        mailingBaseForm.setMailingType(template.getMailingType());
        mailingBaseForm.setMailinglistID(template.getMailinglistID());
        mailingBaseForm.setTargetMode(template.getTargetMode());
        mailingBaseForm.setTargetGroups(template.getTargetGroups());
        mailingBaseForm.setMediatypes(template.getMediatypes());
        mailingBaseForm.setArchived(template.getArchived() != 0);
        mailingBaseForm.setCampaignID(template.getCampaignID());
        mailingBaseForm.setNeedsTarget(template.getNeedsTarget());
        mailingBaseForm.setUseDynamicTemplate(template.getUseDynamicTemplate());

        // load template for this mailing
        if ((tmpComp = template.getHtmlTemplate()) != null) {
            mailingBaseForm.setHtmlTemplate(tmpComp.getEmmBlock());
        }

        if ((tmpComp = template.getTextTemplate()) != null) {
            mailingBaseForm.setTextTemplate(tmpComp.getEmmBlock());
        }
        MediatypeEmail type = template.getEmailParam();
        if (type != null) {
            mailingBaseForm.setEmailOnepixel(type.getOnepixel());
            try {
                mailingBaseForm.setEmailReplytoEmail(new InternetAddress(type.getReplyAdr()).getAddress());
            } catch (Exception e) {
                // do nothing
            }
            try {
                mailingBaseForm.setEmailReplytoFullname(new InternetAddress(type.getReplyAdr()).getPersonal());
            } catch (Exception e) {
                // do nothing
            }
            mailingBaseForm.setEmailLinefeed(type.getLinefeed());
            mailingBaseForm.setEmailCharset(type.getCharset());

        }
    }

    /**
     * Saves current mailing in DB (including mailing components, content blocks, dynamic tags, dynamic tags contents
     * and trackable links)
     *
     * @param aForm MailingBaseForm object
     * @param req  request
     * @param messages  not in use
     * @throws Exception
     */
    protected void saveMailing(MailingBaseForm aForm, HttpServletRequest req, ActionMessages messages)
            throws Exception {
        Mailing aMailing = null;
        Mailing aTemplate = null;
        MediatypeEmail paramEmail = null;
        boolean newMail = false;
        ApplicationContext aContext = WebApplicationContextUtils
                .getRequiredWebApplicationContext(req.getSession().getServletContext());

        if (aForm.getMailingID() != 0) {
            aMailing = mailingDao.getMailing(aForm.getMailingID(), this.getCompanyID(req));
        } else {
            newMail = true;
            if (aForm.getTemplateID() != 0) {
                aTemplate = mailingDao.getMailing(aForm.getTemplateID(), this.getCompanyID(req));
                aMailing = (Mailing) aTemplate.clone(aContext);
                aMailing.setId(0);
                aMailing.setMailTemplateID(aForm.getTemplateID());
                aMailing.setCompanyID(this.getCompanyID(req));
            }
        }

        if (aMailing == null) {
            aMailing = mailingFactory.newMailing();
            aMailing.init(this.getCompanyID(req), aContext);
            aMailing.setId(0);
            aForm.setMailingID(0);
        }

        if (aForm.getMediaEmail().getMailFormat() == 0) {
            aForm.getMediaEmail().setHtmlTemplate("");
        } else if (aForm.getOldMailFormat() == 0) {
            if (aForm.getMediaEmail() != null && StringUtils.isEmpty(aForm.getMediaEmail().getHtmlTemplate())) {
                aForm.getMediaEmail().setHtmlTemplate("[agnDYN name=\"HTML-Version\"/]");
            }
        }

        aMailing.setIsTemplate(aForm.isIsTemplate());
        aMailing.setCampaignID(aForm.getCampaignID());
        aMailing.setDescription(aForm.getDescription());
        aMailing.setShortname(aForm.getShortname());
        aMailing.setMailinglistID(aForm.getMailinglistID());
        aMailing.setMailingType(aForm.getMailingType());
        aMailing.setArchived(aForm.isArchived() ? 1 : 0);
        aMailing.setTargetMode(aForm.getTargetMode());
        aMailing.setTargetGroups(aForm.getTargetGroups());
        aMailing.setMediatypes(aForm.getMediatypes());
        aMailing.setUseDynamicTemplate(aForm.getUseDynamicTemplate());

        try {
            paramEmail = aMailing.getEmailParam();

            paramEmail.setSubject(aForm.getEmailSubject());
            paramEmail.setLinefeed(aForm.getEmailLinefeed());
            paramEmail.setCharset(aForm.getEmailCharset());
            paramEmail.setOnepixel(aForm.getEmailOnepixel());

            aForm.getMediaEmail().syncTemplate(aMailing, aContext);

            aMailing.buildDependencies(true, aContext);
        } catch (Exception e) {
            AgnUtils.logger()
                    .error("Error in save mailing id: " + aForm.getMailingID() + " msg: " + e.getMessage());
        }

        // validate the components
        if (!newMail) {
            Set<Entry<String, MailingComponent>> componentEntries = aMailing.getComponents().entrySet();
            List<String[]> errorReports = new ArrayList<String[]>();
            Vector<String> outFailures = new Vector<String>();
            TAGCheck tagCheck = tagCheckFactory.createTAGCheck(aMailing.getId());

            for (Entry<String, MailingComponent> mapEntry : componentEntries) {
                String tagName = mapEntry.getKey();
                MailingComponent component = mapEntry.getValue();
                String emmBlock = component.getEmmBlock();
                StringBuffer contentOutReport = new StringBuffer();
                if (!tagCheck.checkContent(emmBlock, contentOutReport, outFailures)) {
                    appendErrorsToList(tagName, errorReports, contentOutReport);
                }

            }

            if (errorReports.size() > 0) {
                throw new AgnTagException("error.template.dyntags", errorReports);
            }

        }

        mailingDao.saveMailing(aMailing);
        aForm.setMailingID(aMailing.getId());
        String entityName = aMailing.isIsTemplate() ? "template" : "mailing";

        if (aMailing.isIsTemplate()) {
            updateMailingsWithDynamicTemplate(aMailing);
        }

        if (newMail) {
            AgnUtils.userlogger().info(AgnUtils.getAdmin(req).getUsername() + ": create " + entityName + " "
                    + aMailing.getShortname());
        } else {
            AgnUtils.userlogger().info(
                    AgnUtils.getAdmin(req).getUsername() + ": edit " + entityName + " " + aMailing.getShortname());
        }
    }

    /**
     * Marks mailing as deleted and updated mailing data in database
     *
     * @param aForm MailingBaseForm object
     * @param req  request
     * @throws Exception
     */
    protected void deleteMailing(MailingBaseForm aForm, HttpServletRequest req) throws Exception {
        mailingDao.deleteMailing(aForm.getMailingID(), this.getCompanyID(req));
        String entityName = aForm.isIsTemplate() ? "template" : "mailing";
        AgnUtils.userlogger()
                .info(AgnUtils.getAdmin(req).getUsername() + ": delete " + entityName + " " + aForm.getShortname());
    }

    /**
     * Loads list of emm actions into form
     *
     * @param aForm MailingBaseForm object
     * @param req request
     * @throws Exception
     */
    protected void loadActions(MailingBaseForm aForm, HttpServletRequest req) throws Exception {
        Map<String, String> map = new HashMap<String, String>();
        map = mailingDao.loadAction(aForm.getMailingID(), this.getCompanyID(req));
        aForm.setActions(map);
    }

    /**
     * Creates paginated list by given sorting parameters and filter conditions (templates or mailings, mailings of certain types).
     *
     * @param req  request
     * @param types listed mailing types, separated with comma
     * @param isTemplate  true == templates
     *                    false==mailings
     * @param mailingBaseForm  MailingBaseForm object
     * @return Future object
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public Future getMailingListFuture(HttpServletRequest req, String types, boolean isTemplate,
            MailingBaseForm mailingBaseForm) throws IllegalAccessException, InstantiationException {

        String sort = getSort(req, mailingBaseForm);

        String direction = req.getParameter("dir");
        if (direction == null) {
            direction = mailingBaseForm.getOrder();
        } else {
            mailingBaseForm.setOrder(direction);
        }

        String pageStr = req.getParameter("page");
        if (pageStr == null || "".equals(pageStr.trim())) {
            if (mailingBaseForm.getPage() == null || "".equals(mailingBaseForm.getPage().trim())) {
                mailingBaseForm.setPage("1");
            }
            pageStr = mailingBaseForm.getPage();

        } else {
            mailingBaseForm.setPage(pageStr);
        }

        if (mailingBaseForm.isNumberOfRowsChanged()) {
            mailingBaseForm.setPage("1");
            mailingBaseForm.setNumberOfRowsChanged(false);
            pageStr = "1";
        }

        int page = Integer.parseInt(pageStr);

        int rownums = mailingBaseForm.getNumberofRows();
        Future future = executorService.submit(new MailingsQueryWorker(mailingDao, AgnUtils.getCompanyID(req),
                types, isTemplate, sort, direction, page, rownums));
        return future;

    }

    protected String getSort(HttpServletRequest request, MailingBaseForm aForm) {
        String sort = request.getParameter("sort");
        if (sort == null) {
            sort = aForm.getSort();
        } else {
            aForm.setSort(sort);
        }
        return sort;
    }

    /**
     * Creates report about errors in dynamic tags.
     *
     * @param blockName name of content block with invalid content
     * @param errorReports  list of messages about parsing errors (is changing inside the method)
     * @param templateReport content with errors
     */
    protected void appendErrorsToList(String blockName, List<String[]> errorReports, StringBuffer templateReport) {
        Map<String, String> tagsWithErrors = PreviewHelper.getTagsWithErrors(templateReport);
        for (Entry<String, String> entry : tagsWithErrors.entrySet()) {
            String[] errorRow = new String[3];
            errorRow[0] = blockName; // block
            errorRow[1] = entry.getKey(); // tag
            errorRow[2] = entry.getValue(); // value

            errorReports.add(errorRow);
        }
        List<String> errorsWithoutATag = PreviewHelper.getErrorsWithoutATag(templateReport);
        for (String error : errorsWithoutATag) {
            String[] errorRow = new String[3];
            errorRow[0] = blockName;
            errorRow[1] = "";
            errorRow[2] = error;
            errorReports.add(errorRow);
        }
    }

    public MailingDao getMailingDao() {
        return mailingDao;
    }

    public void setMailingDao(MailingDao mailingDao) {
        this.mailingDao = mailingDao;
    }

    public void setFutureHolder(AbstractMap<String, Future> futureHolder) {
        this.futureHolder = futureHolder;
    }

    public CampaignDao getCampaignDao() {
        return campaignDao;
    }

    public void setCampaignDao(CampaignDao campaignDao) {
        this.campaignDao = campaignDao;
    }

    public MailinglistDao getMailinglistDao() {
        return mailinglistDao;
    }

    public void setMailinglistDao(MailinglistDao mailinglistDao) {
        this.mailinglistDao = mailinglistDao;
    }

    public CharacterEncodingValidator getCharacterEncodingValidator() {
        return characterEncodingValidator;
    }

    public void setCharacterEncodingValidator(CharacterEncodingValidator characterEncodingValidator) {
        this.characterEncodingValidator = characterEncodingValidator;
    }

    public TargetDao getTargetDao() {
        return targetDao;
    }

    public void setTargetDao(TargetDao targetDao) {
        this.targetDao = targetDao;
    }

    public TAGCheckFactory getTagCheckFactory() {
        return tagCheckFactory;
    }

    public void setTagCheckFactory(TAGCheckFactory tagCheckFactory) {
        this.tagCheckFactory = tagCheckFactory;
    }

    public void setExecutorService(ExecutorService executorService) {
        this.executorService = executorService;
    }

    public MailingFactory getMailingFactory() {
        return mailingFactory;
    }

    public void setMailingFactory(MailingFactory mailingFactory) {
        this.mailingFactory = mailingFactory;
    }

    protected void updateMailingsWithDynamicTemplate(Mailing mailTemplate) {
        List<Integer> referencingMailings = mailingDao.getTemplateReferencingMailingIds(mailTemplate);
        if (referencingMailings == null)
            return;

        int companyId = mailTemplate.getCompanyID();

        Mailing mailing;
        MailingComponent mailingComponent;
        MailingComponent templateComponent;

        for (int mailingId : referencingMailings) {
            mailing = mailingDao.getMailing(mailingId, companyId);

            // First, handle text template
            templateComponent = mailTemplate.getTextTemplate();
            mailingComponent = mailing.getTextTemplate();

            // Modify text template only if mailing and template have both a text template
            if (templateComponent != null && mailingComponent != null) {
                mailingComponent.setEmmBlock(templateComponent.getEmmBlock());
            }

            // Next, handle HTML template
            templateComponent = mailTemplate.getHtmlTemplate();
            mailingComponent = mailing.getHtmlTemplate();

            // Modify HTML template only if mailing and template have both a HTML template
            if (templateComponent != null && mailingComponent != null) {
                mailingComponent.setEmmBlock(templateComponent.getEmmBlock());
            }

            try {
                mailing.buildDependencies(true, getWebApplicationContext());
                mailingDao.saveMailing(mailing);
            } catch (Exception e) {
                org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(this.getClass());

                logger.error("unable to update mailing ID " + mailingId + ": " + e.getMessage());

                if (logger.isDebugEnabled())
                    logger.debug("unable to update mailing ID " + mailingId, e);
            }

        }
    }

    protected void checkShowDynamicTemplateCheckbox(MailingBaseForm mailingBaseForm, HttpServletRequest request) {
        boolean showCheckbox = false;

        if (mailingBaseForm.isIsTemplate()) {
            // For templates checkbox is always show and enabled
            showCheckbox = true;
        } else if (mailingBaseForm.getTemplateID() != 0) {
            // For mailings, checkbox is always shows if and only if referenced mailing-record defines template
            // Checkbox is only enabled, if such a mailing has ID 0 (new mailing)

            showCheckbox = mailingDao.checkMailingReferencesTemplate(mailingBaseForm.getTemplateID(),
                    AgnUtils.getCompanyID(request));
        } else {
            // in all other cases, the checkbox is hidden
            showCheckbox = false;
        }

        request.setAttribute("show_dynamic_template_checkbox", showCheckbox);
    }

    protected WebApplicationContext getApplicationContext(HttpServletRequest req) {
        return WebApplicationContextUtils.getRequiredWebApplicationContext(req.getSession().getServletContext());
    }

}