/********************************************************************************* * 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.*; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.agnitas.beans.Mailing; import org.agnitas.beans.MailingComponent; import org.agnitas.beans.TrackableLink; import org.agnitas.beans.impl.MailingComponentImpl; import org.agnitas.dao.MailingComponentDao; import org.agnitas.dao.MailingDao; import org.agnitas.dao.TrackableLinkDao; import org.agnitas.util.AgnUtils; import org.agnitas.web.forms.MailingComponentsForm; import org.apache.commons.lang.StringUtils; 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; import org.apache.struts.upload.FormFile; import org.springframework.dao.TransientDataAccessResourceException; /** * Implementation of <strong>Action</strong> that validates a user logon. * * @author Martin Helff, Nicole Serek */ public class MailingComponentsAction extends StrutsActionBase { public static final int ACTION_SAVE_COMPONENTS = ACTION_LAST+1; public static final int ACTION_SAVE_COMPONENT_EDIT = ACTION_LAST+2; protected static final List imageTypes = Arrays.asList(new String[]{".jpg", ".gif", ".png"}); private MailingDao mailingDao; private MailingComponentDao componentDao; private TrackableLinkDao linkDao; // --------------------------------------------------------- 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. * ACTION_LIST: loads mailing data to form, forwards to "list" * <br><br> * ACTION_SAVE_COMPONENTS: checks if file to upload was selected and that the file has correct file * type (.png, .jsp, .gif). If it is ok - adds the component to database. Also handles updating and deletion * of components: checks the request parameters "delete" + componentID to delete certain components, checks * request parameters "update" + componentID to update certain components. Also loads mailing data to form * and forwards to "list". If no component was updated or removed and there's no file to upload - shows the * error message that no file was selected. * <br><br> * ACTION_SAVE_COMPONENT_EDIT: saves component to database. Also handles updating and deletion * of components: checks the request parameters "delete" + componentID to delete certain components, checks * request parameters "update" + componentID to update certain components. Forwards to "component_edit".<br> * Doesn't seem to be currently used (it seems that it was used for fck-editor). * <br><br> * Any other ACTION_* would cause a forward to "list" * <br><br> * If the forward is "list" - loads components and components links to request. * * @param form ActionForm object * @param req HTTP request * @param res HTTP 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 MailingComponentsForm aForm=null; ActionMessages errors = new ActionMessages(); ActionMessages messages = new ActionMessages(); ActionForward destination=null; if(!AgnUtils.isUserLoggedIn(req)) { return mapping.findForward("logon"); } aForm=(MailingComponentsForm)form; AgnUtils.logger().info("Action: "+aForm.getAction()); try { switch(aForm.getAction()) { case MailingComponentsAction.ACTION_LIST: if(allowed("mailing.components.show", req)) { loadMailing(aForm, req); aForm.setAction(MailingComponentsAction.ACTION_SAVE_COMPONENTS); destination=mapping.findForward("list"); } else { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied")); } break; case MailingComponentsAction.ACTION_SAVE_COMPONENTS: if(allowed("mailing.components.change", req)) { destination=mapping.findForward("list"); if(!"".equals(aForm.getNewFile().getFileName()) && !imageTypes.contains(getFileType(aForm.getNewFile().getFileName()))) { loadMailing(aForm, req); aForm.setAction(MailingComponentsAction.ACTION_SAVE_COMPONENTS); errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("mailing.errors.format.error")); break; } loadMailing(aForm, req); try { saveComponent(aForm, req); } catch (TransientDataAccessResourceException e) { AgnUtils.logger().error("execute: " + e + "\n" + AgnUtils.getStackTrace(e)); errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.hibernate.attachmentTooLarge")); } aForm.setAction(MailingComponentsAction.ACTION_SAVE_COMPONENTS); Enumeration parameterNames = req.getParameterNames(); boolean aComponentWasJustDeleted = false; boolean aComponentWasJustUpdated = false; while (parameterNames.hasMoreElements()) { Object parameter = parameterNames.nextElement(); if (parameter instanceof String){ String parameterString = (String) parameter; if (parameterString.startsWith("delete") && AgnUtils.parameterNotEmpty(req, parameterString)){ aComponentWasJustDeleted = true; break; } if (parameterString.startsWith("update") && AgnUtils.parameterNotEmpty(req, parameterString)){ aComponentWasJustUpdated = true; break; } } } // Show "changes saved" if (errors.isEmpty()) { if (!aComponentWasJustDeleted && !aComponentWasJustUpdated && (aForm.getNewFile() == null || aForm.getNewFile().getFileName() == null || "".equals(aForm.getNewFile().getFileName()))) { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("mailing.errors.no_component_file")); } else { messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("default.changes_saved")); } } } else { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied")); destination=mapping.findForward("list"); } break; case MailingComponentsAction.ACTION_SAVE_COMPONENT_EDIT: if(allowed("mailing.components.change", req)) { destination=mapping.findForward("component_edit"); saveComponent(aForm, req); aForm.setAction(MailingComponentsAction.ACTION_SAVE_COMPONENTS); // Show "changes saved" messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("default.changes_saved")); } else { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied")); } break; default: aForm.setAction(MailingComponentsAction.ACTION_LIST); destination=mapping.findForward("list"); } if (destination != null && "list".equals(destination.getName())) { List<MailingComponent> components = loadComponents(aForm, req); req.setAttribute("components", components); List<TrackableLink> links = loadComponentsLinks(aForm, req, components); req.setAttribute("componentLinks", links); } } catch (Exception e) { AgnUtils.logger().error("execute: "+e+"\n"+AgnUtils.getStackTrace(e)); errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.exception")); } // Report any errors we have discovered back to the original form if (!errors.isEmpty()) { saveErrors(req, errors); } // Report any message (non-errors) we have discovered if (!messages.isEmpty()) { saveMessages(req, messages); } return destination; } /** * Loads mailing. */ protected void loadMailing(MailingComponentsForm aForm, HttpServletRequest req) throws Exception { Mailing aMailing=mailingDao.getMailing(aForm.getMailingID(), this.getCompanyID(req)); aForm.setShortname(aMailing.getShortname()); aForm.setDescription(aMailing.getDescription()); aForm.setIsTemplate(aMailing.isIsTemplate()); aForm.setLink(""); aForm.setWorldMailingSend(aMailing.isWorldMailingSend()); AgnUtils.logger().info("loadMailing: mailing loaded"); } /** * Saves components. */ protected boolean saveComponent(MailingComponentsForm aForm, HttpServletRequest req) { MailingComponent aComp = null; Vector<MailingComponent> deleteEm = new Vector<MailingComponent>(); Mailing aMailing=mailingDao.getMailing(aForm.getMailingID(), this.getCompanyID(req)); addUploadedImage(aForm, aMailing, req, null); Iterator<MailingComponent> it=aMailing.getComponents().values().iterator(); while (it.hasNext()) { aComp = it.next(); switch(aComp.getType()) { case MailingComponent.TYPE_IMAGE: if(AgnUtils.parameterNotEmpty(req, "update" + aComp.getId())) { aComp.loadContentFromURL(); } break; case MailingComponent.TYPE_HOSTED_IMAGE: if(AgnUtils.parameterNotEmpty(req, "delete" + aComp.getId())) { deleteEm.add(aComp); if (AgnUtils.isProjectEMM()){ MailingComponent amComponent=componentDao.getMailingComponentByName(aComp.getMailingID(), aComp.getCompanyID(), aComp.getComponentName()); componentDao.deleteMailingComponent(amComponent); } } break; } } Enumeration<MailingComponent> en = deleteEm.elements(); while(en.hasMoreElements()) { aMailing.getComponents().remove(en.nextElement().getComponentName()); } mailingDao.saveMailing(aMailing); if(deleteEm.size() == 0){ return true; } else { return false; } } protected List<MailingComponent> loadComponents(MailingComponentsForm aForm, HttpServletRequest request) { Vector<MailingComponent> components = componentDao.getMailingComponents(aForm.getMailingID(), getCompanyID(request)); request.setAttribute("components", components); return components; } protected List<TrackableLink> loadComponentsLinks(MailingComponentsForm aForm, HttpServletRequest request, List<MailingComponent> components) { List<TrackableLink> links = new ArrayList<TrackableLink>(); for(MailingComponent component : components) { int urlID = component.getUrlID(); if (urlID > 0) { TrackableLink trackableLink = linkDao.getTrackableLink(urlID, getCompanyID(request)); links.add(trackableLink); } } return links; } protected void addUploadedImage(MailingComponentsForm componentForm, Mailing mailing, HttpServletRequest req, String componentName) { // TODO: This code is partially duplicated in class ComMailingComponentsServiceImpl MailingComponent component = null; FormFile newImage = componentForm.getNewFile(); String newComponentName = componentName; if (StringUtils.isBlank(newComponentName)) { newComponentName = newImage.getFileName(); } try { if (newImage.getFileSize() != 0) { component = mailing.getComponents().get(newImage.getFileName()); if (component != null && component.getType() == MailingComponent.TYPE_HOSTED_IMAGE) { component.setBinaryBlock(newImage.getFileData()); component.setEmmBlock(component.makeEMMBlock()); component.setMimeType(newImage.getContentType()); component.setLink(componentForm.getLink()); component.setDescription(componentForm.getDescription()); } else { component = new MailingComponentImpl(); component.setCompanyID(mailing.getCompanyID()); component.setMailingID(componentForm.getMailingID()); component.setType(MailingComponent.TYPE_HOSTED_IMAGE); component.setDescription(componentForm.getDescription()); component.setComponentName(newComponentName); component.setBinaryBlock(newImage.getFileData()); component.setEmmBlock(component.makeEMMBlock()); component.setMimeType(newImage.getContentType()); component.setLink(componentForm.getLink()); mailing.addComponent(component); } } } catch (Exception e) { AgnUtils.logger().error("saveComponent: " + e); } if (componentForm.getAction() == MailingComponentsAction.ACTION_SAVE_COMPONENT_EDIT) { req.setAttribute("file_path", AgnUtils.getAdmin(req).getCompany().getRdirDomain() + "/image?ci=" + mailing.getCompanyID() + "&mi=" + componentForm.getMailingID() + "&name=" + newImage.getFileName()); } } public void setMailingDao(MailingDao mailingDao) { this.mailingDao = mailingDao; } public MailingDao getMailingDao() { return mailingDao; } public void setComponentDao(MailingComponentDao componentDao) { this.componentDao = componentDao; } public MailingComponentDao getComponentDao() { return componentDao; } public void setLinkDao(TrackableLinkDao linkDao) { this.linkDao = linkDao; } public TrackableLinkDao getLinkDao() { return linkDao; } public String getFileType(String fileName) { return fileName.substring(fileName.length() - 4).toLowerCase(); } }