package org.fenixedu.bennu.alerts; import java.net.URI; import java.net.URISyntaxException; import java.util.Collections; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class exposes the main API for using FlashMap. FlashMap are Maps that * are only available for a short time, that requests can use to store * information between requests. It is particularly useful for POST/GET and * POST/Redirect/GET scenarios where a message should be presented to the user. * * <p> * Each request has available two FlashMaps available, an input and an output. * The input FlashMap is set of objects defined on previous request, and is read * only. The output FlashMap can be use to set attributes to be used on * subsequent requests. FlashMaps are removed after a timeout (180 seconds by * default) if not used. * </p> * * @author Artur Ventura (artur.ventura@tecnico.pt) * @since 3.5.0 * @see org.fenixedu.bennu.alerts.FlashMap */ class RedirectAttributes { private static final String INPUT_FLASH_MAP_ATTRIBUTE = RedirectAttributes.class .getName() + ".INPUT_FLASH_MAP"; private static final String OUTPUT_FLASH_MAP_ATTRIBUTE = RedirectAttributes.class .getName() + ".OUTPUT_FLASH_MAP"; private static final String FLASH_MAP_MANAGER_ATTRIBUTE = RedirectAttributes.class .getName() + ".FLASH_MAP_MANAGER"; private static final Logger LOGGER = LoggerFactory .getLogger(RedirectAttributes.class); /** * Finds a matching input FlashMap and places it on the request as a * attribute. * * @param request * the current request */ protected static void initFromRequest(HttpServletRequest request) { if (request.getAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE) == null) { FlashMapManager sfmm = new FlashMapManager(); FlashMap inputFlashMap = sfmm.retrieveAndUpdate(request); if (inputFlashMap != null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); } request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, sfmm); } } /** * Prepares the FlashMap to be saved, for a next request. If the response is * a 3** code, and we have a next location available, the FlashpMap is * tagged to only be available on that specific URL. This prevents the case * of some other page hijacks the FlashMap. This is particularly useful on * POST/Redirect/GET scenario. * * @param request * the current request * @param response * the current response */ protected static void flush(HttpServletRequest request, HttpServletResponse response) { FlashMap flashMap = (FlashMap) request .getAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE); if (flashMap != null && !flashMap.isEmpty()) { FlashMapManager flashMapManager = getFlashMapManager(request); int status = response.getStatus(); if ((status == HttpServletResponse.SC_MULTIPLE_CHOICES || status == HttpServletResponse.SC_MOVED_PERMANENTLY || status == HttpServletResponse.SC_FOUND || status == HttpServletResponse.SC_SEE_OTHER || status == HttpServletResponse.SC_TEMPORARY_REDIRECT) && response.getHeader("Location") != null) { URI url; try { url = new URI(response.getHeader("Location")); flashMap.setTargetRequestPath(url.getPath()); flashMap.addTargetRequestParams(flashMapManager .splitQuery(url.getQuery())); } catch (URISyntaxException e) { LOGGER.error("problem in "); } } flashMapManager.saveOutputFlashMap(flashMap, request); } } /** * Returns the Input FlashMap for this request. * * @param request * the current request * @return an Map with the available attributes. */ public static Map<String, ?> getInputFlashMap(HttpServletRequest request) { Object obj = request.getAttribute(INPUT_FLASH_MAP_ATTRIBUTE); if (obj != null) { return (Map<String, ?>) obj; } else { FlashMap inputFlashMap = new FlashMapManager() .retrieveAndUpdate(request); if (inputFlashMap != null) { Map<String, ?> map = Collections.unmodifiableMap(inputFlashMap); request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, map); return inputFlashMap; } else { return Collections.emptyMap(); } } } /** * Returns the Output FlashMap for this request. Use this method to set * stuff for the next request. * * @param request * the current request * @return the Output FlashMap */ public static FlashMap getOutputFlashMap(HttpServletRequest request) { return (FlashMap) request.getAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE); } /** * Returns the FlashMapManager for this request * * @param request * the current request * @return a FlashMapManager for this instance */ public static FlashMapManager getFlashMapManager(HttpServletRequest request) { return (FlashMapManager) request .getAttribute(FLASH_MAP_MANAGER_ATTRIBUTE); } /** * Adds a attribute to the output FlashMap. * * @param request * the current request * @param key * the key * @param object * the value */ public static void addFlashAttribute(HttpServletRequest request, String key, Object object) { getOutputFlashMap(request).put(key, object); } /** * ADds a attribute to the output FlashMap, using the object class name as * key. * * @param request * the current request * @param object * the value */ public static void addFlashAttribute(HttpServletRequest request, Object object) { getOutputFlashMap(request).put(object.getClass().getCanonicalName(), object); } }