/*
 * 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.cluster.session;

import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionContext;
import javax.servlet.http.HttpSessionEvent;
import javax.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.cluster.ClusterSession;
import org.apache.catalina.realm.GenericPrincipal;
import org.apache.catalina.util.Enumerator;
import org.apache.catalina.util.StringManager;

/**
 * 
 * Similar to the StandardSession, this code is identical, but for update and
 * some small issues, simply copied in the first release. This session will keep
 * track of deltas during a request.
 * <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 Filip Hanik
 * @author Craig R. McClanahan
 * @author Sean Legassick
 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens </a>
 * @version $Revision$ $Date$
 */

public class DeltaSession implements HttpSession, Session, Serializable,
        ClusterSession {

    public static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
            .getLog(DeltaManager.class);

    /**
     * The string manager for this package.
     */
    protected static StringManager smp = StringManager
            .getManager(Constants.Package);


    // ----------------------------------------------------- Instance Variables

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

    /**
     * The dummy attribute value serialized when a NotSerializableException is
     * encountered in <code>writeObject()</code>.
     */
    private static final String NOT_SERIALIZED = "___NOT_SERIALIZABLE_EXCEPTION___";

    /**
     * The collection of user data attributes associated with this Session.
     */
    private Map attributes = new Hashtable();

    /**
     * The authentication type used to authenticate our cached Principal, if
     * any. NOTE: This value is not included in the serialized version of this
     * object.
     */
    private transient String authType = null;

    /**
     * The <code>java.lang.Method</code> for the
     * <code>fireContainerEvent()</code> method of the
     * <code>org.apache.catalina.core.StandardContext</code> method, if our
     * Context implementation is of this class. This value is computed
     * dynamically the first time it is needed, or after a session reload (since
     * it is declared transient).
     */
    private transient Method containerEventMethod = null;

    /**
     * The method signature for the <code>fireContainerEvent</code> method.
     */
    private static final Class containerEventTypes[] = { String.class,
            Object.class };

    /**
     * The time this session was created, in milliseconds since midnight,
     * January 1, 1970 GMT.
     */
    private 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.
     */
    private transient boolean expiring = false;

    /**
     * The facade associated with this session. NOTE: This value is not included
     * in the serialized version of this object.
     */
    private transient DeltaSessionFacade facade = null;

    /**
     * The session identifier of this Session.
     */
    private String id = null;

    /**
     * Descriptive information describing this Session implementation.
     */
    private static final String info = "DeltaSession/1.1";

    /**
     * The last accessed time for this Session.
     */
    private long lastAccessedTime = creationTime;

    /**
     * The session event listeners for this Session.
     */
    private transient ArrayList listeners = new ArrayList();

    /**
     * The Manager with which this Session is associated.
     */
    private 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.
     */
    private int maxInactiveInterval = -1;

    /**
     * The maxInactiveInterval + tolerance time interval, in seconds, between client requests before
     * the servlet container may invalidate a backup session from other cluster node.
     */
    private int expireTolerance = 300;

    /**
     * Flag indicating whether this session is new or not.
     */
    private 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. <b>IMPLEMENTATION NOTE: </b> This object is <em>not</em>
     * saved and restored across session serializations!
     */
    private transient Map notes = new Hashtable();

    /**
     * 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!
     */
    private transient Principal principal = null;

    /**
     * The string manager for this package.
     */
    private static StringManager sm = StringManager
            .getManager(Constants.Package);

    /**
     * The HTTP session context associated with this session.
     */
    private static HttpSessionContext sessionContext = null;

    /**
     * The property change support for this component. NOTE: This value is not
     * included in the serialized version of this object.
     */
    private transient PropertyChangeSupport support = new PropertyChangeSupport(
            this);

    /**
     * The current accessed time for this session.
     */
    private long thisAccessedTime = creationTime;

    /**
     * only the primary session will expire, or be able to expire due to
     * inactivity. This is set to false as soon as I receive this session over
     * the wire in a session message. That means that someone else has made a
     * request on another server.
     */
    private transient boolean isPrimarySession = true;

    /**
     * The delta request contains all the action info
     *  
     */
    private transient DeltaRequest deltaRequest = null;

    /**
     * Last time the session was replicatd, used for distributed expiring of
     * session
     */
    private transient long lastTimeReplicated = System.currentTimeMillis();

    /**
     * The access count for this session
     */
    protected transient int accessCount = 0;

    private Object lock = new Object();

    // ----------------------------------------------------------- Constructors
    
    /**
     * Construct a new Session associated with the specified Manager.
     * 
     * @param manager
     *            The manager with which this Session is associated
     */
    public DeltaSession(Manager manager) {

        super();
        this.manager = manager;
        this.resetDeltaRequest();
    }

    // ----------------------------------------------------- Session Properties

    /**
     * returns true if this session is the primary session, if that is the case,
     * the manager can expire it upon timeout.
     */
    public boolean isPrimarySession() {
        return isPrimarySession;
    }

    /**
     * Sets whether this is the primary session or not.
     * 
     * @param primarySession
     *            Flag value
     */
    public void setPrimarySession(boolean primarySession) {
        this.isPrimarySession = primarySession;
    }

    /**
     * Return the authentication type used to authenticate our cached Principal,
     * if any.
     */
    public String getAuthType() {

        return (this.authType);

    }

    /**
     * Set the authentication type used to authenticate our cached Principal, if
     * any.
     * 
     * @param authType
     *            The new cached authentication type
     */
    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.
     * 
     * @param time
     *            The new creation time
     */
    public void setCreationTime(long time) {

        this.creationTime = time;
        this.lastAccessedTime = time;
        this.thisAccessedTime = time;

    }

    /**
     * Return the session identifier for this session.
     */
    public String getId() {
        return (this.id);

    }


    /**
     * Return the session identifier for this session.
     */
    public String getIdInternal() {

        return (this.id);

    }


    /**
     * Set the session identifier for this session without notify listeners.
     * 
     * @param id
     *            The new session identifier
     */
    public void setIdInternal(String id) {
        if ((this.id != null) && (manager != null))
            manager.remove(this);

        this.id = id;

        if (manager != null)
            manager.add(this);
        if ( deltaRequest == null ) resetDeltaRequest();
        else deltaRequest.setSessionId(id);
    }

    /**
     * Set the session identifier for this session.
     * 
     * @param id
     *            The new session identifier
     */
    public void setId(String id) {
        setIdInternal(id);
        tellNew();
     }

    /**
     * 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 = (Context) manager.getContainer();
        //fix for standalone manager without container
        if (context != null) {
            Object listeners[] = context.getApplicationLifecycleListeners();
            if (listeners != null) {
                HttpSessionEvent event = new HttpSessionEvent(getSession());
                for (int i = 0; i < listeners.length; i++) {
                    if (!(listeners[i] instanceof HttpSessionListener))
                        continue;
                    HttpSessionListener listener = (HttpSessionListener) listeners[i];
                    try {
                        fireContainerEvent(context, "beforeSessionCreated",
                                listener);
                        listener.sessionCreated(event);
                        fireContainerEvent(context, "afterSessionCreated",
                                listener);
                    } catch (Throwable t) {
                        try {
                            fireContainerEvent(context, "afterSessionCreated",
                                    listener);
                        } catch (Exception e) {
                            ;
                        }
                        manager.getContainer().getLogger().error
                           (sm.getString("standardSession.sessionEvent"), t);
                    }
                }
            }
        }
    }

    /**
     * Return descriptive information about this Session implementation and the
     * corresponding version number, in the format
     * <code>&lt;description&gt;/&lt;version&gt;</code>.
     */
    public String getInfo() {

        return (info);

    }

    /**
     * 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 (!isValid()) {
            throw new IllegalStateException(sm
                    .getString("standardSession.getLastAccessedTime.ise"));
        }
            
        return (this.lastAccessedTime);
    }

    /**
     * Return the last client access time without invalidation check
     * @see #getLastAccessedTime().
     */
    public long getLastAccessedTimeInternal() {
        return (this.lastAccessedTime);
    }

    /**
     * Return the Manager within which this Session is valid.
     */
    public Manager getManager() {

        return (this.manager);

    }

    /**
     * Set the Manager within which this Session is valid.
     * 
     * @param manager
     *            The new Manager
     */
    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.
     */
    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 negative time
     * indicates that the session should never time out.
     * 
     * @param interval
     *            The new maximum interval
     */
    public void setMaxInactiveInterval(int interval) {
        setMaxInactiveInterval(interval, true);
    }

    public void setMaxInactiveInterval(int interval, boolean addDeltaRequest) {

        this.maxInactiveInterval = interval;
        if (isValid && interval == 0) {
            expire();
        } else {
            if (addDeltaRequest && (deltaRequest != null))
                deltaRequest.setMaxInactiveInterval(interval);
        }

    }

    /**
     * Set the <code>isNew</code> flag for this session.
     * 
     * @param isNew
     *            The new value for the <code>isNew</code> flag
     */
    public void setNew(boolean isNew) {
        setNew(isNew, true);
    }

    public void setNew(boolean isNew, boolean addDeltaRequest) {
        this.isNew = isNew;
        if (addDeltaRequest && (deltaRequest != null))
            deltaRequest.setNew(isNew);
    }

    /**
     * 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>.
     */
    public Principal getPrincipal() {

        return (this.principal);

    }

    /**
     * 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
     */
    public void setPrincipal(Principal principal) {
        setPrincipal(principal, true);
    }

    public void setPrincipal(Principal principal, boolean addDeltaRequest) {
        Principal oldPrincipal = this.principal;
        this.principal = principal;
        support.firePropertyChange("principal", oldPrincipal, this.principal);
        if (addDeltaRequest && (deltaRequest != null))
            deltaRequest.setPrincipal(principal);
    }

    /**
     * Return the <code>HttpSession</code> for which this object is the
     * facade.
     */
    public HttpSession getSession() {

        if (facade == null) {
            if (System.getSecurityManager() != null) {
                final DeltaSession fsession = this;
                facade = (DeltaSessionFacade) AccessController
                        .doPrivileged(new PrivilegedAction() {
                            public Object run() {
                                return new DeltaSessionFacade(fsession);
                            }
                        });
            } else {
                facade = new DeltaSessionFacade(this);
            }
        }
        return (facade);

    }

    /**
     * Return the <code>isValid</code> flag for this session.
     */
    public boolean isValid() {

        if (this.expiring) {
            return true;
        }

        if (!this.isValid) {
            return false;
        }

        if (accessCount > 0) {
            return true;
        }

        if (maxInactiveInterval >= 0) {
            long timeNow = System.currentTimeMillis();
            int timeIdle = (int) ((timeNow - thisAccessedTime) / 1000L);
            if (isPrimarySession()) {
                if(timeIdle >= maxInactiveInterval) {
                    expire(true);
                }
            } else {
                if (timeIdle >= (maxInactiveInterval+expireTolerance)) {
                //if the session has been idle twice as long as allowed,
                //the primary session has probably crashed, and no other
                //requests are coming in. that is why we do this. otherwise
                //we would have a memory leak
                    expire(true, false);
                }
            }
        }

        return (this.isValid);
    }

    /**
     * Set the <code>isValid</code> flag for this session.
     * 
     * @param isValid
     *            The new value for the <code>isValid</code> flag
     */
    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.
     */
    public void access() {

        this.lastAccessedTime = this.thisAccessedTime;
        this.thisAccessedTime = System.currentTimeMillis();

        evaluateIfValid();

        if (Globals.STRICT_SERVLET_COMPLIANCE) {
            synchronized (lock) {
                accessCount++;
            }
        }
    }

    public void endAccess() {
        isNew = false;
        if (Globals.STRICT_SERVLET_COMPLIANCE) {
            synchronized (lock) {
                accessCount--;
            }
        }
        if(manager instanceof DeltaManager)
            ((DeltaManager)manager).registerSessionAtReplicationValve(this);
    }

    /**
     * Add a session event listener to this component.
     */
    public void addSessionListener(SessionListener listener) {

        synchronized (listeners) {
            listeners.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.
     * 
     * @param notify
     *            Should we notify listeners about the demise of this session?
     */
    public void expire(boolean notify) {
        expire(notify, true);
    }

    public void expire(boolean notify, boolean notifyCluster) {

        // Mark this session as "being expired" if needed
        if (expiring)
            return;
        String expiredId = getIdInternal();

        synchronized (this) {

            if (manager == null)
                return;

            expiring = true;

            // Notify interested application event listeners
            // FIXME - Assumes we call listeners in reverse order
            Context context = (Context) manager.getContainer();
            //fix for standalone manager without container
            if (context != null) {
                Object listeners[] = context.getApplicationLifecycleListeners();
                if (notify && (listeners != null)) {
                    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 {
                            fireContainerEvent(context,
                                    "beforeSessionDestroyed", listener);
                            listener.sessionDestroyed(event);
                            fireContainerEvent(context,
                                    "afterSessionDestroyed", listener);
                        } catch (Throwable t) {
                            try {
                                fireContainerEvent(context,
                                        "afterSessionDestroyed", listener);
                            } catch (Exception e) {
                                ;
                            }
                            manager.getContainer().getLogger().error(sm
                                    .getString("standardSession.sessionEvent"),
                                    t);
                        }
                    }
                }
            }

            accessCount = 0;
            setValid(false);

            if (manager != null) {

                /*
                 * Compute how long this session has been alive, and update
                 * session manager's related properties accordingly
                 */
                long timeNow = System.currentTimeMillis();
                int timeAlive = (int) ((timeNow - creationTime)/1000);
                synchronized (manager) {
                    if (timeAlive > manager.getSessionMaxAliveTime()) {
                        manager.setSessionMaxAliveTime(timeAlive);
                    }
                    int numExpired = manager.getExpiredSessions();
                    numExpired++;
                    manager.setExpiredSessions(numExpired);
                    int average = manager.getSessionAverageAliveTime();
                    average = ((average * (numExpired-1)) + timeAlive)/numExpired;
                    manager.setSessionAverageAliveTime(average);
                }

                // Remove this session from our manager's active sessions
                manager.remove(this);
            }
            
            // Notify interested session event listeners
            if (notify) {
                fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null);
            }

            // We have completed expire of this session
            expiring = false;

            // Unbind any objects associated with this session
            String keys[] = keys();
            for (int i = 0; i < keys.length; i++)
                removeAttributeInternal(keys[i], notify, false);

            if (notifyCluster && manager != null) {
                if (log.isDebugEnabled())
                    log.debug(smp.getString("deltaSession.notifying",
                        ((DeltaManager) manager).getName(), new Boolean(
                                isPrimarySession()), expiredId));
                ((DeltaManager) manager).sessionExpired(expiredId);
            }
        }

    }

    /**
     * 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
     */
    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.
     */
    public Iterator getNoteNames() {
            return (notes.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
        attributes.clear();
        setAuthType(null);
        creationTime = 0L;
        expiring = false;
        id = null;
        lastAccessedTime = 0L;
        maxInactiveInterval = -1;
        accessCount = 0;
        notes.clear();
        setPrincipal(null);
        isNew = false;
        isValid = false;
        manager = null;
        deltaRequest.clear();

    }

    /**
     * Remove any object bound to the specified name in the internal notes for
     * this session.
     * 
     * @param name
     *            Name of the note to be removed
     */
    public void removeNote(String name) {
        notes.remove(name);
    }

    /**
     * Remove a session event listener from this component.
     */
    public void removeSessionListener(SessionListener listener) {

        synchronized (listeners) {
            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.
     * 
     * @param name
     *            Name to which the object should be bound
     * @param value
     *            Object to be bound to the specified name
     */
    public void setNote(String name, Object value) {
        notes.put(name, value);
    }

    /**
     * Return a string representation of this object.
     */
    public String toString() {

        StringBuffer sb = new StringBuffer();
        sb.append("DeltaSession[");
        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.
     * 
     * @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 {

        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.
     * 
     * @param stream
     *            The object output stream to write to
     * 
     * @exception IOException
     *                if an input/output error occurs
     */
    public void writeObjectData(ObjectOutputStream stream) throws IOException {

        writeObject(stream);

    }

    public void resetDeltaRequest() {
        if (deltaRequest == null) {
            deltaRequest = new DeltaRequest(getIdInternal(), false);
        } else {
            deltaRequest.reset();
            deltaRequest.setSessionId(getIdInternal());
        }
    }

    public DeltaRequest getDeltaRequest() {
        if (deltaRequest == null)
            resetDeltaRequest();
        return deltaRequest;
    }

    // ------------------------------------------------- HttpSession Properties

    /**
     * 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
     */
    public long getCreationTime() {

        if (!expiring && !isValid)
            throw new IllegalStateException(sm
                    .getString("standardSession.getCreationTime.ise"));

        return (this.creationTime);

    }

    /**
     * Return the ServletContext to which this session belongs.
     */
    public ServletContext getServletContext() {

        if (manager == null)
            return (null);
        Context context = (Context) manager.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.
     */
    public 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
     * <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
     */
    public Object getAttribute(String name) {

        if (!isValid())
            throw new IllegalStateException(sm
                    .getString("standardSession.getAttribute.ise"));
        return (attributes.get(name));
    }

    /**
     * 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
     */
    public Enumeration getAttributeNames() {

        if (!isValid())
            throw new IllegalStateException(sm
                    .getString("standardSession.getAttributeNames.ise"));
        return (new Enumerator(attributes.keySet(), true));
    }

    /**
     * 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>
     */
    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.
     * 
     * @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>
     */
    public String[] getValueNames() {

        if (!isValid())
            throw new IllegalStateException(sm
                    .getString("standardSession.getValueNames.ise"));

        return (keys());

    }

    /**
     * Invalidates this session and unbinds any objects bound to it.
     * 
     * @exception IllegalStateException
     *                if this method is called on an invalidated session
     */
    public void invalidate() {

        if (!isValid())
            throw new IllegalStateException(sm
                    .getString("standardSession.invalidate.ise"));

        // Cause this session to expire
        expire();

    }

    /**
     * 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
     */
    public boolean isNew() {

        if (!isValid())
            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.
     * <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>
     */
    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.
     * <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
     */
    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.
     * <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) {
        removeAttribute(name, notify, true);
    }

    public void removeAttribute(String name, boolean notify,
            boolean addDeltaRequest) {

        // Validate our current state
        if (!isValid())
            throw new IllegalStateException(sm
                    .getString("standardSession.removeAttribute.ise"));
        removeAttributeInternal(name, notify, addDeltaRequest);
    }

    /**
     * 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>
     */
    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.
     * <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
     */
    public void setAttribute(String name, Object value) {
        setAttribute(name, value, true, true);
    }

    public void setAttribute(String name, Object value, boolean notify,
            boolean addDeltaRequest) {

        // 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 (!isValid())
            throw new IllegalStateException(sm
                    .getString("standardSession.setAttribute.ise"));
        if (!(value instanceof java.io.Serializable)) {
            throw new IllegalArgumentException("Attribute [" + name
                    + "] is not serializable");
        }

        if (addDeltaRequest && (deltaRequest != null))
            deltaRequest.setAttribute(name, value);


        // Construct an event with the new value
        HttpSessionBindingEvent event = null;

        // Call the valueBound() method if necessary
        if (value instanceof HttpSessionBindingListener && notify) {
            // Don't call any notification if replacing with the same value
            Object oldValue = attributes.get(name);
            if (value != oldValue) {
                event = new HttpSessionBindingEvent(getSession(), name, value);
                try {
                    ((HttpSessionBindingListener) value).valueBound(event);
                } catch (Exception x) {
                    manager.getContainer().getLogger().error
                        (smp.getString("deltaSession.valueBound.ex"), x);
                }
            }
        }

        // Replace or add this attribute
        Object unbound = attributes.put(name, value);
        // Call the valueUnbound() method if necessary
        if ((unbound != null) && (unbound != value) && notify
                && (unbound instanceof HttpSessionBindingListener)) {
            try {
                ((HttpSessionBindingListener) unbound)
                        .valueUnbound(new HttpSessionBindingEvent(
                                (HttpSession) getSession(), name));
            } catch (Exception x) {
                manager.getContainer().getLogger().error
                    (smp.getString("deltaSession.valueBinding.ex"), x);
            }

        }

        //dont notify any listeners
        if (!notify)
            return;

        // Notify interested application event listeners
        Context context = (Context) manager.getContainer();
        if (context != null) {
            Object listeners[] = context.getApplicationEventListeners();
            if (listeners == null)
                return;
            for (int i = 0; i < listeners.length; i++) {
                if (!(listeners[i] instanceof HttpSessionAttributeListener))
                    continue;
                HttpSessionAttributeListener listener = (HttpSessionAttributeListener) listeners[i];
                try {
                    if (unbound != null) {
                        fireContainerEvent(context,
                                "beforeSessionAttributeReplaced", listener);
                        if (event == null) {
                            event = new HttpSessionBindingEvent(getSession(),
                                    name, unbound);
                        }
                        listener.attributeReplaced(event);
                        fireContainerEvent(context,
                                "afterSessionAttributeReplaced", listener);
                    } else {
                        fireContainerEvent(context,
                                "beforeSessionAttributeAdded", listener);
                        if (event == null) {
                            event = new HttpSessionBindingEvent(getSession(),
                                    name, value);
                        }
                        listener.attributeAdded(event);
                        fireContainerEvent(context,
                                "afterSessionAttributeAdded", listener);
                    }
                } catch (Throwable t) {
                    try {
                        if (unbound != null) {
                            fireContainerEvent(context,
                                    "afterSessionAttributeReplaced", listener);
                        } else {
                            fireContainerEvent(context,
                                    "afterSessionAttributeAdded", listener);
                        }
                    } catch (Exception e) {
                        ;
                    }
                    manager.getContainer().getLogger().error
                        (sm.getString("standardSession.attributeEvent"),t);
                }
            }
        }

    }

    // -------------------------------------------- HttpSession Private Methods

    /**
     * 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
     */
    private void readObject(ObjectInputStream stream)
            throws ClassNotFoundException, IOException {

        // Deserialize the scalar instance variables (except Manager)
        authType = null; // Transient only
        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();
        boolean hasPrincipal = stream.readBoolean();
        principal = null;
        if (hasPrincipal) {
            principal = SerializablePrincipal.readPrincipal(stream,
                    getManager().getContainer().getRealm());
        }

        //        setId((String) stream.readObject());
        id = (String) stream.readObject();
        org.apache.commons.logging.Log managerLog = manager.getContainer().getLogger() ;
        if (managerLog.isDebugEnabled())
            managerLog.debug(smp.getString("deltaSession.readSession",  id));

        // Deserialize the attribute count and attribute values
        if (attributes == null)
            attributes = new Hashtable();
        int n = ((Integer) stream.readObject()).intValue();
        boolean isValidSave = isValid;
        isValid = true;
        for (int i = 0; i < n; i++) {
            String name = (String) stream.readObject();
            Object value = (Object) stream.readObject();
            if ((value instanceof String) && (value.equals(NOT_SERIALIZED)))
                continue;
            if (managerLog.isDebugEnabled())
                managerLog.debug("  loading attribute '" + name +
                    "' with value '" + 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.
     * <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
     */
    private void writeObject(ObjectOutputStream stream) throws IOException {

        // Write the scalar instance variables (except Manager)
        stream.writeObject(new Long(creationTime));
        stream.writeObject(new Long(lastAccessedTime));
        stream.writeObject(new Integer(maxInactiveInterval));
        stream.writeObject(new Boolean(isNew));
        stream.writeObject(new Boolean(isValid));
        stream.writeObject(new Long(thisAccessedTime));
        stream.writeBoolean(getPrincipal() != null);
        if (getPrincipal() != null) {
            SerializablePrincipal.writePrincipal((GenericPrincipal) principal,
                    stream);
        }

        stream.writeObject(id);
        org.apache.commons.logging.Log managerLog = manager.getContainer().getLogger() ;
        if (managerLog.isDebugEnabled())
            managerLog.debug(smp.getString("deltaSession.writeSession",id));

        // 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.length; i++) {
            Object value = null;
            value = attributes.get(keys[i]);
            if (value == null)
                continue;
            else if (value instanceof Serializable) {
                saveNames.add(keys[i]);
                saveValues.add(value);
            }
        }

        // Serialize the attribute count and the Serializable attributes
        int n = saveNames.size();
        stream.writeObject(new Integer(n));
        for (int i = 0; i < n; i++) {
            stream.writeObject((String) saveNames.get(i));
            try {
                stream.writeObject(saveValues.get(i));
                if (managerLog.isDebugEnabled()) {
                    managerLog.debug(" storing attribute '" + saveNames.get(i) +
                        "' with value '" + saveValues.get(i) + "'");
                }
            } catch (NotSerializableException e) {
                managerLog.warn(sm.getString("standardSession.notSerializable",
                        saveNames.get(i), id), e);
                stream.writeObject(NOT_SERIALIZED);
                if(managerLog.isDebugEnabled()) {
                    managerLog.debug("  storing attribute '" + saveNames.get(i)
                        + "' with value NOT_SERIALIZED");
                }
            }
        }

    }

    private void evaluateIfValid() {
        /*
         * If this session has expired or is in the process of expiring or will
         * never expire, return
         */
        if (!this.isValid || expiring || maxInactiveInterval < 0)
            return;

        isValid();

    }

    // -------------------------------------------------------- Private Methods

    /**
     * Fire container events if the Context implementation is the
     * <code>org.apache.catalina.core.StandardContext</code>.
     * 
     * @param context
     *            Context for which to fire events
     * @param type
     *            Event type
     * @param data
     *            Event data
     * 
     * @exception Exception
     *                occurred during event firing
     */
    private void fireContainerEvent(Context context, String type, Object data)
            throws Exception {

        if (!"org.apache.catalina.core.StandardContext".equals(context
                .getClass().getName())) {
            return; // Container events are not supported
        }
        // NOTE: Race condition is harmless, so do not synchronize
        if (containerEventMethod == null) {
            containerEventMethod = context.getClass().getMethod(
                    "fireContainerEvent", containerEventTypes);
        }
        Object containerEventParams[] = new Object[2];
        containerEventParams[0] = type;
        containerEventParams[1] = data;
        containerEventMethod.invoke(context, containerEventParams);

    }

    /**
     * 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 = (SessionListener[]) listeners.toArray(list);
        }

        for (int i = 0; i < list.length; i++) {
            ((SessionListener) list[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[]) attributes.keySet().toArray(EMPTY_ARRAY));
    }

    /**
     * Return the value of an attribute without a check for validity.
     */
    protected Object getAttributeInternal(String name) {
        return (attributes.get(name));  
    }

    protected void removeAttributeInternal(String name, boolean notify,
            boolean addDeltaRequest) {

        // Remove this attribute from our collection
        Object value = attributes.remove(name);
        if (value == null)
            return;

        if (addDeltaRequest && (deltaRequest != null))
            deltaRequest.removeAttribute(name);

        // Do we need to do valueUnbound() and attributeRemoved() notification?
        if (!notify) {
            return;
        }

        // Call the valueUnbound() method if necessary
         HttpSessionBindingEvent event = null;
         if (value instanceof HttpSessionBindingListener) {
            event = new HttpSessionBindingEvent(
                (HttpSession) getSession(), name, value);
            try {
                ((HttpSessionBindingListener) value).valueUnbound(event);
            } catch (Exception x) {
                manager.getContainer().getLogger().error
                    (smp.getString("deltaSession.valueUnbound.ex"), x);
            }
        }
        // Notify interested application event listeners
        Context context = (Context) manager.getContainer();
        if (context != null) {
            Object listeners[] = context.getApplicationEventListeners();
            if (listeners == null)
                return;
            for (int i = 0; i < listeners.length; i++) {
                if (!(listeners[i] instanceof HttpSessionAttributeListener))
                    continue;
                HttpSessionAttributeListener listener = (HttpSessionAttributeListener) listeners[i];
                try {
                    fireContainerEvent(context,
                            "beforeSessionAttributeRemoved", listener);
                    if (event == null) {
                        event = new HttpSessionBindingEvent
                            (getSession(), name, value);
                    }
                    listener.attributeRemoved(event);
                    fireContainerEvent(context, "afterSessionAttributeRemoved",
                            listener);
                } catch (Throwable t) {
                    try {
                        fireContainerEvent(context,
                                "afterSessionAttributeRemoved", listener);
                    } catch (Exception e) {
                        ;
                    }
                    manager.getContainer().getLogger().error
                        (sm.getString("standardSession.attributeEvent"),t);
                }
            }
        }

    }

    protected long getLastTimeReplicated() {
        return lastTimeReplicated;
    }

    protected void setLastTimeReplicated(long lastTimeReplicated) {
        this.lastTimeReplicated = lastTimeReplicated;
    }

    protected void setAccessCount(int accessCount) {
        this.accessCount = accessCount;
    }

    protected int getAccessCount() {
        return accessCount;
    }

    protected void setExpireTolerance(int expireTolerance) {
        this.expireTolerance = expireTolerance;
      }
    
    protected int getExpireTolerance() {
        return expireTolerance;
    }

}

// -------------------------------------------------------------- Private Class

/**
 * 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.
 */

final class StandardSessionContext implements HttpSessionContext {

    private HashMap dummy = new HashMap();

    /**
     * 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.
     */
    public Enumeration getIds() {

        return (new Enumerator(dummy));

    }

    /**
     * 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.
     */
    public HttpSession getSession(String id) {

        return (null);

    }

}
