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

org.zkoss.zk.ui.http.SimpleSession Maven / Gradle / Ivy

There is a newer version: 10.0.0-jakarta
Show newest version
/* SimpleSession.java

	Purpose:
		
	Description:
		
	History:
		Fri Jun  3 17:05:30     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.http;

import java.io.Externalizable;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.portlet.PortletSession;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.zkoss.util.CollectionsX;
import org.zkoss.web.servlet.xel.AttributesMap;
import org.zkoss.zk.ui.Execution;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.Session;
import org.zkoss.zk.ui.WebApp;
import org.zkoss.zk.ui.ext.ScopeListener;
import org.zkoss.zk.ui.impl.ScopeListeners;
import org.zkoss.zk.ui.sys.Attributes;
import org.zkoss.zk.ui.sys.DesktopCache;
import org.zkoss.zk.ui.sys.SessionCtrl;
import org.zkoss.zk.ui.sys.SessionsCtrl;
import org.zkoss.zk.ui.sys.WebAppCtrl;
import org.zkoss.zk.ui.util.Configuration;
import org.zkoss.zk.ui.util.Monitor;
import org.zkoss.zk.ui.util.SessionActivationListener;
import org.zkoss.zk.ui.util.SessionSerializationListener;

/** A non-serializable implementation of {@link org.zkoss.zk.ui.Session}.
 * 
 * 

Note:
* Though this class is serializable, it is meaningless to serialize * it directly. Reason: it doesn't serialize any session attributes. * Rather, it is serialized when Web server serialized HttpSession. * Also, notice that {@link SimpleSession} is stored as an attribute * HttpSession. * * @author tomyeh */ @SuppressWarnings("deprecation") public class SimpleSession implements Session, SessionCtrl { private static final Logger log = LoggerFactory.getLogger(SimpleSession.class); /** The attribute used to hold a set of serializable attributes that are written * thru {@link #setAttribute}. * *

Note: once a HttpSession is serialized, all serializable attributes * are serialized. However, if ZK's session is not serializable, it causes * inconsistency. For example, if an application has stored a serializable * attribute, say myAttr, in a session. Then, it will be surprised to see * myAttr is available while the session is actually brand-new * *

It is used if java.io.Serializable is NOT implemented. */ private static final String ATTR_PRIVATE = "javax.zkoss.ui.session.private"; /** The Web application that this session belongs to. */ private WebApp _wapp; /** The HTTP or Portlet session that this session is associated with. */ private Object _navsess; /** The device type. */ private String _devType = "ajax"; /** The attributes belonging to this session. * Note: it is the same map of HttpSession's attributes. * Note: No need to serialize attributes since it is done by Web server. */ private Map _attrs; private DesktopCache _cache; /** Next available component uuid. */ private int _nextUuid; /** When the last client request is received. */ private long _tmLastReq = System.currentTimeMillis(); private final ScopeListeners _scopeListeners = new ScopeListeners(this); private boolean _invalid; /** Indicates if {@link #invalidateNow} was called. */ private boolean _invalidated; /** Constructs a ZK session with a HTTP session. * * @param hsess the original HTTP session. * @param request the original request causing this session to be created. * If HTTP and servlet, it is javax.servlet.http.HttpServletRequest. * If portlet, it is javax.portlet.RenderRequest. * @since 3.0.1 */ public SimpleSession(WebApp wapp, HttpSession hsess, Object request) { this(wapp, (Object) hsess, request); } /** Constructs a ZK session with either a HTTP session or a Portlet session. * *

Note: it assumes the scope of attributes is * PortletSession.APPLICATION_SCOPE. * * @param navsess the original session, either an instance of * HttpSession or PortletSession. * Notice: we don't declare PortletSession in API * to avoid this class failed to be loaded in some system (without * portlet-api.jar) * @param request the original request causing this session to be created. * If portlet, it is javax.portlet.RenderRequest. * @since 3.6.2 */ public SimpleSession(WebApp wapp, Object navsess, Object request) { if (wapp == null || navsess == null) throw new IllegalArgumentException(); SessionsCtrl.updateCount(true); _wapp = wapp; _navsess = navsess; cleanSessAttrs(); //after _navsess is initialized init(); } /** Called to initialize some members after this object is deserialized. *

In other words, it is called by the deriving class if it implements * java.io.Serializable. */ private final void init() { _attrs = new AttributesMap() { protected Enumeration getKeys() { return getAttrNames(); } protected Object getValue(String key) { return getAttribute(key); } protected void setValue(String key, Object val) { setAttribute(key, val); } protected void removeValue(String key) { removeAttribute(key); } }; } /** Cleans up the attribute being set. */ private final void cleanSessAttrs() { final Object names = getAttribute(ATTR_PRIVATE); if (names instanceof Set) { //Bug 1954655: backward-compatible for (Iterator it = ((Set) names).iterator(); it.hasNext();) rmAttr((String) it.next()); } rmAttr(ATTR_PRIVATE); } @SuppressWarnings("unchecked") private final Enumeration getAttrNames() { return _navsess instanceof HttpSession ? ((HttpSession) _navsess).getAttributeNames() : _navsess != null ? ((PortletSession) _navsess).getAttributeNames(PortletSession.APPLICATION_SCOPE) : CollectionsX.EMPTY_ENUMERATION; } public String getDeviceType() { return _devType; } public void setDeviceType(String deviceType) { if (deviceType == null || deviceType.length() == 0) throw new IllegalArgumentException(); //Note: we don't check whether any conflict (e.g., two desktops //have different device types). //The existence and others are checked by DesktopImpl //and this method is called when Desktop.setDeviceType is called _devType = deviceType; } public Object getAttribute(String name) { return _navsess instanceof HttpSession ? ((HttpSession) _navsess).getAttribute(name) : _navsess != null ? ((PortletSession) _navsess).getAttribute(name, PortletSession.APPLICATION_SCOPE) : null; } public Object getAttribute(String name, boolean recurse) { Object val = getAttribute(name); return val != null || !recurse || _wapp == null ? val : _wapp.getAttribute(name, true); } public boolean hasAttribute(String name) { return getAttribute(name) != null; //Servlet limitation } public boolean hasAttribute(String name, boolean recurse) { return hasAttribute(name) || (recurse && _wapp != null && _wapp.hasAttribute(name, true)); } @SuppressWarnings("unchecked") public Object setAttribute(String name, Object value) { final Object old = getAttribute(name); if (!(this instanceof Serializable || this instanceof Externalizable)) { final boolean bStore = value instanceof Serializable || value instanceof Externalizable; synchronized (this) { setAttr(name, value); Object prv = getAttribute(ATTR_PRIVATE); if (bStore) { if (!(prv instanceof Set)) setAttr(ATTR_PRIVATE, prv = new HashSet()); ((Set) prv).add(name); } else { if (prv instanceof Set) ((Set) prv).remove(name); } } } else { setAttr(name, value); } return old; } public Object setAttribute(String name, Object value, boolean recurse) { if (recurse && !hasAttribute(name)) { if (_wapp != null) { if (_wapp.hasAttribute(name, true)) return _wapp.setAttribute(name, value, true); } } return setAttribute(name, value); } public Object removeAttribute(String name, boolean recurse) { if (recurse && !hasAttribute(name)) { if (_wapp != null) { if (_wapp.hasAttribute(name, true)) return _wapp.removeAttribute(name, true); } return null; } return removeAttribute(name); } public Object removeAttribute(String name) { Object old = getAttribute(name); if (!(this instanceof Serializable || this instanceof Externalizable)) { synchronized (this) { rmAttr(name); Object prv = getAttribute(ATTR_PRIVATE); if (prv instanceof Set) ((Set) prv).remove(name); } } else { rmAttr(name); } return old; } public boolean addScopeListener(ScopeListener listener) { return _scopeListeners.addScopeListener(listener); } public boolean removeScopeListener(ScopeListener listener) { return _scopeListeners.removeScopeListener(listener); } /** Returns all scope listeners. */ /*package*/ ScopeListeners getScopeListeners() { return _scopeListeners; } private void setAttr(String name, Object value) { if (_navsess instanceof HttpSession) ((HttpSession) _navsess).setAttribute(name, value); else if (_navsess != null) ((PortletSession) _navsess).setAttribute(name, value, PortletSession.APPLICATION_SCOPE); } private void rmAttr(String name) { if (_navsess instanceof HttpSession) ((HttpSession) _navsess).removeAttribute(name); else if (_navsess != null) ((PortletSession) _navsess).removeAttribute(name, PortletSession.APPLICATION_SCOPE); } public Map getAttributes() { return _attrs; } public String getRemoteAddr() { Execution execution = Executions.getCurrent(); if (execution != null) return execution.getRemoteAddr(); return null; } public String getRemoteHost() { Execution execution = Executions.getCurrent(); if (execution != null) return execution.getRemoteHost(); return null; } public String getServerName() { Execution execution = Executions.getCurrent(); if (execution != null) return execution.getServerName(); return null; } public String getLocalName() { Execution execution = Executions.getCurrent(); if (execution != null) return execution.getLocalName(); return null; } public String getLocalAddr() { Execution execution = Executions.getCurrent(); if (execution != null) return execution.getLocalAddr(); return null; } public void invalidateNow() { _invalid = true; if (!_invalidated) { _invalidated = true; //to avoid called twice rmAttr(Attributes.RENEW_NATIVE_SESSION); //See HttpSessionListener if (_navsess instanceof HttpSession) ((HttpSession) _navsess).invalidate(); else ((PortletSession) _navsess).invalidate(); } } public void setMaxInactiveInterval(int interval) { if (_navsess instanceof HttpSession) ((HttpSession) _navsess).setMaxInactiveInterval(interval); else if (_navsess != null) ((PortletSession) _navsess).setMaxInactiveInterval(interval); } public int getMaxInactiveInterval() { return _navsess instanceof HttpSession ? ((HttpSession) _navsess).getMaxInactiveInterval() : _navsess != null ? ((PortletSession) _navsess).getMaxInactiveInterval() : -1; } public Object getNativeSession() { return _navsess; } public boolean notifyClientRequest(boolean keepAlive) { final long now = System.currentTimeMillis(); if (keepAlive) { _tmLastReq = now; } else { final int tmout = getMaxInactiveInterval(); if (tmout >= 0 && (now - _tmLastReq) / 1000 > tmout) { invalidate(); return true; } } return false; } public final WebApp getWebApp() { return _wapp; } public final void invalidate() { _invalid = true; } public final boolean isInvalidated() { return _invalid; } public DesktopCache getDesktopCache() { return _cache; } public void setDesktopCache(DesktopCache cache) { _cache = cache; } public void recover(Object nativeSession) { _invalidated = _invalid = false; if (_navsess == null) sessionDidActivate((HttpSession) nativeSession); else _navsess = nativeSession; //Session Fixation Protection might change native session //Not sure it is clever to call sessionDidActivate //To be safe, we recover _navsess only } public void onDestroyed() { SessionsCtrl.updateCount(false); _invalidated = _invalid = true; final Configuration config = getWebApp().getConfiguration(); config.invokeSessionCleanups(this); cleanSessAttrs(); final Monitor monitor = config.getMonitor(); if (monitor != null) { try { monitor.sessionDestroyed(this); } catch (Throwable ex) { log.error("", ex); } } _navsess = null; //clean up } //--Serializable for deriving classes--// /** Used by the deriving class, * only if the deriving class implements java.io.Serializable. */ protected SimpleSession() { } /** Used by the deriving class to write this object, * only if the deriving class implements java.io.Serializable. */ protected void writeThis(java.io.ObjectOutputStream s) throws java.io.IOException { s.writeObject(_cache); s.writeInt(_nextUuid); //Since HttpSession will serialize attributes by the container //we ony invoke the notification for (Enumeration en = getAttrNames(); en.hasMoreElements();) { final String nm = en.nextElement(); // Skip to write ZK Session for Weblogic to avoid an infinite loop if (!Attributes.ZK_SESSION.equals(nm)) { willSerialize(getAttribute(nm)); } } } private void willSerialize(Object o) { if (o instanceof SessionSerializationListener) ((SessionSerializationListener) o).willSerialize(this); } /** Used by the deriving class to read back this object, * only if the deriving class implements java.io.Serializable. */ protected void readThis(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { init(); _cache = (DesktopCache) s.readObject(); _nextUuid = s.readInt(); } /** Used by the deriving class to pre-process a session before writing * the session */ protected void sessionWillPassivate() { final Object old = SessionsCtrl.getRawCurrent(); //shall be null; just in case SessionsCtrl.setCurrent(this); try { ((WebAppCtrl) _wapp).sessionWillPassivate(this); for (Enumeration en = getAttrNames(); en.hasMoreElements();) { final String nm = en.nextElement(); willPassivate(getAttribute(nm)); } } finally { SessionsCtrl.setRawCurrent(old); } } /** Used by the deriving class to post-process a session after * it is read back. * *

Application shall not call this method directly. */ protected void sessionDidActivate(HttpSession hsess) { //Note: in Tomcat, servlet is activated later, so we have to //add listener to WebManager instead of process now final Object old = SessionsCtrl.getRawCurrent(); //shall be null; just in case SessionsCtrl.setCurrent(this); try { _navsess = hsess; WebManager.addActivationListener(hsess.getServletContext(), //FUTURE: getServletContext only in Servlet 2.3 or later new WebManagerActivationListener() { public void didActivate(WebManager webman) { _wapp = webman.getWebApp(); ((WebAppCtrl) _wapp).sessionDidActivate(SimpleSession.this); } }); for (Enumeration en = getAttrNames(); en.hasMoreElements();) { final String nm = en.nextElement(); didActivate(getAttribute(nm)); } } finally { SessionsCtrl.setRawCurrent(old); } } private void willPassivate(Object o) { if (o instanceof SessionActivationListener) ((SessionActivationListener) o).willPassivate(this); } private void didActivate(Object o) { if (o instanceof SessionActivationListener) ((SessionActivationListener) o).didActivate(this); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy