All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.icefaces.impl.application.ExtendedExceptionHandler Maven / Gradle / Ivy

There is a newer version: 4.3.0
Show newest version
/*
 * Copyright 2004-2014 ICEsoft Technologies Canada Corp.
 *
 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS
 * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */

package org.icefaces.impl.application;

import org.icefaces.application.SessionExpiredException;
import org.icefaces.util.EnvUtils;

import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.ApplicationFactory;
import javax.faces.application.ProjectStage;
import javax.faces.application.ViewExpiredException;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;
import javax.faces.event.PhaseId;
import javax.servlet.http.HttpSession;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ExtendedExceptionHandler extends ExceptionHandlerWrapper {

    private final static Logger log = Logger.getLogger(ExtendedExceptionHandler.class.getName());

    private ExceptionHandler wrapped;

    public ExtendedExceptionHandler(ExceptionHandler wrapped) {
        this.wrapped = wrapped;
    }

    public ExceptionHandler getWrapped() {
        return wrapped;
    }

    @Override
    public boolean isListenerForSource(Object o) {
        return super.isListenerForSource(o);
    }

    /**
     * Logic in here is based on Ed Burn's example at
     * http://weblogs.java.net/blog/edburns/archive/2009/09/03/dealing-gracefully-viewexpiredexception-jsf2
     * 

* The basic premise is that when sessions expire, the next request from the client will trigger a * ViewExpiredException and we'd rather see a SessionExpiredException. So under specific circumstances, * we handle ViewExpiredExceptions by removing them and pushing a custom SessionExpiredException into the * queue. * * @throws FacesException */ @Override public void handle() throws FacesException { boolean sessionExpired = false; for (Iterator iter = getUnhandledExceptionQueuedEvents().iterator(); iter.hasNext(); ) { ExceptionQueuedEvent event = iter.next(); ExceptionQueuedEventContext queueContext = (ExceptionQueuedEventContext) event.getSource(); Throwable ex = queueContext.getException(); FacesContext fc = FacesContext.getCurrentInstance(); if (fc.isProjectStage(ProjectStage.Development)) { log.log(Level.WARNING,"queued exception", ex); } if ((ex instanceof ViewExpiredException) && PhaseId.RESTORE_VIEW.equals(queueContext.getPhaseId())) { ViewExpiredException vex = (ViewExpiredException)ex; String viewId = vex.getViewId(); ExternalContext ec = fc.getExternalContext(); Object sessObj = ec.getSession(false); boolean isPortalEnvironment = EnvUtils.instanceofPortletSession(sessObj); if (sessObj != null || !isPortalEnvironment) { if (!isValidSession(fc,viewId) || isPortalEnvironment) { //Remove the ViewExpiredException and set the sessionExpired flag so that we know //to add the SessionExpiredException which is done late to avoid ConcurrentModificationException. iter.remove(); sessionExpired = true; break; } } } } //Do the processing outside of the iterator to avoid ConcurrentModificationException FacesContext fc = FacesContext.getCurrentInstance(); if (sessionExpired) { Application app = fc.getApplication(); final HttpSession session = EnvUtils.getSafeSession(fc, false); //mark session as being expired session.setAttribute(this.getClass().getName(), true); if (app == null) { ApplicationFactory factory = (ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY); app = factory.getApplication(); } ExceptionQueuedEventContext ctxt = new ExceptionQueuedEventContext(fc, new SessionExpiredException("session expired (causing view to expire)")); app.publishEvent(fc, ExceptionQueuedEvent.class, ctxt); } //create fake view root to workaround Mojarra's failure to send the exception message when javax.faces.PARTIAL_STATE_SAVING=false if (fc.getViewRoot() == null) { UIViewRoot viewRoot = new UIViewRoot(); viewRoot.setRenderKitId("HTML_BASIC"); fc.setViewRoot(viewRoot); } //Once we've removed the ViewExpiredException and added the SessionExpiredException, we can //let default processing take over again. getWrapped().handle(); } private boolean isValidSession(FacesContext fc, String viewId) { //If the session is available but the getters on the session throw IllegalStateExceptions, //then the session is considered invalid. If the session is not new and the calculation //passes, then the session is considered valid. boolean validSession = false; HttpSession httpSession = EnvUtils.getSafeSession(fc,false); try { boolean newSession = httpSession.isNew(); long lastAccessed = httpSession.getLastAccessedTime(); int maxInactive = httpSession.getMaxInactiveInterval(); long now = System.currentTimeMillis(); if (!newSession && (now - lastAccessed) <= (maxInactive * 1000)) { validSession = true; } log.log(Level.FINE, "checking for session validity: " + "\n isNew : " + newSession + "\n now : " + now + "\n last accessed : " + lastAccessed + "\n max inactive : " + (maxInactive * 1000) + "\n time is fine : " + ((now - lastAccessed) <= (maxInactive * 1000)) + "\n valid : " + validSession ); //expired session still in use, make sure it's considered invalid/expired if (httpSession.getAttribute(this.getClass().getName()) != null) { validSession = false; } } catch (IllegalStateException ignored) { //An IllegalStateException here simply means the session is invalid } return validSession; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy