/*
* 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 org.jvnet.glassfish.comms.deployment.backend.SipApplicationListeners;
import com.ericsson.ssa.sip.PathNode.Type;
import com.ericsson.ssa.sip.dialog.DialogCleaner;
import org.apache.catalina.Globals;
import org.jvnet.glassfish.comms.util.LogUtil;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Externalizable;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.sip.Address;
import javax.servlet.sip.SipSession;
import javax.servlet.sip.SipSessionActivationListener;
import javax.servlet.sip.SipSessionAttributeListener;
import javax.servlet.sip.SipSessionBindingEvent;
import javax.servlet.sip.SipSessionBindingListener;
import javax.servlet.sip.SipSessionEvent;
import javax.servlet.sip.SipSessionListener;
import javax.servlet.sip.URI;
import javax.servlet.sip.ar.SipApplicationRoutingRegion;
public class SipSessionDialogImpl extends SipSessionImplBase
implements LifeCycle {
private static Logger logger = LogUtil.SIP_LOGGER.getLogger();
private static final long serialVersionUID = 3762535598732096310L;
private static final String SS_DESCRIPTION = "SipSession with id ";
/** The serialized format versioning. 1 = first version. */
private static final short serializedFormVersion = 1;
private transient ArrayList<SipSessionListener> sessionListeners = null;
private Map<String, Object> sessionAttributeMap;
protected SipApplicationSessionImpl sipApplicationSession = null;
protected SipSessionManager sipSessionManager = null;
protected String sasId = null;
private String handler = null;
private Type type = null;
protected String id; // final
private Address to; // Final
private long creationDate = new Date().getTime(); // Final
private long lastAccessedTime;
private long currentAccessedTime;
private long expirationTime;
private String dialogFragmentId; // Final
private boolean isDerived = false;
private AtomicInteger cSeq = null;
private URI remoteTarget = null;
private boolean is1xxReliableOngoing = false;
private boolean is1xxReliableSDP = false;
private boolean updateOngoing = false;
private State sessionState = State.INITIAL;
private transient boolean shouldBePersisted = false;
// JSR289
private SipApplicationRoutingRegion routingRegion = null;
private URI subscriberURI = null;
private String linkedSipSessionId = null;
private String correspondingJoin = null;
private String correspondingReplaces = null;
/**
* This boolean controls the values that getLocalParty() and
* getRemoteParty() should return. It is false by default, which provides
* the correct behaviour for UAC and proxy SipSessions. When an application
* has decided to take the UAS role this attribute is set to true for the
* SipSession, causing getLocalParty() and getRemoteParty() to respond
* differently.
*/
private boolean swapLocalRemote = false;
public SipSessionDialogImpl(SipSessionManagerBase manager, DialogSet set,
Address to, SipApplicationSessionImpl appSession, String handler,
Type type) {
super(set);
init(manager, to, appSession, handler, type);
initListeners(sipApplicationSession.getSipApplicationListeners());
initInvalidateWhenReady();
}
protected void init(SipSessionManagerBase manager,
Address to, SipApplicationSessionImpl appSession, String handler,
Type type) {
sipSessionManager = manager;
// remove to-tag
this.to = (Address) ((AddressImpl) to).clone(false, false);
((AddressImpl) this.to).setReadOnly(true);
sipApplicationSession = appSession;
sasId = appSession.getId();
this.handler = handler;
this.type = type;
// if user agent then a cseq counter is needed, otherwise save memory...
if (type.equals(Type.Caller) || type.equals(Type.Callee)) {
createPFieldCSeq();
}
// important that id exist before adding to app session...
id = createID().toString();
sipApplicationSession.addSession(this);
currentAccessedTime = System.currentTimeMillis();
lastAccessedTime = currentAccessedTime;
}
/**
* For serialization only.
*/
public SipSessionDialogImpl() {
super(null);
}
/**
* Gets the id to be included in the serialized representation of this
* SipSession. Normally, this will be the same as the id of
* this SipSession, 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 id;
}
/**
* Notifies any interested session attributes that this session has been
* activated.
*/
public void notifySessionDidActivate() {
Iterator attrValues = getSessionAttributeMap(false).values().iterator();
SipSessionEvent sipSessionEvent = new SipSessionEvent(this);
while (attrValues.hasNext()) {
Object attrValue = attrValues.next();
if (attrValue instanceof SipSessionActivationListener) {
((SipSessionActivationListener) attrValue).sessionDidActivate(sipSessionEvent);
}
}
}
/**
* Notifies any interested session attributes that this session is about
* to be passivated.
*/
public void notifySessionWillPassivate() {
Iterator attrValues = getSessionAttributeMap(false).values().iterator();
SipSessionEvent sipSessionEvent = new SipSessionEvent(this);
while (attrValues.hasNext()) {
Object attrValue = attrValues.next();
if (attrValue instanceof SipSessionActivationListener) {
((SipSessionActivationListener) attrValue).sessionWillPassivate(sipSessionEvent);
}
}
}
public void doCleanup() {
sipSessionManager.removeSipSession(this);
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "The sip session with ID="+getId()+" has been removed from the active cache.");
}
SipApplicationSessionImpl sas = (SipApplicationSessionImpl) getApplicationSessionLocally();
if (sas != null && !sas.isValid() && !sas.isForegroundLocked()) {
sas.doCleanup();
} else if (sas != null && !sas.isValid()) {
// The SAS is still FG locked give it another 32 seconds, then remove it regardless of lock state.
DialogCleaner.getInstance().registerForSupervision(sas, 32000);
}
}
protected final void notifySessionCreated() {
ArrayList<SipSessionListener> someSessionListeners = getSipSessionListeners();
if (someSessionListeners == null) {
return;
}
SipSessionEvent sipSessionEvent = new SipSessionEvent(this);
for (Iterator<SipSessionListener> lIter = someSessionListeners.iterator();
lIter.hasNext();) {
SipSessionListener listener = lIter.next();
listener.sessionCreated(sipSessionEvent);
}
}
protected final void notifySessionDestroyed() {
ArrayList<SipSessionListener> someSessionListeners = getSipSessionListeners();
if (someSessionListeners == null) {
return;
}
SipSessionEvent sipSessionEvent = new SipSessionEvent(this);
for (Iterator<SipSessionListener> lIter = someSessionListeners.iterator();
lIter.hasNext();) {
SipSessionListener listener = lIter.next();
listener.sessionDestroyed(sipSessionEvent);
}
}
protected final void initListeners(SipApplicationListeners appListeners) {
if (appListeners != null) {
setSipSessionListeners(appListeners.getSipSessionListeners());
}
notifySessionCreated();
}
protected void setSipSessionListeners(
ArrayList<SipSessionListener> sipSessionListeners) {
this.sessionListeners = sipSessionListeners;
}
@Override
protected synchronized ArrayList<SipSessionListener> getSipSessionListeners() {
if (sessionListeners == null) {
SipSessionManager ssm = getPFieldSipSessionManagerField();
if (ssm != null) {
sessionListeners = ssm.getContext()
.getSipApplicationListeners()
.getSipSessionListeners();
}
if (sessionListeners == null) {
logger.log(Level.WARNING, "SipSessionListener list not found");
}
}
return sessionListeners;
}
public int getCSeq() {
return getPFieldCSeq();
}
@Override
protected Object getFromPFieldSessionAttribute(String name) {
return getSessionAttributeMap(false).get(name);
}
@Override
protected void addToPFieldSessionAttribute(String name, Object value) {
Object oldValue = getSessionAttributeMap(true).put(name, value);
if(oldValue==null){
// No old value => the attribute was added
attributeAdded(name,value);
}
else {
// An old value
if(oldValue!=value){
// Call replaced only if it is a different value.
attributeReplaced(name,oldValue,value);
}
}
}
@Override
protected Collection<String> getFromPFieldSessionAttributeNames() {
return getSessionAttributeMap(false).keySet();
}
@Override
protected void removeFromPFieldSessionAttribute(String name) {
Object removedAttribute = getSessionAttributeMap(false).remove(name);
if (removedAttribute != null) {
// Call attributeRemoved on listeners ONLY if an attribute actually
// has been removed
attributeRemoved(name, removedAttribute);
}
}
/**
* 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(SipSessionBindingEvent event,
SipSessionAttributeListener listener);
static final AttributeCallback ADDED = new AttributeCallback() {
public void call(SipSessionBindingEvent event,
SipSessionAttributeListener listener) {
listener.attributeAdded(event);
}
};
static final AttributeCallback REPLACED = new AttributeCallback() {
public void call(SipSessionBindingEvent event,
SipSessionAttributeListener listener) {
listener.attributeReplaced(event);
}
};
static final AttributeCallback REMOVED = new AttributeCallback() {
public void call(SipSessionBindingEvent event,
SipSessionAttributeListener listener) {
listener.attributeRemoved(event);
}
};
}
/**
* 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<SipSessionAttributeListener> sipSessionAttributeListeners = getApplicationSessionImpl()
.getSipApplicationListeners().getSipSessionAttributeListeners();
// If there are at least one, create event and call all of them.
if (sipSessionAttributeListeners != null
&& !sipSessionAttributeListeners.isEmpty()) {
SipSessionBindingEvent event = new SipSessionBindingEvent(this,
attributeName);
for (SipSessionAttributeListener listener : sipSessionAttributeListeners) {
callback.call(event, listener);
}
}
}
/**
* Called when an attribute is added
*
* @param name
*/
private void attributeAdded(String name,Object addedObject) {
callAttributeListeners(AttributeCallback.ADDED, name);
if(addedObject instanceof SipSessionBindingListener){
((SipSessionBindingListener)addedObject).valueBound(new SipSessionBindingEvent(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 SipSessionBindingListener){
((SipSessionBindingListener)oldValue).valueUnbound(new SipSessionBindingEvent(this,name));
}
if(newValue instanceof SipSessionBindingListener){
((SipSessionBindingListener)newValue).valueBound(new SipSessionBindingEvent(this,name));
}
}
/**
* Called when an attribute is removed
*
* @param name
*/
private void attributeRemoved(String name, Object removedValue) {
callAttributeListeners(AttributeCallback.REMOVED, name);
if(removedValue instanceof SipSessionBindingListener){
((SipSessionBindingListener)removedValue).valueUnbound(new SipSessionBindingEvent(this,name));
}
}
/**
* Notify all SipSessionBindingListeners that are values that this
* the binding to this SipSession is due.
*/
@Override
protected void notifyAttributesUnbound() {
if(sessionAttributeMap!=null){
Set<Entry<String, Object>> entries = sessionAttributeMap.entrySet();
for(Entry<String, Object> entry : entries){
Object value = entry.getValue();
if(value instanceof SipSessionBindingListener){
((SipSessionBindingListener)value).valueUnbound(new SipSessionBindingEvent(this,entry.getKey()));
}
}
}
}
private Map<String, Object> getSessionAttributeMap(boolean create) {
if (sessionAttributeMap == null) {
if (create) {
sessionAttributeMap = new HashMap<String, Object>(8);
} else {
return Collections.emptyMap();
}
}
return sessionAttributeMap;
}
@Override
protected boolean getPField1xxReliableOngoing() {
return is1xxReliableOngoing;
}
@Override
protected boolean getPField1xxReliableSDP() {
return is1xxReliableSDP;
}
@Override
protected int incrementAndGetPFieldCSeq() {
return cSeq.incrementAndGet();
}
@Override
protected boolean hasPFieldCSeq() {
return cSeq != null;
}
@Override
protected void createPFieldCSeq() {
cSeq = new AtomicInteger(SipFactoryImpl.START_CSEQ);
}
// also give subclasses access cseq
protected void setPFieldCSeq(int aCseq) {
cSeq = new AtomicInteger(aCseq);
}
public int getPFieldCSeq() {
if (cSeq == null) {
return -1;
}
return cSeq.get();
}
@Override
protected long getPFieldCreationDate() {
return creationDate;
}
@Override
protected boolean getPFieldDerived() {
return isDerived;
}
@Override
public String getPFieldDialogFragmentId() {
return dialogFragmentId;
}
@Override
protected String getPFieldHandler() {
return handler;
}
@Override
protected String getPFieldId() {
return id;
}
@Override
protected long getPFieldLastAccessedTime() {
return lastAccessedTime;
}
@Override
protected long getPFieldCurrentAccessedTime() {
return currentAccessedTime;
}
@Override
protected String getPFieldLinkedSipSessionId() {
return linkedSipSessionId;
}
@Override
protected String getPFieldCorrespondingSipSessionId(String header) {
if (header.equals(Header.JOIN)) {
return correspondingJoin;
} else {
return correspondingReplaces;
}
}
@Override
protected SipApplicationRoutingRegion getPFieldRoutingRegion() {
return routingRegion;
}
@Override
protected URI getPFieldRemoteTarget() {
return remoteTarget;
}
@Override
protected synchronized SipApplicationSessionImpl getPFieldSipApplicationSession() {
if (sipApplicationSession == null) {
try {
SipSessionManager ssm = getPFieldSipSessionManagerField();
if(ssm != null) {
sipApplicationSession = (SipApplicationSessionImpl) ssm.findSipApplicationSession(sasId);
}
} catch (RemoteLockException e) {
throw new RemoteLockRuntimeException(e);
}
}
return sipApplicationSession;
}
/**
* sipSessionManager will be null after deserializing the SS object
* back from the ObjectInputStream. So, the deserializer must explicitly
* set the sipSessionManager after deserialization, which means that the
* serialization/deserialization of the SS object should only be done in a
* context using the appropriate SipStore interfaces.
*
* @return the sip session manager.
*/
@Override
protected SipSessionManager getPFieldSipSessionManagerField() {
return sipSessionManager;
}
/**
* The sipSessionManager must be explicitly set by the deserializer after
* deserializing the SS object back from the ObjectInputStream.
*
* @see org.jvnet.glassfish.comms.replication.sessmgmt.SipSessionStoreImpl
*
* @param manager sip session mananger.
*/
public void setSipSessionManager(SipSessionManager manager) {
this.sipSessionManager = manager;
}
@Override
protected State getPFieldSessionState() {
return sessionState;
}
@Override
protected URI getPFieldSubscriberURI() {
return subscriberURI;
}
@Override
protected boolean getPFieldSwapLocalRemote() {
return swapLocalRemote;
}
@Override
protected Address getPFieldTo() {
return to;
}
@Override
protected Type getPFieldType() {
return type;
}
@Override
protected boolean getPFieldUpdateOngoing() {
return updateOngoing;
}
@Override
protected void setPField1xxReliableOngoing(boolean is1xxReliableOngoing) {
this.is1xxReliableOngoing = is1xxReliableOngoing;
}
@Override
protected void setPField1xxReliableSDP(boolean is1xxReliableSDP) {
this.is1xxReliableSDP = is1xxReliableSDP;
}
@Override
protected void setPFieldDerived(boolean isDerived) {
this.isDerived = isDerived;
}
@Override
protected void setPFieldDialogFragmentId(String dialogFragmentId) {
this.dialogFragmentId = dialogFragmentId;
}
@Override
protected void setPFieldHandler(String handler) {
this.handler = handler;
}
@Override
protected void setPFieldLinkedSipSessionId(String linkedSipSessionId) {
this.linkedSipSessionId = linkedSipSessionId;
}
@Override
protected void setPFieldCorrespondingSipSessionId(String id, String header) {
if (header.equals(Header.JOIN)) {
this.correspondingJoin = id;
} else {
this.correspondingReplaces = id;
}
}
@Override
protected void setPFieldRemoteTarget(URI remoteContact) {
this.remoteTarget = remoteContact;
}
@Override
protected void setPFieldRoutingRegion(SipApplicationRoutingRegion routingRegion) {
this.routingRegion = routingRegion;
}
@Override
protected synchronized void setPFieldSipApplicationSession(
SipApplicationSessionImpl sipApplicationSession) {
this.sipApplicationSession = (SipApplicationSessionImpl) sipApplicationSession;
}
@Override
protected void setPFieldSessionState(State state) {
this.sessionState = state;
}
@Override
protected void setPFieldSubscriberURI(URI subscriberURI) {
this.subscriberURI = subscriberURI;
}
@Override
protected void setPFieldSwapLocalRemote(boolean swapLocalRemote) {
this.swapLocalRemote = swapLocalRemote;
}
@Override
protected void setPFieldTo(Address to) {
this.to = to;
}
@Override
protected void setPFieldType(Type type) {
this.type = type;
}
@Override
protected void setPFieldUpdateOngoing(boolean updateOngoing) {
this.updateOngoing = updateOngoing;
}
@Override
protected void setPFieldLastAccessedTime(long lastAccessedTime) {
this.lastAccessedTime = lastAccessedTime;
}
@Override
protected void setPFieldCurrentAccessedTime(long currentAccessedTime) {
this.currentAccessedTime = currentAccessedTime;
}
@Override
protected long getPFieldExpirationTime() {
return expirationTime;
}
@Override
protected void setPFieldExpirationTime(long expTime) {
expirationTime = expTime;
}
public void setShouldBePersisted() {
sipApplicationSession.setSipSessionShouldBePersisted(this);
shouldBePersisted = true;
}
public boolean shouldBePersisted() {
SipSessionManager manager = getSipSessionManager();
if (manager != null && manager.isBeingReleased()) {
return false;
}
return shouldBePersisted;
}
/**
* @serialData See serialized form version 1 in #readExternal(ObjectInput in)
*
* @param oos the stream to write the object members
* @throws IOException
*/
public void writeExternal(ObjectOutput out) throws IOException {
out.writeShort(serializedFormVersion);
super.writeExternal(out);
// FIXME check that we are in confirmed state, otherwise throw IllegalStateException
out.writeObject(sasId);
// Serialize session attributes
IOUtil.writeSessionAttributes(getSessionAttributeMap(false), out);
out.writeObject(handler);
out.writeObject(type);
out.writeObject(getIdForSerial());
out.writeObject(to);
out.writeLong(creationDate);
out.writeLong(expirationTime); // possibly overridden by extraparams
out.writeLong(lastAccessedTime);
out.writeLong(currentAccessedTime);
out.writeObject(dialogFragmentId);
out.writeBoolean(isDerived);
out.writeBoolean(swapLocalRemote);
if (cSeq != null) {
out.writeInt(cSeq.get());
} else {
out.writeInt(-1); // Indicate null cSeq
}
out.writeObject(remoteTarget);
// JSR289
out.writeObject(subscriberURI);
out.writeObject(routingRegion);
out.writeObject(linkedSipSessionId);
out.writeObject(correspondingJoin);
out.writeObject(correspondingReplaces);
out.writeObject(sessionState);
}
/**
* @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>Externalizable</b> and represents superclass externalized data</li>
* <li>field is a <b>String</b> and represents application id</li>
* <li>field is a <b>String</b> and represents sip application session id</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>
* <li>field is a <b>String</b> and represents the name of the servlet handler</li>
*
* <li>field is a <b>Type</b> and represents the Type</li>
* <li>field is a <b>String</b> and represents session id</li>
* <li>field is a <b>javax.servlet.sip.Address</b> and represents the to field</li>
* <li>field is a <b>Long</b> and represents the creation date of session</li>
* <li>field is a <b>Long</b> and represents the expirationTime field as absolute time</li>
* <li>field is a <b>Long</b> and represents the lastAccessedTime field as absolute time</li>
* <li>field is a <b>Long</b> and represents the currentAccessedTime field as absolute time</li>
* <li>field is a <b>String</b> and represents the dialogFragmentId</li>
* <li>field is a <b>Boolean</b> and represents the isDerived field</li>
* <li>field is a <b>Boolean</b> and represents the swapLocalRemote field</li>
* <li>field is a <b>Integer</b> and represents the cseq field</li>
* <li>field is a <b>javax.servlet.sip.URI</b> and represents the remote target</li>
* <li>field is a <b>javax.servlet.sip.URI</b> and represents the suscriber URI</li>
* <li>field is a <b>String</b> and represents the routing region</li>
* <li>field is a <b>String</b> and represents the linkedSipSessionId</li>
* <li>field is a <b>String</b> and represents the corresponding join id.</li>
* <li>field is a <b>String</b> and represents the corresponding replace id.</li>
* <li>field is a <b>javax.servlet.sip.SipSession.State</b> and represents the sessionState</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);
// Read the appid, and use it to get the corresponding
// SipSessionManager and associated context.
sasId = (String) in.readObject();
// Deserialize session attributes
sessionAttributeMap = IOUtil.readSessionAttributes(in);
handler = (String) in.readObject();
type = (Type) in.readObject();
id = (String) in.readObject();
to = (Address) in.readObject();
creationDate = in.readLong();
expirationTime = in.readLong();
lastAccessedTime = in.readLong();
currentAccessedTime = in.readLong();
dialogFragmentId = (String) in.readObject();
isDerived = in.readBoolean();
swapLocalRemote = in.readBoolean();
int cseqInt = in.readInt();
if (cseqInt > -1) {
// OK cSeq was not null at writeObject()
cSeq = new AtomicInteger(cseqInt);
}
remoteTarget = (URI) in.readObject();
// JSR289
subscriberURI = (URI) in.readObject();
routingRegion = (SipApplicationRoutingRegion) in.readObject();
linkedSipSessionId = (String) in.readObject();
correspondingJoin = (String) in.readObject();
correspondingReplaces = (String) in.readObject();
sessionState = (State) in.readObject();
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 SipSession.
*/
public boolean activate() {
// Add to active cache
SipSessionManager mgr = getSipSessionManager();
if (mgr != null) {
SipSession ss = mgr.addSipSession(this);
if (ss != null) {
// While this thread has been in the process of loading the
// requested SipSession, and is now trying to activate it,
// another thread has also loaded the same SipSession, and
// has already added it to the active cache. Abort activation.
return true;
}
}
notifySessionDidActivate();
return true;
}
/**
* Passivates this SipSession.
*/
public void passivate() {
notifySessionWillPassivate();
// Remove from active cache
SipSessionManager mgr = getSipSessionManager();
if (mgr != null) {
mgr.removeSipSession(this);
}
}
public String toString() {
return SS_DESCRIPTION + getApplicationId() + ":" + id;
}
/**
* Gets the application session from the local cache only. If it is not found in the local cache null is returned.
* @return
*/
public SipApplicationSessionImpl getApplicationSessionLocally() {
try {
return sipSessionManager.findSipApplicationSession(sasId);
} catch (RemoteLockException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, "This can never happen: SipApplicationSession was remotely locked: " + sasId);
}
return null;
}
}
/*
* Returns the application id of this SipSession.
*
* @return the application id of this SipSession
*/
public String getApplicationId() {
return sipSessionManager != null
? sipSessionManager.getApplicationId() : null;
}
}