Java tutorial
/* * $Id$ * $URL$ * * ==================================================================== * Ikasan Enterprise Integration Platform * * Distributed under the Modified BSD License. * Copyright notice: The copyright for this software and a full listing * of individual contributors are as shown in the packaged copyright.txt * file. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the ORGANIZATION nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ package org.ikasan.console.web.controller; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashSet; 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.ikasan.spec.flow.FlowEvent; import org.ikasan.spec.management.PointToPointFlowProfile; import org.ikasan.spec.search.PagedSearchResult; import org.ikasan.spec.wiretap.WiretapEvent; import org.ikasan.spec.wiretap.WiretapService; import org.ikasan.console.module.Module; import org.ikasan.console.module.service.ModuleService; import org.ikasan.console.pointtopointflow.service.PointToPointFlowProfileService; import org.ikasan.console.web.command.WiretapSearchCriteria; import org.ikasan.console.web.command.WiretapSearchCriteriaValidator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import org.apache.commons.lang.StringEscapeUtils; import org.apache.log4j.Logger; /** * This class is the Controller for the WiretapEvent Search Form * * @author Ikasan Development Team */ @Controller @RequestMapping("/events") public class WiretapEventsSearchFormController { /** The logger */ private Logger logger = Logger.getLogger(WiretapEventsSearchFormController.class); /** The wiretap service */ private WiretapService<FlowEvent, PagedSearchResult<WiretapEvent>> wiretapService; /** The module service */ private ModuleService moduleService; /** The point to point flow profile service */ private PointToPointFlowProfileService pointToPointFlowProfileService; /** The search criteria validator to use */ private WiretapSearchCriteriaValidator validator = new WiretapSearchCriteriaValidator(); /** * Constructor * * @param wiretapService - The wiretap service to use * @param moduleService - The module service to use * @param pointToPointFlowProfileService - The point to point flow profile * container to use */ @Autowired public WiretapEventsSearchFormController(WiretapService wiretapService, ModuleService moduleService, PointToPointFlowProfileService pointToPointFlowProfileService) { super(); this.wiretapService = wiretapService; this.moduleService = moduleService; this.pointToPointFlowProfileService = pointToPointFlowProfileService; } /** * Get the modules * * @return Set of modules */ @ModelAttribute("modules") public Set<Module> getModules() { Set<Module> modules = this.moduleService.getAllModules(); return modules; } /** * Get the point to point flow profiles * * @return List of point to point flow profiles */ @ModelAttribute("pointToPointFlowProfiles") public Set<PointToPointFlowProfile> getPointToPointFlowProfiles() { Set<PointToPointFlowProfile> pointToPointFlowProfiles = this.pointToPointFlowProfileService .getAllPointToPointFlowProfiles(); return pointToPointFlowProfiles; } /** * Show the combined wiretap event search and search results view * * @return wiretap events view */ @RequestMapping("newSearch.htm") public String initialiseWiretapEventSearch() { return "redirect:list.htm?pointToPointFlowProfileSearch=true"; } /** * Show the combined wiretap event search and search results view * * @param request - Standard HttpRequest * @param page - page index into the greater result set * @param orderBy - The field to order by * @param orderAsc - Ascending flag * @param pointToPointFlowProfileSearch - Flag to indicate what type of * search * @param pointToPointFlowProfileSelectAll - Select all boolean for * pointToPointFlowProfile based search * @param moduleSelectAll - Select all boolean for module based search * @param pageSize - Number of search results to display per page * @param moduleIds - Set of ids of modules to include in search - must * contain at least one id * @param pointToPointFlowProfileIds - Set of ids of point to point flow * profiles to include in search - must contain at least one * pointToPointFlowProfileId * @param moduleFlow - The internal Flow of the Module to search on * @param componentName - The name of the component * @param eventId - The Event Id * @param payloadId - The Payload Id * @param fromDateString - Include only events after fromDate * @param fromTimeString - Include only events after fromDate * @param untilDateString - Include only events before untilDate * @param untilTimeString - Include only events before untilDate * @param payloadContent - The Payload content * @param model - The model (map) * * @return wiretap events view */ @RequestMapping("list.htm") public String listWiretapEvents(HttpServletRequest request, @RequestParam(required = false) Integer page, @RequestParam(required = false) String orderBy, @RequestParam(required = false) Boolean orderAsc, @RequestParam(required = false) String pointToPointFlowProfileSearch, @RequestParam(required = false) Boolean pointToPointFlowProfileSelectAll, @RequestParam(required = false) Boolean moduleSelectAll, @RequestParam(required = false) Integer pageSize, @RequestParam(required = false) Set<Long> moduleIds, @RequestParam(required = false) Set<Long> pointToPointFlowProfileIds, @RequestParam(required = false) String moduleFlow, @RequestParam(required = false) String componentName, @RequestParam(required = false) String eventId, @RequestParam(required = false) String payloadId, @RequestParam(required = false) String fromDateString, @RequestParam(required = false) String fromTimeString, @RequestParam(required = false) String untilDateString, @RequestParam(required = false) String untilTimeString, @RequestParam(required = false) String payloadContent, ModelMap model) { Integer pageSizeToReturn = pageSize; Set<Long> moduleIdsToSearchOn = moduleIds; List<String> errors = new ArrayList<String>(); boolean noErrors = true; // Execute a pointToPointFlowProfile based search, so get the module ids // from those. if (pointToPointFlowProfileSearch.equals("true")) { logger.debug("This is a PointToPointFlowProfile Based Search."); moduleIdsToSearchOn = getModuleIdsFromPointToPointFlowProfiles(pointToPointFlowProfileIds); } // If a search is executed from a page that has no search results // defined then the pageSize is null, we therefore default it to 10 if (pageSize == null) { pageSizeToReturn = 10; } // Log the search criteria coming in // TODO Fix log4j config with Jboss in order to be able to log.debug if (logger.isDebugEnabled()) { logger.debug("Form values that came in:"); logSearch(page, orderBy, orderAsc, pointToPointFlowProfileSearch, pointToPointFlowProfileSelectAll, moduleSelectAll, pageSizeToReturn, moduleIdsToSearchOn, pointToPointFlowProfileIds, moduleFlow, componentName, eventId, payloadId, fromDateString, fromTimeString, untilDateString, untilTimeString, payloadContent); } // Set the search criteria from the values that came in and then // validate them WiretapSearchCriteria wiretapSearchCriteria = new WiretapSearchCriteria(moduleIdsToSearchOn); wiretapSearchCriteria.setModuleFlow(moduleFlow); wiretapSearchCriteria.setComponentName(componentName); wiretapSearchCriteria.setEventId(eventId); wiretapSearchCriteria.setPayloadId(payloadId); wiretapSearchCriteria.setFromDate(fromDateString); wiretapSearchCriteria.setFromTime(fromTimeString); wiretapSearchCriteria.setUntilDate(untilDateString); wiretapSearchCriteria.setUntilTime(untilTimeString); wiretapSearchCriteria.setPayloadContent(payloadContent); // Validate the criteria and add any errors to the model this.validator.validate(wiretapSearchCriteria, errors); model.addAttribute("errors", errors); if (!errors.isEmpty()) { noErrors = false; } // Setup the generic search criteria int pageNo = MasterDetailControllerUtil.defaultZero(page); String orderByField = MasterDetailControllerUtil.resolveOrderBy(orderBy); boolean orderAscending = MasterDetailControllerUtil.defaultFalse(orderAsc); Date fromDate = wiretapSearchCriteria.getFromDateTime(); Date untilDate = wiretapSearchCriteria.getUntilDateTime(); // Log the search criteria we're sending down if (logger.isDebugEnabled()) { logger.debug("Executing Search with:"); logSearch(pageNo, orderByField, orderAscending, pointToPointFlowProfileSearch, pointToPointFlowProfileSelectAll, moduleSelectAll, pageSizeToReturn, moduleIdsToSearchOn, pointToPointFlowProfileIds, moduleFlow, componentName, eventId, payloadId, fromDateString, fromTimeString, untilDateString, untilTimeString, payloadContent); logger.debug("From Date/Time [" + fromDate + "]"); logger.debug("Until Date/Time [" + untilDate + "]"); } // Perform the paged search PagedSearchResult<WiretapEvent> pagedResult = null; if (noErrors) { Set<String> moduleNames = this.moduleService.getModuleNames(moduleIdsToSearchOn); pagedResult = this.wiretapService.findWiretapEvents(pageNo, pageSizeToReturn, orderByField, orderAscending, moduleNames, moduleFlow, componentName, eventId, payloadId, fromDate, untilDate, payloadContent); // pagedResult = this.wiretapService.findWiretapEvents(pageNo, pageSizeToReturn, orderByField, orderAscending, moduleNames, moduleFlow, componentName, eventId, // payloadId, fromDate, untilDate, payloadContent); } // Store the search parameters used Map<String, Object> searchParams = new HashMap<String, Object>(); if (pointToPointFlowProfileSearch.equals("true")) { MasterDetailControllerUtil.addParam(searchParams, "pointToPointFlowProfileIds", pointToPointFlowProfileIds); } else { MasterDetailControllerUtil.addParam(searchParams, "moduleIds", moduleIdsToSearchOn); } MasterDetailControllerUtil.addParam(searchParams, "moduleFlow", moduleFlow); MasterDetailControllerUtil.addParam(searchParams, "componentName", componentName); MasterDetailControllerUtil.addParam(searchParams, "eventId", eventId); MasterDetailControllerUtil.addParam(searchParams, "payloadId", payloadId); MasterDetailControllerUtil.addParam(searchParams, "fromDateString", fromDateString); MasterDetailControllerUtil.addParam(searchParams, "fromTimeString", fromTimeString); MasterDetailControllerUtil.addParam(searchParams, "untilDateString", untilDateString); MasterDetailControllerUtil.addParam(searchParams, "untilTimeString", untilTimeString); MasterDetailControllerUtil.addParam(searchParams, "payloadContent", payloadContent); MasterDetailControllerUtil.addPagedModelAttributes(orderByField, orderAscending, pointToPointFlowProfileSearch, pointToPointFlowProfileSelectAll, moduleSelectAll, model, pageNo, pageSizeToReturn, pagedResult, request, searchParams); // Return back to the combined search / search results view return "events/wiretapEvents"; } /** * Get a Set of module ids from the list of given pointToPointFlowProfileIds * * @param pointToPointFlowProfileIds - The list of * pointToPointFlowProfileIds to get the Module Ids from * @return Set of module ids */ private Set<Long> getModuleIdsFromPointToPointFlowProfiles(Set<Long> pointToPointFlowProfileIds) { Set<Long> moduleIds = pointToPointFlowProfileService .getModuleIdsFromPointToPointFlowProfiles(pointToPointFlowProfileIds); return moduleIds; } /** * View a specified WiretapEvent * * @param wiretapEventId The id of the wiretapped event to get * @param searchResultsUrl The Search Results Page we came from * @param modelMap The model * @return The model and view representing the wiretap event */ @RequestMapping("viewEvent.htm") public ModelAndView viewEvent(@RequestParam("wiretapEventId") long wiretapEventId, @RequestParam(required = false) String searchResultsUrl, ModelMap modelMap) { this.logger.debug("inside viewEvent, wiretapEventId=[" + wiretapEventId + "]"); WiretapEvent wiretapEvent = this.wiretapService.getWiretapEvent(new Long(wiretapEventId)); String payloadContent = wiretapEvent.getEvent().toString(); String prettyXMLContent = ""; if (payloadContentIsXML(payloadContent)) { // Escape the HTML prettyXMLContent = StringEscapeUtils.escapeHtml(payloadContent); // Then add <br> instead of newline prettyXMLContent = prettyXMLContent.replaceAll(System.getProperty("line.separator"), "<br />"); // Then add instead of ' ' prettyXMLContent = prettyXMLContent.replaceAll(" ", " "); payloadContent = prettyXMLContent; } modelMap.addAttribute("wiretapEvent", this.wiretapService.getWiretapEvent(new Long(wiretapEventId))); modelMap.addAttribute("payloadContent", payloadContent); modelMap.addAttribute("searchResultsUrl", searchResultsUrl); return new ModelAndView("events/viewWiretapEvent", modelMap); } /** * Helper method to determine if payload content is XML * * @param payloadContent - The content to check * @return true of the content is XML */ private boolean payloadContentIsXML(String payloadContent) { if (payloadContent.startsWith("<?xml")) { return true; } return false; } /** * View a specific payload content in a best guess native format * * @param wiretapEventId The id of the wiretap event to get * @param response - Standard response stream * @return null */ @RequestMapping("viewPrettyPayloadContent.htm") public ModelAndView viewPrettyPayloadContent(@RequestParam("wiretapEventId") long wiretapEventId, HttpServletResponse response) { this.logger.debug("inside viewPrettyPayloadContent, wiretapEventId=[" + wiretapEventId + "]"); WiretapEvent wiretapEvent = this.wiretapService.getWiretapEvent(new Long(wiretapEventId)); response.setContentType("text/xml"); try { response.getOutputStream().write(wiretapEvent.getEvent().toString().getBytes()); } catch (IOException e) { this.logger.error("Could not render payload content.", e); } return null; } /** * Retrieve a link to a module design resource that can be displayed to the end user (or perhaps downloaded) * * TODO Improve Error handling? * * @param moduleId - The id of the module to get the resource for * @param response - The response stream to output the resource to * @return null */ @RequestMapping("viewModuleDesign.htm") public ModelAndView viewModuleDesign(@RequestParam("moduleId") long moduleId, HttpServletResponse response) { this.logger.debug("inside viewModuleDesign, moduleId= [" + moduleId + "]"); Module module = this.moduleService.getModule(new Long(moduleId)); try { if (module != null) { if (module.getDesignDiagramURL() != null) { response.sendRedirect(module.getDesignDiagramURL()); } else { return null; } } else { throw new IOException("Module was NULL."); } } catch (IOException e) { logger.error("URL could not be resolved."); } return null; } /** * Download the payload content as a file * * TODO Improve Error handling? * * @param wiretapEventId - The Event id of the wiretapped event to download * @param response - The HttpServletResponse object, content is streamed to * this */ @RequestMapping("downloadPayloadContent.htm") public void outputFile(@RequestParam("wiretapEventId") long wiretapEventId, final HttpServletResponse response) { this.logger.debug("inside downloadPayloadContent, wiretapEventId=[" + wiretapEventId + "]"); WiretapEvent wiretapEvent = this.wiretapService.getWiretapEvent(new Long(wiretapEventId)); String outgoingFileName = String.valueOf(wiretapEvent.getIdentifier()); response.setContentType("application/download"); response.setHeader("Content-Disposition", "attachment; filename=\"" + outgoingFileName + "\""); try { ServletOutputStream op = response.getOutputStream(); op.write(wiretapEvent.getEvent().toString().getBytes()); op.flush(); } catch (IOException e) { this.logger.error("Could not download payload content.", e); } } /** * Log the search * * @param page - page index into the greater result set * @param orderBy - The field to order by * @param orderAsc - Ascending flag * @param pointToPointFlowProfileSearch - Flag to indicate what type of * search * @param pointToPointFlowProfileSelectAll - Select all boolean for * pointToPointFlowProfile based search * @param moduleSelectAll - Select all boolean for module based search * @param pageSize - Page Size, number of search results per page * @param moduleIds - Set of ids of modules to include in search * @param pointToPointFlowProfileIds - Set of ids of * pointToPointFlowProfiles to include in search * @param moduleFlow - The name of Flow internal to the Module * @param componentName - The name of the component * @param eventId - The Event Id * @param payloadId - The Payload Id * @param fromDateString - fromDate String * @param fromTimeString - fromTime String * @param untilDateString - untilDate String * @param untilTimeString - untilTime String * @param payloadContent - The Payload content */ private void logSearch(Integer page, String orderBy, Boolean orderAsc, String pointToPointFlowProfileSearch, Boolean pointToPointFlowProfileSelectAll, Boolean moduleSelectAll, Integer pageSize, Set<Long> moduleIds, Set<Long> pointToPointFlowProfileIds, String moduleFlow, String componentName, String eventId, String payloadId, String fromDateString, String fromTimeString, String untilDateString, String untilTimeString, String payloadContent) { logger.debug("Page [" + page + "]"); logger.debug("Order By [" + orderBy + "]"); logger.debug("Order Ascending Flag [" + orderAsc + "]"); logger.debug("Point To Point Flow Profile Search Flag [" + pointToPointFlowProfileSearch + "]"); logger.debug("Point To Point Flow Profile Select All Flag [" + pointToPointFlowProfileSelectAll + "]"); logger.debug("Module Select All Flag [" + moduleSelectAll + "]"); logger.debug("Number of search results per page [" + pageSize + "]"); logger.debug("Module Ids [" + moduleIds + "]"); logger.debug("PointToPointFlowProfile Ids [" + pointToPointFlowProfileIds + "]"); logger.debug("Module Flow [" + moduleFlow + "]"); logger.debug("Component Name [" + componentName + "]"); logger.debug("Event Id [" + eventId + "]"); logger.debug("Payload Id [" + payloadId + "]"); logger.debug("From Date String [" + fromDateString + "]"); logger.debug("From Time String [" + fromTimeString + "]"); logger.debug("Until Date String [" + untilDateString + "]"); logger.debug("Until Time String [" + untilTimeString + "]"); logger.debug("Payload Content [" + payloadContent + "]"); } }