/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/sam/trunk/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/web/session/SessionUtil.java $ * $Id: SessionUtil.java 106463 2012-04-02 12:20:09Z david.horwitz@uct.ac.za $ *********************************************************************************** * * Copyright (c) 2004, 2005, 2006, 2008, 2009 The Sakai Foundation * * Licensed under the Educational Community 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.opensource.org/licenses/ECL-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.sakaiproject.tool.assessment.ui.web.session; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.tool.api.ToolSession; import org.sakaiproject.tool.cover.SessionManager; import org.sakaiproject.tool.assessment.ui.bean.delivery.DeliveryBean; import org.sakaiproject.tool.assessment.integration.context.IntegrationContextFactory; /** * <p> * <code>SessionUtil</code> provides a mechanism to assign the inactive * interval for the current session. In the event that user has more than one * thread accessing the same or separate assessments, <code> SessionUtil </code> * guarantees that the session will have the (maximum assessment time limit among threads) * as the value of the inactive interval. * * <pre> * <tt>Scenarios which require a greater inactive interval than the default interval: * - Assessments or surveys which are delivered on a single page * - Questions which require more time than the default application timeout setting * </tt> * </pre> * * * @author Jarrod Lannan * @version $Revision: 106463 $ * @see javax.servlet.http.HttpSession * @see javax.servlet.http.HttpSession#setMaxInactiveInterval(int) * */ public class SessionUtil { public static final String EXTERNAL_APP_INTERVAL = "app_interval_val"; public static final int HOURS_TO_SECONDS_MULTIPLIER = 60 * 60; public static final int MINUTES_TO_SECONDS_MULTIPLIER = 60; public static final int DEFAULT_APP_INTERVAL_VAL = 5 * HOURS_TO_SECONDS_MULTIPLIER; private static final int INTERVAL_BUFFER = 60 * 15; private static Log log = LogFactory.getLog(SessionUtil.class); /** * Sets the current <code>HttpSession</code> maxInactiveInterval value * @param context the faces context * @param delivery the delivery bean * @param beginAssessment true if called from the beginning of an assessment, otherwise false * * @see org.sakaiproject.tool.assessment.ui.bean.delivery.DeliveryBean */ public static void setSessionTimeout(FacesContext context, DeliveryBean delivery, boolean beginAssessment){ boolean standalone = !IntegrationContextFactory.getInstance().isIntegrated(); if (standalone) return; ExternalContext exContext = context.getExternalContext(); HttpSession session = (HttpSession) exContext.getSession(false); if (session == null){ return; } /** if we have a tool session then get big session (MySession) */ if (session instanceof ToolSession){ session = (HttpSession) SessionManager.getCurrentSession(); } synchronized (session){ if (beginAssessment){ /** * if we have not already set value * (ensure setSessionTimeout is called only once at beginning of assessment) */ int interval = DEFAULT_APP_INTERVAL_VAL; if (session.getAttribute(EXTERNAL_APP_INTERVAL) == null) { if (delivery != null && delivery.getHasTimeLimit()) { interval = delivery.getTimeLimit_hour() * HOURS_TO_SECONDS_MULTIPLIER; interval += delivery.getTimeLimit_minute() * MINUTES_TO_SECONDS_MULTIPLIER; } else { /** for assessments without time limit */ interval = DEFAULT_APP_INTERVAL_VAL; } } if (interval > session.getMaxInactiveInterval()){ if (log.isDebugEnabled()){ log.debug("begin_assessment: Setting session " + session.getId() + " inactive interval= " + interval + " seconds"); } /** store current interval value */ session.setAttribute(EXTERNAL_APP_INTERVAL, Integer.valueOf(session.getMaxInactiveInterval())); session.setMaxInactiveInterval(interval + INTERVAL_BUFFER); } } else{ /** on assessment submission or 'save and exit' from assessment */ Integer returnVal = (Integer) session.getAttribute(EXTERNAL_APP_INTERVAL); if (returnVal == null){ return; } else{ session.removeAttribute(EXTERNAL_APP_INTERVAL); if (log.isDebugEnabled()){ log.debug("end_assessment: Setting session " + session.getId() + " inactive interval= " + returnVal + " seconds"); } /** set to value of interval before taking */ session.setMaxInactiveInterval(returnVal.intValue()); } } } } }