FileDocCategorySizeDatePackage
DeltaSession.javaAPI DocApache Tomcat 6.0.1426529Fri Jul 20 04:20:34 BST 2007org.apache.catalina.ha.session

DeltaSession

public class DeltaSession extends org.apache.catalina.session.StandardSession implements org.apache.catalina.ha.ClusterSession, Externalizable, org.apache.catalina.tribes.tipis.ReplicatedMapEntry
Similar to the StandardSession except that this session will keep track of deltas during a request.
author
Filip Hanik
version
$Revision: 522786 $ $Date: 2007-03-27 08:52:10 +0200 (mar., 27 mars 2007) $

Fields Summary
public static org.apache.juli.logging.Log
log
protected static org.apache.catalina.util.StringManager
sm
The string manager for this package.
private transient boolean
isPrimarySession
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 DeltaRequest
deltaRequest
The delta request contains all the action info
private transient long
lastTimeReplicated
Last time the session was replicatd, used for distributed expiring of session
protected Lock
diffLock
private long
version
Constructors Summary
public DeltaSession()
Construct a new Session associated with the specified Manager.

param
manager The manager with which this Session is associated


    // ----------------------------------------------------------- Constructors

                                       
      
        this(null);
    
public DeltaSession(org.apache.catalina.Manager manager)

        super(manager);
        this.resetDeltaRequest();
    
Methods Summary
public voidapplyDiff(byte[] diff, int offset, int length)
Applies a diff to an existing object.

param
diff byte[]
param
offset int
param
length int
throws
IOException

            ReplicationStream stream = ((ClusterManager)getManager()).getReplicationStream(diff,offset,length);
            getDeltaRequest().readExternal(stream);
            ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
            try {
                ClassLoader[] loaders = getClassLoaders();
                if ( loaders != null && loaders.length >0 ) Thread.currentThread().setContextClassLoader(loaders[0]);
                getDeltaRequest().execute(this);
            }finally {
                Thread.currentThread().setContextClassLoader(contextLoader);
            }
        
public voidexpire(boolean notify)
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?

        expire(notify, true);
    
public voidexpire(boolean notify, boolean notifyCluster)

        String expiredId = getIdInternal();
        super.expire(notify);

        if (notifyCluster) {
            if (log.isDebugEnabled())
                log.debug(sm.getString("deltaSession.notifying",
                                       ((ClusterManager)manager).getName(), 
                                       new Boolean(isPrimarySession()), 
                                       expiredId));
            if ( manager instanceof DeltaManager ) {
                ( (DeltaManager) manager).sessionExpired(expiredId);
            }
        }
    
protected java.lang.ObjectgetAttributeInternal(java.lang.String name)
Return the value of an attribute without a check for validity.

        return (attributes.get(name));
    
public java.lang.ClassLoader[]getClassLoaders()

            if ( manager instanceof BackupManager ) return ((BackupManager)manager).getClassLoaders();
            else if ( manager instanceof ClusterManagerBase ) return ((ClusterManagerBase)manager).getClassLoaders();
            else if ( manager instanceof StandardManager ) {
                StandardManager sm = (StandardManager)manager;
                return ClusterManagerBase.getClassLoaders(sm.getContainer());
            } else if ( manager instanceof ManagerBase ) {
                ManagerBase mb = (ManagerBase)manager;
                return ClusterManagerBase.getClassLoaders(mb.getContainer());
            }//end if
            return null;
        
public DeltaRequestgetDeltaRequest()

        if (deltaRequest == null) resetDeltaRequest();
        return deltaRequest;
    
public byte[]getDiff()
Returns a diff and sets the dirty map to false

return
byte[]
throws
IOException

            return getDeltaRequest().serialize();
        
public longgetLastAccessedTimeInternal()
Return the last client access time without invalidation check

see
#getLastAccessedTime().

        return (this.lastAccessedTime);
    
protected longgetLastTimeReplicated()

        return lastTimeReplicated;
    
public longgetVersion()

        return version;
    
public booleanisDiffable()
If this returns true, the map will extract the diff using getDiff() Otherwise it will serialize the entire object.

return
boolean

            return true;
        
public booleanisDirty()
Has the object changed since last replication and is not in a locked state

return
boolean

            return getDeltaRequest().getSize()>0;
        
public booleanisPrimarySession()
returns true if this session is the primary session, if that is the case, the manager can expire it upon timeout.

        return isPrimarySession;
    
public booleanisValid()
Return the isValid flag for this session.

        if (this.expiring) {
            return true;
        }
        if (!this.isValid) {
            return false;
        }
        if (ACTIVITY_CHECK && accessCount.get() > 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 >= (2 * maxInactiveInterval)) {
                    //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);
    
public voidlock()
Lock during serialization

            diffLock.lock();
        
public synchronized voidreadExternal(java.io.ObjectInput in)

        readObjectData(in);
    
private voidreadObject(java.io.ObjectInput stream)
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.

param
stream The input stream to read from
exception
ClassNotFoundException if an unknown class is specified
exception
IOException if an input/output error occurs


        // 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();
        version = ( (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();
        if (log.isDebugEnabled()) log.debug(sm.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;
            attributes.put(name, value);
        }
        isValid = isValidSave;

        if (listeners == null) {
            listeners = new ArrayList();
        }

        if (notes == null) {
            notes = new Hashtable();
        }
        activate();
    
public voidreadObjectData(java.io.ObjectInput stream)
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

        readObject(stream);
    
public voidrecycle()
Release all object references, and initialize instance variables, in preparation for reuse of this object.

        super.recycle();
        deltaRequest.clear();
    
public voidremoveAttribute(java.lang.String name, boolean notify)
Remove the object bound with the specified name from this session. If the session does not have an object bound with this name, this method does nothing.

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

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

        removeAttribute(name, notify, true);
    
public voidremoveAttribute(java.lang.String name, boolean notify, boolean addDeltaRequest)

        // Validate our current state
        if (!isValid()) throw new IllegalStateException(sm.getString("standardSession.removeAttribute.ise"));
        removeAttributeInternal(name, notify, addDeltaRequest);
    
protected voidremoveAttributeInternal(java.lang.String name, boolean notify, boolean addDeltaRequest)

        try {
            lock();
            // Remove this attribute from our collection
            Object value = attributes.get(name);
            if (value == null) return;

            super.removeAttributeInternal(name,notify);
            if (addDeltaRequest && (deltaRequest != null)) deltaRequest.removeAttribute(name);

        }finally {
            unlock();
        }
    
public voidresetDeltaRequest()

        if (deltaRequest == null) {
            deltaRequest = new DeltaRequest(getIdInternal(), false);
        } else {
            deltaRequest.reset();
            deltaRequest.setSessionId(getIdInternal());
        }
    
public voidresetDiff()
Resets the current diff state and resets the dirty flag

            resetDeltaRequest();
        
protected voidsetAccessCount(int count)

        if ( accessCount == null && ACTIVITY_CHECK ) accessCount = new AtomicInteger();
        if ( accessCount != null ) super.accessCount.set(count);
    
public voidsetAttribute(java.lang.String name, java.lang.Object value)
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.

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

        setAttribute(name, value, true, true);
    
public voidsetAttribute(java.lang.String name, java.lang.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;
        }

        try {
            lock();
            super.setAttribute(name,value, notify);
            if (addDeltaRequest && (deltaRequest != null)) deltaRequest.setAttribute(name, value);
        } finally {
            unlock();
        }
    
public voidsetId(java.lang.String id)
Set the session identifier for this session.

param
id The new session identifier

        super.setId(id);
        resetDeltaRequest();
    
public voidsetIdInternal(java.lang.String id)
Set the session identifier for this session without notify listeners.

param
id The new session identifier

        this.id = id;
        resetDeltaRequest();
    
protected voidsetLastTimeReplicated(long lastTimeReplicated)

        this.lastTimeReplicated = lastTimeReplicated;
    
public voidsetMaxInactiveInterval(int interval, boolean addDeltaRequest)

        super.maxInactiveInterval = interval;
        if (isValid && interval == 0) {
            expire();
        } else {
            if (addDeltaRequest && (deltaRequest != null))
                deltaRequest.setMaxInactiveInterval(interval);
        }
    
public voidsetNew(boolean isNew)
Set the isNew flag for this session.

param
isNew The new value for the isNew flag

        setNew(isNew, true);
    
public voidsetNew(boolean isNew, boolean addDeltaRequest)

        super.setNew(isNew);
        if (addDeltaRequest && (deltaRequest != null))
            deltaRequest.setNew(isNew);
    
public voidsetOwner(java.lang.Object owner)

            if ( owner instanceof ClusterManager && getManager()==null) {
                ClusterManager cm = (ClusterManager)owner;
                this.setManager(cm);
                this.setValid(true);
                this.setPrimarySession(false);
                this.access();
                this.resetDeltaRequest();
                this.endAccess();
            }
        
public voidsetPrimarySession(boolean primarySession)
Sets whether this is the primary session or not.

param
primarySession Flag value

        this.isPrimarySession = primarySession;
    
public voidsetPrincipal(java.security.Principal principal)
Set the authenticated Principal that is associated with this Session. This provides an Authenticator with a means to cache a previously authenticated Principal, and avoid potentially expensive Realm.authenticate() calls on every request.

param
principal The new Principal, or null if none

        setPrincipal(principal, true);
    
public voidsetPrincipal(java.security.Principal principal, boolean addDeltaRequest)

        try { 
            lock();
            super.setPrincipal(principal);
            if (addDeltaRequest && (deltaRequest != null))
                deltaRequest.setPrincipal(principal);
        } finally {
            unlock();
        }
    
public voidsetVersion(long version)

        this.version = version;
    
public java.lang.StringtoString()
Return a string representation of this object.

        StringBuffer sb = new StringBuffer();
        sb.append("DeltaSession[");
        sb.append(id);
        sb.append("]");
        return (sb.toString());
    
public voidunlock()
Unlock after serialization

            diffLock.unlock();
        
public synchronized voidwriteExternal(java.io.ObjectOutput out)

        writeObject(out);
    
private voidwriteObject(java.io.ObjectOutput stream)
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.

param
stream The output stream to write to
exception
IOException if an input/output error occurs

        // 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.writeObject(new Long(version));
        stream.writeBoolean(getPrincipal() != null);
        if (getPrincipal() != null) {
            SerializablePrincipal.writePrincipal((GenericPrincipal) principal,stream);
        }

        stream.writeObject(id);
        if (log.isDebugEnabled()) log.debug(sm.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));
            } catch (NotSerializableException e) {
                log.error(sm.getString("standardSession.notSerializable",saveNames.get(i), id), e);
                stream.writeObject(NOT_SERIALIZED);
                log.error("  storing attribute '" + saveNames.get(i)+ "' with value NOT_SERIALIZED");
            }
        }

    
public voidwriteObjectData(java.io.ObjectOutput 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

        writeObject(stream);