Java tutorial
/********************************************************************************* * 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.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.sql.DataSource; import org.agnitas.beans.Campaign; import org.agnitas.beans.Company; import org.agnitas.beans.MaildropEntry; import org.agnitas.beans.Mailing; import org.agnitas.dao.CampaignDao; import org.agnitas.dao.CompanyDao; import org.agnitas.dao.MailingDao; import org.agnitas.service.CampaignQueryWorker; import org.agnitas.util.AgnUtils; import org.agnitas.web.forms.CampaignForm; import org.agnitas.web.forms.StrutsFormBase; import org.apache.commons.beanutils.BasicDynaClass; import org.apache.commons.beanutils.DynaBean; import org.apache.commons.beanutils.DynaProperty; 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.displaytag.tags.TableTagParameters; import org.displaytag.util.ParamEncoder; import org.springframework.context.ApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; public class CampaignAction extends StrutsActionBase { public static final int ACTION_STAT = ACTION_LAST + 1; public static final int ACTION_SPLASH = ACTION_LAST + 2; /** * 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. * * @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 IOException, ServletException { ApplicationContext aContext = this.getWebApplicationContext(); // our application Context // Validate the request parameters specified by the user CampaignForm aForm = null; ActionMessages errors = new ActionMessages(); ActionForward destination = null; if (!this.checkLogon(req)) { return mapping.findForward("logon"); } if (form != null) { aForm = (CampaignForm) form; } else { aForm = new CampaignForm(); } AgnUtils.logger().info("Action: " + aForm.getAction()); if (req.getParameter("delete.x") != null) { aForm.setAction(ACTION_CONFIRM_DELETE); } try { switch (aForm.getAction()) { case CampaignAction.ACTION_LIST: if (allowed("campaign.show", req)) { destination = mapping.findForward("list"); aForm.reset(mapping, req); aForm.setAction(CampaignAction.ACTION_LIST); // reset Action! } break; case CampaignAction.ACTION_VIEW: if (allowed("campaign.show", req)) { aForm.reset(mapping, req); loadCampaign(aForm, req); aForm.setAction(CampaignAction.ACTION_SAVE); destination = mapping.findForward("view"); } else { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied")); } break; case CampaignAction.ACTION_SAVE: if (allowed("campaign.change", req)) { saveCampaign(aForm, req); } else { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied")); } destination = mapping.findForward("list"); break; case CampaignAction.ACTION_NEW: if (allowed("campaign.show", req)) { aForm.reset(mapping, req); aForm.setAction(CampaignAction.ACTION_SAVE); aForm.setCampaignID(0); destination = mapping.findForward("view"); } else { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied")); destination = mapping.findForward("list"); } break; case CampaignAction.ACTION_CONFIRM_DELETE: loadCampaign(aForm, req); aForm.setAction(CampaignAction.ACTION_DELETE); destination = mapping.findForward("delete"); break; case CampaignAction.ACTION_DELETE: if (allowed("campaign.show", req)) { if (req.getParameter("kill.x") != null) { this.deleteCampaign(aForm, req); aForm.setAction(CampaignAction.ACTION_LIST); } } else { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.permissionDenied")); } destination = mapping.findForward("list"); break; case CampaignAction.ACTION_STAT: destination = mapping.findForward("splash"); // default is splash-screen. aForm.setAction(CampaignAction.ACTION_SPLASH); setNumberOfRows(req, (StrutsFormBase) form); // could change till next call on this variable is done. loadCampaign(aForm, req); try { // look if we have a Future, if not, get one. if (aForm.getCurrentFuture() == null) { aForm.setCurrentFuture(getCampaignListFuture(req, aContext, aForm)); } // look if we are already done. if (aForm.getCurrentFuture().isDone()) {// Campaign.Stats stat = (Campaign.Stats) aForm.getCurrentFuture().get(); // get the results. if (stat != null) { setFormStat(aForm, stat); } setSortedMailingList(stat, req, aForm); aForm.setStatReady(true); aForm.setAction(CampaignAction.ACTION_STAT); destination = mapping.findForward("stat"); // set destination to Statistic-page. aForm.setCurrentFuture(null); // reset Future because we are already done. aForm.setRefreshMillis(RecipientForm.DEFAULT_REFRESH_MILLIS); // set refresh-time to default. // } } else { // increment Refresh-Rate. if it is a very long request, // we dont have to refresh every 250ms, then 1 second is enough. if (aForm.getRefreshMillis() < 1000) { // raise the refresh time aForm.setRefreshMillis(aForm.getRefreshMillis() + 50); } } } catch (NullPointerException e) { AgnUtils.logger().error("getCampaignList: " + e + "\n" + AgnUtils.getStackTrace(e)); errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.exception")); } break; case CampaignAction.ACTION_SPLASH: if (aForm.getCurrentFuture() != null && aForm.getCurrentFuture().isDone()) { aForm.setAction(CampaignAction.ACTION_STAT); destination = mapping.findForward("stat"); } else { loadCampaign(aForm, req); aForm.setAction(CampaignAction.ACTION_SPLASH); destination = mapping.findForward("splash"); } break; default: aForm.setAction(CampaignAction.ACTION_LIST); destination = mapping.findForward("list"); } } 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())) { try { setNumberOfRows(req, (StrutsFormBase) form); req.setAttribute("campaignlist", getCampaignList(req)); } catch (Exception e) { AgnUtils.logger().error("getCampaignList: " + 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); } return destination; } /* * this method sets the Form-Stats. It would be good, if stat is not null */ private void setFormStat(CampaignForm aForm, Campaign.Stats stat) { if (stat != null) { aForm.setOpened(stat.getOpened()); aForm.setOptouts(stat.getOptouts()); aForm.setBounces(stat.getBounces()); aForm.setSubscribers(stat.getSubscribers()); aForm.setClicks(stat.getClicks()); aForm.setMaxClicks(stat.getMaxClicks()); aForm.setMaxOpened(stat.getMaxOpened()); aForm.setMaxOptouts(stat.getMaxOptouts()); aForm.setMaxSubscribers(stat.getMaxSubscribers()); aForm.setMaxBounces(stat.getMaxBounces()); aForm.setMailingData(stat.getMailingData()); } } /* * this method creates a List with all Mailing-IDs in a sorted order an writes it into the * CampaignForm. */ private void setSortedMailingList(Campaign.Stats stat, HttpServletRequest req, CampaignForm aForm) { LinkedList<Number> resultList = new LinkedList<Number>(); MailingDao mailDao = (MailingDao) getBean("MailingDao"); // this hashmap contains the mapping from a Date back to the Mail-ID. HashMap<Date, Number> tmpDate2MailIDMapping = new HashMap<Date, Number>(); LinkedList<Date> sortedMailingList = new LinkedList<Date>(); Hashtable map = stat.getMailingData(); // holds the complete mailing Data map.keySet(); // all keys for the mailingData (mailIDs) Number tmpMailID = null; MaildropEntry tmpEntry = null; Mailing tmpMailing = null; // loop over all keys. Iterator it = map.keySet().iterator(); while (it.hasNext()) { LinkedList<Date> sortDates = new LinkedList<Date>(); tmpMailID = (Number) it.next(); // get the mailID // get one Mailing with tmpMailID tmpMailing = (Mailing) mailDao.getMailing(tmpMailID.intValue(), getCompanyID(req)); // check if it is a World-Mailing. We have testmailings and dont care about them! if (tmpMailing.isWorldMailingSend() == true) { // loop over all tmpMailingdropStatus. // we look over all mails and take the first send mailing Time. // unfortunately is the set not sorted, so we have to sort it ourself. Iterator it2 = tmpMailing.getMaildropStatus().iterator(); while (it2.hasNext()) { tmpEntry = (MaildropEntry) it2.next(); sortDates.add(tmpEntry.getSendDate()); } // check if sortDates has entries and put the one into the Hashmap. if (sortDates.size() != 0) { Collections.sort(sortDates); tmpDate2MailIDMapping.put(sortDates.get(0), tmpMailID); sortedMailingList.add(sortDates.get(0)); } } } // at this point, we have a Hashmap with all Dates and Mailing ID's and a List with all Date's. // now we sort this List and put the result into the Form (sort with reverse Order ;-) ). Collections.sort(sortedMailingList, Collections.reverseOrder()); // loop over the List and put the corresponding MailID into the List. for (int i = 0; i < sortedMailingList.size(); i++) { resultList.add(tmpDate2MailIDMapping.get(sortedMailingList.get(i))); } aForm.setSortedKeys(resultList); } /** * Loads campaign. */ protected void loadCampaign(CampaignForm aForm, HttpServletRequest req) { int campaignID = aForm.getCampaignID(); int companyID = getCompanyID(req); CampaignDao campaignDao = (CampaignDao) getBean("CampaignDao"); Campaign myCamp = campaignDao.getCampaign(campaignID, companyID); if (myCamp != null) { aForm.setShortname(myCamp.getShortname()); aForm.setDescription(myCamp.getDescription()); } else { AgnUtils.logger().error("could not load campaign: " + aForm.getTargetID()); } } /** * Saves campaign. */ protected void saveCampaign(CampaignForm aForm, HttpServletRequest req) { int campaignID = aForm.getCampaignID(); int companyID = getCompanyID(req); CampaignDao campaignDao = (CampaignDao) getBean("CampaignDao"); Campaign myCamp = campaignDao.getCampaign(campaignID, companyID); if (myCamp == null) { aForm.setCampaignID(0); myCamp = (Campaign) getBean("Campaign"); myCamp.setCompanyID(companyID); } myCamp.setShortname(aForm.getShortname()); myCamp.setDescription(aForm.getDescription()); getHibernateTemplate().saveOrUpdate("Campaign", myCamp); getHibernateTemplate().flush(); } /** * Deletes campaign. */ protected void deleteCampaign(CampaignForm aForm, HttpServletRequest req) { int campaignID = aForm.getCampaignID(); int companyID = getCompanyID(req); CampaignDao campaignDao = (CampaignDao) getBean("CampaignDao"); Campaign myCamp = campaignDao.getCampaign(campaignID, companyID); if (myCamp != null) { getHibernateTemplate().delete(myCamp); getHibernateTemplate().flush(); } } /** * loads the campaigns * @throws InstantiationException * @throws IllegalAccessException * * */ public List<DynaBean> getCampaignList(HttpServletRequest request) throws IllegalAccessException, InstantiationException { ApplicationContext aContext = getWebApplicationContext(); JdbcTemplate aTemplate = new JdbcTemplate((DataSource) aContext.getBean("dataSource")); List<Integer> charColumns = Arrays.asList(new Integer[] { 0, 1 }); String[] columns = new String[] { "shortname", "description", "" }; int sortcolumnindex = 0; if (request.getParameter( new ParamEncoder("campaign").encodeParameterName(TableTagParameters.PARAMETER_SORT)) != null) { sortcolumnindex = Integer.parseInt(request.getParameter( new ParamEncoder("campaign").encodeParameterName(TableTagParameters.PARAMETER_SORT))); } String sort = columns[sortcolumnindex]; if (charColumns.contains(sortcolumnindex)) { sort = "upper( " + sort + " )"; } int order = 1; if (request.getParameter( new ParamEncoder("campaign").encodeParameterName(TableTagParameters.PARAMETER_ORDER)) != null) { order = new Integer(request.getParameter( new ParamEncoder("campaign").encodeParameterName(TableTagParameters.PARAMETER_ORDER))); } String sqlStatement = "SELECT campaign_id, shortname, description FROM campaign_tbl WHERE company_id=" + AgnUtils.getCompanyID(request) + " ORDER BY " + sort + " " + (order == 2 ? "DESC" : "ASC"); List<Map> tmpList = aTemplate.queryForList(sqlStatement); DynaProperty[] properties = new DynaProperty[] { new DynaProperty("campaignId", Integer.class), new DynaProperty("shortname", String.class), new DynaProperty("description", String.class) }; if (AgnUtils.isOracleDB()) { properties = new DynaProperty[] { new DynaProperty("campaignId", BigDecimal.class), new DynaProperty("shortname", String.class), new DynaProperty("description", String.class) }; } BasicDynaClass dynaClass = new BasicDynaClass("campaign", null, properties); List<DynaBean> result = new ArrayList<DynaBean>(); for (Map row : tmpList) { DynaBean newBean = dynaClass.newInstance(); newBean.set("campaignId", row.get("CAMPAIGN_ID")); newBean.set("shortname", row.get("SHORTNAME")); newBean.set("description", row.get("DESCRIPTION")); result.add(newBean); } return result; } /* * returns a Future for asynchronous computation of the CampaignStats. */ public Future getCampaignListFuture(HttpServletRequest req, ApplicationContext aContext, CampaignForm aForm) throws NumberFormatException, IllegalAccessException, InstantiationException, InterruptedException, ExecutionException { CampaignDao campaignDao = (CampaignDao) aContext.getBean("CampaignDao"); CompanyDao compDao = (CompanyDao) getBean("CompanyDao"); Company comp = (Company) compDao.getCompany(AgnUtils.getCompanyID(req)); Locale aLoc = (Locale) req.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY); boolean mailtracking; // i dont know why mailtracking returns an int here, but i use boolean though its not handsome but it works (hopefully). if (comp.getMailtracking() == 0) { mailtracking = false; } else { mailtracking = true; } // now we start get the data. But we start that as background job. // the result is available via future.get(). ExecutorService service = (ExecutorService) aContext.getBean("workerExecutorService"); Future future = service .submit(new CampaignQueryWorker(campaignDao, aLoc, aForm, req, mailtracking, aContext)); return future; } }