/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.catalina.session;

import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.io.WriteAbortedException;
import java.security.AccessController;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpSessionActivationListener;
import jakarta.servlet.http.HttpSessionAttributeListener;
import jakarta.servlet.http.HttpSessionBindingEvent;
import jakarta.servlet.http.HttpSessionBindingListener;
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionIdListener;
import jakarta.servlet.http.HttpSessionListener;

import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.Manager;
import org.apache.catalina.Session;
import org.apache.catalina.SessionEvent;
import org.apache.catalina.SessionListener;
import org.apache.catalina.TomcatPrincipal;
import org.apache.catalina.security.SecurityUtil;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.res.StringManager;

Standard implementation of the Session interface. This object is serializable, so that it can be stored in persistent storage or transferred to a different JVM for distributable session support.

IMPLEMENTATION NOTE: An instance of this class represents both the internal (Session) and application level (HttpSession) view of the session. However, because the class itself is not declared public, Java logic outside of the org.apache.catalina.session package cannot cast an HttpSession view of this instance back to a Session view.

IMPLEMENTATION NOTE: If you add fields to this class, you must make sure that you carry them over in the read/writeObject methods so that this class is properly serialized.

Author:Craig R. McClanahan, Sean Legassick, Jon S. Stevens
/** * Standard implementation of the <b>Session</b> interface. This object is * serializable, so that it can be stored in persistent storage or transferred * to a different JVM for distributable session support. * <p> * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * internal (Session) and application level (HttpSession) view of the session. * However, because the class itself is not declared public, Java logic outside * of the <code>org.apache.catalina.session</code> package cannot cast an * HttpSession view of this instance back to a Session view. * <p> * <b>IMPLEMENTATION NOTE</b>: If you add fields to this class, you must * make sure that you carry them over in the read/writeObject methods so * that this class is properly serialized. * * @author Craig R. McClanahan * @author Sean Legassick * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a> */
public class StandardSession implements HttpSession, Session, Serializable { private static final long serialVersionUID = 1L; // ----------------------------------------------------------- Constructors
Construct a new Session associated with the specified Manager.
Params:
  • manager – The manager with which this Session is associated
/** * Construct a new Session associated with the specified Manager. * * @param manager The manager with which this Session is associated */
public StandardSession(Manager manager) { super(); this.manager = manager; if (manager != null) { // Manager could be null in test environments activityCheck = manager.getSessionActivityCheck(); lastAccessAtStart = manager.getSessionLastAccessAtStart(); } // Initialize access count if (activityCheck) { accessCount = new AtomicInteger(); } } // ----------------------------------------------------- Instance Variables
Type array.
/** * Type array. */
protected static final String EMPTY_ARRAY[] = new String[0];
The collection of user data attributes associated with this Session.
/** * The collection of user data attributes associated with this Session. */
protected ConcurrentMap<String, Object> attributes = new ConcurrentHashMap<>();
The authentication type used to authenticate our cached Principal, if any. NOTE: This value is not included in the serialized version of this object.
/** * The authentication type used to authenticate our cached Principal, * if any. NOTE: This value is not included in the serialized * version of this object. */
protected transient String authType = null;
The time this session was created, in milliseconds since midnight, January 1, 1970 GMT.
/** * The time this session was created, in milliseconds since midnight, * January 1, 1970 GMT. */
protected long creationTime = 0L;
We are currently processing a session expiration, so bypass certain IllegalStateException tests. NOTE: This value is not included in the serialized version of this object.
/** * We are currently processing a session expiration, so bypass * certain IllegalStateException tests. NOTE: This value is not * included in the serialized version of this object. */
protected transient volatile boolean expiring = false;
The facade associated with this session. NOTE: This value is not included in the serialized version of this object.
/** * The facade associated with this session. NOTE: This value is not * included in the serialized version of this object. */
protected transient StandardSessionFacade facade = null;
The session identifier of this Session.
/** * The session identifier of this Session. */
protected String id = null;
The last accessed time for this Session.
/** * The last accessed time for this Session. */
protected volatile long lastAccessedTime = creationTime;
The session event listeners for this Session.
/** * The session event listeners for this Session. */
protected transient ArrayList<SessionListener> listeners = new ArrayList<>();
The Manager with which this Session is associated.
/** * The Manager with which this Session is associated. */
protected transient Manager manager = null;
The maximum time interval, in seconds, between client requests before the servlet container may invalidate this session. A negative time indicates that the session should never time out.
/** * The maximum time interval, in seconds, between client requests before * the servlet container may invalidate this session. A negative time * indicates that the session should never time out. */
protected volatile int maxInactiveInterval = -1;
Flag indicating whether this session is new or not.
/** * Flag indicating whether this session is new or not. */
protected volatile boolean isNew = false;
Flag indicating whether this session is valid or not.
/** * Flag indicating whether this session is valid or not. */
protected volatile boolean isValid = false;
Internal notes associated with this session by Catalina components and event listeners. IMPLEMENTATION NOTE: This object is not saved and restored across session serializations!
/** * Internal notes associated with this session by Catalina components * and event listeners. <b>IMPLEMENTATION NOTE:</b> This object is * <em>not</em> saved and restored across session serializations! */
protected transient Map<String, Object> notes = new Hashtable<>();
The authenticated Principal associated with this session, if any. IMPLEMENTATION NOTE: This object is not saved and restored across session serializations!
/** * The authenticated Principal associated with this session, if any. * <b>IMPLEMENTATION NOTE:</b> This object is <i>not</i> saved and * restored across session serializations! */
protected transient Principal principal = null;
The string manager for this package.
/** * The string manager for this package. */
protected static final StringManager sm = StringManager.getManager(StandardSession.class);
The HTTP session context associated with this session.
/** * The HTTP session context associated with this session. */
@Deprecated protected static volatile jakarta.servlet.http.HttpSessionContext sessionContext = null;
The property change support for this component. NOTE: This value is not included in the serialized version of this object.
/** * The property change support for this component. NOTE: This value * is not included in the serialized version of this object. */
protected final transient PropertyChangeSupport support = new PropertyChangeSupport(this);
The current accessed time for this session.
/** * The current accessed time for this session. */
protected volatile long thisAccessedTime = creationTime;
The access count for this session.
/** * The access count for this session. */
protected transient AtomicInteger accessCount = null;
The activity check for this session.
/** * The activity check for this session. */
protected transient boolean activityCheck;
The behavior of the last access check.
/** * The behavior of the last access check. */
protected transient boolean lastAccessAtStart; // ----------------------------------------------------- Session Properties
Return the authentication type used to authenticate our cached Principal, if any.
/** * Return the authentication type used to authenticate our cached * Principal, if any. */
@Override public String getAuthType() { return this.authType; }
Set the authentication type used to authenticate our cached Principal, if any.
Params:
  • authType – The new cached authentication type
/** * Set the authentication type used to authenticate our cached * Principal, if any. * * @param authType The new cached authentication type */
@Override public void setAuthType(String authType) { String oldAuthType = this.authType; this.authType = authType; support.firePropertyChange("authType", oldAuthType, this.authType); }
Set the creation time for this session. This method is called by the Manager when an existing Session instance is reused.
Params:
  • time – The new creation time
/** * Set the creation time for this session. This method is called by the * Manager when an existing Session instance is reused. * * @param time The new creation time */
@Override public void setCreationTime(long time) { this.creationTime = time; this.lastAccessedTime = time; this.thisAccessedTime = time; }
Return the session identifier for this session.
/** * Return the session identifier for this session. */
@Override public String getId() { return this.id; }
Return the session identifier for this session.
/** * Return the session identifier for this session. */
@Override public String getIdInternal() { return this.id; }
Set the session identifier for this session.
Params:
  • id – The new session identifier
/** * Set the session identifier for this session. * * @param id The new session identifier */
@Override public void setId(String id) { setId(id, true); }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public void setId(String id, boolean notify) { if ((this.id != null) && (manager != null)) manager.remove(this); this.id = id; if (manager != null) manager.add(this); if (notify) { tellNew(); } }
Inform the listeners about the new session.
/** * Inform the listeners about the new session. * */
public void tellNew() { // Notify interested session event listeners fireSessionEvent(Session.SESSION_CREATED_EVENT, null); // Notify interested application event listeners Context context = manager.getContext(); Object listeners[] = context.getApplicationLifecycleListeners(); if (listeners != null && listeners.length > 0) { HttpSessionEvent event = new HttpSessionEvent(getSession()); for (Object o : listeners) { if (!(o instanceof HttpSessionListener)) continue; HttpSessionListener listener = (HttpSessionListener) o; try { context.fireContainerEvent("beforeSessionCreated", listener); listener.sessionCreated(event); context.fireContainerEvent("afterSessionCreated", listener); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); try { context.fireContainerEvent("afterSessionCreated", listener); } catch (Exception e) { // Ignore } manager.getContext().getLogger().error (sm.getString("standardSession.sessionEvent"), t); } } } }
Inform the listeners about the change session ID.
Params:
  • newId – new session ID
  • oldId – old session ID
  • notifySessionListeners – Should any associated sessionListeners be notified that session ID has been changed?
  • notifyContainerListeners – Should any associated ContainerListeners be notified that session ID has been changed?
/** * Inform the listeners about the change session ID. * * @param newId new session ID * @param oldId old session ID * @param notifySessionListeners Should any associated sessionListeners be * notified that session ID has been changed? * @param notifyContainerListeners Should any associated ContainerListeners * be notified that session ID has been changed? */
@Override public void tellChangedSessionId(String newId, String oldId, boolean notifySessionListeners, boolean notifyContainerListeners) { Context context = manager.getContext(); // notify ContainerListeners if (notifyContainerListeners) { context.fireContainerEvent(Context.CHANGE_SESSION_ID_EVENT, new String[] {oldId, newId}); } // notify HttpSessionIdListener if (notifySessionListeners) { Object listeners[] = context.getApplicationEventListeners(); if (listeners != null && listeners.length > 0) { HttpSessionEvent event = new HttpSessionEvent(getSession()); for(Object listener : listeners) { if (!(listener instanceof HttpSessionIdListener)) continue; HttpSessionIdListener idListener = (HttpSessionIdListener)listener; try { idListener.sessionIdChanged(event, oldId); } catch (Throwable t) { manager.getContext().getLogger().error (sm.getString("standardSession.sessionEvent"), t); } } } } }
Return the last time the client sent a request associated with this session, as the number of milliseconds since midnight, January 1, 1970 GMT. Actions that your application takes, such as getting or setting a value associated with the session, do not affect the access time. This one gets updated whenever a request starts.
/** * Return the last time the client sent a request associated with this * session, as the number of milliseconds since midnight, January 1, 1970 * GMT. Actions that your application takes, such as getting or setting * a value associated with the session, do not affect the access time. * This one gets updated whenever a request starts. */
@Override public long getThisAccessedTime() { if (!isValidInternal()) { throw new IllegalStateException (sm.getString("standardSession.getThisAccessedTime.ise")); } return this.thisAccessedTime; }
Return the last client access time without invalidation check
See Also:
  • getThisAccessedTime()
/** * Return the last client access time without invalidation check * @see #getThisAccessedTime() */
@Override public long getThisAccessedTimeInternal() { return this.thisAccessedTime; }
Return the last time the client sent a request associated with this session, as the number of milliseconds since midnight, January 1, 1970 GMT. Actions that your application takes, such as getting or setting a value associated with the session, do not affect the access time. This one gets updated whenever a request finishes.
/** * Return the last time the client sent a request associated with this * session, as the number of milliseconds since midnight, January 1, 1970 * GMT. Actions that your application takes, such as getting or setting * a value associated with the session, do not affect the access time. * This one gets updated whenever a request finishes. */
@Override public long getLastAccessedTime() { if (!isValidInternal()) { throw new IllegalStateException (sm.getString("standardSession.getLastAccessedTime.ise")); } return this.lastAccessedTime; }
Return the last client access time without invalidation check
See Also:
  • getLastAccessedTime()
/** * Return the last client access time without invalidation check * @see #getLastAccessedTime() */
@Override public long getLastAccessedTimeInternal() { return this.lastAccessedTime; }
Return the idle time (in milliseconds) from last client access time.
/** * Return the idle time (in milliseconds) from last client access time. */
@Override public long getIdleTime() { if (!isValidInternal()) { throw new IllegalStateException (sm.getString("standardSession.getIdleTime.ise")); } return getIdleTimeInternal(); }
Return the idle time from last client access time without invalidation check
See Also:
  • getIdleTime()
/** * Return the idle time from last client access time without invalidation check * @see #getIdleTime() */
@Override public long getIdleTimeInternal() { long timeNow = System.currentTimeMillis(); long timeIdle; if (lastAccessAtStart) { timeIdle = timeNow - lastAccessedTime; } else { timeIdle = timeNow - thisAccessedTime; } return timeIdle; }
Return the Manager within which this Session is valid.
/** * Return the Manager within which this Session is valid. */
@Override public Manager getManager() { return this.manager; }
Set the Manager within which this Session is valid.
Params:
  • manager – The new Manager
/** * Set the Manager within which this Session is valid. * * @param manager The new Manager */
@Override public void setManager(Manager manager) { this.manager = manager; }
Return the maximum time interval, in seconds, between client requests before the servlet container will invalidate the session. A negative time indicates that the session should never time out.
/** * Return the maximum time interval, in seconds, between client requests * before the servlet container will invalidate the session. A negative * time indicates that the session should never time out. */
@Override public int getMaxInactiveInterval() { return this.maxInactiveInterval; }
Set the maximum time interval, in seconds, between client requests before the servlet container will invalidate the session. A zero or negative time indicates that the session should never time out.
Params:
  • interval – The new maximum interval
/** * Set the maximum time interval, in seconds, between client requests * before the servlet container will invalidate the session. A zero or * negative time indicates that the session should never time out. * * @param interval The new maximum interval */
@Override public void setMaxInactiveInterval(int interval) { this.maxInactiveInterval = interval; }
Set the isNew flag for this session.
Params:
  • isNew – The new value for the isNew flag
/** * Set the <code>isNew</code> flag for this session. * * @param isNew The new value for the <code>isNew</code> flag */
@Override public void setNew(boolean isNew) { this.isNew = isNew; }
Return the authenticated Principal that is associated with this Session. This provides an Authenticator with a means to cache a previously authenticated Principal, and avoid potentially expensive Realm.authenticate() calls on every request. If there is no current associated Principal, return null.
/** * Return the authenticated Principal that is associated with this Session. * This provides an <code>Authenticator</code> with a means to cache a * previously authenticated Principal, and avoid potentially expensive * <code>Realm.authenticate()</code> calls on every request. If there * is no current associated Principal, return <code>null</code>. */
@Override public Principal getPrincipal() { return this.principal; }
Set the authenticated Principal that is associated with this Session. This provides an Authenticator with a means to cache a previously authenticated Principal, and avoid potentially expensive Realm.authenticate() calls on every request.
Params:
  • principal – The new Principal, or null if none
/** * Set the authenticated Principal that is associated with this Session. * This provides an <code>Authenticator</code> with a means to cache a * previously authenticated Principal, and avoid potentially expensive * <code>Realm.authenticate()</code> calls on every request. * * @param principal The new Principal, or <code>null</code> if none */
@Override public void setPrincipal(Principal principal) { Principal oldPrincipal = this.principal; this.principal = principal; support.firePropertyChange("principal", oldPrincipal, this.principal); }
Return the HttpSession for which this object is the facade.
/** * Return the <code>HttpSession</code> for which this object * is the facade. */
@Override public HttpSession getSession() { if (facade == null) { if (SecurityUtil.isPackageProtectionEnabled()) { facade = AccessController.doPrivileged(new PrivilegedNewSessionFacade(this)); } else { facade = new StandardSessionFacade(this); } } return facade; }
Return the isValid flag for this session.
/** * Return the <code>isValid</code> flag for this session. */
@Override public boolean isValid() { if (!this.isValid) { return false; } if (this.expiring) { return true; } if (activityCheck && accessCount.get() > 0) { return true; } if (maxInactiveInterval > 0) { int timeIdle = (int) (getIdleTimeInternal() / 1000L); if (timeIdle >= maxInactiveInterval) { expire(true); } } return this.isValid; }
Set the isValid flag for this session.
Params:
  • isValid – The new value for the isValid flag
/** * Set the <code>isValid</code> flag for this session. * * @param isValid The new value for the <code>isValid</code> flag */
@Override public void setValid(boolean isValid) { this.isValid = isValid; } // ------------------------------------------------- Session Public Methods
Update the accessed time information for this session. This method should be called by the context when a request comes in for a particular session, even if the application does not reference it.
/** * Update the accessed time information for this session. This method * should be called by the context when a request comes in for a particular * session, even if the application does not reference it. */
@Override public void access() { this.thisAccessedTime = System.currentTimeMillis(); if (activityCheck) { accessCount.incrementAndGet(); } }
End the access.
/** * End the access. */
@Override public void endAccess() { isNew = false; /** * The servlet spec mandates to ignore request handling time * in lastAccessedTime. */ if (lastAccessAtStart) { this.lastAccessedTime = this.thisAccessedTime; this.thisAccessedTime = System.currentTimeMillis(); } else { this.thisAccessedTime = System.currentTimeMillis(); this.lastAccessedTime = this.thisAccessedTime; } if (activityCheck) { accessCount.decrementAndGet(); } }
Add a session event listener to this component.
/** * Add a session event listener to this component. */
@Override public void addSessionListener(SessionListener listener) { listeners.add(listener); }
Perform the internal processing required to invalidate this session, without triggering an exception if the session has already expired.
/** * Perform the internal processing required to invalidate this session, * without triggering an exception if the session has already expired. */
@Override public void expire() { expire(true); }
Perform the internal processing required to invalidate this session, without triggering an exception if the session has already expired.
Params:
  • notify – Should we notify listeners about the demise of this session?
/** * Perform the internal processing required to invalidate this session, * without triggering an exception if the session has already expired. * * @param notify Should we notify listeners about the demise of * this session? */
public void expire(boolean notify) { // Check to see if session has already been invalidated. // Do not check expiring at this point as expire should not return until // isValid is false if (!isValid) return; synchronized (this) { // Check again, now we are inside the sync so this code only runs once // Double check locking - isValid needs to be volatile // The check of expiring is to ensure that an infinite loop is not // entered as per bug 56339 if (expiring || !isValid) return; if (manager == null) return; // Mark this session as "being expired" expiring = true; // Notify interested application event listeners // FIXME - Assumes we call listeners in reverse order Context context = manager.getContext(); // The call to expire() may not have been triggered by the webapp. // Make sure the webapp's class loader is set when calling the // listeners if (notify) { ClassLoader oldContextClassLoader = null; try { oldContextClassLoader = context.bind(Globals.IS_SECURITY_ENABLED, null); Object listeners[] = context.getApplicationLifecycleListeners(); if (listeners != null && listeners.length > 0) { HttpSessionEvent event = new HttpSessionEvent(getSession()); for (int i = 0; i < listeners.length; i++) { int j = (listeners.length - 1) - i; if (!(listeners[j] instanceof HttpSessionListener)) continue; HttpSessionListener listener = (HttpSessionListener) listeners[j]; try { context.fireContainerEvent("beforeSessionDestroyed", listener); listener.sessionDestroyed(event); context.fireContainerEvent("afterSessionDestroyed", listener); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); try { context.fireContainerEvent( "afterSessionDestroyed", listener); } catch (Exception e) { // Ignore } manager.getContext().getLogger().error (sm.getString("standardSession.sessionEvent"), t); } } } } finally { context.unbind(Globals.IS_SECURITY_ENABLED, oldContextClassLoader); } } if (activityCheck) { accessCount.set(0); } // Remove this session from our manager's active sessions manager.remove(this, true); // Notify interested session event listeners if (notify) { fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null); } // Call the logout method if (principal instanceof TomcatPrincipal) { TomcatPrincipal gp = (TomcatPrincipal) principal; try { gp.logout(); } catch (Exception e) { manager.getContext().getLogger().error( sm.getString("standardSession.logoutfail"), e); } } // We have completed expire of this session setValid(false); expiring = false; // Unbind any objects associated with this session String keys[] = keys(); ClassLoader oldContextClassLoader = null; try { oldContextClassLoader = context.bind(Globals.IS_SECURITY_ENABLED, null); for (String key : keys) { removeAttributeInternal(key, notify); } } finally { context.unbind(Globals.IS_SECURITY_ENABLED, oldContextClassLoader); } } }
Perform the internal processing required to passivate this session.
/** * Perform the internal processing required to passivate * this session. */
public void passivate() { // Notify interested session event listeners fireSessionEvent(Session.SESSION_PASSIVATED_EVENT, null); // Notify ActivationListeners HttpSessionEvent event = null; String keys[] = keys(); for (String key : keys) { Object attribute = attributes.get(key); if (attribute instanceof HttpSessionActivationListener) { if (event == null) event = new HttpSessionEvent(getSession()); try { ((HttpSessionActivationListener) attribute).sessionWillPassivate(event); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); manager.getContext().getLogger().error(sm.getString("standardSession.attributeEvent"), t); } } } }
Perform internal processing required to activate this session.
/** * Perform internal processing required to activate this * session. */
public void activate() { // Initialize access count if (activityCheck) { accessCount = new AtomicInteger(); } // Notify interested session event listeners fireSessionEvent(Session.SESSION_ACTIVATED_EVENT, null); // Notify ActivationListeners HttpSessionEvent event = null; String keys[] = keys(); for (String key : keys) { Object attribute = attributes.get(key); if (attribute instanceof HttpSessionActivationListener) { if (event == null) event = new HttpSessionEvent(getSession()); try { ((HttpSessionActivationListener) attribute).sessionDidActivate(event); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); manager.getContext().getLogger().error(sm.getString("standardSession.attributeEvent"), t); } } } }
Return the object bound with the specified name to the internal notes for this session, or null if no such binding exists.
Params:
  • name – Name of the note to be returned
/** * Return the object bound with the specified name to the internal notes * for this session, or <code>null</code> if no such binding exists. * * @param name Name of the note to be returned */
@Override public Object getNote(String name) { return notes.get(name); }
Return an Iterator containing the String names of all notes bindings that exist for this session.
/** * Return an Iterator containing the String names of all notes bindings * that exist for this session. */
@Override public Iterator<String> getNoteNames() { return notes.keySet().iterator(); }
Release all object references, and initialize instance variables, in preparation for reuse of this object.
/** * Release all object references, and initialize instance variables, in * preparation for reuse of this object. */
@Override public void recycle() { // Reset the instance variables associated with this Session attributes.clear(); setAuthType(null); creationTime = 0L; expiring = false; id = null; lastAccessedTime = 0L; maxInactiveInterval = -1; notes.clear(); setPrincipal(null); isNew = false; isValid = false; manager = null; }
Remove any object bound to the specified name in the internal notes for this session.
Params:
  • name – Name of the note to be removed
/** * Remove any object bound to the specified name in the internal notes * for this session. * * @param name Name of the note to be removed */
@Override public void removeNote(String name) { notes.remove(name); }
Remove a session event listener from this component.
/** * Remove a session event listener from this component. */
@Override public void removeSessionListener(SessionListener listener) { listeners.remove(listener); }
Bind an object to a specified name in the internal notes associated with this session, replacing any existing binding for this name.
Params:
  • name – Name to which the object should be bound
  • value – Object to be bound to the specified name
/** * Bind an object to a specified name in the internal notes associated * with this session, replacing any existing binding for this name. * * @param name Name to which the object should be bound * @param value Object to be bound to the specified name */
@Override public void setNote(String name, Object value) { notes.put(name, value); }
Return a string representation of this object.
/** * Return a string representation of this object. */
@Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("StandardSession["); sb.append(id); sb.append(']'); return sb.toString(); } // ------------------------------------------------ Session Package Methods
Read a serialized version of the contents of this session object from the specified object input stream, without requiring that the StandardSession itself have been serialized.
Params:
  • stream – The object input stream to read from
Throws:
/** * Read a serialized version of the contents of this session object from * the specified object input stream, without requiring that the * StandardSession itself have been serialized. * * @param stream The object input stream to read from * * @exception ClassNotFoundException if an unknown class is specified * @exception IOException if an input/output error occurs */
public void readObjectData(ObjectInputStream stream) throws ClassNotFoundException, IOException { doReadObject(stream); }
Write a serialized version of the contents of this session object to the specified object output stream, without requiring that the StandardSession itself have been serialized.
Params:
  • stream – The object output stream to write to
Throws:
/** * Write a serialized version of the contents of this session object to * the specified object output stream, without requiring that the * StandardSession itself have been serialized. * * @param stream The object output stream to write to * * @exception IOException if an input/output error occurs */
public void writeObjectData(ObjectOutputStream stream) throws IOException { doWriteObject(stream); } // ------------------------------------------------- HttpSession Properties
Return the time when this session was created, in milliseconds since midnight, January 1, 1970 GMT.
Throws:
  • IllegalStateException – if this method is called on an invalidated session
/** * Return the time when this session was created, in milliseconds since * midnight, January 1, 1970 GMT. * * @exception IllegalStateException if this method is called on an * invalidated session */
@Override public long getCreationTime() { if (!isValidInternal()) throw new IllegalStateException (sm.getString("standardSession.getCreationTime.ise")); return this.creationTime; }
Return the time when this session was created, in milliseconds since midnight, January 1, 1970 GMT, bypassing the session validation checks.
/** * Return the time when this session was created, in milliseconds since * midnight, January 1, 1970 GMT, bypassing the session validation checks. */
@Override public long getCreationTimeInternal() { return this.creationTime; }
Return the ServletContext to which this session belongs.
/** * Return the ServletContext to which this session belongs. */
@Override public ServletContext getServletContext() { if (manager == null) { return null; } Context context = manager.getContext(); return context.getServletContext(); }
Return the session context with which this session is associated.
Deprecated:As of Version 2.1, this method is deprecated and has no replacement. It will be removed in a future version of the Java Servlet API.
/** * Return the session context with which this session is associated. * * @deprecated As of Version 2.1, this method is deprecated and has no * replacement. It will be removed in a future version of the * Java Servlet API. */
@Override @Deprecated public jakarta.servlet.http.HttpSessionContext getSessionContext() { if (sessionContext == null) sessionContext = new StandardSessionContext(); return sessionContext; } // ----------------------------------------------HttpSession Public Methods
Return the object bound with the specified name in this session, or null if no object is bound with that name.
Params:
  • name – Name of the attribute to be returned
Throws:
/** * Return the object bound with the specified name in this session, or * <code>null</code> if no object is bound with that name. * * @param name Name of the attribute to be returned * * @exception IllegalStateException if this method is called on an * invalidated session */
@Override public Object getAttribute(String name) { if (!isValidInternal()) throw new IllegalStateException (sm.getString("standardSession.getAttribute.ise")); if (name == null) return null; return attributes.get(name); }
Return an Enumeration of String objects containing the names of the objects bound to this session.
Throws:
  • IllegalStateException – if this method is called on an invalidated session
/** * Return an <code>Enumeration</code> of <code>String</code> objects * containing the names of the objects bound to this session. * * @exception IllegalStateException if this method is called on an * invalidated session */
@Override public Enumeration<String> getAttributeNames() { if (!isValidInternal()) throw new IllegalStateException (sm.getString("standardSession.getAttributeNames.ise")); Set<String> names = new HashSet<>(attributes.keySet()); return Collections.enumeration(names); }
Return the object bound with the specified name in this session, or null if no object is bound with that name.
Params:
  • name – Name of the value to be returned
Throws:
Deprecated:As of Version 2.2, this method is replaced by getAttribute()
/** * Return the object bound with the specified name in this session, or * <code>null</code> if no object is bound with that name. * * @param name Name of the value to be returned * * @exception IllegalStateException if this method is called on an * invalidated session * * @deprecated As of Version 2.2, this method is replaced by * <code>getAttribute()</code> */
@Override @Deprecated public Object getValue(String name) { return getAttribute(name); }
Return the set of names of objects bound to this session. If there are no such objects, a zero-length array is returned.
Throws:
  • IllegalStateException – if this method is called on an invalidated session
Deprecated:As of Version 2.2, this method is replaced by getAttributeNames()
/** * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * * @exception IllegalStateException if this method is called on an * invalidated session * * @deprecated As of Version 2.2, this method is replaced by * <code>getAttributeNames()</code> */
@Override @Deprecated public String[] getValueNames() { if (!isValidInternal()) throw new IllegalStateException (sm.getString("standardSession.getValueNames.ise")); return keys(); }
Invalidates this session and unbinds any objects bound to it.
Throws:
  • IllegalStateException – if this method is called on an invalidated session
/** * Invalidates this session and unbinds any objects bound to it. * * @exception IllegalStateException if this method is called on * an invalidated session */
@Override public void invalidate() { if (!isValidInternal()) throw new IllegalStateException (sm.getString("standardSession.invalidate.ise")); // Cause this session to expire expire(); }
Return true if the client does not yet know about the session, or if the client chooses not to join the session. For example, if the server used only cookie-based sessions, and the client has disabled the use of cookies, then a session would be new on each request.
Throws:
  • IllegalStateException – if this method is called on an invalidated session
/** * Return <code>true</code> if the client does not yet know about the * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client * has disabled the use of cookies, then a session would be new on each * request. * * @exception IllegalStateException if this method is called on an * invalidated session */
@Override public boolean isNew() { if (!isValidInternal()) throw new IllegalStateException (sm.getString("standardSession.isNew.ise")); return this.isNew; }
Bind an object to this session, using the specified name. If an object of the same name is already bound to this session, the object is replaced.

After this method executes, and if the object implements HttpSessionBindingListener, the container calls valueBound() on the object.

Params:
  • name – Name to which the object is bound, cannot be null
  • value – Object to be bound, cannot be null
Throws:
Deprecated:As of Version 2.2, this method is replaced by setAttribute()
/** * Bind an object to this session, using the specified name. If an object * of the same name is already bound to this session, the object is * replaced. * <p> * After this method executes, and if the object implements * <code>HttpSessionBindingListener</code>, the container calls * <code>valueBound()</code> on the object. * * @param name Name to which the object is bound, cannot be null * @param value Object to be bound, cannot be null * * @exception IllegalStateException if this method is called on an * invalidated session * * @deprecated As of Version 2.2, this method is replaced by * <code>setAttribute()</code> */
@Override @Deprecated public void putValue(String name, Object value) { setAttribute(name, value); }
Remove the object bound with the specified name from this session. If the session does not have an object bound with this name, this method does nothing.

After this method executes, and if the object implements HttpSessionBindingListener, the container calls valueUnbound() on the object.

Params:
  • name – Name of the object to remove from this session.
Throws:
/** * Remove the object bound with the specified name from this session. If * the session does not have an object bound with this name, this method * does nothing. * <p> * After this method executes, and if the object implements * <code>HttpSessionBindingListener</code>, the container calls * <code>valueUnbound()</code> on the object. * * @param name Name of the object to remove from this session. * * @exception IllegalStateException if this method is called on an * invalidated session */
@Override public void removeAttribute(String name) { removeAttribute(name, true); }
Remove the object bound with the specified name from this session. If the session does not have an object bound with this name, this method does nothing.

After this method executes, and if the object implements HttpSessionBindingListener, the container calls valueUnbound() on the object.

Params:
  • name – Name of the object to remove from this session.
  • notify – Should we notify interested listeners that this attribute is being removed?
Throws:
/** * Remove the object bound with the specified name from this session. If * the session does not have an object bound with this name, this method * does nothing. * <p> * After this method executes, and if the object implements * <code>HttpSessionBindingListener</code>, the container calls * <code>valueUnbound()</code> on the object. * * @param name Name of the object to remove from this session. * @param notify Should we notify interested listeners that this * attribute is being removed? * * @exception IllegalStateException if this method is called on an * invalidated session */
public void removeAttribute(String name, boolean notify) { // Validate our current state if (!isValidInternal()) throw new IllegalStateException (sm.getString("standardSession.removeAttribute.ise")); removeAttributeInternal(name, notify); }
Remove the object bound with the specified name from this session. If the session does not have an object bound with this name, this method does nothing.

After this method executes, and if the object implements HttpSessionBindingListener, the container calls valueUnbound() on the object.

Params:
  • name – Name of the object to remove from this session.
Throws:
Deprecated:As of Version 2.2, this method is replaced by removeAttribute()
/** * Remove the object bound with the specified name from this session. If * the session does not have an object bound with this name, this method * does nothing. * <p> * After this method executes, and if the object implements * <code>HttpSessionBindingListener</code>, the container calls * <code>valueUnbound()</code> on the object. * * @param name Name of the object to remove from this session. * * @exception IllegalStateException if this method is called on an * invalidated session * * @deprecated As of Version 2.2, this method is replaced by * <code>removeAttribute()</code> */
@Override @Deprecated public void removeValue(String name) { removeAttribute(name); }
Bind an object to this session, using the specified name. If an object of the same name is already bound to this session, the object is replaced.

After this method executes, and if the object implements HttpSessionBindingListener, the container calls valueBound() on the object.

Params:
  • name – Name to which the object is bound, cannot be null
  • value – Object to be bound, cannot be null
Throws:
/** * Bind an object to this session, using the specified name. If an object * of the same name is already bound to this session, the object is * replaced. * <p> * After this method executes, and if the object implements * <code>HttpSessionBindingListener</code>, the container calls * <code>valueBound()</code> on the object. * * @param name Name to which the object is bound, cannot be null * @param value Object to be bound, cannot be null * * @exception IllegalArgumentException if an attempt is made to add a * non-serializable object in an environment marked distributable. * @exception IllegalStateException if this method is called on an * invalidated session */
@Override public void setAttribute(String name, Object value) { setAttribute(name,value,true); }
Bind an object to this session, using the specified name. If an object of the same name is already bound to this session, the object is replaced.

After this method executes, and if the object implements HttpSessionBindingListener, the container calls valueBound() on the object.

Params:
  • name – Name to which the object is bound, cannot be null
  • value – Object to be bound, cannot be null
  • notify – whether to notify session listeners
Throws:
/** * Bind an object to this session, using the specified name. If an object * of the same name is already bound to this session, the object is * replaced. * <p> * After this method executes, and if the object implements * <code>HttpSessionBindingListener</code>, the container calls * <code>valueBound()</code> on the object. * * @param name Name to which the object is bound, cannot be null * @param value Object to be bound, cannot be null * @param notify whether to notify session listeners * @exception IllegalArgumentException if an attempt is made to add a * non-serializable object in an environment marked distributable. * @exception IllegalStateException if this method is called on an * invalidated session */
public void setAttribute(String name, Object value, boolean notify) { // Name cannot be null if (name == null) { throw new IllegalArgumentException( sm.getString("standardSession.setAttribute.namenull")); } // Null value is the same as removeAttribute() if (value == null) { removeAttribute(name); return; } // Validate our current state if (!isValidInternal()) { throw new IllegalStateException( sm.getString("standardSession.setAttribute.ise", getIdInternal())); } Context context = manager.getContext(); if (context.getDistributable() && !isAttributeDistributable(name, value) && !exclude(name, value)) { throw new IllegalArgumentException(sm.getString("standardSession.setAttribute.iae", name)); } // Construct an event with the new value HttpSessionBindingEvent event = null; // Call the valueBound() method if necessary if (notify && value instanceof HttpSessionBindingListener) { // Don't call any notification if replacing with the same value // unless configured to do so Object oldValue = attributes.get(name); if (value != oldValue || manager.getNotifyBindingListenerOnUnchangedValue()) { event = new HttpSessionBindingEvent(getSession(), name, value); try { ((HttpSessionBindingListener) value).valueBound(event); } catch (Throwable t){ manager.getContext().getLogger().error( sm.getString("standardSession.bindingEvent"), t); } } } // Replace or add this attribute Object unbound = attributes.put(name, value); // Call the valueUnbound() method if necessary if (notify && unbound instanceof HttpSessionBindingListener) { // Don't call any notification if replacing with the same value // unless configured to do so if (unbound != value || manager.getNotifyBindingListenerOnUnchangedValue()) { try { ((HttpSessionBindingListener) unbound).valueUnbound (new HttpSessionBindingEvent(getSession(), name)); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); manager.getContext().getLogger().error (sm.getString("standardSession.bindingEvent"), t); } } } if (!notify) { return; } // Notify interested application event listeners Object listeners[] = context.getApplicationEventListeners(); if (listeners == null) { return; } for (Object o : listeners) { if (!(o instanceof HttpSessionAttributeListener)) { continue; } HttpSessionAttributeListener listener = (HttpSessionAttributeListener) o; try { if (unbound != null) { if (unbound != value || manager.getNotifyAttributeListenerOnUnchangedValue()) { context.fireContainerEvent("beforeSessionAttributeReplaced", listener); if (event == null) { event = new HttpSessionBindingEvent(getSession(), name, unbound); } listener.attributeReplaced(event); context.fireContainerEvent("afterSessionAttributeReplaced", listener); } } else { context.fireContainerEvent("beforeSessionAttributeAdded", listener); if (event == null) { event = new HttpSessionBindingEvent(getSession(), name, value); } listener.attributeAdded(event); context.fireContainerEvent("afterSessionAttributeAdded", listener); } } catch (Throwable t) { ExceptionUtils.handleThrowable(t); try { if (unbound != null) { if (unbound != value || manager.getNotifyAttributeListenerOnUnchangedValue()) { context.fireContainerEvent("afterSessionAttributeReplaced", listener); } } else { context.fireContainerEvent("afterSessionAttributeAdded", listener); } } catch (Exception e) { // Ignore } manager.getContext().getLogger().error( sm.getString("standardSession.attributeEvent"), t); } } } // ------------------------------------------ HttpSession Protected Methods
Returns:the isValid flag for this session without any expiration check.
/** * @return the <code>isValid</code> flag for this session without any expiration * check. */
protected boolean isValidInternal() { return this.isValid; }
{@inheritDoc}

This implementation simply checks the value for serializability. Sub-classes might use other distribution technology not based on serialization and can override this check.

/** * {@inheritDoc} * <p> * This implementation simply checks the value for serializability. * Sub-classes might use other distribution technology not based on * serialization and can override this check. */
@Override public boolean isAttributeDistributable(String name, Object value) { return value instanceof Serializable; }
Read a serialized version of this session object from the specified object input stream.

IMPLEMENTATION NOTE: The reference to the owning Manager is not restored by this method, and must be set explicitly.

Params:
  • stream – The input stream to read from
Throws:
/** * Read a serialized version of this session object from the specified * object input stream. * <p> * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager * is not restored by this method, and must be set explicitly. * * @param stream The input stream to read from * * @exception ClassNotFoundException if an unknown class is specified * @exception IOException if an input/output error occurs */
protected void doReadObject(ObjectInputStream stream) throws ClassNotFoundException, IOException { // Deserialize the scalar instance variables (except Manager) authType = null; // Transient (may be set later) creationTime = ((Long) stream.readObject()).longValue(); lastAccessedTime = ((Long) stream.readObject()).longValue(); maxInactiveInterval = ((Integer) stream.readObject()).intValue(); isNew = ((Boolean) stream.readObject()).booleanValue(); isValid = ((Boolean) stream.readObject()).booleanValue(); thisAccessedTime = ((Long) stream.readObject()).longValue(); principal = null; // Transient (may be set later) // setId((String) stream.readObject()); id = (String) stream.readObject(); if (manager.getContext().getLogger().isDebugEnabled()) manager.getContext().getLogger().debug ("readObject() loading session " + id); // The next object read could either be the number of attributes (Integer) or the session's // authType followed by a Principal object (not an Integer) Object nextObject = stream.readObject(); if (!(nextObject instanceof Integer)) { setAuthType((String) nextObject); try { setPrincipal((Principal) stream.readObject()); } catch (ClassNotFoundException | ObjectStreamException e) { String msg = sm.getString("standardSession.principalNotDeserializable", id); if (manager.getContext().getLogger().isDebugEnabled()) { manager.getContext().getLogger().debug(msg, e); } else { manager.getContext().getLogger().warn(msg); } throw e; } // After that, the next object read should be the number of attributes (Integer) nextObject = stream.readObject(); } // Deserialize the attribute count and attribute values if (attributes == null) attributes = new ConcurrentHashMap<>(); int n = ((Integer) nextObject).intValue(); boolean isValidSave = isValid; isValid = true; for (int i = 0; i < n; i++) { String name = (String) stream.readObject(); final Object value; try { value = stream.readObject(); } catch (WriteAbortedException wae) { if (wae.getCause() instanceof NotSerializableException) { String msg = sm.getString("standardSession.notDeserializable", name, id); if (manager.getContext().getLogger().isDebugEnabled()) { manager.getContext().getLogger().debug(msg, wae); } else { manager.getContext().getLogger().warn(msg); } // Skip non serializable attributes continue; } throw wae; } if (manager.getContext().getLogger().isDebugEnabled()) manager.getContext().getLogger().debug(" loading attribute '" + name + "' with value '" + value + "'"); // Handle the case where the filter configuration was changed while // the web application was stopped. if (exclude(name, value)) { continue; } // ConcurrentHashMap does not allow null keys or values if(null != value) attributes.put(name, value); } isValid = isValidSave; if (listeners == null) { listeners = new ArrayList<>(); } if (notes == null) { notes = new Hashtable<>(); } }
Write a serialized version of this session object to the specified object output stream.

IMPLEMENTATION NOTE: The owning Manager will not be stored in the serialized representation of this Session. After calling readObject(), you must set the associated Manager explicitly.

IMPLEMENTATION NOTE: Any attribute that is not Serializable will be unbound from the session, with appropriate actions if it implements HttpSessionBindingListener. If you do not want any such attributes, be sure the distributable property of the associated Manager is set to true.

Params:
  • stream – The output stream to write to
Throws:
/** * Write a serialized version of this session object to the specified * object output stream. * <p> * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored * in the serialized representation of this Session. After calling * <code>readObject()</code>, you must set the associated Manager * explicitly. * <p> * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable * will be unbound from the session, with appropriate actions if it * implements HttpSessionBindingListener. If you do not want any such * attributes, be sure the <code>distributable</code> property of the * associated Manager is set to <code>true</code>. * * @param stream The output stream to write to * * @exception IOException if an input/output error occurs */
protected void doWriteObject(ObjectOutputStream stream) throws IOException { // Write the scalar instance variables (except Manager) stream.writeObject(Long.valueOf(creationTime)); stream.writeObject(Long.valueOf(lastAccessedTime)); stream.writeObject(Integer.valueOf(maxInactiveInterval)); stream.writeObject(Boolean.valueOf(isNew)); stream.writeObject(Boolean.valueOf(isValid)); stream.writeObject(Long.valueOf(thisAccessedTime)); stream.writeObject(id); if (manager.getContext().getLogger().isDebugEnabled()) manager.getContext().getLogger().debug ("writeObject() storing session " + id); // Gather authentication information (if configured) String sessionAuthType = null; Principal sessionPrincipal = null; if (getPersistAuthentication()) { sessionAuthType = getAuthType(); sessionPrincipal = getPrincipal(); if (!(sessionPrincipal instanceof Serializable)) { sessionPrincipal = null; manager.getContext().getLogger().warn( sm.getString("standardSession.principalNotSerializable", id)); } } // Write authentication information (may be null values) stream.writeObject(sessionAuthType); try { stream.writeObject(sessionPrincipal); } catch (NotSerializableException e) { manager.getContext().getLogger().warn( sm.getString("standardSession.principalNotSerializable", id), e); } // Accumulate the names of serializable and non-serializable attributes String keys[] = keys(); List<String> saveNames = new ArrayList<>(); List<Object> saveValues = new ArrayList<>(); for (String key : keys) { Object value = attributes.get(key); if (value == null) { continue; } else if (isAttributeDistributable(key, value) && !exclude(key, value)) { saveNames.add(key); saveValues.add(value); } else { removeAttributeInternal(key, true); } } // Serialize the attribute count and the Serializable attributes int n = saveNames.size(); stream.writeObject(Integer.valueOf(n)); for (int i = 0; i < n; i++) { stream.writeObject(saveNames.get(i)); try { stream.writeObject(saveValues.get(i)); if (manager.getContext().getLogger().isDebugEnabled()) manager.getContext().getLogger().debug( " storing attribute '" + saveNames.get(i) + "' with value '" + saveValues.get(i) + "'"); } catch (NotSerializableException e) { manager.getContext().getLogger().warn( sm.getString("standardSession.notSerializable", saveNames.get(i), id), e); } } }
Return whether authentication information shall be persisted or not.
Returns:true, if authentication information shall be persisted; false otherwise
/** * Return whether authentication information shall be persisted or not. * * @return {@code true}, if authentication information shall be persisted; * {@code false} otherwise */
private boolean getPersistAuthentication() { if (manager instanceof ManagerBase) { return ((ManagerBase) manager).getPersistAuthentication(); } return false; }
Should the given session attribute be excluded? This implementation checks: Note: This method deliberately does not check isAttributeDistributable(String, Object) which is kept separate to support the checks required in setAttribute(String, Object, boolean)
Params:
  • name – The attribute name
  • value – The attribute value
Returns:true if the attribute should be excluded from distribution, otherwise false
/** * Should the given session attribute be excluded? This implementation * checks: * <ul> * <li>{@link Constants#excludedAttributeNames}</li> * <li>{@link Manager#willAttributeDistribute(String, Object)}</li> * </ul> * Note: This method deliberately does not check * {@link #isAttributeDistributable(String, Object)} which is kept * separate to support the checks required in * {@link #setAttribute(String, Object, boolean)} * * @param name The attribute name * @param value The attribute value * * @return {@code true} if the attribute should be excluded from * distribution, otherwise {@code false} */
protected boolean exclude(String name, Object value) { if (Constants.excludedAttributeNames.contains(name)) { return true; } // Manager is required for remaining check Manager manager = getManager(); if (manager == null) { // Manager may be null during replication of new sessions in a // cluster. Avoid the NPE. return false; } // Last check so use a short-cut return !manager.willAttributeDistribute(name, value); } // ------------------------------------------------------ Protected Methods
Notify all session event listeners that a particular event has occurred for this Session. The default implementation performs this notification synchronously using the calling thread.
Params:
  • type – Event type
  • data – Event data
/** * Notify all session event listeners that a particular event has * occurred for this Session. The default implementation performs * this notification synchronously using the calling thread. * * @param type Event type * @param data Event data */
public void fireSessionEvent(String type, Object data) { if (listeners.size() < 1) return; SessionEvent event = new SessionEvent(this, type, data); SessionListener list[] = new SessionListener[0]; synchronized (listeners) { list = listeners.toArray(list); } for (SessionListener sessionListener : list) { sessionListener.sessionEvent(event); } }
Returns:the names of all currently defined session attributes as an array of Strings. If there are no defined attributes, a zero-length array is returned.
/** * @return the names of all currently defined session attributes * as an array of Strings. If there are no defined attributes, a * zero-length array is returned. */
protected String[] keys() { return attributes.keySet().toArray(EMPTY_ARRAY); }
Remove the object bound with the specified name from this session. If the session does not have an object bound with this name, this method does nothing.

After this method executes, and if the object implements HttpSessionBindingListener, the container calls valueUnbound() on the object.

Params:
  • name – Name of the object to remove from this session.
  • notify – Should we notify interested listeners that this attribute is being removed?
/** * Remove the object bound with the specified name from this session. If * the session does not have an object bound with this name, this method * does nothing. * <p> * After this method executes, and if the object implements * <code>HttpSessionBindingListener</code>, the container calls * <code>valueUnbound()</code> on the object. * * @param name Name of the object to remove from this session. * @param notify Should we notify interested listeners that this * attribute is being removed? */
protected void removeAttributeInternal(String name, boolean notify) { // Avoid NPE if (name == null) return; // Remove this attribute from our collection Object value = attributes.remove(name); // Do we need to do valueUnbound() and attributeRemoved() notification? if (!notify || (value == null)) { return; } // Call the valueUnbound() method if necessary HttpSessionBindingEvent event = null; if (value instanceof HttpSessionBindingListener) { event = new HttpSessionBindingEvent(getSession(), name, value); ((HttpSessionBindingListener) value).valueUnbound(event); } // Notify interested application event listeners Context context = manager.getContext(); Object listeners[] = context.getApplicationEventListeners(); if (listeners == null) return; for (Object o : listeners) { if (!(o instanceof HttpSessionAttributeListener)) { continue; } HttpSessionAttributeListener listener = (HttpSessionAttributeListener) o; try { context.fireContainerEvent("beforeSessionAttributeRemoved", listener); if (event == null) { event = new HttpSessionBindingEvent(getSession(), name, value); } listener.attributeRemoved(event); context.fireContainerEvent("afterSessionAttributeRemoved", listener); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); try { context.fireContainerEvent("afterSessionAttributeRemoved", listener); } catch (Exception e) { // Ignore } manager.getContext().getLogger().error(sm.getString("standardSession.attributeEvent"), t); } } } private static class PrivilegedNewSessionFacade implements PrivilegedAction<StandardSessionFacade> { private final HttpSession session; public PrivilegedNewSessionFacade(HttpSession session) { this.session = session; } @Override public StandardSessionFacade run(){ return new StandardSessionFacade(session); } } } // ------------------------------------------------------------ Protected Class
This class is a dummy implementation of the HttpSessionContext interface, to conform to the requirement that such an object be returned when HttpSession.getSessionContext() is called.
Author:Craig R. McClanahan
Deprecated:As of Java Servlet API 2.1 with no replacement. The interface will be removed in a future version of this API.
/** * This class is a dummy implementation of the <code>HttpSessionContext</code> * interface, to conform to the requirement that such an object be returned * when <code>HttpSession.getSessionContext()</code> is called. * * @author Craig R. McClanahan * * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. */
@Deprecated final class StandardSessionContext implements jakarta.servlet.http.HttpSessionContext { private static final List<String> emptyString = Collections.emptyList();
Return the session identifiers of all sessions defined within this context.
Deprecated:As of Java Servlet API 2.1 with no replacement. This method must return an empty Enumeration and will be removed in a future version of the API.
/** * Return the session identifiers of all sessions defined * within this context. * * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> * and will be removed in a future version of the API. */
@Override @Deprecated public Enumeration<String> getIds() { return Collections.enumeration(emptyString); }
Return the HttpSession associated with the specified session identifier.
Params:
  • id – Session identifier for which to look up a session
Deprecated:As of Java Servlet API 2.1 with no replacement. This method must return null and will be removed in a future version of the API.
/** * Return the <code>HttpSession</code> associated with the * specified session identifier. * * @param id Session identifier for which to look up a session * * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return null and will be removed in a * future version of the API. */
@Override @Deprecated public HttpSession getSession(String id) { return null; } }