/* * JBoss, Home of Professional Open Source. * Copyright 2006, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file 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; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.WeakHashMap; import javax.management.ObjectName; import javax.transaction.TransactionManager; import org.apache.catalina.Context; import org.jboss.aspects.patterns.observable.Observer; import org.jboss.aspects.patterns.observable.Subject; import org.jboss.cache.CacheException; import org.jboss.cache.Fqn; import org.jboss.cache.aop.PojoCacheMBean; import org.jboss.cache.buddyreplication.BuddyManager; import org.jboss.cache.transaction.BatchModeTransactionManager; import org.jboss.invocation.MarshalledValue; import org.jboss.invocation.MarshalledValueInputStream; import org.jboss.invocation.MarshalledValueOutputStream; import org.jboss.logging.Logger; import org.jboss.mx.util.MBeanProxyExt; import org.mobicents.servlet.sip.startup.SipContext; /** * Implementation of a converged wrapper jboss cache service. * * Based on JBossCacheService JBOSS AS 4.2.2 Tag * I was forced to copy over most of the code since some things that needed to be adapted * were private */ public class ConvergedJBossCacheService extends JBossCacheService { protected static Logger log_ = Logger.getLogger(ConvergedJBossCacheService.class); public static final String BUDDY_BACKUP = BuddyManager.BUDDY_BACKUP_SUBTREE; public static final Fqn BUDDY_BACKUP_FQN = BuddyManager.BUDDY_BACKUP_SUBTREE_FQN; public static final String SESSION = "JSESSION"; public static final String SIPSESSION = "SIPSESSION"; public static final String ATTRIBUTE = "ATTRIBUTE"; // Needed for cache invalidation public static final String VERSION_KEY = "VERSION"; static final String FQN_DELIMITER = "/"; private PojoCacheMBean proxy_; // name of webapp's virtual host(JBAS-2194). // Idea is host_name + web_app_path + session id is a unique combo. private String hostName_; // web app path (JBAS-1367 and JBAS-2194). // Idea is host_name + web_app_path + session id is a unique combo. private String webAppPath_; // Idea is host_name + sip_application_name + session id is a unique combo. private String sipApplicationName; private TransactionManager tm; private JBossCacheSipManager manager_; private CacheListener cacheListener_; private SipCacheListener sipCacheListener_; private JBossCacheWrapper cacheWrapper_; // Do we have to marshall attributes ourself or can we let // the TreeCache do it? private boolean useTreeCacheMarshalling_ = false; private WeakHashMap typeMap = new WeakHashMap(); /** * Creates a JMX proxy PojoCacheMBean for the given object name. * * @param objectName the object name * @return the proxy * @throws ClusteringNotSupportedException if there is a problem */ private static PojoCacheMBean getPojoCacheMBean(String objectName) throws ClusteringNotSupportedException { try { ObjectName cacheServiceName = new ObjectName(objectName); // Create Proxy-Object for this service return (PojoCacheMBean) MBeanProxyExt.create(PojoCacheMBean.class, cacheServiceName); } catch (Throwable t) { String str = "Could not access TreeCache service " + (objectName == null ? "<null>" : objectName) + " for Tomcat clustering"; log_.debug(str); throw new ClusteringNotSupportedException(str, t); } } public ConvergedJBossCacheService(PojoCacheMBean pojoCache) { super(pojoCache); this.proxy_ = pojoCache; cacheWrapper_ = new JBossCacheWrapper(proxy_); useTreeCacheMarshalling_ = proxy_.getUseRegionBasedMarshalling(); } public ConvergedJBossCacheService(String treeCacheObjectName) throws ClusteringNotSupportedException { this(getPojoCacheMBean(treeCacheObjectName)); } public void start(ClassLoader tcl, JBossCacheSipManager manager) { manager_ = manager; Context webapp = (Context) manager_.getContainer(); String path = webapp.getName(); if( path.length() == 0 || path.equals("/")) { // If this is root. webAppPath_ = "ROOT"; } else if ( path.startsWith("/") ) { webAppPath_ = path.substring(1); } else { webAppPath_ = path; } // JBAS-3941 -- context path can be multi-level, but we don't // want that turning into a multilevel Fqn, so escape it // Use '?' which is illegal in a context path webAppPath_ = webAppPath_.replace('/', '?'); log_.debug("Old and new web app path are: " +path + ", " +webAppPath_); String host = webapp.getParent().getName(); if( host == null || host.length() == 0) { hostName_ = "localhost"; }else { hostName_ = host; } log_.debug("Old and new virtual host name are: " + host + ", " + hostName_); // Listen for cache changes cacheListener_ = new CacheListener(cacheWrapper_, manager_, hostName_, webAppPath_); proxy_.addTreeCacheListener(cacheListener_); // register the tcl and bring over the state for the webapp Object[] objs = new Object[]{SESSION, hostName_, webAppPath_}; Fqn pathFqn = new Fqn( objs ); String fqnStr = pathFqn.toString(); try { if(useTreeCacheMarshalling_) { log_.debug("UseMarshalling is true. We will register the fqn: " + fqnStr + " with class loader" +tcl + " and activate the webapp's Region"); proxy_.registerClassLoader(fqnStr, tcl); proxy_.activateRegion(fqnStr); } } catch (Exception ex) { throw new RuntimeException("Can't register class loader", ex); } if(webapp instanceof SipContext) { SipContext sipApp = (SipContext) webapp; //As per JSR 289, application name should be unique sipApplicationName = sipApp.getApplicationName(); // Listen for cache changes sipCacheListener_ = new SipCacheListener(cacheWrapper_, manager_, hostName_, sipApplicationName); proxy_.addTreeCacheListener(sipCacheListener_); // register the tcl and bring over the state for the webapp Object[] sipObjs = new Object[]{SIPSESSION, hostName_, sipApplicationName}; Fqn sipPathFqn = new Fqn( sipObjs ); String sipFqnStr = sipPathFqn.toString(); log_.info("Adding jboss cache listener for sip application : " + sipApplicationName + " on following fqn : " + sipFqnStr); try { if(useTreeCacheMarshalling_) { log_.debug("UseMarshalling is true. We will register the fqn: " + sipFqnStr + " with class loader" +tcl + " and activate the sipapp's Region"); proxy_.registerClassLoader(sipFqnStr, tcl); proxy_.activateRegion(sipFqnStr); } } catch (Exception ex) { throw new RuntimeException("Can't register class loader", ex); } } // We require the cache tm to be BatchModeTransactionManager now. tm = proxy_.getTransactionManager(); if( ! (tm instanceof BatchModeTransactionManager) ) { throw new RuntimeException("JBossCacheService.start(): JBossCacheAop transaction manager is not type BatchModeTransactionManager." + " Please check the tc5-cluster-service.xml TransactionManagerClassLookup field."); } } public void stop() { proxy_.removeTreeCacheListener(cacheListener_); if(sipCacheListener_ != null) { proxy_.removeTreeCacheListener(sipCacheListener_); } // Construct the fqn Object[] objs = new Object[]{SESSION, hostName_, webAppPath_}; Fqn pathFqn = new Fqn( objs ); String fqnStr = pathFqn.toString(); if(useTreeCacheMarshalling_) { log_.debug("UseMarshalling is true. We will inactivate the fqn: " + fqnStr + " and un-register its classloader"); try { proxy_.inactivateRegion(fqnStr); proxy_.unregisterClassLoader(fqnStr); } catch (Exception e) { log_.error("Exception during inactivation of webapp region " + fqnStr + " or un-registration of its class loader", e); } } // remove session data cacheWrapper_.evictSubtree(pathFqn); if(sipApplicationName != null) { // Construct the fqn Object[] sipObjs = new Object[]{SIPSESSION, hostName_, sipApplicationName}; Fqn sipPathFqn = new Fqn( sipObjs ); String sipFqnStr = sipPathFqn.toString(); if(useTreeCacheMarshalling_) { log_.debug("UseMarshalling is true. We will inactivate the fqn: " + sipFqnStr + " and un-register its classloader"); try { proxy_.inactivateRegion(sipFqnStr); proxy_.unregisterClassLoader(sipFqnStr); } catch (Exception e) { log_.error("Exception during inactivation of sipapp region " + sipFqnStr + " or un-registration of its class loader", e); } } // remove session data cacheWrapper_.evictSubtree(pathFqn); } } /** * Get specfically the BatchModeTransactionManager. */ public TransactionManager getTransactionManager() { return tm; } /** * Gets whether TreeCache-based marshalling is available */ public boolean isMarshallingAvailable() { return useTreeCacheMarshalling_; } /** * Loads any serialized data in the cache into the given session * using its <code>readExternal</code> method. * * @return the session passed as <code>toLoad</code>, or * <code>null</code> if the cache had no data stored * under the given session id. */ public ClusteredSession loadSession(String realId, ClusteredSession toLoad) { if(log_.isDebugEnabled()) { log_.debug("loading session from the cache " + realId); } Fqn fqn = getSessionFqn(realId); Object sessionData = cacheWrapper_.get(fqn, realId, true); if (sessionData == null) { // Requested session is no longer in the cache; return null return null; } boolean firstLoad = (toLoad.getVersion() == 0); // if (useTreeCacheMarshalling_) // { // toLoad.update((ClusteredSession) sessionData); // } // else // { byte[] sessionBytes = (byte[]) sessionData; // Swap in/out the webapp classloader so we can deserialize // attributes whose classes are only available to the webapp ClassLoader prevTCL = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(manager_.getWebappClassLoader()); try { ByteArrayInputStream bais = new ByteArrayInputStream(sessionBytes); // Use MarshalledValueInputStream instead of superclass ObjectInputStream // or else there are problems finding classes with scoped loaders MarshalledValueInputStream input = new MarshalledValueInputStream(bais); toLoad.readExternal(input); input.close(); } catch (Exception e) { log_.error("loadSession(): id: " + realId + " exception occurred during deserialization", e); return null; } finally { Thread.currentThread().setContextClassLoader(prevTCL); } // } // The internal version of the serialized session may be less than the // real one due to not replicating metadata. If our listener hasn't // been keeping the outdatedVersion of the session up to date because // the session has never been loaded into the JBCManager cache, we // need to fix the version if (firstLoad) { Integer ver = (Integer) cacheWrapper_.get(fqn, VERSION_KEY); if (ver != null) toLoad.setVersion(ver.intValue()); } return toLoad; } /** * Loads any serialized data in the cache into the given session * using its <code>readExternal</code> method. * * @return the session passed as <code>toLoad</code>, or * <code>null</code> if the cache had no data stored * under the given session id. */ public Object getSipSessionData(String id, String realId) { if(log_.isDebugEnabled()) { log_.debug("getting sip session data from the cache " + id + " / " + realId); } Fqn fqn = getSipSessionFqn(id, realId); return cacheWrapper_.get(fqn, realId, true); } /** * Loads any serialized data in the cache into the given session * using its <code>readExternal</code> method. * * @return the session passed as <code>toLoad</code>, or * <code>null</code> if the cache had no data stored * under the given session id. */ public ClusteredSipSession loadSipSession(String id, ClusteredSipSession toLoad, Object sessionData) { String realId = toLoad.getId(); if(log_.isDebugEnabled()) { log_.debug("loading sip session from the cache " + id + " / " + realId); } boolean firstLoad = (toLoad.getVersion() == 0); // if (useTreeCacheMarshalling_) // { // toLoad.update((ClusteredSession) sessionData); // } // else // { byte[] sessionBytes = (byte[]) sessionData; // Swap in/out the webapp classloader so we can deserialize // attributes whose classes are only available to the webapp ClassLoader prevTCL = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(manager_.getWebappClassLoader()); try { ByteArrayInputStream bais = new ByteArrayInputStream(sessionBytes); // Use MarshalledValueInputStream instead of superclass ObjectInputStream // or else there are problems finding classes with scoped loaders MarshalledValueInputStream input = new MarshalledValueInputStream(bais); toLoad.readExternal(input); input.close(); } catch (Exception e) { log_.error("loadSession(): id: " + realId + " exception occurred during deserialization", e); return null; } finally { Thread.currentThread().setContextClassLoader(prevTCL); } // } // The internal version of the serialized session may be less than the // real one due to not replicating metadata. If our listener hasn't // been keeping the outdatedVersion of the session up to date because // the session has never been loaded into the JBCManager cache, we // need to fix the version if (firstLoad) { Fqn fqn = getSipSessionFqn(id, realId); Integer ver = (Integer) cacheWrapper_.get(fqn, VERSION_KEY); if (ver != null) toLoad.setVersion(ver.intValue()); } return toLoad; } /** * Loads any serialized data in the cache into the given session * using its <code>readExternal</code> method. * * @return the session passed as <code>toLoad</code>, or * <code>null</code> if the cache had no data stored * under the given session id. */ public Object getSipApplicationSessionData(String realId) { if(log_.isDebugEnabled()) { log_.debug("loading sip app session from the cache " + realId); } Fqn fqn = getSipApplicationSessionFqn(realId); return cacheWrapper_.get(fqn, realId, true); } /** * Loads any serialized data in the cache into the given session * using its <code>readExternal</code> method. * * @return the session passed as <code>toLoad</code>, or * <code>null</code> if the cache had no data stored * under the given session id. */ public ClusteredSipApplicationSession loadSipApplicationSession(ClusteredSipApplicationSession toLoad, Object sessionData) { boolean firstLoad = (toLoad.getVersion() == 0); // if (useTreeCacheMarshalling_) // { // toLoad.update((ClusteredSession) sessionData); // } // else // { byte[] sessionBytes = (byte[]) sessionData; // Swap in/out the webapp classloader so we can deserialize // attributes whose classes are only available to the webapp ClassLoader prevTCL = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(manager_.getWebappClassLoader()); try { ByteArrayInputStream bais = new ByteArrayInputStream(sessionBytes); // Use MarshalledValueInputStream instead of superclass ObjectInputStream // or else there are problems finding classes with scoped loaders MarshalledValueInputStream input = new MarshalledValueInputStream(bais); toLoad.readExternal(input); input.close(); } catch (Exception e) { log_.error("loadSession(): id: " + toLoad.getId() + " exception occurred during deserialization", e); return null; } finally { Thread.currentThread().setContextClassLoader(prevTCL); } // } // The internal version of the serialized session may be less than the // real one due to not replicating metadata. If our listener hasn't // been keeping the outdatedVersion of the session up to date because // the session has never been loaded into the JBCManager cache, we // need to fix the version if (firstLoad) { Fqn fqn = getSipApplicationSessionFqn(toLoad.getId()); Integer ver = (Integer) cacheWrapper_.get(fqn, VERSION_KEY); if (ver != null) toLoad.setVersion(ver.intValue()); } return toLoad; } public void putSession(String realId, ClusteredSession session) { Fqn fqn = getSessionFqn(realId); if (session.getReplicateSessionBody()) { Map map = new HashMap(); // if (useTreeCacheMarshalling_) // map.put(realId, session); // else map.put(realId, externalizeSession(session)); // Put in (VERSION_KEY, version) after the real put for cache invalidation map.put(VERSION_KEY, new Integer(session.getVersion())); cacheWrapper_.put(fqn, map); } else { // Invalidate the remote caches cacheWrapper_.put(fqn, VERSION_KEY, new Integer(session.getVersion())); } } public void putSipSession(String realId, ClusteredSipSession session) { Fqn fqn = getSipSessionFqn(session.getSipApplicationSession().getId(), realId); if (session.getReplicateSessionBody()) { Map map = new HashMap(); // if (useTreeCacheMarshalling_) // map.put(realId, session); // else map.put(realId, externalizeSipSession(session)); // Put in (VERSION_KEY, version) after the real put for cache invalidation map.put(VERSION_KEY, new Integer(session.getVersion())); cacheWrapper_.put(fqn, map); } else { // Invalidate the remote caches cacheWrapper_.put(fqn, VERSION_KEY, new Integer(session.getVersion())); } } public void putSipApplicationSession(String realId, ClusteredSipApplicationSession session) { Fqn fqn = getSipApplicationSessionFqn(realId); if (session.getReplicateSessionBody()) { Map map = new HashMap(); // if (useTreeCacheMarshalling_) // map.put(realId, session); // else map.put(realId, externalizeSipApplicationSession(session)); // Put in (VERSION_KEY, version) after the real put for cache invalidation map.put(VERSION_KEY, new Integer(session.getVersion())); cacheWrapper_.put(fqn, map); } else { // Invalidate the remote caches cacheWrapper_.put(fqn, VERSION_KEY, new Integer(session.getVersion())); } } public void removeSession(String realId) { Fqn fqn = getSessionFqn(realId); if (log_.isDebugEnabled()) { log_.debug("Remove session from distributed store. Fqn: " + fqn); } //Object obj = getUnMarshalledValue(cacheWrapper_.remove(fqn, realId)); cacheWrapper_.remove(fqn, realId); // This needs to go after object removal to support correct cache invalidation. // _remove(fqn, VERSION_KEY); // Let just remove the whole thing (including the fqn) cacheWrapper_.remove(fqn); //return obj; } public void removeSipSession(String sipApplicationSessionId, String realId) { Fqn fqn = getSipSessionFqn(sipApplicationSessionId, realId); if (log_.isDebugEnabled()) { log_.debug("Remove session from distributed store. Fqn: " + fqn); } //Object obj = getUnMarshalledValue(cacheWrapper_.remove(fqn, realId)); cacheWrapper_.remove(fqn, realId); // This needs to go after object removal to support correct cache invalidation. // _remove(fqn, VERSION_KEY); // Let just remove the whole thing (including the fqn) cacheWrapper_.remove(fqn); //return obj; } public void removeSipApplicationSession(String realId) { Fqn fqn = getSipApplicationSessionFqn(realId); if (log_.isDebugEnabled()) { log_.debug("Remove session from distributed store. Fqn: " + fqn); } //Object obj = getUnMarshalledValue(cacheWrapper_.remove(fqn, realId)); cacheWrapper_.remove(fqn, realId); // This needs to go after object removal to support correct cache invalidation. // _remove(fqn, VERSION_KEY); // Let just remove the whole thing (including the fqn) cacheWrapper_.remove(fqn); //return obj; } public void removeSessionLocal(String realId) { Fqn fqn = getSessionFqn(realId); if (log_.isDebugEnabled()) { log_.debug("Remove session from my own distributed store only. Fqn: " + fqn); } cacheWrapper_.evictSubtree(fqn); } public void removeSipSessionLocal(String id, String realId) { Fqn fqn = getSipSessionFqn(id, realId); if (log_.isDebugEnabled()) { log_.debug("Remove session from my own distributed store only. Fqn: " + fqn); } cacheWrapper_.evictSubtree(fqn); } public void removeSipApplicationSessionLocal(String realId) { Fqn fqn = getSipApplicationSessionFqn(realId); if (log_.isDebugEnabled()) { log_.debug("Remove session from my own distributed store only. Fqn: " + fqn); } cacheWrapper_.evictSubtree(fqn); } public void removeSessionLocal(String realId, String dataOwner) { if (dataOwner == null) { removeSessionLocal(realId); } else { Fqn fqn = getSessionFqn(realId, dataOwner); if (log_.isDebugEnabled()) { log_.debug("Remove session from my own distributed store only. Fqn: " + fqn); } cacheWrapper_.evictSubtree(fqn); } } public boolean exists(String realId) { Fqn fqn = getSessionFqn(realId); return proxy_.exists(fqn); } public Object getAttribute(String realId, String key) { Fqn fqn = getAttributeFqn(realId); return getUnMarshalledValue(cacheWrapper_.get(fqn, key)); } public Object getSipApplicationSessionAttribute(String realId, String key) { Fqn fqn = getSipApplicationSessionAttributeFqn(realId); return getUnMarshalledValue(cacheWrapper_.get(fqn, key)); } public Object getSipSessionAttribute(String id, String realId, String key) { Fqn fqn = getSipSessionAttributeFqn(id, realId); return getUnMarshalledValue(cacheWrapper_.get(fqn, key)); } public void putAttribute(String realId, String key, Object value) { Fqn fqn = getAttributeFqn(realId); cacheWrapper_.put(fqn, key, getMarshalledValue(value)); } public void putSipApplicationSessionAttribute(String realId, String key, Object value) { Fqn fqn = getSipApplicationSessionAttributeFqn(realId); cacheWrapper_.put(fqn, key, getMarshalledValue(value)); } public void putSipSessionAttribute(String id, String realId, String key, Object value) { Fqn fqn = getSipSessionAttributeFqn(id, realId); cacheWrapper_.put(fqn, key, getMarshalledValue(value)); } public void putAttribute(String realId, Map map) { // Duplicate the map with marshalled values Map marshalled = new HashMap(map.size()); Set entries = map.entrySet(); for (Iterator it = entries.iterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry) it.next(); marshalled.put(entry.getKey(), getMarshalledValue(entry.getValue())); } Fqn fqn = getAttributeFqn(realId); cacheWrapper_.put(fqn, marshalled); } public void putSipApplicationSessionAttribute(String realId, Map map) { // Duplicate the map with marshalled values Map marshalled = new HashMap(map.size()); Set entries = map.entrySet(); for (Iterator it = entries.iterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry) it.next(); marshalled.put(entry.getKey(), getMarshalledValue(entry.getValue())); } Fqn fqn = getSipApplicationSessionAttributeFqn(realId); cacheWrapper_.put(fqn, marshalled); } public void putSipSessionAttribute(String id, String realId, Map map) { // Duplicate the map with marshalled values Map marshalled = new HashMap(map.size()); Set entries = map.entrySet(); for (Iterator it = entries.iterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry) it.next(); marshalled.put(entry.getKey(), getMarshalledValue(entry.getValue())); } Fqn fqn = getSipSessionAttributeFqn(id, realId); cacheWrapper_.put(fqn, marshalled); } public void removeAttributes(String realId) { Fqn fqn = getAttributeFqn(realId); cacheWrapper_.remove(fqn); } public Object removeAttribute(String realId, String key) { Fqn fqn = getAttributeFqn(realId); if (log_.isTraceEnabled()) { log_.trace("Remove attribute from distributed store. Fqn: " + fqn + " key: " + key); } return getUnMarshalledValue(cacheWrapper_.remove(fqn, key)); } public Object removeSipApplicationSessionAttribute(String realId, String key) { Fqn fqn = getSipApplicationSessionAttributeFqn(realId); if (log_.isTraceEnabled()) { log_.trace("Remove attribute from distributed store. Fqn: " + fqn + " key: " + key); } return getUnMarshalledValue(cacheWrapper_.remove(fqn, key)); } public Object removeSipSessionAttribute(String id, String realId, String key) { Fqn fqn = getSipSessionAttributeFqn(id, realId); if (log_.isTraceEnabled()) { log_.trace("Remove attribute from distributed store. Fqn: " + fqn + " key: " + key); } return getUnMarshalledValue(cacheWrapper_.remove(fqn, key)); } public void removeAttributesLocal(String realId) { Fqn fqn = getAttributeFqn(realId); if (log_.isDebugEnabled()) { log_.debug("Remove attributes from my own distributed store only. Fqn: " + fqn); } cacheWrapper_.evict(fqn); } public void removeSipApplicationSessionAttributesLocal(String realId) { Fqn fqn = getSipApplicationSessionAttributeFqn(realId); if (log_.isDebugEnabled()) { log_.debug("Remove attributes from my own distributed store only. Fqn: " + fqn); } cacheWrapper_.evict(fqn); } public void removeSipSessionAttributesLocal(String id, String realId) { Fqn fqn = getSipSessionAttributeFqn(id, realId); if (log_.isDebugEnabled()) { log_.debug("Remove attributes from my own distributed store only. Fqn: " + fqn); } cacheWrapper_.evict(fqn); } /** * Obtain the keys associated with this fqn. Note that it is not the fqn children. * */ public Set getAttributeKeys(String realId) { Set keys = null; Fqn fqn = getAttributeFqn(realId); try { keys = proxy_.getKeys(fqn); } catch (CacheException e) { log_.error("getAttributeKeys(): Exception getting keys for session " + realId, e); } return keys; } /** * Return all attributes associated with this session id. * * @param realId the session id with any jvmRoute removed * @return the attributes, or any empty Map if none are found. */ public Map getAttributes(String realId) { if (realId == null || realId.length() == 0) return new HashMap(); Map map = new HashMap(); Set set = getAttributeKeys(realId); if(set != null) { for (Iterator it = set.iterator(); it.hasNext();) { String key = (String) it.next(); Object value = getAttribute(realId, key); map.put(key, value); } } return map; } /** * Return all attributes associated with this session id. * * @param realId the session id with any jvmRoute removed * @return the attributes, or any empty Map if none are found. */ public Map getSipApplicationSessionAttributes(String realId) { if (realId == null || realId.length() == 0) return new HashMap(); Map map = new HashMap(); Set set = getAttributeKeys(realId); if(set != null) { for (Iterator it = set.iterator(); it.hasNext();) { String key = (String) it.next(); Object value = getSipApplicationSessionAttribute(realId, key); map.put(key, value); } } return map; } /** * Return all attributes associated with this session id. * * @param realId the session id with any jvmRoute removed * @return the attributes, or any empty Map if none are found. */ public Map getSipSessionAttributes(String id, String realId) { if (realId == null || realId.length() == 0) return new HashMap(); Map map = new HashMap(); Set set = getAttributeKeys(realId); if(set != null) { for (Iterator it = set.iterator(); it.hasNext();) { String key = (String) it.next(); Object value = getSipSessionAttribute(id, realId, key); map.put(key, value); } } return map; } /** * Gets the ids of all sessions in the underlying cache. * * @return Set containing all of the session ids of sessions in the cache * (with any jvmRoute removed) or <code>null</code> if there * are no sessions in the cache. */ public Map getSessionIds() throws CacheException { Map result = new HashMap(); Set owners = proxy_.getChildrenNames(BUDDY_BACKUP_FQN); if (owners != null) { for (Iterator it = owners.iterator(); it.hasNext();) { Object owner = it.next(); Set ids = proxy_.getChildrenNames(getWebappFqn(owner)); storeSessionOwners(ids, owner, result); } } storeSessionOwners(proxy_.getChildrenNames(getWebappFqn()), null, result); return result; } /** * Gets the ids of all sessions in the underlying cache. * * @return Set containing all of the session ids of sessions in the cache * (with any jvmRoute removed) or <code>null</code> if there * are no sessions in the cache. */ public Map getSipSessionIds(Set sipApplicationSessionIds, Object owner) throws CacheException { Map result = new HashMap(); for (Object object : sipApplicationSessionIds) { Set ids = proxy_.getChildrenNames(getSipApplicationSessionFqn((String)object, (String)owner)); storeSessionOwners(ids, owner, result); } return result; } /** * Gets the ids of all sessions in the underlying cache. * * @return Set containing all of the session ids of sessions in the cache * (with any jvmRoute removed) or <code>null</code> if there * are no sessions in the cache. */ public Map getSipApplicationSessionIds() throws CacheException { Map result = new HashMap(); Set owners = proxy_.getChildrenNames(BUDDY_BACKUP_FQN); if (owners != null) { for (Iterator it = owners.iterator(); it.hasNext();) { Object owner = it.next(); Set ids = proxy_.getChildrenNames(getSipappFqn(owner)); storeSessionOwners(ids, owner, result); getSipSessionIds(ids, owner); } } storeSessionOwners(proxy_.getChildrenNames(getSipappFqn()), null, result); return result; } private void storeSessionOwners(Set ids, Object owner, Map map) { if (ids != null) { for (Iterator it = ids.iterator(); it.hasNext();) { map.put(it.next(), owner); } } } /** * store the pojo instance in the cache. Note that this is for the aop cache. * THe pojo needs to be "aspectized". * * @param realId the session id with any jvmRoute removed * @param key the attribute key * @param pojo */ public Object setPojo(String realId, String key, Object pojo) { if(log_.isTraceEnabled()) { log_.trace("setPojo(): session id: " + realId + " key: " + key + " object: " + pojo.toString()); } // Construct the fqn. Fqn fqn = getFieldFqn(realId, key); try { // Ignore any cache notifications that our own work generates ConvergedSessionReplicationContext.startCacheActivity(); return proxy_.putObject(fqn, pojo); } catch (CacheException e) { throw new RuntimeException("JBossCacheService: exception occurred in cache setPojo ... ", e); } finally { ConvergedSessionReplicationContext.finishCacheActivity(); } } /** * store the pojo instance in the cache. Note that this is for the aop cache. * THe pojo needs to be "aspectized". * * @param realId the session id with any jvmRoute removed * @param key the attribute key * @param pojo */ public Object setSipApplicationSessionPojo(String realId, String key, Object pojo) { if(log_.isTraceEnabled()) { log_.trace("setPojo(): sipa app session id: " + realId + " key: " + key + " object: " + pojo.toString()); } // Construct the fqn. Fqn fqn = getSipApplicationSessionFieldFqn(realId, key); try { // Ignore any cache notifications that our own work generates ConvergedSessionReplicationContext.startSipCacheActivity(); return proxy_.putObject(fqn, pojo); } catch (CacheException e) { throw new RuntimeException("JBossCacheService: exception occurred in cache setSipApplicationSessionPojo ... ", e); } finally { ConvergedSessionReplicationContext.finishSipCacheActivity(); } } /** * store the pojo instance in the cache. Note that this is for the aop cache. * THe pojo needs to be "aspectized". * * @param realId the session id with any jvmRoute removed * @param key the attribute key * @param pojo */ public Object setSipSessionPojo(String id, String realId, String key, Object pojo) { if(log_.isTraceEnabled()) { log_.trace("setPojo(): sip session id: " + realId + " key: " + key + " object: " + pojo.toString()); } // Construct the fqn. Fqn fqn = getSipSessionFieldFqn(id, realId, key); try { // Ignore any cache notifications that our own work generates ConvergedSessionReplicationContext.startSipCacheActivity(); return proxy_.putObject(fqn, pojo); } catch (CacheException e) { throw new RuntimeException("JBossCacheService: exception occurred in cache setSipSessionPojo ... ", e); } finally { ConvergedSessionReplicationContext.finishSipCacheActivity(); } } /** * Remove pojo from the underlying cache store. * @param realId the session id with any jvmRoute removed * @param key the attribute key * @return pojo that just removed. Null if there none. */ public Object removePojo(String realId, String key) { if(log_.isTraceEnabled()) { log_.trace("removePojo(): session id: " +realId + " key: " +key); } // Construct the fqn. Fqn fqn = getFieldFqn(realId, key); try { // Ignore any cache notifications that our own work generates ConvergedSessionReplicationContext.startCacheActivity(); return proxy_.removeObject(fqn); } catch (CacheException e) { throw new RuntimeException("JBossCacheService: exception occurred in cache removePojo ... ", e); } finally { ConvergedSessionReplicationContext.finishCacheActivity(); } } /** * Remove pojo from the underlying cache store. * @param realId the session id with any jvmRoute removed * @param key the attribute key * @return pojo that just removed. Null if there none. */ public Object removeSipApplicationSessionPojo(String realId, String key) { if(log_.isTraceEnabled()) { log_.trace("removePojo(): sip app session id: " +realId + " key: " +key); } // Construct the fqn. Fqn fqn = getSipApplicationSessionFieldFqn(realId, key); try { // Ignore any cache notifications that our own work generates ConvergedSessionReplicationContext.startSipCacheActivity(); return proxy_.removeObject(fqn); } catch (CacheException e) { throw new RuntimeException("JBossCacheService: exception occurred in cache removeSipApplicationSessionPojo ... ", e); } finally { ConvergedSessionReplicationContext.finishSipCacheActivity(); } } /** * Remove pojo from the underlying cache store. * @param realId the session id with any jvmRoute removed * @param key the attribute key * @return pojo that just removed. Null if there none. */ public Object removeSipSessionPojo(String id, String realId, String key) { if(log_.isTraceEnabled()) { log_.trace("removePojo(): sip session id: " +realId + " key: " +key); } // Construct the fqn. Fqn fqn = getSipSessionFieldFqn(id, realId, key); try { // Ignore any cache notifications that our own work generates ConvergedSessionReplicationContext.startSipCacheActivity(); return proxy_.removeObject(fqn); } catch (CacheException e) { throw new RuntimeException("JBossCacheService: exception occurred in cache removeSipSessionPojo ... ", e); } finally { ConvergedSessionReplicationContext.finishSipCacheActivity(); } } /** * Remove all the pojos from the underlying cache store locally * without replication. * * @param realId the session id with any jvmRoute removed */ public void removePojosLocal(String realId) { if(log_.isDebugEnabled()) { log_.debug("removePojoLocal(): session id: " +realId); } // Construct the fqn. Fqn fqn = getAttributeFqn(realId); try { // Ignore any cache notifications that our own work generates ConvergedSessionReplicationContext.startCacheActivity(); cacheWrapper_.evictSubtree(fqn); } finally { ConvergedSessionReplicationContext.finishCacheActivity(); } } /** * Remove all the pojos from the underlying cache store locally * without replication. * * @param realId the session id with any jvmRoute removed */ public void removeSipSessionPojosLocal(String id, String realId) { if(log_.isDebugEnabled()) { log_.debug("removeSipSessionPojosLocal(): session id: " +realId); } // Construct the fqn. Fqn fqn = getSipSessionAttributeFqn(id, realId); try { // Ignore any cache notifications that our own work generates ConvergedSessionReplicationContext.startSipCacheActivity(); cacheWrapper_.evictSubtree(fqn); } finally { ConvergedSessionReplicationContext.finishSipCacheActivity(); } } /** * Remove all the pojos from the underlying cache store locally * without replication. * * @param realId the session id with any jvmRoute removed */ public void removeSipApplicationSessionPojosLocal(String realId) { if(log_.isDebugEnabled()) { log_.debug("removeSipApplicationSessionPojosLocal(): session id: " +realId); } // Construct the fqn. Fqn fqn = getSipApplicationSessionAttributeFqn(realId); try { // Ignore any cache notifications that our own work generates ConvergedSessionReplicationContext.startSipCacheActivity(); cacheWrapper_.evictSubtree(fqn); } finally { ConvergedSessionReplicationContext.finishSipCacheActivity(); } } /** * Remove all the pojos from the underlying cache store locally * without replication. * * @param realId the session id with any jvmRoute removed */ public void removePojoLocal(String realId, String key) { if(log_.isTraceEnabled()) { log_.trace("removePojoLocal(): session id: " + realId + " key: " +key); } // Construct the fqn. Fqn fqn = getFieldFqn(realId, key); try { // Ignore any cache notifications that our own work generates ConvergedSessionReplicationContext.startCacheActivity(); cacheWrapper_.evictSubtree(fqn); } finally { ConvergedSessionReplicationContext.finishCacheActivity(); } } /** * Remove all the pojos from the underlying cache store locally * without replication. * * @param realId the session id with any jvmRoute removed */ public void removeSipApplicationSessionPojoLocal(String realId, String key) { if(log_.isTraceEnabled()) { log_.trace("removeSipApplicationPojoLocal(): sip app session id: " + realId + " key: " +key); } // Construct the fqn. Fqn fqn = getSipApplicationSessionFieldFqn(realId, key); try { // Ignore any cache notifications that our own work generates ConvergedSessionReplicationContext.startSipCacheActivity(); cacheWrapper_.evictSubtree(fqn); } finally { ConvergedSessionReplicationContext.finishSipCacheActivity(); } } /** * Remove all the pojos from the underlying cache store locally * without replication. * * @param realId the session id with any jvmRoute removed */ public void removeSipSessionPojoLocal(String id, String realId, String key) { if(log_.isTraceEnabled()) { log_.trace("removeSipSessionPojoLocal(): sip session id: " + realId + " key: " +key); } // Construct the fqn. Fqn fqn = getSipSessionFieldFqn(id, realId, key); try { // Ignore any cache notifications that our own work generates ConvergedSessionReplicationContext.startSipCacheActivity(); cacheWrapper_.evictSubtree(fqn); } finally { ConvergedSessionReplicationContext.finishSipCacheActivity(); } } public Set getPojoKeys(String realId) { Set keys = null; Fqn fqn = getAttributeFqn(realId); try { keys = proxy_.getChildrenNames(fqn); } catch (CacheException e) { log_.error("getPojoKeys(): Exception getting keys for session " + realId, e); } return keys; } public Set getSipApplicationSessionPojoKeys(String realId) { Set keys = null; Fqn fqn = getSipApplicationSessionAttributeFqn(realId); try { keys = proxy_.getChildrenNames(fqn); } catch (CacheException e) { log_.error("getPojoKeys(): Exception getting keys for session " + realId, e); } return keys; } public Set getSipSessionPojoKeys(String id, String realId) { Set keys = null; Fqn fqn = getSipSessionAttributeFqn(id, realId); try { keys = proxy_.getChildrenNames(fqn); } catch (CacheException e) { log_.error("getPojoKeys(): Exception getting keys for session " + realId, e); } return keys; } /** * * @param realId the session id with any jvmRoute removed * @param key the attribute key * @return Pojo that is associated with the attribute */ public Object getPojo(String realId, String key) { if(log_.isTraceEnabled()) { log_.trace("getPojo(): session id: " +realId + " key: " +key); } // Construct the fqn. Fqn fqn = getFieldFqn(realId, key); try { return proxy_.getObject(fqn); } catch (CacheException e) { throw new RuntimeException("JBossCacheService: exception occurred in cache getPojo ... ", e); } } /** * * @param realId the session id with any jvmRoute removed * @param key the attribute key * @return Pojo that is associated with the attribute */ public Object getSipApplicationSessionPojo(String realId, String key) { if(log_.isTraceEnabled()) { log_.trace("getSipApplicationSessionPojo(): sip app session id: " +realId + " key: " +key); } // Construct the fqn. Fqn fqn = getSipApplicationSessionFieldFqn(realId, key); try { return proxy_.getObject(fqn); } catch (CacheException e) { throw new RuntimeException("JBossCacheService: exception occurred in cache getSipApplicationPojo ... ", e); } } /** * * @param realId the session id with any jvmRoute removed * @param key the attribute key * @return Pojo that is associated with the attribute */ public Object getSipSessionPojo(String id, String realId, String key) { if(log_.isTraceEnabled()) { log_.trace("getSipSessionPojo(): sip session id: " +realId + " key: " +key); } // Construct the fqn. Fqn fqn = getSipSessionFieldFqn(id, realId, key); try { return proxy_.getObject(fqn); } catch (CacheException e) { throw new RuntimeException("JBossCacheService: exception occurred in cache getSipSessionPojo ... ", e); } } /** * Recursively adds session as observer to the pojo graph. Assumes the * whole object graph has Subject "introduction" declared. If a portion * of the graph isn't a Subject, the recursion does not continue below * that part of the graph. * * @param session the session * @param pojo the pojo. Can be <code>null</code>. */ public void addObserver(Observer session, Object pojo) { addObserver(session, pojo, new HashSet()); } private void addObserver(Observer session, Object pojo, Set processed) { if ( pojo instanceof Collection ) { Collection col = (Collection)pojo; for (Iterator i = col.iterator(); i.hasNext();) { // If not a managed pojo, will return anyway addObserver(session, i.next(), processed); } return; } else if (pojo instanceof Map) { for (Iterator i = ((Map)pojo).entrySet().iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); // Walk thru key and value addObserver(session, entry.getKey(), processed); addObserver(session, entry.getValue(), processed); } return; } if(! (pojo instanceof Subject) ) { return; // No need to add observer since it is primitive. } Subject subject = (Subject)pojo; subject.addObserver(session); if(log_.isTraceEnabled()) { log_.trace("addObserver(): session: " +session + " pojo name: " +pojo.getClass().getName()); } // Examine each field of the type and its superclasses to see if // we need to add the observer to the pojo held by that field // Traverse recursively // First identify and cache the names of all the class' // non-immediate fields Class type = pojo.getClass(); Set complexFields = (Set) typeMap.get(type); if (complexFields == null) { complexFields = Util.parseComplexFields(type); typeMap.put(type, complexFields); } if (complexFields.size() == 0) return; // Store a ref to the pojo to avoid cyclic additions processed.add(pojo); for (Iterator iter = complexFields.iterator(); iter.hasNext();) { String fieldName = (String) iter.next(); Class curType = type; while (curType != null) { try { Field field = curType.getDeclaredField(fieldName); boolean accessible = field.isAccessible(); Object value = null; try { field.setAccessible(true); value=field.get(pojo); // Continue recursively unless we've already handled this value if (value != null && !processed.contains(value)) addObserver(session, value, processed); break; } catch(IllegalAccessException e) { throw new RuntimeException("field access failed", e); } finally { field.setAccessible(accessible); } } catch (NoSuchFieldException e) { // Check if the field is declared in a superclass curType = curType.getSuperclass(); if (curType == null) throw new RuntimeException("Field " + fieldName + " does not exist", e); } } } } /** * Recursively removes session as observer to the pojo graph. Assumes the * whole object graph has Subject "introduction" declared. If a portion * of the graph isn't a Subject, the recursion does not continue below * that part of the graph. * * @param session the session * @param pojo the pojo to stop observing. Can be <code>null</code>. */ public void removeObserver(Observer session, Object pojo) { removeObserver(session, pojo, new HashSet()); } private void removeObserver(Observer session, Object pojo, Set stack) { if ( pojo instanceof Collection ) { Collection col = (Collection)pojo; for (Iterator i = col.iterator(); i.hasNext();) { Object obj = i.next(); // If not a managed pojo, will return anyway removeObserver(session, obj, stack); } return; } else if (pojo instanceof Map) { Map map = (Map)pojo; for (Iterator i = map.keySet().iterator(); i.hasNext();) { Object key = i.next(); Object value = map.get(key); // Walk thru key and value removeObserver(session, key, stack); removeObserver(session, value, stack); } return; } // BRIAN 3/14 changed this from checking Advised to checking Subject // since that is what we cast to below if(! (pojo instanceof Subject) ) { return; // No need to add observer since it is primitive. } Subject subject = (Subject)pojo; subject.removeObserver(session); if(log_.isTraceEnabled()) { log_.trace("removeObserver(): session: " +session + " pojo name: " +pojo.getClass().getName()); } // Examine each field of the type and its superclasses to see if // we need to remove the observer from the pojo held by that field // Traverse recursively // First identify and cache the names of all the class' // non-immediate fields Class type = pojo.getClass(); Set complexFields = (Set) typeMap.get(type); if (complexFields == null) { complexFields = Util.parseComplexFields(type); typeMap.put(type, complexFields); } if (complexFields.size() == 0) return; // Store a ref to the pojo to avoid cyclic removals stack.add(pojo); for (Iterator iter = complexFields.iterator(); iter.hasNext();) { String fieldName = (String) iter.next(); Class curType = type; while (curType != null) { try { Field field = curType.getDeclaredField(fieldName); boolean accessible = field.isAccessible(); Object value = null; try { field.setAccessible(true); value=field.get(pojo); // Continue recursively unless we've already handled this value if (value != null && !stack.contains(value)) removeObserver(session, value, stack); break; } catch(IllegalAccessException e) { throw new RuntimeException("field access failed", e); } finally { field.setAccessible(accessible); } } catch (NoSuchFieldException e) { // Check if the field is declared in a superclass curType = curType.getSuperclass(); if (curType == null) throw new RuntimeException("Field " + fieldName + " does not exist", e); } } } } private Fqn getFieldFqn(String id, String key) { // /SESSION/id/ATTR/key // Guard against string with delimiter. List list = new ArrayList(6); list.add(SESSION); list.add(hostName_); list.add(webAppPath_); list.add(id); list.add(ATTRIBUTE); breakKeys(key, list); return new Fqn(list); } private Fqn getSipApplicationSessionFieldFqn(String id, String key) { // /SIPSESSION/id/ATTR/key // Guard against string with delimiter. List list = new ArrayList(6); list.add(SIPSESSION); list.add(hostName_); list.add(sipApplicationName); list.add(id); list.add(ATTRIBUTE); breakKeys(key, list); return new Fqn(list); } private Fqn getSipSessionFieldFqn(String id, String sessionId, String key) { // /SIPSESSION/id/sessionid/ATTR/key // Guard against string with delimiter. List list = new ArrayList(6); list.add(SIPSESSION); list.add(hostName_); list.add(sipApplicationName); list.add(id); list.add(sessionId); list.add(ATTRIBUTE); breakKeys(key, list); return new Fqn(list); } private void breakKeys(String key, List list) { StringTokenizer token = new StringTokenizer(key, FQN_DELIMITER); while(token.hasMoreTokens()) { list.add(token.nextToken()); } } private Fqn getWebappFqn() { // /SESSION/hostname/webAppPath Object[] objs = new Object[]{SESSION, hostName_, webAppPath_}; return new Fqn(objs); } private Fqn getSipappFqn() { // /SIPSESSION/hostname/sipApplicationName Object[] objs = new Object[]{SIPSESSION, hostName_, sipApplicationName}; return new Fqn(objs); } private Fqn getWebappFqn(Object dataOwner) { if (dataOwner == null) return getWebappFqn(); // /SESSION/hostname/webAppPath Object[] objs = new Object[]{BUDDY_BACKUP, dataOwner, SESSION, hostName_, webAppPath_}; return new Fqn(objs); } private Fqn getSipappFqn(Object dataOwner) { if (dataOwner == null) return getSipappFqn(); // /SIPSESSION/hostname/sipApplicationName Object[] objs = new Object[]{BUDDY_BACKUP, dataOwner, SIPSESSION, hostName_, sipApplicationName}; return new Fqn(objs); } private Fqn getSessionFqn(String id) { // /SESSION/hostname/webAppPath/id Object[] objs = new Object[]{SESSION, hostName_, webAppPath_, id}; return new Fqn(objs); } private Fqn getSipApplicationSessionFqn(String id) { // /SIPSESSION/hostname/sipApplicationName/id Object[] objs = new Object[]{SIPSESSION, hostName_, sipApplicationName, id}; return new Fqn(objs); } private Fqn getSipSessionFqn(String id, String sessionId) { // /SIPSESSION/hostname/sipApplicationName/id/sessionId Object[] objs = new Object[]{SIPSESSION, hostName_, sipApplicationName, id, sessionId}; return new Fqn(objs); } private Fqn getSessionFqn(String id, String dataOwner) { // /_BUDDY_BACKUP_/dataOwner/SESSION/hostname/webAppPath/id Object[] objs = new Object[]{BUDDY_BACKUP, dataOwner, SESSION, hostName_, webAppPath_, id}; return new Fqn(objs); } private Fqn getSipApplicationSessionFqn(String id, String dataOwner) { // /_BUDDY_BACKUP_/dataOwner/SIPSESSION/hostname/sipApplicationName/id Object[] objs = new Object[]{BUDDY_BACKUP, dataOwner, SIPSESSION, hostName_, sipApplicationName, id}; return new Fqn(objs); } private Fqn getSipSessionFqn(String id, String sessionId, String dataOwner) { // /_BUDDY_BACKUP_/dataOwner/SIPSESSION/hostname/sipApplicationName/id/sessionId Object[] objs = new Object[]{BUDDY_BACKUP, dataOwner, SIPSESSION, hostName_, sipApplicationName, id, sessionId}; return new Fqn(objs); } private Fqn getAttributeFqn(String id) { // /SESSION/hostName/webAppPath/id/ATTR Object[] objs = new Object[]{SESSION, hostName_, webAppPath_, id, ATTRIBUTE}; return new Fqn(objs); } private Fqn getSipApplicationSessionAttributeFqn(String id) { // /SIPSESSION/hostName/sipapplicationname/id/ATTR Object[] objs = new Object[]{SIPSESSION, hostName_, sipApplicationName, id, ATTRIBUTE}; return new Fqn(objs); } private Fqn getSipSessionAttributeFqn(String id, String sessionId) { // /SIPSESSION/hostName/sipapplicationname/id/sessionid/ATTR Object[] objs = new Object[]{SIPSESSION, hostName_, sipApplicationName, id, sessionId, ATTRIBUTE}; return new Fqn(objs); } private Object getMarshalledValue(Object value) { // JBAS-2920. For now, continue using MarshalledValue, as // it allows lazy deserialization of the attribute on remote nodes // For Branch_4_0 this is what we have to do anyway for backwards // compatibility. For HEAD we'll follow suit for now. // TODO consider only using MV for complex objects (i.e. not primitives) // and Strings longer than X. // if (useTreeCacheMarshalling_) // { // return value; // } // else // { try { MarshalledValue mv = new MarshalledValue(value); if (log_.isTraceEnabled()) { log_.trace("marshalled object to size " + mv.size() + " bytes"); } return mv; } catch (IOException e) { log_.error("IOException occurred marshalling value ", e); return null; } // } } private Object getUnMarshalledValue(Object mv) { // JBAS-2920. For now, continue using MarshalledValue, as // it allows lazy deserialization of the attribute on remote nodes // For Branch_4_0 this is what we have to do anyway for backwards // compatibility. For HEAD we'll follow suit for now. // if (useTreeCacheMarshalling_) // { // return mv; // } // else // { if (mv == null) return null; // Swap in/out the tcl for this web app. Needed only for un marshalling. ClassLoader prevTCL = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(manager_.getWebappClassLoader()); try { return ((MarshalledValue) mv).get(); } catch (IOException e) { log_.error("IOException occurred unmarshalling value ", e); return null; } catch (ClassNotFoundException e) { log_.error("ClassNotFoundException occurred unmarshalling value ", e); return null; } finally { Thread.currentThread().setContextClassLoader(prevTCL); } // } } private byte[] externalizeSession(ClusteredSession session) { try { // Write the contents of session to a byte array and store that ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Use MarshalledValueOutputStream instead of superclass ObjectOutputStream // or else there are problems finding classes with scoped loaders MarshalledValueOutputStream oos = new MarshalledValueOutputStream(baos); session.writeExternal(oos); oos.close(); // flushes bytes to baos byte[] bytes = baos.toByteArray(); if (log_.isDebugEnabled()) { log_.debug("marshalled object to size " + bytes.length + " bytes"); } return bytes; } catch (Exception e) { log_.error("externalizeSession(): exception occurred externalizing session " + session, e); return null; } } private byte[] externalizeSipSession(ClusteredSipSession session) { try { // Write the contents of session to a byte array and store that ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Use MarshalledValueOutputStream instead of superclass ObjectOutputStream // or else there are problems finding classes with scoped loaders MarshalledValueOutputStream oos = new MarshalledValueOutputStream(baos); session.writeExternal(oos); oos.close(); // flushes bytes to baos byte[] bytes = baos.toByteArray(); if (log_.isDebugEnabled()) { log_.debug("marshalled object to size " + bytes.length + " bytes"); } return bytes; } catch (Exception e) { log_.error("externalizeSession(): exception occurred externalizing session " + session, e); return null; } } private byte[] externalizeSipApplicationSession(ClusteredSipApplicationSession session) { try { // Write the contents of session to a byte array and store that ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Use MarshalledValueOutputStream instead of superclass ObjectOutputStream // or else there are problems finding classes with scoped loaders MarshalledValueOutputStream oos = new MarshalledValueOutputStream(baos); session.writeExternal(oos); oos.close(); // flushes bytes to baos byte[] bytes = baos.toByteArray(); if (log_.isTraceEnabled()) { log_.trace("marshalled object to size " + bytes.length + " bytes"); } return bytes; } catch (Exception e) { log_.error("externalizeSession(): exception occurred externalizing session " + session, e); return null; } } }