/* * RHQ Management Platform * Copyright (C) 2005-2008 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.enterprise.gui.common.framework; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.faces.application.FacesMessage; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import javax.faces.event.PhaseEvent; import javax.faces.event.PhaseId; import javax.faces.event.PhaseListener; import org.ajax4jsf.context.AjaxContext; import org.jetbrains.annotations.Nullable; /** * A phase listener that propogates global JSF messages across redirects. * * @author Joseph Marques * @author Ian Springer */ public class FacesMessagePropogationPhaseListener implements PhaseListener { private static final long serialVersionUID = 5393413660742308456L; private static final String SAVED_GLOBAL_FACES_MESSAGES = "SAVED_GLOBAL_FACES_MESSAGES"; public PhaseId getPhaseId() { return PhaseId.ANY_PHASE; } public void beforePhase(PhaseEvent event) { if (AjaxContext.getCurrentInstance().isAjaxRequest()) { return; } PhaseId phaseId = event.getPhaseId(); if (phaseId == PhaseId.RESTORE_VIEW) { // We want to add the saved messages back to the context immediately after the view is restored. // Remove them from the session once we've added them back, otherwise the messages will just keep // building up, since they are stored in session scope. List<FacesMessage> savedMessages = removeGlobalFacesMessagesFromSession(); putGlobalFacesMessagesInFacesContext(savedMessages); } } public void afterPhase(PhaseEvent event) { if (AjaxContext.getCurrentInstance().isAjaxRequest()) { return; } PhaseId phaseId = event.getPhaseId(); if (phaseId == PhaseId.INVOKE_APPLICATION) { // We want to store the messages in the context after the application has done its processing. putGlobalFacesMessagesInSession(); } else if (phaseId == PhaseId.RENDER_RESPONSE) { // If we've just rendered a response, this isn't a redirect, so we don't want to propogate messages. // (fix for http://jira.jboss.com/jira/browse/JBNADM-1548, ips, 08/15/07) removeGlobalFacesMessagesFromSession(); } } private void putGlobalFacesMessagesInSession() { FacesContext facesContext = FacesContext.getCurrentInstance(); Iterator<FacesMessage> messages = facesContext.getMessages(); List<FacesMessage> savedMessages = new ArrayList<FacesMessage>(); while (messages.hasNext()) { FacesMessage message = messages.next(); savedMessages.add(message); } ExternalContext externalContext = facesContext.getExternalContext(); Map<String, Object> sessionMap = externalContext.getSessionMap(); sessionMap.put(SAVED_GLOBAL_FACES_MESSAGES, savedMessages); } @Nullable @SuppressWarnings("unchecked") private List<FacesMessage> removeGlobalFacesMessagesFromSession() { Map<String, Object> sessionMap = getSessionMap(); return (List<FacesMessage>) sessionMap.remove(SAVED_GLOBAL_FACES_MESSAGES); } private void putGlobalFacesMessagesInFacesContext(@Nullable List<FacesMessage> messages) { // no work to do, if there weren't any messages if (messages == null) { return; } FacesContext facesContext = FacesContext.getCurrentInstance(); // Only add the messages if there aren't already any messages in the context. If there's already messages, // it's probably because Seam FacesMessages already took care of propogating them. if (!facesContext.getMessages().hasNext()) { for (FacesMessage message : messages) { facesContext.addMessage(null, message); } } } private Map<String, Object> getSessionMap() { FacesContext facesContext = FacesContext.getCurrentInstance(); ExternalContext externalContext = facesContext.getExternalContext(); return externalContext.getSessionMap(); } }