/********************************************************************************* * 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 java.io.IOException; import java.util.GregorianCalendar; import java.util.AbstractMap; import java.util.concurrent.Future; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.agnitas.beans.Mailloop; import org.agnitas.beans.factory.MailloopFactory; import org.agnitas.dao.MailinglistDao; import org.agnitas.dao.MailloopDao; import org.agnitas.dao.UserFormDao; import org.agnitas.util.AgnUtils; import org.agnitas.web.forms.StrutsFormBase; import org.agnitas.service.MailloopListQueryWorker; import org.apache.commons.beanutils.BeanUtils; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ActionMessages; /** * Implementation of <strong>Action</strong> that handles Mailloop-Data * * @author Martin Helff */ public final class MailloopAction extends StrutsActionBase { public static final int ACTION_SEND_TEST = ACTION_LAST + 1; public static final int ACTION_VIEW_WITHOUT_LOAD = ACTION_LAST + 2; private static final String FUTURE_TASK = "GET_MAILLOOP_LIST"; private MailloopDao mailloopDao; private MailinglistDao mailinglistDao; private UserFormDao userFormDao; private ExecutorService executorService; private AbstractMap<String, Future> futureHolder; private MailloopFactory mailloopFactory; // --------------------------------------------------------- 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. * All actions requires "mailing.show" permission. <br> * ACTION_LIST: calls a FutureHolder to get the list of entries.<br> * While FutureHolder is running destination is "loading". <br> * After FutureHolder is finished destination is "list". * <br><br> * ACTION_VIEW: loads data of chosen bounce-filter into form,<br> * forwards to view page. * <br><br> * ACTION_NEW: clears form data, <br> * loads form data from database, <br> * forwards to page of creation new bounce-filter entry * <br><br> * ACTION_SAVE: saves new bounce-filter or updates existing bounce-filter in database. <br> * Requires request parameters "saveMailloop" for saving. <br> * Calls a FutureHolder to get the list of entries.<br> * While FutureHolder is running destination is "loading". <br> * After FutureHolder is finished destination is "list". * <br><br> * ACTION_CONFIRM_DELETE: loads form data, <br> * forwards to jsp with question to confirm deletion. * <br><br> * ACTION_DELETE: deletes the entry of bounce-filter, <br> * calls a FutureHolder to get the list of entries.<br> * While FutureHolder is running destination is "loading". <br> * After FutureHolder is finished destination is "list". * <br><br> * ACTION_VIEW_WITHOUT_LOAD: is used after failing form validation <br> * for loading essential data into request before returning to the view page;<br> * does not reload form data * <br><br> * Any other ACTION_* would cause a forward to "list" * <br><br> * @param mapping The ActionMapping used to select this instance * @param form The optional ActionForm bean for this request (if any) * @param req The HTTP request we are processing * @param res The HTTP response we are creating * * @exception IOException if an input/output error occurs * @exception ServletException if a servlet exception occurs */ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest req, HttpServletResponse res) throws Exception { // Validate the request parameters specified by the user MailloopForm aForm=null; ActionMessages errors = new ActionMessages(); ActionMessages messages = new ActionMessages(); ActionForward destination=null; if(!AgnUtils.isUserLoggedIn(req)) { return mapping.findForward("logon"); } aForm=(MailloopForm)form; try { switch(aForm.getAction()) { case MailloopAction.ACTION_LIST: if(allowed("mailing.show", req)) { destination = prepareList(mapping, req, errors, destination, aForm); } else { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied")); } break; case MailloopAction.ACTION_VIEW: if(allowed("mailing.show", req)) { if(aForm.getMailloopID()!=0) { loadMailloop(aForm, req); } else { aForm.clearData(); } loadMailloopFormData(aForm, req); aForm.setAction(MailloopAction.ACTION_SAVE); destination=mapping.findForward("view"); } else { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied")); } break; case MailloopAction.ACTION_NEW: if(allowed("mailing.show", req)) { aForm.clearData(); aForm.setAction(MailloopAction.ACTION_SAVE); destination=mapping.findForward("view"); loadMailloopFormData(aForm, req); } else { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied")); } break; case MailloopAction.ACTION_SAVE: if(allowed("mailing.show", req)) { if (AgnUtils.parameterNotEmpty(req, "saveMailloop")) { saveMailloop(aForm, req); destination = prepareList(mapping, req, errors, destination, aForm); // Show "changes saved" messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("default.changes_saved")); } } else { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied")); } break; case MailloopAction.ACTION_CONFIRM_DELETE: if(allowed("mailing.show", req)) { loadMailloop(aForm, req); destination=mapping.findForward("delete"); aForm.setAction(MailloopAction.ACTION_DELETE); } else { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied")); } break; case MailloopAction.ACTION_DELETE: if(allowed("mailing.show", req)) { deleteMailloop(aForm, req); // aForm.setAction(MailloopAction.ACTION_LIST); destination=prepareList(mapping, req, errors, destination, aForm); // Show "changes saved" messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("default.changes_saved")); } else { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied")); } break; case MailloopAction.ACTION_VIEW_WITHOUT_LOAD: if(allowed("mailing.show", req)) { loadMailloopFormData(aForm, req); aForm.setAction(MailloopAction.ACTION_SAVE); destination=mapping.findForward("view"); } else { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied")); } break; default: aForm.setAction(MailloopAction.ACTION_LIST); destination=mapping.findForward("list"); break; } } catch (Exception e) { AgnUtils.logger().error("execute: "+e+"\n"+AgnUtils.getStackTrace(e)); errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.exception")); } if(destination != null && "list".equals(destination.getName())) { setNumberOfRows(req, aForm); } // Report any errors we have discovered back to the original form if (!errors.isEmpty()) { saveErrors(req, errors); return (new ActionForward(mapping.getInput())); } // Report any message (non-errors) we have discovered if (!messages.isEmpty()) { saveMessages(req, messages); } return destination; } protected void loadMailloop(MailloopForm aForm, HttpServletRequest req) { Mailloop aLoop = mailloopDao.getMailloop(aForm.getMailloopID(), getCompanyID(req)); if(aLoop!=null) { try { BeanUtils.copyProperties(aForm, aLoop); AgnUtils.userlogger().info(AgnUtils.getAdmin(req).getUsername() + ": do load bounce filter " + aLoop.getShortname()); } catch (Exception e) { AgnUtils.logger().error("loadMailloop: "+e); } } else { AgnUtils.logger().error("loadMailloop: could not load Mailloop"); } } protected void loadMailloopFormData(MailloopForm aForm, HttpServletRequest req) { int companyID = AgnUtils.getCompanyID(req); aForm.setMailinglists(mailinglistDao.getMailinglists(companyID)); aForm.setUserforms(userFormDao.getUserForms(companyID)); } /** * Saves mailloop. */ protected void saveMailloop(MailloopForm aForm, HttpServletRequest req) { java.util.Calendar cal=new GregorianCalendar(); Mailloop aLoop=null; int loopID=aForm.getMailloopID(); java.sql.Timestamp ts = new java.sql.Timestamp(cal.getTime().getTime()); aForm.setChangedate(ts); if(loopID!=0) { aLoop=mailloopDao.getMailloop(aForm.getMailloopID(), getCompanyID(req)); } if(aLoop==null) { aLoop=mailloopFactory.newMailloop(); aLoop.setCompanyID(getCompanyID(req)); loopID=0; } try { BeanUtils.copyProperties(aLoop, aForm); aLoop.setId(loopID); } catch (Exception e) { AgnUtils.logger().error("saveMailloop: "+e); } mailloopDao.saveMailloop(aLoop); if (loopID==0){ AgnUtils.userlogger().info(AgnUtils.getAdmin(req).getUsername() + ": create bounce filter " + aLoop.getShortname()); }else{ AgnUtils.userlogger().info(AgnUtils.getAdmin(req).getUsername() + ": edit bounce filter " + aLoop.getShortname()); } } /** * Removes mailloop. */ protected void deleteMailloop(MailloopForm aForm, HttpServletRequest req) { if(aForm.getMailloopID()!=0) { mailloopDao.deleteMailloop(aForm.getMailloopID(), getCompanyID(req)); AgnUtils.userlogger().info(AgnUtils.getAdmin(req).getUsername() + ": delete bounce filter " + aForm.getShortname()); } } private ActionForward prepareList(ActionMapping mapping, HttpServletRequest req, ActionMessages errors, ActionForward destination, MailloopForm mailloopForm) { ActionMessages messages = null; try { setNumberOfRows(req, mailloopForm); destination = mapping.findForward("loading"); String key = FUTURE_TASK + "@" + req.getSession(false).getId(); if (!futureHolder.containsKey(key)) { Future mailloopFuture = getMaillooplistFuture(req, mailloopForm); futureHolder.put(key, mailloopFuture); } if (futureHolder.containsKey(key) && futureHolder.get(key).isDone()) { req.setAttribute("mailloopEntries", futureHolder.get(key).get()); destination = mapping.findForward("list"); futureHolder.remove(key); mailloopForm.setRefreshMillis(RecipientForm.DEFAULT_REFRESH_MILLIS); messages = mailloopForm.getMessages(); if (messages != null && !messages.isEmpty()) { saveMessages(req, messages); mailloopForm.setMessages(null); } } else { if (mailloopForm.getRefreshMillis() < 1000) { // raise the refresh time mailloopForm.setRefreshMillis(mailloopForm.getRefreshMillis() + 50); } mailloopForm.setError(false); } } catch (Exception e) { AgnUtils.logger().error("mailloop: " + e + "\n" + AgnUtils.getStackTrace(e)); errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.exception")); mailloopForm.setError(true); // do not refresh when an error has been occurred } return destination; } protected Future getMaillooplistFuture(HttpServletRequest request, StrutsFormBase aForm) throws NumberFormatException, IllegalAccessException, InstantiationException, InterruptedException, ExecutionException { String sort = getSort(request, aForm); String direction = request.getParameter("dir"); int rownums = aForm.getNumberofRows(); if (direction == null) { direction = aForm.getOrder(); } else { aForm.setOrder(direction); } String pageStr = request.getParameter("page"); if (pageStr == null || "".equals(pageStr.trim())) { if (aForm.getPage() == null || "".equals(aForm.getPage().trim())) { aForm.setPage("1"); } pageStr = aForm.getPage(); } else { aForm.setPage(pageStr); } if (aForm.isNumberOfRowsChanged()) { aForm.setPage("1"); aForm.setNumberOfRowsChanged(false); pageStr = "1"; } int companyID = AgnUtils.getCompanyID(request); Future future = executorService.submit(new MailloopListQueryWorker(mailloopDao, companyID, sort, direction, Integer.parseInt(pageStr), rownums)); return future; } public void setMailloopDao(MailloopDao mailloopDao) { this.mailloopDao = mailloopDao; } public void setMailinglistDao(MailinglistDao mailinglistDao) { this.mailinglistDao = mailinglistDao; } public void setExecutorService(ExecutorService executorService) { this.executorService = executorService; } public void setFutureHolder(AbstractMap<String, Future> futureHolder) { this.futureHolder = futureHolder; } public void setMailloopFactory(MailloopFactory mailloopFactory) { this.mailloopFactory = mailloopFactory; } public void setUserFormDao(UserFormDao userFormDao) { this.userFormDao = userFormDao; } }