Java tutorial
/*Copyright (C) 2014 JD Software, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.jd.survey.web.settings; import java.io.InputStreamReader; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.security.Principal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.Velocity; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.security.access.annotation.Secured; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.util.UriUtils; import org.springframework.web.util.WebUtils; import au.com.bytecode.opencsv.CSVReader; import com.jd.survey.domain.security.User; import com.jd.survey.domain.settings.Invitation; import com.jd.survey.domain.settings.SurveyDefinition; import com.jd.survey.service.security.SecurityService; import com.jd.survey.service.security.UserService; import com.jd.survey.service.settings.SurveySettingsService; @RequestMapping("/settings/invitations") @Controller public class InvitationController { private static final Log log = LogFactory.getLog(InvitationController.class); @Autowired private MessageSource messageSource; @Autowired private UserService userService; @Autowired private SurveySettingsService surveySettingsService; @Autowired private SecurityService securityService; private static final String FIRST_NAME_MESSAGE = "com.jd.survey.domain.settings.invitation.firstname_label"; private static final String MIDDLE_NAME_MESSAGE = "com.jd.survey.domain.settings.invitation.middlename_label"; private static final String LAST_NAME_MESSAGE = "com.jd.survey.domain.settings.invitation.lastname_label"; private static final String EMAIL_MESSAGE = "com.jd.survey.domain.settings.invitation.email_label"; private static final String INVITATION_EMAIL_TITLE = "invitation_email_title"; private static final String INVITEE_FULLNAME_PARAMETER_NAME = "invitee_fullname_parameter_name"; private static final String SURVEY_NAME = "survey_name"; private static final String INVITE_FILL_SURVEY_LINK_PARAMETER_NAME = "invite_fill_survey_link_parameter_name"; private static final String INVITE_FILL_SURVEY_LINK_LABEL = "invite_fill_survey_link_label"; //private static final String INTERNAL_SITE_BASE_URL="internal_site_base_url"; //private static final String EXTERNAL_SITE_BASE_URL="external_site_base_url"; @Value("${external.base.url}") String externalBaseUrl; @Value("${internal.base.url}") String internalBaseUrl; /** * exports a sample invitations comma delimited file * @param dataSetId * @param principal * @param response */ @Secured({ "ROLE_ADMIN", "ROLE_SURVEY_ADMIN" }) @RequestMapping(value = "/example", produces = "text/html") public void getExampleCsvFile(Principal principal, HttpServletResponse response) { try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(messageSource.getMessage(FIRST_NAME_MESSAGE, null, LocaleContextHolder.getLocale()) .replace(",", "")); stringBuilder.append(","); stringBuilder.append(messageSource .getMessage(MIDDLE_NAME_MESSAGE, null, LocaleContextHolder.getLocale()).replace(",", "")); stringBuilder.append(","); stringBuilder.append(messageSource.getMessage(LAST_NAME_MESSAGE, null, LocaleContextHolder.getLocale()) .replace(",", "")); stringBuilder.append(","); stringBuilder.append(messageSource.getMessage(EMAIL_MESSAGE, null, LocaleContextHolder.getLocale()) .replace(",", "")); stringBuilder.append("\n"); stringBuilder.append("a,b,c,abc@jdsoft.com\n"); //response.setContentType("text/html; charset=utf-8"); response.setContentType("application/octet-stream"); // Set standard HTTP/1.1 no-cache headers. response.setHeader("Cache-Control", "no-store, no-cache,must-revalidate"); // Set IE extended HTTP/1.1 no-cache headers (use addHeader). response.addHeader("Cache-Control", "post-check=0, pre-check=0"); // Set standard HTTP/1.0 no-cache header. response.setHeader("Pragma", "no-cache"); response.setHeader("Content-Disposition", "inline;filename=Invitationsexample.csv"); ServletOutputStream servletOutputStream = response.getOutputStream(); servletOutputStream.write(stringBuilder.toString().getBytes("UTF-8")); servletOutputStream.flush(); } catch (Exception e) { log.error(e.getMessage(), e); throw (new RuntimeException(e)); } } /** * Shows a list of completed Survey Definitions for the user * @param surveyId * @param principal * @param uiModel * @param httpServletRequest * @return */ @Secured({ "ROLE_ADMIN", "ROLE_SURVEY_ADMIN" }) @RequestMapping(produces = "text/html", method = RequestMethod.GET) public String listSurveys(Model uiModel, Principal principal) { try { User user = userService.user_findByLogin(principal.getName()); Set<SurveyDefinition> surveyDefinitions = surveySettingsService .surveyDefinition_findAllCompletedInternal(user); uiModel.addAttribute("surveyDefinitions", surveyDefinitions); return "settings/invitations/invitations"; } catch (Exception e) { log.error(e.getMessage(), e); throw (new RuntimeException(e)); } } /** * Shows the list of Survey Invitations for a Survey Definition, Supports Paging * @param surveyId * @param principal * @param uiModel * @param httpServletRequest * @return */ @Secured({ "ROLE_ADMIN", "ROLE_SURVEY_ADMIN" }) @RequestMapping(value = "/list", produces = "text/html", method = RequestMethod.GET) public String listSurveyInvitations(@RequestParam(value = "id", required = true) Long surveyDefinitionId, @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, @RequestParam(value = "fileContentError", required = false) boolean contentError, Model uiModel, Principal principal, HttpServletRequest httpServletRequest) { try { User user = userService.user_findByLogin(principal.getName()); if (!securityService.userIsAuthorizedToManageSurvey(surveyDefinitionId, user)) { log.warn("Unauthorized access to url path " + httpServletRequest.getPathInfo() + " attempted by user login:" + principal.getName() + "from IP:" + httpServletRequest.getLocalAddr()); return "accessDenied"; } Set<SurveyDefinition> surveyDefinitions = surveySettingsService .surveyDefinition_findAllCompletedInternal(user); uiModel.addAttribute("surveyDefinitions", surveyDefinitions); uiModel.addAttribute("surveyDefinition", surveySettingsService.surveyDefinition_findById(surveyDefinitionId)); Long surveyInvitationsCount = surveySettingsService.invitation_getSurveyCount(surveyDefinitionId); uiModel.addAttribute("surveyInvitationsCount", surveyInvitationsCount); uiModel.addAttribute("surveyInvitationsOpenedCount", surveySettingsService.invitation_getSurveyOpenedCount(surveyDefinitionId)); int sizeNo = size == null ? 25 : size.intValue(); final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo; Set<Invitation> invitations = surveySettingsService.invitation_findSurveyAll(surveyDefinitionId, firstResult, sizeNo); float nrOfPages = (float) surveyInvitationsCount / sizeNo; int maxPages = (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages); uiModel.addAttribute("maxPages", maxPages); uiModel.addAttribute("invitations", invitations); uiModel.addAttribute("fileContentError", contentError);// Used to carry error from file upload over and make it available to the view return "settings/invitations/invitations"; } catch (Exception e) { log.error(e.getMessage(), e); throw (new RuntimeException(e)); } } /** * prepares the page to import invitations from a csv file * @param dataSetId * @param principal * @param uiModel * @param httpServletRequest * @return */ @Secured({ "ROLE_ADMIN", "ROLE_SURVEY_ADMIN" }) @RequestMapping(value = "/import", produces = "text/html") public String prepareForImport(@RequestParam(value = "id", required = false) Long surveyDefinitionId, Principal principal, Model uiModel, HttpServletRequest httpServletRequest) { try { User user = userService.user_findByLogin(principal.getName()); Set<SurveyDefinition> surveyDefinitions = surveySettingsService .surveyDefinition_findAllCompletedInternal(user); uiModel.addAttribute("surveyDefinitions", surveyDefinitions); if (surveyDefinitionId != null) { if (!securityService.userIsAuthorizedToManageSurvey(surveyDefinitionId, user)) { log.warn("Unauthorized access to url path " + httpServletRequest.getPathInfo() + " attempted by user login:" + principal.getName() + "from IP:" + httpServletRequest.getLocalAddr()); return "accessDenied"; } uiModel.addAttribute("surveyDefinition", surveySettingsService.surveyDefinition_findById(surveyDefinitionId)); } return "settings/invitations/upload"; } catch (Exception e) { log.error(e.getMessage(), e); throw (new RuntimeException(e)); } } /** * Sends email invitations to the list of invitees from csv file. * @param file * @param surveyDefinitionId * @param proceed * @param principal * @param uiModel * @param httpServletRequest * @return */ @SuppressWarnings("unchecked") @Secured({ "ROLE_ADMIN", "ROLE_SURVEY_ADMIN" }) @RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "text/html") public String sendInvitations(@RequestParam("file") MultipartFile file, @RequestParam("id") Long surveyDefinitionId, @RequestParam(value = "_proceed", required = false) String proceed, Principal principal, Model uiModel, HttpServletRequest httpServletRequest) { try { short firstNameFieldIndex = 0; short middleNameFieldIndex = 1; short lastNameFieldIndex = 2; short emailNameFieldIndex = 3; if (proceed != null) { //prepare the base url links String emailSubject = messageSource.getMessage(INVITATION_EMAIL_TITLE, null, LocaleContextHolder.getLocale()); //String surveyLink =messageSource.getMessage(EXTERNAL_SITE_BASE_URL, null, LocaleContextHolder.getLocale()); String surveyLink = externalBaseUrl; //String trackingImageLink =messageSource.getMessage(INTERNAL_SITE_BASE_URL, null, LocaleContextHolder.getLocale()); String trackingImageLink = internalBaseUrl; SurveyDefinition surveyDefinition = surveySettingsService .surveyDefinition_findById(surveyDefinitionId); User user = userService.user_findByLogin(principal.getName()); Set<SurveyDefinition> surveyDefinitions = surveySettingsService .surveyDefinition_findAllCompletedInternal(user); //Check if the user is authorized if (!securityService.userIsAuthorizedToManageSurvey(surveyDefinitionId, user)) { log.warn("Unauthorized access to url path " + httpServletRequest.getPathInfo() + " attempted by user login:" + principal.getName() + "from IP:" + httpServletRequest.getLocalAddr()); return "accessDenied"; } if (trackingImageLink.endsWith("/")) { trackingImageLink = trackingImageLink + "public/w/"; } else { trackingImageLink = trackingImageLink + "/public/w/"; } if (surveyDefinition.getIsPublic()) { if (surveyLink.endsWith("/")) { surveyLink = surveyLink + "open/"; } else { surveyLink = surveyLink + "/open/"; } } else { if (surveyLink.endsWith("/")) { surveyLink = surveyLink + "private/"; } else { surveyLink = surveyLink + "/private/"; } } String emailContent; if (!file.isEmpty() && ((file.getContentType().equalsIgnoreCase("application/vnd.ms-excel")) || (file.getContentType().equalsIgnoreCase("text/csv")) || (file.getContentType().equalsIgnoreCase("text/plain")))) { CSVReader csvReader = new CSVReader(new InputStreamReader(file.getInputStream())); String[] nextLine; nextLine = csvReader.readNext(); //skip the first row the continue on with loop while ((nextLine = csvReader.readNext()) != null) { emailContent = ""; StringWriter sw = new StringWriter(); // Prevents IndexOutOfBoundException by skipping line if there are not enough elements in the array nextLine. if (nextLine.length < 4) { //Continues if a blank line is present without setting an error message (if a new line character is present CSVReader will return and array with one empty string at index 0). if (nextLine.length == 1 && nextLine[0].isEmpty()) { continue; } uiModel.addAttribute("fileContentError", true); continue; } //Prevents exception from attempting to send an email with an empty string for an email address. if (nextLine[3].isEmpty()) { uiModel.addAttribute("fileContentError", true); continue; } //creating the Invitation Invitation invitation = new Invitation(nextLine[firstNameFieldIndex].trim(), nextLine[middleNameFieldIndex].trim(), nextLine[lastNameFieldIndex].trim(), nextLine[emailNameFieldIndex].trim(), surveyDefinition); Map model = new HashMap(); //survey name model.put(messageSource.getMessage(SURVEY_NAME, null, LocaleContextHolder.getLocale()) .replace("${", "").replace("}", ""), surveyDefinition.getName()); //full name model.put( messageSource.getMessage(INVITEE_FULLNAME_PARAMETER_NAME, null, LocaleContextHolder.getLocale()).replace("${", "").replace("}", ""), invitation.getFullName()); //survey link model.put( messageSource.getMessage(INVITE_FILL_SURVEY_LINK_PARAMETER_NAME, null, LocaleContextHolder.getLocale()).replace("${", "").replace("}", ""), "<a href='" + surveyLink + surveyDefinition.getId() + "?list'>" + messageSource.getMessage(INVITE_FILL_SURVEY_LINK_LABEL, null, LocaleContextHolder.getLocale()) + "</a>"); VelocityContext velocityContext = new VelocityContext(model); Velocity.evaluate(velocityContext, sw, "velocity-log", surveyDefinition.getEmailInvitationTemplate()); emailContent = sw.toString().trim(); if (emailContent.length() > 14 && emailContent.substring(emailContent.length() - 14) .toUpperCase().equalsIgnoreCase("</BODY></HTML>")) { emailContent = emailContent.substring(0, emailContent.length() - 14) + "<img src='" + trackingImageLink + invitation.getUuid() + "'/></BODY></HTML>"; emailContent = "<BODY><HTML>" + emailContent; } else { // template is incorrect or not html do not include tracking white gif emailContent = emailContent + "<img src='" + trackingImageLink + invitation.getUuid() + "'/></BODY></HTML>"; } surveySettingsService.invitation_send(invitation, emailSubject, emailContent); } return "redirect:/settings/invitations/list?id=" + encodeUrlPathSegment(surveyDefinitionId.toString(), httpServletRequest); } else { uiModel.addAttribute("surveyDefinitions", surveyDefinitions); uiModel.addAttribute("surveyDefinition", surveyDefinition); uiModel.addAttribute("emptyFileError", true); return "settings/invitations/upload"; } } else { return "redirect:/settings/invitations/list?id=" + encodeUrlPathSegment(surveyDefinitionId.toString(), httpServletRequest); } } catch (Exception e) { log.error(e.getMessage(), e); throw new RuntimeException(e); } } String encodeUrlPathSegment(String pathSegment, HttpServletRequest httpServletRequest) { log.info("encodeUrlPathSegment()"); try { String enc = httpServletRequest.getCharacterEncoding(); if (enc == null) { enc = WebUtils.DEFAULT_CHARACTER_ENCODING; } try { pathSegment = UriUtils.encodePathSegment(pathSegment, enc); } catch (UnsupportedEncodingException uee) { log.error(uee); } return pathSegment; } catch (Exception e) { log.error(e.getMessage(), e); throw (new RuntimeException(e)); } } @ExceptionHandler(RuntimeException.class) public String handleRuntimeException(RuntimeException ex, HttpServletRequest request) { log.error(ex); log.error("redirect to /uncaughtException"); return "redirect:/uncaughtException"; } }