Package com.ericsson.ssa.sip

Source Code of com.ericsson.ssa.sip.SipApplicationSessionImpl$AttributeCallback

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) Ericsson AB, 2004-2008. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.ericsson.ssa.sip;

import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Externalizable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.http.HttpSession;
import javax.servlet.sip.ServletTimer;
import javax.servlet.sip.SipApplicationSession;
import javax.servlet.sip.SipApplicationSessionAttributeListener;
import javax.servlet.sip.SipApplicationSessionBindingEvent;
import javax.servlet.sip.SipApplicationSessionBindingListener;

import org.apache.catalina.Manager;
import org.apache.catalina.Session;
import org.apache.catalina.session.PersistentManagerBase;
import org.jvnet.glassfish.comms.util.LogUtil;

import com.ericsson.ssa.config.ConvergedContext;
import org.jvnet.glassfish.comms.deployment.backend.SipApplicationListeners;

import com.ericsson.ssa.sip.timer.ServletTimerImpl;
import com.ericsson.ssa.sip.timer.ServletTimerImplBase;


public class SipApplicationSessionImpl extends SipApplicationSessionBase
    implements Externalizable, LifeCycle {
    private static final Logger logger = LogUtil.SIP_LOGGER.getLogger();
    private static final long serialVersionUID = 1972145565288132288L;
    private static final String SAS_DESCRIPTION = "SipApplicationSession with id ";

    /** The serialized format versioning. 1 = first version. */
    private static final short serializedFormVersion  = 1;

    private transient SipSessionManager sipSessionManager;

    // ---- Persistable fields ----
    private String applicationName;
    private long creationDate = new Date().getTime();
    private Map<String, Object> applicationAttributes;
    private Set<String> persistentSipSessionIds;
    private Set<String> transientSipSessionIds;
    private Set<String> httpProtocolSessionIds;
    private Set<String> nonPersistentApplicationTimerIds;
    private Set<String> persistentApplicationTimerIds;
    protected String id;
    private transient boolean shouldBePersisted;


    // ----- Extra param field -------
    // these are persisted as well, but maybe overridden later
    private long expirationTime;

    /**
     * Constructor.
     */
    public SipApplicationSessionImpl(SipSessionManagerBase manager, String id) {
        this.id = id;
        this.sipSessionManager = manager;
        initInvalidateWhenReady();
    }

    public SipApplicationSessionImpl() { // default constructor for externalization.
    }
   
    /**
     * sipSessionManager will be null after deserializing the SAS object
     * back from the ObjectInputStream. So, the deserializer must explicitly
     * set the sipSessionManager after deserialization, which means that the
     * serialization/deserialization of the SAS object should only be done in a
     * context using the appropriate SipStore interfaces.
     *
     * @return the sip session manager.
     */
    @Override
    public SipSessionManager getSipSessionManager() {
        synchronized (getSasObjectLock()) {
            return sipSessionManager;
        }
    }

    /**
     * The sipSessionManager must be explicitly set by the deserializer after
     * deserializing the SAS object back from the ObjectInputStream.
     *
     * @see org.jvnet.glassfish.comms.replication.sessmgmt.SipApplicationSessionStoreImpl
     *
     * @param manager sip session mananger.
     */
    public void setSipSessionManager(SipSessionManager manager) {
        synchronized (getSasObjectLock()) {
            this.sipSessionManager = manager;
        }
    }
   
    public void doCleanup() {
        sipSessionManager.removeSipApplicationSession(this);
    }

    public Set<String> getPersistentSessionIds() {
        return new HashSet<String>(getPersistentSipSessionIds(false));
    }

    public Set<String> getPersistentTimerIds() {
        return new HashSet<String>(getPersistentApplicationTimerIds(false));
    }

    protected Manager getHttpSessionManager() {
       SipSessionManager manager = getSipSessionManager();
       if (manager != null) {
          ConvergedContext ctxt = manager.getContext();

          if (ctxt != null) {
              return ctxt.getManager();
          }
      }

      return null;
    }

    @Override
    protected String getPFieldApplicationName() {
        return applicationName;
    }

    @Override
    protected void setPFieldApplicationName(String applicationName) {
        this.applicationName = applicationName;
    }

    @Override
    protected Object getPFieldApplicationAttribute(String key) {
        if (applicationAttributes == null) {
            return null;
        }

        return applicationAttributes.get(key);
    }

    @Override
    protected void setPFieldApplicationAttribute(String key, Object value) {
        if (applicationAttributes == null) {
            applicationAttributes = new HashMap<String, Object>();
        }

        Object oldValue = applicationAttributes.put(key, value);
        if(oldValue==null){
          // No old value => the attribute was added
          attributeAdded(key,value);
        }
        else {
          // An old value
          if(oldValue!=value){
            // Call replaced only if it is a different value.
            attributeReplaced(key,oldValue,value);
          }
        }
    }

    @Override
    protected Iterator<String> getPFieldApplicationAttributeNames() {
        if (applicationAttributes == null) {
            return null;
        }

        return applicationAttributes.keySet().iterator();
    }

    @Override
    protected void removePFieldApplicationAttribute(String key) {
        if (applicationAttributes != null) {
            Object removedObject = applicationAttributes.remove(key);
            if(removedObject!=null){
              attributeRemoved(key,removedObject);
            }
        }
    }

    /**
     * Helper interface for invocation of a callback on a listener.
     *
     * This interface is used to be able to write the <code>callAttributeListeners</code>
     * method without duplicating that code and hence have a maintenance problem.
     *
     * An alternative to this approach is to use a switch case on an enum or
     * to use reflection. I like this approach best since it is the most object oriented
     * and type safe approach.
     *
     * @author Magnus Hessel, HiQ Stockholm AB
     *
     */
   private static interface AttributeCallback {
    void call(SipApplicationSessionBindingEvent event,
        SipApplicationSessionAttributeListener listener);
    static final AttributeCallback ADDED = new AttributeCallback() {
      public void call(SipApplicationSessionBindingEvent event,
          SipApplicationSessionAttributeListener listener) {
        listener.attributeAdded(event);
      }
    };

     static final AttributeCallback REPLACED = new AttributeCallback() {
      public void call(SipApplicationSessionBindingEvent event,
          SipApplicationSessionAttributeListener listener) {
        listener.attributeReplaced(event);
      }
    };

     static final AttributeCallback REMOVED = new AttributeCallback() {
      public void call(SipApplicationSessionBindingEvent event,
          SipApplicationSessionAttributeListener listener) {
        listener.attributeRemoved(event);
      }
    };
  }

  
  /**
   * Called when an attribute is added
   *
   * @param name
   */
  private void attributeAdded(String name,Object addedObject) {
    callAttributeListeners(AttributeCallback.ADDED, name);
    if(addedObject instanceof SipApplicationSessionBindingListener){
      ((SipApplicationSessionBindingListener)addedObject).valueBound(new SipApplicationSessionBindingEvent(this,name));
    }
  }

  /**
   * Called when an attribute is replaced
   *
   * @param name
   */
  private void attributeReplaced(String name,Object oldValue,Object newValue) {
    callAttributeListeners(AttributeCallback.REPLACED, name);
    if(oldValue instanceof SipApplicationSessionBindingListener){
      ((SipApplicationSessionBindingListener)oldValue).valueUnbound(new SipApplicationSessionBindingEvent(this,name));
    }
    if(newValue instanceof SipApplicationSessionBindingListener){
      ((SipApplicationSessionBindingListener)newValue).valueBound(new SipApplicationSessionBindingEvent(this,name));
    }
  }

  /**
   * Called when an attribute is removed
   *
   * @param name
   */
  private void attributeRemoved(String name, Object removedValue) {
    callAttributeListeners(AttributeCallback.REMOVED, name);
    if(removedValue instanceof SipApplicationSessionBindingListener){
      ((SipApplicationSessionBindingListener)removedValue).valueUnbound(new SipApplicationSessionBindingEvent(this,name));
    }
  }

 
   /**
    * Helper to call a callback on all SipSessionAttributeListeners.
    *
    * @param callback Which callback to invoke
    * @param attributeName Name of attribute the callback involves
    */
  private void callAttributeListeners(AttributeCallback callback, String attributeName) {
    // List all listeners
    List<SipApplicationSessionAttributeListener> sipApplicationSessionAttributeListeners =
        getSipApplicationListeners().getSipApplicationSessionAttributeListeners();
    // If there are at least one, create event and call all of them.
    if (sipApplicationSessionAttributeListeners != null
        && !sipApplicationSessionAttributeListeners.isEmpty()) {
      SipApplicationSessionBindingEvent event = new SipApplicationSessionBindingEvent(this,
          attributeName);
      for (SipApplicationSessionAttributeListener listener : sipApplicationSessionAttributeListeners) {
        callback.call(event, listener);
      }
    }
  }
   
  /**
   * Notify all SipApplicationSessionBindingListeners that are values that this
   * the binding to this SipApplicationSession is due.
   */
    @Override
  protected void notifyAttributesUnbound() {
      if(applicationAttributes!=null){                       
      Iterator<Entry<String, Object>> entries = applicationAttributes.entrySet().iterator();                      
      while(entries.hasNext()){
                                Entry<String, Object> entry = entries.next();
                                entries.remove();
        Object value = entry.getValue();                               
        if(value instanceof SipApplicationSessionBindingListener){
          ((SipApplicationSessionBindingListener)value).valueUnbound(new SipApplicationSessionBindingEvent(this,entry.getKey()));
        }
      }
      }
  }

  @Override
    protected long getPFieldCreationDate() {
        return creationDate;
    }

    @Override
    public long getPFieldExpirationTime() {
        return expirationTime;
    }

    @Override
    protected void setPFieldExpirationTime(long anExpirationTime) {
        expirationTime = anExpirationTime;
    }

    @Override
    protected Iterable<SipSessionBase> getPFieldSipSessions() {
        return getPFieldSipSessions(true);
    }

    protected Iterable<SipSessionBase> getPFieldSipSessions(
                            final boolean loadDependencies) {
        final Set<String> allSsIds =
            new HashSet<String>(getTransientSipSessionIds(false));
        allSsIds.addAll(getPersistentSipSessionIds(false));

        return new Iterable<SipSessionBase>() {
            // The iterator skips SS:es that can not be found in the
            // SipSessionManager
            public Iterator<SipSessionBase> iterator() {
                return new Iterator<SipSessionBase>() {
                    Iterator<String> idIterator = allSsIds.iterator();
                    private SipSessionDialogImpl nextSs;

                    public boolean hasNext() {
                        while (idIterator.hasNext()) {
                            nextSs = null;
                            try {
                                 nextSs = getSipSessionManager()
                                     .findSipSession(idIterator.next(),
                                                     loadDependencies);
                            } catch (RemoteLockException ex) {
                                 throw new RemoteLockRuntimeException(ex);
                            }

                            if (nextSs != null) {
                                return true;
                            }
                        }

                        return false;
                    }

                    public SipSessionBase next() {
                       
                        SipSessionDialogImpl ssTmp = nextSs;
                        nextSs = null;

                        if (ssTmp != null) {
                            return ssTmp;
                        }

                        if (hasNext()) {
                            return nextSs;
                        } else {
                            throw new NoSuchElementException();
                        }
                    }

                    public void remove() {
                        throw new UnsupportedOperationException(
                            "Removal via iterator is not supported");
                    }
                };
            }
        };
    }

    /**
     * Gets all SIP protocol sessions that are currently active.
     *
     * @return the currently active SIP protocol sessions
     */
    @Override
    protected Iterable<SipSessionBase> getPFieldSipSessionsActiveOnly() {
        final Set<String> allSsIds =
            new HashSet<String>(getTransientSipSessionIds(false));
        allSsIds.addAll(getPersistentSipSessionIds(false));

        return new Iterable<SipSessionBase>() {

            public Iterator<SipSessionBase> iterator() {
                return new Iterator<SipSessionBase>() {
                    Iterator<String> idIterator = allSsIds.iterator();
                    private SipSessionDialogImpl nextSs;
                    SipSessionManager manager = getSipSessionManager();

                    public boolean hasNext() {
                        while (idIterator.hasNext()) {
                            String id = idIterator.next();
                            nextSs = null;
                            try {
                                if (manager instanceof
                                        PersistentSipSessionManagerBase) {
                                    nextSs =
                                        ((PersistentSipSessionManagerBase)manager).
                                        findSipSessionFromCacheOnly(id);
                                } else {
                                    nextSs = manager.findSipSession(id);
                                }
                            } catch (Exception ioe) {
                                // Ignore, skip to the next session
                                // TODO add warning logging
                            }

                            if (nextSs != null) {
                                return true;
                            }
                        }

                        return false;
                    }

                    public SipSessionBase next() {
                       
                        SipSessionDialogImpl ssTmp = nextSs;
                        nextSs = null;

                        if (ssTmp != null) {
                            return ssTmp;
                        }

                        if (hasNext()) {
                            return nextSs;
                        } else {
                            throw new NoSuchElementException();
                        }
                    }

                    public void remove() {
                        throw new UnsupportedOperationException(
                            "Removal via iterator is not supported");
                    }
                };
            }
        };
    }

    @Override
    protected SipSessionBase getPFieldSipSession(String id) {
        try {
            return getSipSessionManager().findSipSession(id);
        } catch(RemoteLockException rle) {
            logger.log(Level.SEVERE, rle.getMessage(), rle);
            return null;
        }
    }

    @Override
    protected void removePFieldSipProtocolSession(SipSessionBase session) {
        if (checkSessionReadyToInvalidate()) {
            if (logger.isLoggable(Level.FINE)) {
                logger.log(Level.FINE, "Transitioning " + this + " to" +
                        " ready-to-invalidate state upon invalidation of last " + session);
            }
            sessionReadyToInvalidate();
        }
        getPersistentSipSessionIds(false).remove(session.getId());
        getTransientSipSessionIds(false).remove(session.getId());
    }

    @Override
    protected void addSipProtocolSession(SipSessionBase session) {
        getTransientSipSessionIds(true).add(session.getId());
        setReadyToInvalidate(false);
    }

    private Set<String> getTransientSipSessionIds(boolean create) {
        if (transientSipSessionIds == null) {
            if (!create) {
                return Collections.emptySet();
            } else {
                transientSipSessionIds = new HashSet<String>(8);
            }
        }

        return transientSipSessionIds;
    }

    private Set<String> getPersistentSipSessionIds(boolean create) {
        if (persistentSipSessionIds == null) {
            if (!create) {
                return Collections.emptySet();
            } else {
                persistentSipSessionIds = new HashSet<String>(8);
            }
        }

        return persistentSipSessionIds;
    }

    private boolean hasValidSipSession() {
        if (getTransientSipSessionIds(false).isEmpty() &&
                getPersistentSipSessionIds(false).isEmpty()) {
            return false;
        }
        boolean hasValidSession = false;
        for (SipSessionBase sess : getPFieldSipSessions()) {
            if (sess.isValid()) {
                hasValidSession = true; // this session is valid.
                break;
            }
        }
        return hasValidSession;
    }

    private boolean hasValidHttpSession() {
        if (getHttpProtocolSessionIds(false).isEmpty()) { // no http sessions.
            return false;
        }
        boolean hasValidSession = false;
        for (HttpSession sess : getPFieldHttpSessions()) {
            ConvergedHttpSessionFacade s = (ConvergedHttpSessionFacade) sess;
            if(s.isValid()) {
                hasValidSession = true; // this session is valid.
                break;
            }
        }
        return hasValidSession;
    }

    private boolean hasServletTimer() {
        if(getPersistentApplicationTimerIds(false).isEmpty() &&
                getNonPersistentApplicationTimerIds(false).isEmpty()) {
            return false;
        }
        return true;
    }

    @Override
    protected boolean isEmpty() {
        if(hasValidSipSession() || hasServletTimer() || hasValidHttpSession()) {
            return false;
        }
        return true;
    }
   
    @Override
    protected Iterable<HttpSession> getPFieldHttpSessions() {
        final Set<String> sessionIds =
            new HashSet<String>(getHttpProtocolSessionIds(false));

        return new Iterable<HttpSession>() {
            public Iterator<HttpSession> iterator() {
                return new Iterator<HttpSession>() {
                    Iterator<String> idIterator = sessionIds.iterator();
                    private HttpSession nextSess;

                    public boolean hasNext() {
                        while (idIterator.hasNext()) {
                            try {
                                Session sess = getHttpSessionManager()
                                           .findSession(idIterator.next());
                                if (sess != null) {
                                    nextSess = sess.getSession();
                                }
                            } catch (IOException e) {
                                // Ignore, skip to the next session
                                // TODO add warning logging
                            }

                            if (nextSess != null) {
                                return true;
                            }
                        }

                        return false;
                    }

                    public HttpSession next() {
                        HttpSession sessTmp = nextSess;
                        nextSess = null;

                        if (sessTmp != null) {
                            return sessTmp;
                        }

                        if (hasNext()) {
                            return nextSess;
                        } else {
                            throw new NoSuchElementException();
                        }
                    }

                    public void remove() {
                        throw new UnsupportedOperationException(
                            "Removal via iterator is not supported");
                    }
                };
            }
        };
    }

    /**
     * Gets all HTTP protocol sessions that are currently active.
     *
     * @return the currently active HTTP protocol sessions
     */
    @Override
    protected Iterable<HttpSession> getPFieldHttpSessionsActiveOnly() {

        return new Iterable<HttpSession>() {

            public Iterator<HttpSession> iterator() {

                return new Iterator<HttpSession>() {

                    Iterator<String> idIterator =
                        getHttpProtocolSessionIds(false).iterator();
                    private HttpSession nextSess = null;
                    Manager manager = getHttpSessionManager();

                    public boolean hasNext() {
                        while (idIterator.hasNext()) {
                            String id = idIterator.next();
                            try {
                                Session sess = null;
                                if (manager instanceof PersistentManagerBase) {
                                    sess = ((PersistentManagerBase)manager).
                                        findSessionFromCacheOnly(id);
                                } else {
                                    sess = manager.findSession(id);
                                }
                                if (sess != null) {
                                    nextSess = sess.getSession();
                                }
                            } catch (Exception ioe) {
                                // Ignore, skip to the next session
                                // TODO add warning logging
                            }

                            if (nextSess != null) {
                                return true;
                            }
                        }

                        return false;
                    }

                    public HttpSession next() {
                        HttpSession sessTmp = nextSess;
                        nextSess = null;

                        if (sessTmp != null) {
                            return sessTmp;
                        }

                        if (hasNext()) {
                            return nextSess;
                        } else {
                            throw new NoSuchElementException();
                        }
                    }

                    public void remove() {
                        throw new UnsupportedOperationException(
                            "Removal via iterator is not supported");
                    }
                };
            }
        };
    }

    @Override
    protected HttpSession getPFieldHttpSession(String id) {
        Session sess = null;
        try {
            sess = getHttpSessionManager().findSession(id);
        } catch(IOException ioe) {
            logger.log(Level.SEVERE, ioe.getMessage(), ioe);
        }
        return sess == null ? null : sess.getSession();
    }
   
    @Override
    protected void removePFieldHttpProtocolSession(HttpSession session) {
        this.removePFieldHttpProtocolSession(session, true);
    }

    @Override
    protected void removePFieldHttpProtocolSession(
            HttpSession session, boolean removeFromManager) {
        if (removeFromManager) {
            try {
                Manager m = getHttpSessionManager();
                if (m != null) {
                    Session s = m.findSession(session.getId());
                    if (s != null) {
                        m.remove(s);
                    }
                }
            } catch (IOException e) {
                // Ignore, the session apparently does not exist anyway
            }
        }
        getHttpProtocolSessionIds(false).remove(session.getId());
        if (checkSessionReadyToInvalidate()) {
            if (logger.isLoggable(Level.FINE)) {
                logger.log(Level.FINE, "Transitioning " + this + " to" +
                        " ready-to-invalidate state upon invalidation of last" +
                        " HttpSession " + session);
            }
            sessionReadyToInvalidate();
        }
    }

    @Override
    protected void addPFieldHttpProtocolSession(HttpSession session) {
        getHttpProtocolSessionIds(true).add(session.getId());
        setReadyToInvalidate(false);
        setShouldBePersisted();
    }

    private Set<String> getHttpProtocolSessionIds(boolean create) {
        if (httpProtocolSessionIds == null) {
            if (!create) {
                return Collections.emptySet();
            } else {
                httpProtocolSessionIds = new HashSet<String>(8);
            }
        }

        return httpProtocolSessionIds;
    }

    @Override
    protected Collection<ServletTimer> getPFieldApplicationTimers() {
        return getPFieldApplicationTimers(true);
    }

    protected Collection<ServletTimer> getPFieldApplicationTimers(boolean loadDependencies)  {
        Set<String> persistentTimerIds = getPersistentApplicationTimerIds(false);
        Set<String> nonPersistentTimerIds = getNonPersistentApplicationTimerIds(false);
        List<ServletTimer> timers = new ArrayList<ServletTimer>(persistentTimerIds.size() +
                nonPersistentTimerIds.size());

        for (String id : persistentTimerIds) {
            ServletTimerImpl st = null;
            try {
                st = getSipSessionManager().findServletTimer(id, loadDependencies);
            } catch (RemoteLockException e) {
                throw new RemoteLockRuntimeException(e);
            }
            if (st != null) {
                timers.add(st);
            }
        }

        for (String id : nonPersistentTimerIds) {
            ServletTimerImpl st = null;
            st = findServletTimerLocally(id, loadDependencies);
            if (st != null) {
                timers.add(st);
            }
        }

        return timers;
    }

    @Override
    protected ServletTimer getPFieldApplicationTimer(String id) {
        Set<String> persistentTimerIds =
                getPersistentApplicationTimerIds(false);
        if (persistentTimerIds.contains(id)) {
            try {
                return getSipSessionManager().findServletTimer(id, true);
            } catch (RemoteLockException rle) {
                logger.log(Level.SEVERE, rle.getMessage(), rle);
                return null;
            }
        }
        Set<String> nonPersistentTimerIds =
                getNonPersistentApplicationTimerIds(false);
        if (nonPersistentTimerIds.contains(id)) {
            return findServletTimerLocally(id, true);
        }
        return null;
    }
   
    public boolean hasServletTimer(String timerId) {
        return (getNonPersistentApplicationTimerIds(false).contains(timerId) ||
        getPersistentApplicationTimerIds(false).contains(timerId));
    }

    protected ServletTimerImpl findServletTimerLocally(String id, boolean loadDependencies) {
        try {
            return getSipSessionManager().findServletTimer(id, loadDependencies);
        } catch (RemoteLockException e) {
            if (logger.isLoggable(Level.FINE))
            logger.log(Level.FINE, "ignoring RemoteLockException for non persistent timers", e);
            return null;
        }
    }

    /**
     * @see com.ericsson.ssa.sip.SipApplicationSessionImpl#addPFieldApplicationTimer(com.ericsson.ssa.sip.timer.ServletTimerImpl)
     */
    @Override
    protected void addPFieldApplicationTimer(ServletTimerImpl timer) {
        if (timer.isPersistent()) {
            getPersistentApplicationTimerIds(true).add(timer.getId());
        } else {
            getNonPersistentApplicationTimerIds(true).add(timer.getId());
        }
        setReadyToInvalidate(false);
    }

    /**
     * @see com.ericsson.ssa.sip.SipApplicationSessionImpl#removePFieldApplicationTimer(com.ericsson.ssa.sip.timer.ServletTimerImpl)
     */
    @Override
    protected void removePFieldApplicationTimer(ServletTimerImpl timer) {
        getNonPersistentApplicationTimerIds(false).remove(timer.getId());
        getPersistentApplicationTimerIds(false).remove(timer.getId());
    }

    private Set<String> getPersistentApplicationTimerIds(boolean create) {
        if (persistentApplicationTimerIds == null) {
            if (!create) {
                return Collections.emptySet();
            } else {
                persistentApplicationTimerIds = new HashSet<String>(8);
            }
        }

        return persistentApplicationTimerIds;
    }

    private Set<String> getNonPersistentApplicationTimerIds(boolean create) {
        if (nonPersistentApplicationTimerIds == null) {
            if (!create) {
                return Collections.emptySet();
            } else {
                nonPersistentApplicationTimerIds = new HashSet<String>(8);
            }
        }

        return nonPersistentApplicationTimerIds;
    }

    /**
     * @see com.ericsson.ssa.sip.SipApplicationSessionImpl#getId()
     */
    @Override
    public String getId() {
        return id;
    }
   

    /**
     * Gets the id to be included in the serialized representation of this
     * SipApplicationSession. Normally, this will be the same as the id of
     * this SipApplicationSession, but subclasses may override this method to
     * return null or an empty string (for optimization purposes), if they
     * are able to obtain the id from another source after deserialization.
     */
    protected String getIdForSerial() {
        return getId();
    }


    /**
     * @see com.ericsson.ssa.sip.SipApplicationSessionImpl#getAppId()
     */
    public String getAppId() {
        return sipSessionManager != null
                ? sipSessionManager.getApplicationId() : null;
    }

    /**
     * Check if this SipApplicationSession should be persisted.
     * @return true if this SAS shall be persisted
     */
    public boolean shouldBePersisted() {
        SipSessionManager manager = getSipSessionManager();
        if (manager != null && manager.isBeingReleased()) {
            return false;
        }

        return shouldBePersisted;
    }

    /**
     * Indicate that this SipApplicationSession should from now on be persisted.
     */
    public void setShouldBePersisted() {
        shouldBePersisted = true;
    }

    protected void setSipSessionShouldBePersisted(
        SipSessionDialogImpl sipSession) {
        synchronized (getSasObjectLock()) {
            getTransientSipSessionIds(false).remove(sipSession.getId());
            getPersistentSipSessionIds(true).add(sipSession.getId());
            setShouldBePersisted();
        }
    }

    public void setServletTimerShouldBePersisted(ServletTimerImplBase timer) {
        synchronized (getSasObjectLock()) {
            getNonPersistentApplicationTimerIds(false).remove(timer.getId());
            getPersistentApplicationTimerIds(true).add(timer.getId());
        }
    }

    /**
     * @serialData See serialized form version 1 in #readExternal(ObjectInput in)
     * 
     * @param out the stream to write the object members
     *
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeShort(serializedFormVersion);
        super.writeExternal(out);       
        out.writeUTF(getIdForSerial());
        out.writeUTF(applicationName);
        out.writeLong(creationDate);
        out.writeLong(expirationTime); // possibly overridden by extraparams

        Set<String> sipSessionIds = getPersistentSipSessionIds(false);
        out.writeInt(sipSessionIds.size());

        for (String ssId : sipSessionIds) {
            out.writeUTF(ssId);
        }

        Set<String> httpSessionIds = getHttpProtocolSessionIds(false);
        out.writeInt(httpSessionIds.size());

        for (String hsId : httpSessionIds) {
            out.writeUTF(hsId);
        }

        Set<String> appTimerIds = getPersistentApplicationTimerIds(false);
        out.writeInt(appTimerIds.size());

        for (String atId : appTimerIds) {
            out.writeUTF(atId);
        }

        // Serialize session attributes
        IOUtil.writeSessionAttributes(applicationAttributes, out);
    }

   
    /**
     * Identifies this SAS as non SSR enabled.
     *
     * This is used by the non-persistent ServletTimers of this SAS to decide
     * whether they need to establish and save a UOW during their firing.
     */
    public boolean isReplicationEnabled() {
        return false;
    }

   
    public SipApplicationListeners getSipApplicationListeners()
    {
       SipSessionManager manager = getSipSessionManager();
       if (manager != null) {
          ConvergedContext ctxt = manager.getContext();

          if (ctxt != null) {
              return ctxt.getSipApplicationListeners();
          }
      }

      return null;
    }
   
   
    /**
     * @serialData first field is an short and represents the serializedFormVersion.<br><br>
     * <h3>Data layout for serializedFormVersion = 1 follows</h3>
     *
     * <li>field is a <b>String</b> and represents sipApplicationId field</li>
     * <li>field is a <b>String</b> and represents applicationName field</li>
     * <li>field is a <b>Long</b> and represents creationDate field as absolute time</li>
     * <li>field is a <b>Long</b> and represents expirationTime field as absolute time</li>
     * <li>field is a <b>String</b> and represents beKey field</li>
     * <li>field is a <b>Integer</b> and represents number of persistent sip session ids</li>
     * <li>0..n fields as <b>String</b> and represents sessionId of persistent sip session</li>
     * <li>field is a <b>Integer</b> and represents number of persistent http session ids</li>
     * <li>0..n fields as <b>String</b> and represents sessionId of persistent http session</li>
     * <li>field is a <b>Integer</b> and represents number of timer ids</li>
     * <li>0..n fields as <b>String</b> and represents timerId of timer</li>
     * <li>field is a <b>Integer</b> and represents number of key-value attributes serialized</li>
     * <li>0..n key-value fields as <b>Object</b> and represents key-value attributes</li>
     *
     * @param in the stream to read the object members
     *
     * @throws IOException is thrown when unsupported version is detected
     * @throws ClassNotFoundException
     */
    public void readExternal(ObjectInput in)
        throws IOException, ClassNotFoundException {
        short readSerializedFormVersion = in.readShort();
        switch(readSerializedFormVersion) {
        case 1:
            super.readExternal(in);
            id = in.readUTF();       
            applicationName = in.readUTF();
            creationDate = in.readLong();
            expirationTime = in.readLong();
       
            int size = in.readInt();
       
            if (size > 0) {
                persistentSipSessionIds = new HashSet<String>(size);
       
                for (int i = 0; i < size; i++) {
                    persistentSipSessionIds.add(in.readUTF());
                }
            }
       
            size = in.readInt();
       
            if (size > 0) {
                httpProtocolSessionIds = new HashSet<String>(size);
       
                for (int i = 0; i < size; i++) {
                    httpProtocolSessionIds.add(in.readUTF());
                }
            }
       
            size = in.readInt();
       
            if (size > 0) {
                persistentApplicationTimerIds = new HashSet<String>(size);
       
                for (int i = 0; i < size; i++) {
                    persistentApplicationTimerIds.add(in.readUTF());
                }
            }
       
            // Deserialize session attributes
            applicationAttributes = IOUtil.readSessionAttributes(in);

            shouldBePersisted = true;
            break;
        default:
            throw new IOException("Unable to deserialize into "
                    + this.getClass().getName()
                    + " with serialVersionUID = " + serialVersionUID
                    + " due to unknown serializedFormVersion of "
                    + readSerializedFormVersion);
        }       
    }

    /**
     * Activates this SipApplicationSession.
     */
    public boolean activate() {
        if (logger.isLoggable(Level.FINE)) {
            logger.fine("IN " + this.getClass().getName() +
                        ">>activate: " + this);
        }

        // Add to active cache
        SipSessionManager mgr = getSipSessionManager();
        if (mgr != null) {
            SipApplicationSession sas = mgr.addSipApplicationSession(this);
            if (sas != null) {
                // While this thread has been in the process of loading the
                // requested sas, and is now trying to activate it, another
                // thread has also loaded the same sas, and has already
                // added it to the active cache. Abort activation.
                return true;
            }
        }

        // Make sure to notify any listeners before restarting the activation
        // timer, see SailFin Issue 615
        long oldExpirationTime = getPFieldExpirationTime();
        notifySessionDidActivate();
        restartAppSessionTimer();
        long newExpirationTime = getPFieldExpirationTime();
        //this does touch and save - updating the wiggled expiration
        //times for SAS, SS and DF
        if (isUpdateExpiration(isValid, oldExpirationTime,
                               newExpirationTime)) {
            this.setPFieldExpirationTime(this.getPFieldExpirationTime());
        }
        //returning isValid because restartAppSessionTimer
        //may have invalidated the SAS
        return isValid;
    }


    protected boolean isUpdateExpiration(boolean isValid,
                                         long oldExpirationTime,
                                         long newExpirationTime) {
        return isValid && (oldExpirationTime != newExpirationTime);
    }


    /**
     * Passivates this SipApplicationSession.
     */
    public void passivate() {
        if (logger.isLoggable(Level.FINE)) {
            logger.fine("IN " + this.getClass().getName() +
                        ">>passivate: " + this);
        }

        notifySessionWillPassivate();
        // cancel the NonPersistetTimers.
        // the persistent timers will be migrated at expiration
        cancelNonPersistentTimers();
        // Remove from active cache
        SipSessionManager mgr = getSipSessionManager();
        if (mgr != null) {
            mgr.removeSipApplicationSession(this);
        }

        if (sasTimer != null) {
            sasTimer.cancel();
        }
    }

    protected void cancelNonPersistentTimers() {
        Set<String> nonPersistentTimerIds = getNonPersistentApplicationTimerIds(false);
        for (String id : nonPersistentTimerIds) {
            ServletTimerImpl st = findServletTimerLocally(id, false);
            if (st != null) {
                st.cancel(true);
            }
        }
    }



    public String toString() {
        return SAS_DESCRIPTION + getAppId() + ":" + id;
    }

    public String getObjectRefString() {
        return this.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(this));
    }
}
TOP

Related Classes of com.ericsson.ssa.sip.SipApplicationSessionImpl$AttributeCallback

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.