001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/sam/tags/sakai_2-4-1/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/web/session/SessionUtil.java $
003: * $Id: SessionUtil.java 9268 2006-05-10 21:27:24Z daisyf@stanford.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2004, 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the"License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.tool.assessment.ui.web.session;
021:
022: import javax.faces.context.ExternalContext;
023: import javax.faces.context.FacesContext;
024: import javax.servlet.http.HttpSession;
025:
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.sakaiproject.tool.api.ToolSession;
029: import org.sakaiproject.tool.cover.SessionManager;
030: import org.sakaiproject.tool.assessment.ui.bean.delivery.DeliveryBean;
031: import org.sakaiproject.tool.assessment.integration.context.IntegrationContextFactory;
032:
033: /**
034: * <p>
035: * <code>SessionUtil</code> provides a mechanism to assign the inactive
036: * interval for the current session. In the event that user has more than one
037: * thread accessing the same or separate assessments, <code> SessionUtil </code>
038: * guarantees that the session will have the (maximum assessment time limit among threads)
039: * as the value of the inactive interval.
040: *
041: * <pre>
042: * <tt>Scenarios which require a greater inactive interval than the default interval:
043: * - Assessments or surveys which are delivered on a single page
044: * - Questions which require more time than the default application timeout setting
045: * </tt>
046: * </pre>
047: *
048: *
049: * @author Jarrod Lannan
050: * @version $Revision: 9268 $
051: * @see javax.servlet.http.HttpSession
052: * @see javax.servlet.http.HttpSession#setMaxInactiveInterval(int)
053: *
054: */
055: public class SessionUtil {
056:
057: public static final String EXTERNAL_APP_INTERVAL = "app_interval_val";
058: public static final int HOURS_TO_SECONDS_MULTIPLIER = 60 * 60;
059: public static final int MINUTES_TO_SECONDS_MULTIPLIER = 60;
060: public static final int DEFAULT_APP_INTERVAL_VAL = 5 * HOURS_TO_SECONDS_MULTIPLIER;
061:
062: private static final int INTERVAL_BUFFER = 60 * 15;
063: private static Log log = LogFactory.getLog(SessionUtil.class);
064:
065: /**
066: * Sets the current <code>HttpSession</code> maxInactiveInterval value
067: * @param context the faces context
068: * @param delivery the delivery bean
069: * @param beginAssessment true if called from the beginning of an assessment, otherwise false
070: *
071: * @see org.sakaiproject.tool.assessment.ui.bean.delivery.DeliveryBean
072: */
073: public static void setSessionTimeout(FacesContext context,
074: DeliveryBean delivery, boolean beginAssessment) {
075: boolean standalone = !IntegrationContextFactory.getInstance()
076: .isIntegrated();
077: if (standalone)
078: return;
079:
080: ExternalContext exContext = context.getExternalContext();
081: HttpSession session = (HttpSession) exContext.getSession(false);
082:
083: if (session == null) {
084: return;
085: }
086:
087: /** if we have a tool session then get big session (MySession) */
088: if (session instanceof ToolSession) {
089: session = (HttpSession) SessionManager.getCurrentSession();
090: }
091:
092: synchronized (session) {
093:
094: if (beginAssessment) {
095:
096: /**
097: * if we have not already set value
098: * (ensure setSessionTimeout is called only once at beginning of assessment)
099: */
100: int interval = DEFAULT_APP_INTERVAL_VAL;
101: if (session != null
102: && session.getAttribute(EXTERNAL_APP_INTERVAL) == null) {
103: if (delivery != null && delivery.getHasTimeLimit()) {
104: interval = delivery.getTimeLimit_hour()
105: * HOURS_TO_SECONDS_MULTIPLIER;
106: interval += delivery.getTimeLimit_minute()
107: * MINUTES_TO_SECONDS_MULTIPLIER;
108: } else {
109: /** for assessments without time limit */
110: interval = DEFAULT_APP_INTERVAL_VAL;
111: }
112: }
113:
114: if (interval > session.getMaxInactiveInterval()) {
115: if (log.isDebugEnabled()) {
116: log.debug("begin_assessment: Setting session "
117: + session.getId()
118: + " inactive interval= " + interval
119: + " seconds");
120: }
121: /** store current interval value */
122: session.setAttribute(EXTERNAL_APP_INTERVAL,
123: new Integer(session
124: .getMaxInactiveInterval()));
125: session.setMaxInactiveInterval(interval
126: + INTERVAL_BUFFER);
127: }
128: } else {
129: /** on assessment submission or 'save and exit' from assessment */
130: Integer returnVal = (Integer) session
131: .getAttribute(EXTERNAL_APP_INTERVAL);
132: if (returnVal == null) {
133: return;
134: } else {
135: session.removeAttribute(EXTERNAL_APP_INTERVAL);
136: if (log.isDebugEnabled()) {
137: log.debug("end_assessment: Setting session "
138: + session.getId()
139: + " inactive interval= " + returnVal
140: + " seconds");
141: }
142: /** set to value of interval before taking */
143: session
144: .setMaxInactiveInterval(returnVal
145: .intValue());
146: }
147: }
148: }
149: }
150: }
|