Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * 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 static org.jboss.web.CatalinaMessages.MESSAGES;
  
  import java.util.HashMap;
  import java.util.Map;
  
  
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(s):
Craig R. McClanahan
Sean Legassick
Jon S. Stevens
Version:
$Revision: 2044 $ $Date: 2012-06-27 17:29:53 +0200 (Wed, 27 Jun 2012) $
  
  
  public class StandardSession
      implements HttpSessionSessionSerializable {
  
  
      private static final long serialVersionUID = -4294597583262209053L;
  
  
      protected static final boolean ACTIVITY_CHECK = 
          || Boolean.valueOf(System.getProperty("org.apache.catalina.session.StandardSession.ACTIVITY_CHECK""false")).booleanValue();
  
  
      // ----------------------------------------------------------- Constructors
  

    
Construct a new Session associated with the specified Manager.

Parameters:
manager The manager with which this Session is associated
 
     public StandardSession(Manager manager) {
 
         super();
         this. = manager;
 
         // Initialize access count
         if () {
              = new AtomicInteger();
         }
 
     }
 
 
     // ----------------------------------------------------- Instance Variables
 

    
Type array.
 
     protected static final String EMPTY_ARRAY[] = new String[0];


    
The dummy attribute value serialized when a NotSerializableException is encountered in writeObject().
 
     protected static final String NOT_SERIALIZED =
         "___NOT_SERIALIZABLE_EXCEPTION___";


    
The collection of user data attributes associated with this Session.
 
     protected Map<StringObjectattributes = new ConcurrentHashMap<StringObject>();


    
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.
 
     protected long creationTime = 0L;


    
Set of attribute names which are not allowed to be persisted.
 
     protected static final String[] excludedAttributes = {
         .
     };


    
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 boolean expiring = false;


    
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.
 
     protected String id = null;


    
Descriptive information describing this Session implementation.
 
     protected static final String info = "StandardSession/1.0";


    
The last accessed time for this Session.
 
     protected int lastAccessedTime = 0;


    
The session event listeners for this Session.
 
     protected transient ArrayList<SessionListenerlisteners = new ArrayList<SessionListener>();


    
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.
 
     protected int maxInactiveInterval = -1;


    
Flag indicating whether this session is new or not.
 
     protected boolean isNew = false;


    
Flag indicating whether this session is valid or not.
 
     protected 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!
 
     protected transient Map<StringObjectnotes = new ConcurrentHashMap<StringObject>();


    
The authenticated Principal associated with this session, if any. IMPLEMENTATION NOTE: This object is not saved and restored across session serializations!
 
     protected transient Principal principal = null;


    
The HTTP session context associated with this session.
 
     protected static HttpSessionContext sessionContext = null;


    
The current accessed time for this session.
 
     protected int thisAccessedTime = 0;


    
The access count for this session.
 
     protected transient AtomicInteger accessCount = null;
 
     
     // ----------------------------------------------------- Session Properties
 

    
Return the authentication type used to authenticate our cached Principal, if any.
 
     public String getAuthType() {
 
         return (this.);
 
     }


    
Set the authentication type used to authenticate our cached Principal, if any.

Parameters:
authType The new cached authentication type
 
     public void setAuthType(String authType) {
 
         this. = authType;
 
     }


    
Set the creation time for this session. This method is called by the Manager when an existing Session instance is reused.

Parameters:
time The new creation time
 
     public void setCreationTime(long time) {
 
         this. = time;
         this. = 0;
         this. = 0;
 
     }


    
Return the session identifier for this session.
 
     public String getId() {
 
         return (this.);
 
     }


    
Return the session identifier for this session.
 
     public String getIdInternal() {
 
         return (this.);
 
     }


    
Set the session identifier for this session.

Parameters:
id The new session identifier
 
     public void setId(String id) {
 
         if ((this. != null) && ( != null))
                 .remove(this);
 
         String oldId = this.;
         this. = id;
 
         if ( != null)
             .add(this);
 
         if (oldId == null) {
             tellNew();
         } else {
             // Notify interested session event listeners
             fireSessionEvent(.oldId);
         }
     }


    
Inform the listeners about the new session.
 
     public void tellNew() {
 
         // Notify interested session event listeners
 
         // Notify interested application event listeners
         Context context = (Context.getContainer();
         Object listeners[] = context.getApplicationSessionLifecycleListeners();
         if (listeners != null && listeners.length > 0) {
             HttpSessionEvent event =
                 new HttpSessionEvent(getSession());
             for (int i = 0; i < listeners.lengthi++) {
                 if (!(listeners[iinstanceof HttpSessionListener))
                     continue;
                 HttpSessionListener listener =
                     (HttpSessionListenerlisteners[i];
                 try {
                     context.fireContainerEvent("beforeSessionCreated"listener);
                     listener.sessionCreated(event);
                     context.fireContainerEvent("afterSessionCreated"listener);
                 } catch (Throwable t) {
                     try {
                         context.fireContainerEvent("afterSessionCreated"listener);
                     } catch (Exception e) {
                         ;
                     }
                     .getContainer().getLogger().error(.sessionEventListenerException(), t);
                 }
             }
         }
 
     }


    
Return descriptive information about this Session implementation and the corresponding version number, in the format <description>/<version>.
 
     public String getInfo() {
 
         return ();
 
     }


    
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.
 
     public long getThisAccessedTime() {
 
         if (!isValidInternal()) {
             throw .invalidSession();
         }
 
         return (this.);
     }

    
Return the last client access time without invalidation check

See also:
getThisAccessedTime().
 
     public long getThisAccessedTimeInternal() {
         return (this.);
     }

    
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.
 
     public long getLastAccessedTime() {
 
         if (!isValidInternal()) {
             throw .invalidSession();
         }
 
         return ( + );
     }

    
Return the last client access time without invalidation check

See also:
getLastAccessedTime().
 
     public long getLastAccessedTimeInternal() {
         return ( + );
     }

    
Return the Manager within which this Session is valid.
 
     public Manager getManager() {
 
         return (this.);
 
     }


    
Set the Manager within which this Session is valid.

Parameters:
manager The new Manager
 
     public void setManager(Manager manager) {
 
         this. = 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.
 
     public int getMaxInactiveInterval() {
 
         return (this.);
 
     }


    
Set 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.

Parameters:
interval The new maximum interval
 
     public void setMaxInactiveInterval(int interval) {
 
         this. = interval;
         
     }


    
Set the isNew flag for this session.

Parameters:
isNew The new value for the isNew flag
 
     public void setNew(boolean isNew) {
 
         this. = 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.
 
     public Principal getPrincipal() {
 
         return (this.);
 
     }


    
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.

Parameters:
principal The new Principal, or null if none
 
     public void setPrincipal(Principal principal) {
 
         this. = principal;
 
     }


    
Return the HttpSession for which this object is the facade.
 
     public HttpSession getSession() {
 
         if ( == null){
             if (SecurityUtil.isPackageProtectionEnabled()){
                 final StandardSession fsession = this;
                  = (StandardSessionFacade)AccessController.doPrivileged(new PrivilegedAction(){
                     public Object run(){
                         return new StandardSessionFacade(fsession);
                     }
                 });
             } else {
                  = new StandardSessionFacade(this);
             }
         }
         return ();
 
     }


    
Return the isValid flag for this session.
 
     public boolean isValid() {
 
         if (this.) {
             return true;
         }
 
         if (!this.) {
             return false;
         }
 
         if ( && .get() > 0) {
             return true;
         }
 
         if ( > 0) { 
             int offset = (int) (System.currentTimeMillis() - );
             int timeIdle = (offset - ) / 1000;
             if (timeIdle >= ) {
                 expire(true);
             }
         }
 
         return (this.);
     }


    
Set the isValid flag for this session.

Parameters:
isValid The new value for the isValid flag
 
     public void setValid(boolean isValid) {
         this. = 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.
 
     public void access() {
 
         this. = this.;
         this. = (int) (System.currentTimeMillis() - );
         
         if () {
             .incrementAndGet();
         }
 
     }


    
End the access.
 
     public void endAccess() {
 
          = false;
 
         if () {
             .decrementAndGet();
         }
 
     }


    
Add a session event listener to this component.
 
     public void addSessionListener(SessionListener listener) {
 
         .add(listener);
 
     }


    
Perform the internal processing required to invalidate this session, without triggering an exception if the session has already expired.
 
     public void expire() {
 
         expire(true);
 
     }

    
    
Perform the internal processing required to invalidate this session, without triggering an exception if the session has already expired.

Parameters:
notify Should we notify listeners about the demise of this session?
 
     public void expire(boolean notify) {
 
         // Mark this session as "being expired" if needed
         if ()
             return;
 
         synchronized (this) {
 
             if ( == null)
                 return;
 
              = true;
         
             // Notify interested application event listeners
             Context context = (Context.getContainer();
             Object listeners[] = context.getApplicationSessionLifecycleListeners();
             if (notify && listeners != null && (listeners.length > 0)) {
                 HttpSessionEvent event =
                     new HttpSessionEvent(getSession());
                 for (int i = listeners.length - 1; i >= 0; i--) {
                     if (!(listeners[iinstanceof HttpSessionListener))
                         continue;
                     HttpSessionListener listener = (HttpSessionListenerlisteners[i];
                     try {
                         context.fireContainerEvent("beforeSessionDestroyed"listener);
                         listener.sessionDestroyed(event);
                         context.fireContainerEvent("afterSessionDestroyed"listener);
                     } catch (Throwable t) {
                         try {
                             context.fireContainerEvent("afterSessionDestroyed"listener);
                         } catch (Exception e) {
                             ;
                         }
                         .getContainer().getLogger().error(.sessionEventListenerException(), t);
                     }
                 }
             }
             if () {
                 .set(0);
             }
             setValid(false);
 
             /*
              * Compute how long this session has been alive, and update
              * session manager's related properties accordingly
              */
             long timeNow = System.currentTimeMillis();
             int timeAlive = (int) ((timeNow - )/1000);
             synchronized () {
                 if (timeAlive > .getSessionMaxAliveTime()) {
                     .setSessionMaxAliveTime(timeAlive);
                 }
                 int numExpired = .getExpiredSessions();
                 numExpired++;
                 .setExpiredSessions(numExpired);
                 int average = .getSessionAverageAliveTime();
                 average = ((average * (numExpired-1)) + timeAlive)/numExpired;
                 .setSessionAverageAliveTime(average);
             }
 
             // Remove this session from our manager's active sessions
             .remove(this);
 
             // Notify interested session event listeners
             if (notify) {
                 fireSessionEvent(.null);
             }
 
             // Call the logout method
             if ( instanceof GenericPrincipal) {
                 GenericPrincipal gp = (GenericPrincipal;
                 try {
                     gp.logout();
                 } catch (Exception e) {
                     .getContainer().getLogger().error(.sessionLogoutException(), e);
                 }
             }
 
             // We have completed expire of this session
              = false;
 
             // Unbind any objects associated with this session
             String keys[] = keys();
             for (int i = 0; i < keys.lengthi++)
                 removeAttributeInternal(keys[i], notify);
 
         }
 
     }


    
Perform the internal processing required to passivate this session.
 
     public void passivate() {
 
         // Notify interested session event listeners
 
         // Notify ActivationListeners
         HttpSessionEvent event = null;
         String keys[] = keys();
         for (int i = 0; i < keys.lengthi++) {
             Object attribute = .get(keys[i]);
             if (attribute instanceof HttpSessionActivationListener) {
                 if (event == null)
                     event = new HttpSessionEvent(getSession());
                 try {
                     ((HttpSessionActivationListener)attribute)
                         .sessionWillPassivate(event);
                 } catch (Throwable t) {
                     .getContainer().getLogger().error(.sessionAttributeEventListenerException(), t);
                 }
             }
         }
 
     }


    
Perform internal processing required to activate this session.
 
     public void activate() {
 
         // Initialize access count
         if () {
              = new AtomicInteger();
         }
         
         // Notify interested session event listeners
 
         // Notify ActivationListeners
         HttpSessionEvent event = null;
         String keys[] = keys();
         for (int i = 0; i < keys.lengthi++) {
             Object attribute = .get(keys[i]);
             if (attribute instanceof HttpSessionActivationListener) {
                 if (event == null)
                     event = new HttpSessionEvent(getSession());
                 try {
                     ((HttpSessionActivationListener)attribute)
                         .sessionDidActivate(event);
                 } catch (Throwable t) {
                     .getContainer().getLogger().error(.sessionAttributeEventListenerException(), t);
                 }
             }
         }
 
     }


    
Return the object bound with the specified name to the internal notes for this session, or null if no such binding exists.

Parameters:
name Name of the note to be returned
 
     public Object getNote(String name) {
 
         return (.get(name));
 
     }


    
Return an Iterator containing the String names of all notes bindings that exist for this session.
 
     public Iterator getNoteNames() {
 
         return (.keySet().iterator());
 
     }


    
Release all object references, and initialize instance variables, in preparation for reuse of this object.
 
     public void recycle() {
 
         // Reset the instance variables associated with this Session
         .clear();
         setAuthType(null);
          = 0L;
          = false;
          = null;
          = 0;
          = -1;
         .clear();
         setPrincipal(null);
          = false;
          = false;
          = null;
 
     }


    
Remove any object bound to the specified name in the internal notes for this session.

Parameters:
name Name of the note to be removed
 
     public void removeNote(String name) {
 
         .remove(name);
 
     }


    
Remove a session event listener from this component.
 
     public void removeSessionListener(SessionListener listener) {
 
         .remove(listener);
 
     }


    
Bind an object to a specified name in the internal notes associated with this session, replacing any existing binding for this name.

Parameters:
name Name to which the object should be bound
value Object to be bound to the specified name
 
     public void setNote(String nameObject value) {
 
         .put(namevalue);
 
     }


    
Return a string representation of this object.
 
     public String toString() {
 
         StringBuilder sb = new StringBuilder();
         sb.append("StandardSession[");
         sb.append();
         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.

Parameters:
stream The object input stream to read from
Throws:
java.lang.ClassNotFoundException if an unknown class is specified
java.io.IOException if an input/output error occurs
 
     public void readObjectData(ObjectInputStream stream)
         throws ClassNotFoundExceptionIOException {
 
         readObject(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.

Parameters:
stream The object output stream to write to
Throws:
java.io.IOException if an input/output error occurs
 
     public void writeObjectData(ObjectOutputStream stream)
         throws IOException {
 
         writeObject(stream);
 
     }
 
 
     // ------------------------------------------------- HttpSession Properties
 

    
Return the time when this session was created, in milliseconds since midnight, January 1, 1970 GMT.

Throws:
java.lang.IllegalStateException if this method is called on an invalidated session
 
     public long getCreationTime() {
 
         if (!isValidInternal())
             throw .invalidSession();
 
         return (this.);
 
     }


    
Return the ServletContext to which this session belongs.
 
     public ServletContext getServletContext() {
 
         if ( == null)
             return (null);
         Context context = (Context.getContainer();
         if (context == null)
             return (null);
         else
             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.
 
 
         if ( == null)
              = new StandardSessionContext();
         return ();
 
     }
 
 
     // ----------------------------------------------HttpSession Public Methods
 

    
Return the object bound with the specified name in this session, or null if no object is bound with that name.

Parameters:
name Name of the attribute to be returned
Throws:
java.lang.IllegalStateException if this method is called on an invalidated session
    public Object getAttribute(String name) {
        if (!isValidInternal())
            throw .invalidSession();
        if (name == null) {
            return null;
        }
        return (.get(name));
    }


    
Return an Enumeration of String objects containing the names of the objects bound to this session.

Throws:
java.lang.IllegalStateException if this method is called on an invalidated session
    public Enumeration getAttributeNames() {
        if (!isValidInternal())
            throw .invalidSession();
        return (new Enumerator(.keySet(), true));
    }


    
Return the object bound with the specified name in this session, or null if no object is bound with that name.

Deprecated:
As of Version 2.2, this method is replaced by getAttribute()
Parameters:
name Name of the value to be returned
Throws:
java.lang.IllegalStateException if this method is called on an invalidated session
    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.

Deprecated:
As of Version 2.2, this method is replaced by getAttributeNames()
Throws:
java.lang.IllegalStateException if this method is called on an invalidated session
    public String[] getValueNames() {
        if (!isValidInternal())
            throw .invalidSession();
        return (keys());
    }


    
Invalidates this session and unbinds any objects bound to it.

Throws:
java.lang.IllegalStateException if this method is called on an invalidated session
    public void invalidate() {
        if (!isValidInternal())
            throw .invalidSession();
        // 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:
java.lang.IllegalStateException if this method is called on an invalidated session
    public boolean isNew() {
        if (!isValidInternal())
            throw .invalidSession();
        return (this.);
    }



    
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.

Deprecated:
As of Version 2.2, this method is replaced by setAttribute()
Parameters:
name Name to which the object is bound, cannot be null
value Object to be bound, cannot be null
Throws:
java.lang.IllegalStateException if this method is called on an invalidated session
    public void putValue(String nameObject value) {
        setAttribute(namevalue);
    }


    
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.

Parameters:
name Name of the object to remove from this session.
Throws:
java.lang.IllegalStateException if this method is called on an invalidated session
    public void removeAttribute(String name) {
        removeAttribute(nametrue);
    }


    
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.

Parameters:
name Name of the object to remove from this session.
notify Should we notify interested listeners that this attribute is being removed?
Throws:
java.lang.IllegalStateException if this method is called on an invalidated session
    public void removeAttribute(String nameboolean notify) {
        // Validate our current state
        if (!isValidInternal())
            throw .invalidSession();
        removeAttributeInternal(namenotify);
    }


    
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.

Deprecated:
As of Version 2.2, this method is replaced by removeAttribute()
Parameters:
name Name of the object to remove from this session.
Throws:
java.lang.IllegalStateException if this method is called on an invalidated session
    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.

Parameters:
name Name to which the object is bound, cannot be null
value Object to be bound, cannot be null
Throws:
java.lang.IllegalArgumentException if an attempt is made to add a non-serializable object in an environment marked distributable.
java.lang.IllegalStateException if this method is called on an invalidated session
    public void setAttribute(String nameObject 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.

Parameters:
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:
java.lang.IllegalArgumentException if an attempt is made to add a non-serializable object in an environment marked distributable.
java.lang.IllegalStateException if this method is called on an invalidated session
    public void setAttribute(String nameObject valueboolean notify) {
        // Name cannot be null
        if (name == null)
            throw .sessionAttributeNameIsNull();
        // Null value is the same as removeAttribute()
        if (value == null) {
            removeAttribute(name);
            return;
        }
        // Validate our current state
        if (!isValidInternal())
            throw .invalidSession();
        if (( != null) && .getDistributable() &&
          !(value instanceof Serializable))
            throw .sessionAttributeIsNotSerializable(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
            Object oldValue = .get(name);
            if (value != oldValue) {
                event = new HttpSessionBindingEvent(getSession(), namevalue);
                try {
                    ((HttpSessionBindingListenervalue).valueBound(event);
                } catch (Throwable t){
                    .getContainer().getLogger().error(.sessionBindingEventListenerException(), t); 
                }
            }
        }
        // Replace or add this attribute
        Object unbound = .put(namevalue);
        // Call the valueUnbound() method if necessary
        if (notify && (unbound != null) && (unbound != value) &&
            (unbound instanceof HttpSessionBindingListener)) {
            try {
                ((HttpSessionBindingListenerunbound).valueUnbound
                    (new HttpSessionBindingEvent(getSession(), name));
            } catch (Throwable t) {
            }
        }
        
        if ( !notify ) return;
        
        // Notify interested application event listeners
        Context context = (Context.getContainer();
        Object listeners[] = context.getApplicationEventListeners();
        if (listeners == null)
            return;
        for (int i = 0; i < listeners.lengthi++) {
            if (!(listeners[iinstanceof HttpSessionAttributeListener))
                continue;
            HttpSessionAttributeListener listener =
                (HttpSessionAttributeListenerlisteners[i];
            try {
                if (unbound != null) {
                    context.fireContainerEvent("beforeSessionAttributeReplaced",
                                       listener);
                    if (event == null) {
                        event = new HttpSessionBindingEvent
                            (getSession(), nameunbound);
                    }
                    listener.attributeReplaced(event);
                    context.fireContainerEvent("afterSessionAttributeReplaced",
                                       listener);
                } else {
                    context.fireContainerEvent("beforeSessionAttributeAdded",
                                       listener);
                    if (event == null) {
                        event = new HttpSessionBindingEvent
                            (getSession(), namevalue);
                    }
                    listener.attributeAdded(event);
                    context.fireContainerEvent("afterSessionAttributeAdded",
                                       listener);
                }
            } catch (Throwable t) {
                try {
                    if (unbound != null) {
                        context.fireContainerEvent("afterSessionAttributeReplaced",
                                           listener);
                    } else {
                        context.fireContainerEvent("afterSessionAttributeAdded",
                                           listener);
                    }
                } catch (Exception e) {
                    ;
                }
            }
        }
    }
    // ------------------------------------------ HttpSession Protected Methods


    
Return the isValid flag for this session without any expiration check.
    public boolean isValidInternal() {
        return (this. || this.);
    }


    
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.

Parameters:
stream The input stream to read from
Throws:
java.lang.ClassNotFoundException if an unknown class is specified
java.io.IOException if an input/output error occurs
    protected void readObject(ObjectInputStream stream)
        throws ClassNotFoundExceptionIOException {
        // Deserialize the scalar instance variables (except Manager)
         = null;        // Transient only
         = ((Longstream.readObject()).longValue();
         = (int) (((Longstream.readObject()).longValue() - );
         = ((Integerstream.readObject()).intValue();
         = ((Booleanstream.readObject()).booleanValue();
         = ((Booleanstream.readObject()).booleanValue();
         = (int) (((Longstream.readObject()).longValue() - );
         = null;        // Transient only
        //        setId((String) stream.readObject());
         = (Stringstream.readObject();
        if (.getContainer().getLogger().isDebugEnabled())
            .getContainer().getLogger().debug
                ("readObject() loading session " + );
        // Deserialize the attribute count and attribute values
        if ( == null)
             = new ConcurrentHashMap<StringObject>();
        int n = ((Integerstream.readObject()).intValue();
        boolean isValidSave = ;
         = true;
        for (int i = 0; i < ni++) {
            String name = (Stringstream.readObject();
            Object value = (Objectstream.readObject();
            if ((value instanceof String) && (value.equals()))
                continue;
            .put(namevalue);
        }
         = isValidSave;
        if ( == null) {
             = new ArrayList<SessionListener>();
        }
        if ( == null) {
             = new ConcurrentHashMap<StringObject>();
        }
    }


    
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.

Parameters:
stream The output stream to write to
Throws:
java.io.IOException if an input/output error occurs
    protected void writeObject(ObjectOutputStream streamthrows IOException {
        // Write the scalar instance variables (except Manager)
        stream.writeObject(new Long());
        stream.writeObject(new Long( + ));
        stream.writeObject(new Integer());
        stream.writeObject(new Boolean());
        stream.writeObject(new Boolean());
        stream.writeObject(new Long( + ));
        stream.writeObject();
        if (.getContainer().getLogger().isDebugEnabled())
            .getContainer().getLogger().debug
                ("writeObject() storing session " + );
        // Accumulate the names of serializable and non-serializable attributes
        String keys[] = keys();
        ArrayList saveNames = new ArrayList();
        ArrayList saveValues = new ArrayList();
        for (int i = 0; i < keys.lengthi++) {
            Object value = .get(keys[i]);
            if (value == null)
                continue;
            else if ( (value instanceof Serializable
                    && (!exclude(keys[i]) )) {
                saveNames.add(keys[i]);
                saveValues.add(value);
            } else {
                removeAttributeInternal(keys[i], true);
            }
        }
        // Serialize the attribute count and the Serializable attributes
        int n = saveNames.size();
        stream.writeObject(new Integer(n));
        for (int i = 0; i < ni++) {
            stream.writeObject((StringsaveNames.get(i));
            try {
                stream.writeObject(saveValues.get(i));
            } catch (NotSerializableException e) {
                .getContainer().getLogger().warn
                    (.sessionAttributeSerializationException(saveNames.get(i), ), e);
                stream.writeObject();
                if (.getContainer().getLogger().isDebugEnabled())
                    .getContainer().getLogger().debug
                       ("  storing attribute '" + saveNames.get(i) +
                        "' with value NOT_SERIALIZED");
            }
        }
    }


    
Exclude attribute that cannot be serialized.

Parameters:
name the attribute's name
    protected boolean exclude(String name){
        for (int i = 0; i < .i++) {
            if (name.equalsIgnoreCase([i]))
                return true;
        }
        return false;
    }
    // ------------------------------------------------------ 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.

Parameters:
type Event type
data Event data
    public void fireSessionEvent(String typeObject data) {
        if (.size() < 1)
            return;
        SessionEvent event = new SessionEvent(thistypedata);
        SessionListener list[] = new SessionListener[0];
        synchronized () {
            list = (SessionListener[]) .toArray(list);
        }
        for (int i = 0; i < list.lengthi++){
            ((SessionListenerlist[i]).sessionEvent(event);
        }
    }


    
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 ((String[]) .keySet().toArray());
    }


    
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.

Parameters:
name Name of the object to remove from this session.
notify Should we notify interested listeners that this attribute is being removed?
    protected void removeAttributeInternal(String nameboolean notify) {
        // Avoid NPE
        if (name == nullreturn;
        // Remove this attribute from our collection
        Object value = .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(), namevalue);
            ((HttpSessionBindingListenervalue).valueUnbound(event);
        }
        // Notify interested application event listeners
        Context context = (Context.getContainer();
        Object listeners[] = context.getApplicationEventListeners();
        if (listeners == null || (listeners.length < 1))
            return;
        for (int i = listeners.length - 1; i >= 0; i--) {
            if (!(listeners[iinstanceof HttpSessionAttributeListener))
                continue;
            HttpSessionAttributeListener listener =
                (HttpSessionAttributeListenerlisteners[i];
            try {
                context.fireContainerEvent("beforeSessionAttributeRemoved",
                                   listener);
                if (event == null) {
                    event = new HttpSessionBindingEvent
                        (getSession(), namevalue);
                }
                listener.attributeRemoved(event);
                context.fireContainerEvent("afterSessionAttributeRemoved",
                                   listener);
            } catch (Throwable t) {
                try {
                    context.