/* * JBoss, Home of Professional Open Source * Copyright 2008, Red Hat Middleware LLC, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.web.tomcat.service.session.distributedcache.impl.jbc; import java.text.ParseException; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.apache.catalina.Context; import org.jboss.cache.Fqn; import org.jboss.cache.Node; import org.jboss.cache.pojo.impl.InternalConstant; import org.jboss.logging.Logger; import org.jboss.web.tomcat.service.session.ClusteredManager; import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributableSipApplicationSessionMetadata; import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributableSipSessionMetadata; import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheConvergedSipManager; import org.jboss.web.tomcat.service.session.distributedcache.spi.IncomingDistributableSessionData; import org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager; import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData; import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSipApplicationSessionData; import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSipSessionData; import org.mobicents.servlet.sip.core.session.SessionManagerUtil; import org.mobicents.servlet.sip.core.session.SipApplicationSessionKey; import org.mobicents.servlet.sip.core.session.SipSessionKey; import org.mobicents.servlet.sip.startup.SipContext; /** * @author jean.deruelle@gmail.com * */ public class DistributedCacheConvergedSipManagerDelegate<T extends OutgoingDistributableSessionData> { protected Logger log_ = Logger.getLogger(getClass()); public static final String SIPSESSION = "SIPSESSION"; protected String sipApplicationName; private SipCacheListener sipCacheListener_; private SipPassivationListener sipPassivationListener_; AbstractJBossCacheService<OutgoingDistributableSessionData> jBossCacheService; LocalDistributableSessionManager manager; public DistributedCacheConvergedSipManagerDelegate(AbstractJBossCacheService<OutgoingDistributableSessionData> jBossCacheService, LocalDistributableSessionManager localManager) { this.jBossCacheService = jBossCacheService; manager = localManager; } public void start() { Context webapp = (Context) ((ClusteredManager<OutgoingDistributableSessionData>) manager).getContainer(); if (webapp instanceof SipContext) { SipContext sipApp = (SipContext) webapp; // As per JSR 289, application name should be unique sipApplicationName = sipApp.getApplicationName(); sipCacheListener_ = new SipCacheListener( jBossCacheService.cacheWrapper_, manager, jBossCacheService.combinedPath_, Util.getReplicationGranularity(manager), sipApplicationName); jBossCacheService.getCache().addCacheListener(sipCacheListener_); if (manager.isPassivationEnabled()) { log_.debug("Passivation is enabled"); sipPassivationListener_ = new SipPassivationListener( manager, jBossCacheService.combinedPath_, sipApplicationName); jBossCacheService.getCache().addCacheListener( sipPassivationListener_); } } } public void stop() { //FIXME : this is a hack to remove exception on shutdown, when releasing the cache to the manager jBossCacheService.cacheConfigName_ = null; if (sipCacheListener_ != null) { jBossCacheService.getCache().removeCacheListener(sipCacheListener_); if (sipPassivationListener_ != null) { jBossCacheService.getCache().removeCacheListener( sipPassivationListener_); } } } public void evictSession(SipApplicationSessionKey sipAppSessionKey, SipSessionKey key) { evictSession(sipAppSessionKey, key, null); } public void evictSession(SipApplicationSessionKey key) { evictSession(key, (String)null); } public void evictSession(SipApplicationSessionKey sipAppSessionKey, SipSessionKey key, String dataOwner) { Fqn<String> fqn = dataOwner == null ? getSipSessionFqn(jBossCacheService.combinedPath_, sipAppSessionKey.toString(), key.toString()) : getBuddyBackupSipSessionFqn(dataOwner, jBossCacheService.combinedPath_, sipAppSessionKey.toString(), key.toString()); if (log_.isTraceEnabled()) { log_ .trace("evictSession(): evicting session from my distributed store. Fqn: " + fqn); } jBossCacheService.cacheWrapper_.evictSubtree(fqn); } public void evictSession(SipApplicationSessionKey key, String dataOwner) { Fqn<String> fqn = dataOwner == null ? getSipApplicationSessionFqn(jBossCacheService.combinedPath_, key.toString()) : getBuddyBackupSipApplicationSessionFqn(dataOwner, jBossCacheService.combinedPath_, key.toString()); if (log_.isTraceEnabled()) { log_ .trace("evictSession(): evicting session from my distributed store. Fqn: " + fqn); } jBossCacheService.cacheWrapper_.evictSubtree(fqn); } public IncomingDistributableSessionData getSessionData(SipApplicationSessionKey sipAppSessionKey, SipSessionKey key, boolean initialLoad) { if (key == null) { throw new IllegalArgumentException("Null key"); } Fqn<String> fqn = getSipSessionFqn(jBossCacheService.combinedPath_, sipAppSessionKey.toString(), key.toString()); Map<Object, Object> sessionData = jBossCacheService.cacheWrapper_.getData(fqn, true); if (sessionData == null) { // Requested session is no longer in the cache; return null return null; } if (initialLoad) { jBossCacheService.setupSessionRegion(fqn); } IncomingDistributableSessionData dsd = null; try { dsd = jBossCacheService.getDistributableSessionData(key.toString(), sessionData, true); } catch (Exception e) { log_.warn("Problem accessing session data : " + e.getClass() + " " + e.getLocalizedMessage()); // Clean up removeSessionLocal(sipAppSessionKey, key); return null; } return dsd; } public IncomingDistributableSessionData getSessionData(SipApplicationSessionKey sipAppSessionKey, SipSessionKey key, String dataOwner, boolean includeAttributes) { Fqn<String> fqn = dataOwner == null ? getSipSessionFqn(jBossCacheService.combinedPath_, sipAppSessionKey.toString(), key.toString()) : getBuddyBackupSipSessionFqn(dataOwner, jBossCacheService.combinedPath_, sipAppSessionKey.toString(), key.toString()); Map<Object, Object> distributedCacheData = jBossCacheService.cacheWrapper_.getData(fqn, false); return jBossCacheService.getDistributableSessionData(key.toString(), distributedCacheData, includeAttributes); } public IncomingDistributableSessionData getSessionData( SipApplicationSessionKey key, boolean initialLoad) { if (key == null) { throw new IllegalArgumentException("Null key"); } Fqn<String> fqn = getSipApplicationSessionFqn(jBossCacheService.combinedPath_, key.toString()); Map<Object, Object> sessionData = jBossCacheService.cacheWrapper_.getData(fqn, true); if (sessionData == null) { // Requested session is no longer in the cache; return null return null; } if (initialLoad) { jBossCacheService.setupSessionRegion(fqn); } IncomingDistributableSessionData dsd = null; try { dsd = jBossCacheService.getDistributableSessionData(key.toString(), sessionData, true); } catch (Exception e) { log_.warn("Problem accessing session data : " + e.getClass() + " " + e.getLocalizedMessage()); // Clean up removeSessionLocal(key); return null; } return dsd; } public IncomingDistributableSessionData getSessionData( SipApplicationSessionKey key, String dataOwner, boolean includeAttributes) { Fqn<String> fqn = dataOwner == null ? getSipApplicationSessionFqn(jBossCacheService.combinedPath_, key.toString()) : getBuddyBackupSipApplicationSessionFqn(dataOwner, jBossCacheService.combinedPath_, key.toString()); Map<Object, Object> distributedCacheData = jBossCacheService.cacheWrapper_.getData(fqn, false); return jBossCacheService.getDistributableSessionData(key.toString(), distributedCacheData, includeAttributes); } public Map<SipApplicationSessionKey, String> getSipApplicationSessionKeys() { Map<SipApplicationSessionKey, String> result = new HashMap<SipApplicationSessionKey, String>(); Fqn<String> sipappFqn = getSipappFqn(); Node<Object, Object> bbRoot = jBossCacheService.getCache().getRoot() .getChild(jBossCacheService.BUDDY_BACKUP_FQN); if (bbRoot != null) { Set<Node<Object, Object>> owners = bbRoot.getChildren(); if (owners != null) { for (Node<Object, Object> owner : owners) { @SuppressWarnings("unchecked") Node sipRoot = owner.getChild(sipappFqn); if (sipRoot != null) { @SuppressWarnings("unchecked") Set<String> ids = sipRoot.getChildrenNames(); storeSipApplicationSessionOwners(ids, (String) owner.getFqn() .getLastElement(), result); } } } } storeSipApplicationSessionOwners(jBossCacheService.getChildrenNames(sipappFqn), null, result); return result; } protected Fqn<String> getSipappFqn() { // /SIPSESSION/sipAppPath_hostName String[] objs = new String[] { SIPSESSION, jBossCacheService.combinedPath_ }; return Fqn.fromList(Arrays.asList(objs), true); } private void storeSipSessionOwners(Set<String> ids, String owner, Map<SipSessionKey, String> map) { if (ids != null) { for (String id : ids) { if (!InternalConstant.JBOSS_INTERNAL_STRING.equals(id)) { SipSessionKey key = null; try { key = SessionManagerUtil.parseSipSessionKey(id); } catch (ParseException e) { //should never happen log_.error("An unexpected exception happened on parsing the following sip session key " + id, e); return; } map.put(key, owner); } } } } private void storeSipApplicationSessionOwners(Set<String> ids, String owner, Map<SipApplicationSessionKey, String> map) { if (ids != null) { for (String id : ids) { if (!InternalConstant.JBOSS_INTERNAL_STRING.equals(id)) { SipApplicationSessionKey key = null; try { key = SessionManagerUtil.parseSipApplicationSessionKey(id); } catch (ParseException e) { //should never happen log_.error("An unexpected exception happened on parsing the following sip application session key " + id, e); return; } map.put(key, owner); } } } } public Map<SipSessionKey, String> getSipSessionKeys() { Map<SipSessionKey, String> result = new HashMap<SipSessionKey, String>(); Fqn<String> sipappFqn = getSipappFqn(); Node<Object, Object> bbRoot = jBossCacheService.getCache().getRoot() .getChild(jBossCacheService.BUDDY_BACKUP_FQN); if (bbRoot != null) { Set<Node<Object, Object>> owners = bbRoot.getChildren(); if (owners != null) { for (Node<Object, Object> owner : owners) { @SuppressWarnings("unchecked") Node sipRoot = owner.getChild(sipappFqn); if (sipRoot != null) { @SuppressWarnings("unchecked") Set<String> ids = sipRoot.getChildrenNames(); storeSipSessionOwners(ids, (String) owner.getFqn() .getLastElement(), result); } } } } storeSipSessionOwners(jBossCacheService.getChildrenNames(sipappFqn), null, result); return result; } public void removeSessionLocal(SipApplicationSessionKey key) { Fqn<String> fqn = getSipApplicationSessionFqn( jBossCacheService.combinedPath_, key.toString()); if (log_.isTraceEnabled()) { log_ .trace("Remove session from my own distributed store only. Fqn: " + fqn); } jBossCacheService.cacheWrapper_.removeLocal(fqn); jBossCacheService.removeSessionRegion(key.toString(), fqn); } public void removeSessionLocal(SipApplicationSessionKey sipAppSessionKey, SipSessionKey key) { Fqn<String> fqn = getSipSessionFqn( jBossCacheService.combinedPath_, sipAppSessionKey.toString(), key.toString()); if (log_.isTraceEnabled()) { log_ .trace("Remove session from my own distributed store only. Fqn: " + fqn); } jBossCacheService.cacheWrapper_.removeLocal(fqn); jBossCacheService.removeSessionRegion(key.toString(), fqn); } public void removeSessionLocal(SipApplicationSessionKey key, String dataOwner) { if (dataOwner == null) { removeSessionLocal(key); } else { Fqn<String> fqn = getBuddyBackupSipApplicationSessionFqn(dataOwner, jBossCacheService.combinedPath_, key.toString()); if (log_.isTraceEnabled()) { log_ .trace("Remove session from my own distributed store only. Fqn: " + fqn); } jBossCacheService.cacheWrapper_.removeLocal(fqn); } } public void removeSessionLocal(SipApplicationSessionKey sipAppSessionKey, SipSessionKey key, String dataOwner) { if (dataOwner == null) { removeSessionLocal(sipAppSessionKey, key); } else { Fqn<String> fqn = getBuddyBackupSipSessionFqn(dataOwner, jBossCacheService.combinedPath_, sipAppSessionKey.toString(), key.toString()); if (log_.isTraceEnabled()) { log_ .trace("Remove session from my own distributed store only. Fqn: " + fqn); } jBossCacheService.cacheWrapper_.removeLocal(fqn); } } public Fqn<String> getSipSessionFqn(String contextHostPath, String appSessionId, String sessionId) { // /SIPSESSION/contextHostPath/sipApplicationName/id/sessionId String[] objs = new String[] { SIPSESSION, contextHostPath, sipApplicationName, appSessionId, sessionId }; return Fqn.fromList(Arrays.asList(objs), true); } public Fqn<String> getSipApplicationSessionFqn(String contextHostPath, String sessionId) { // /SIPSESSION/contextHostPath/sipApplicationName/id String[] objs = new String[] { SIPSESSION, contextHostPath, sipApplicationName, sessionId }; return Fqn.fromList(Arrays.asList(objs), true); } public Fqn<String> getBuddyBackupSipSessionFqn(String dataOwner, String contextHostPath, String appSessionId, String sessionId) { String[] objs = new String[] { jBossCacheService.BUDDY_BACKUP, dataOwner, SIPSESSION, contextHostPath, sipApplicationName, appSessionId, sessionId }; return Fqn.fromList(Arrays.asList(objs), true); } public Fqn<String> getBuddyBackupSipApplicationSessionFqn(String dataOwner, String contextHostPath, String sessionId) { String[] objs = new String[] { jBossCacheService.BUDDY_BACKUP, dataOwner, SIPSESSION, contextHostPath, sipApplicationName, sessionId }; return Fqn.fromList(Arrays.asList(objs), true); } public void storeSipApplicationSessionData(OutgoingDistributableSipApplicationSessionData sipApplicationSessionData) { String realId = sipApplicationSessionData.getRealId(); if (log_.isTraceEnabled()) { log_.trace("putSipSession(): putting sip session " + realId); } Fqn<String> fqn = getSipApplicationSessionFqn(jBossCacheService.combinedPath_, realId); Map<Object, Object> map = new HashMap<Object, Object>(); map.put(jBossCacheService.VERSION_KEY, Integer.valueOf(sipApplicationSessionData.getVersion())); DistributableSipApplicationSessionMetadata dsm = (DistributableSipApplicationSessionMetadata)sipApplicationSessionData.getMetadata(); if (dsm != null) { map.put(jBossCacheService.METADATA_KEY, dsm); } Long timestamp = sipApplicationSessionData.getTimestamp(); if (timestamp != null) { map.put(jBossCacheService.TIMESTAMP_KEY, timestamp); } ((DistributedCacheConvergedSipManager)jBossCacheService).storeSipApplicationSessionAttributes(map, sipApplicationSessionData); jBossCacheService.cacheWrapper_.put(fqn, map); } public void storeSipSessionData( OutgoingDistributableSipSessionData sipSessionData) { SipApplicationSessionKey sipApplicationSessionKey = sipSessionData.getSipApplicationSessionKey(); SipSessionKey sessionKey = sipSessionData.getSipSessionKey(); if (log_.isTraceEnabled()) { log_.trace("putSipSession(): putting sip session " + sessionKey.toString()); } Fqn<String> fqn = getSipSessionFqn(jBossCacheService.combinedPath_, sipApplicationSessionKey.toString(), sessionKey.toString()); Map<Object, Object> map = new HashMap<Object, Object>(); map.put(jBossCacheService.VERSION_KEY, Integer.valueOf(sipSessionData.getVersion())); DistributableSipSessionMetadata dsm = (DistributableSipSessionMetadata)sipSessionData.getMetadata(); if (dsm != null) { map.put(jBossCacheService.METADATA_KEY, dsm); } Long timestamp = sipSessionData.getTimestamp(); if (timestamp != null) { map.put(jBossCacheService.TIMESTAMP_KEY, timestamp); } ((DistributedCacheConvergedSipManager)jBossCacheService).storeSipSessionAttributes(map, sipSessionData); jBossCacheService.cacheWrapper_.put(fqn, map); } }