/* SessionsCtrl.java Purpose: Description: History: Mon May 30 22:03:45 2005, Created by tomyeh Copyright (C) 2005 Potix Corporation. All Rights Reserved. {{IS_RIGHT This program is distributed under LGPL Version 2.1 in the hope that it will be useful, but WITHOUT ANY WARRANTY. }}IS_RIGHT */ package org.zkoss.zk.ui.sys; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zkoss.zk.ui.Session; import org.zkoss.zk.ui.Sessions; import org.zkoss.zk.ui.WebApp; import org.zkoss.zk.ui.util.Configuration; import org.zkoss.zk.ui.util.Monitor; /** * An additional utilities for implementation related to {@link Session}. * * @author tomyeh */ public class SessionsCtrl extends Sessions { private static final Logger log = LoggerFactory.getLogger(SessionsCtrl.class); protected SessionsCtrl() { } //prevent from instantiation /** Sets the session for the current thread. * Called only internally. */ public static final void setCurrent(Session sess) { _sess.set(sess); } /** Sets the session for the current thread. * Unlike {@link #setCurrent(Session)}, the session is resolved * later (when {@link #getCurrent} is called). * @since 5.0.0 */ public static final void setCurrent(SessionResolver sr) { _sess.set(sr); } /** Returns the current {@link SessionCtrl}. */ public static final SessionCtrl getCurrentCtrl() { return (SessionCtrl) getCurrent(); } /** Returns the current session or the current session resolver. * The returned value is either {@link Session} or {@link SessionResolver}. * @see #setRawCurrent * @see #setCurrent(Session) * @see #setCurrent(SessionResolver) * @since 5.0.0 */ public static final Object getRawCurrent() { return _sess.get(); } /** Sets the current session or the current session resolver. * @param rawsess the raw session. It can be null, an instance of * {@link Session} and {@link SessionResolver}. * Notice: it is usually the return value of {@link #getRawCurrent}. * @see #getRawCurrent * @since 5.0.0 */ public static final void setRawCurrent(Object rawsess) { if (rawsess != null && !(rawsess instanceof Session) && !(rawsess instanceof SessionResolver)) throw new IllegalArgumentException(rawsess.getClass().getName()); _sess.set(rawsess); } /** Update the session count. * <p>Called only internally. * @since 5.0.0 */ public static final void updateCount(boolean inc) { synchronized (SessionsCtrl.class) { if (inc) ++_cnt; else --_cnt; } } /** Called when a servlet/portlet starts to serve a request. * It checks whether the number of concurrent requests per session * exceeds the number specified in * {@link org.zkoss.zk.ui.util.Configuration#getSessionMaxRequests}. * If exceeded, false is returned, and the servlet/portlet shall stop * processing and return an error code back the client. * * <p>If not exceeded, true is returned, and the servlet/portlet * can continue the processing and it shall invoke {@link #requestExit} * in the finally clause. * * @since 3.0.1 */ public static boolean requestEnter(Session sess) { final Integer v = (Integer) sess.getAttribute(ATTR_REQUEST_COUNT); final int i = v != null ? v.intValue() + 1 : 1; final int max = sess.getWebApp().getConfiguration().getSessionMaxRequests(); if (max < 0 || i <= max) { sess.setAttribute(ATTR_REQUEST_COUNT, new Integer(i)); return true; } return false; } /** * Called when a servlet/portlet completes the service of a request. * This method must be called if {@link #requestEnter} is called * and returns true. This method shall not be called, otherwise. * * @since 3.0.1 */ public static void requestExit(Session sess) { final Integer v = (Integer) sess.getAttribute(ATTR_REQUEST_COUNT); final int i = v != null ? v.intValue() - 1 : 0; sess.setAttribute(ATTR_REQUEST_COUNT, new Integer(i >= 0 ? i : 0)); } private static final String ATTR_REQUEST_COUNT = "org.zkoss.zk.ui.sys.RequestCount"; /** Returns the ZK session associated with the specified native session, * or null if not found. * * @param navsess the native session (never null). * If HTTP, it is HttpSession. If portlet, it is PortletSession. * @since 3.0.5 */ public static final Session getSession(WebApp wapp, Object navsess) { final SessionCache sc = ((WebAppCtrl) wapp).getSessionCache(); if (sc == null) return null; //bug 2668190: happens when destroying app in WebSphere 7 final Session sess = sc.get(navsess); if (sess != null && sess.getNativeSession() != navsess) ((SessionCtrl) sess).recover(navsess); return sess; } /** Instantiates a ZK session that is associated with the specified * native session and request. * * @param navsess the native session (never null). * If HTTP, it is HttpSession. If portlet, it is PortletSession. * @since 3.0.5 */ public static final Session newSession(WebApp wapp, Object navsess, Object request) { final WebAppCtrl wappc = (WebAppCtrl) wapp; final Session sess = wappc.getUiFactory().newSession(wapp, navsess, request); wappc.getSessionCache().put(sess); final Configuration config = wapp.getConfiguration(); config.invokeSessionInits(sess, request); //it might throw exception final Monitor monitor = config.getMonitor(); if (monitor != null) { try { monitor.sessionCreated(sess); } catch (Throwable ex) { log.error("", ex); } } //Note: we set timeout here, because HttpSession might have been created //by other servlet or filter final int v = wapp.getConfiguration().getSessionMaxInactiveInterval(); if (v != 0) sess.setMaxInactiveInterval(v); return sess; } }