/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, 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.distributedcache.impl.jbc;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.jboss.cache.CacheException;
import org.jboss.cache.Fqn;
import org.jboss.cache.pojo.PojoCache;
import org.jboss.ha.framework.server.PojoCacheManager;
import org.jboss.ha.framework.server.PojoCacheManagerLocator;
import org.jboss.web.tomcat.service.session.distributedcache.spi.ClusteringNotSupportedException;
import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributableSession;
import org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager;
/**
* DistributedCacheManager impl for ReplicationGranularity.FIELD.
*
* @author Brian Stansberry *
*/
public class FieldBasedJBossCacheService extends AbstractJBossCacheService
{
public static final String ATTRIBUTE = "ATTRIBUTE";
public static Fqn getAttributeFqn(String contextHostPath, String sessionId)
{
Object[] objs = new Object[]{SESSION, contextHostPath, sessionId, ATTRIBUTE};
return Fqn.fromList(Arrays.asList(objs), true);
}
public static Fqn getFieldFqn(String contextHostPath, String sessionId, String attributeKey)
{
List list = new ArrayList(5);
list.add(SESSION);
list.add(contextHostPath);
list.add(sessionId);
list.add(ATTRIBUTE);
// Guard against string with delimiter.
breakKeys(attributeKey, list);
return Fqn.fromList(list, true);
}
private static void breakKeys(String key, List list)
{
StringTokenizer token = new StringTokenizer(key, FQN_DELIMITER);
while(token.hasMoreTokens())
{
list.add(token.nextToken());
}
}
private final PojoCache pojoCache_;
public FieldBasedJBossCacheService(LocalDistributableSessionManager localManager) throws ClusteringNotSupportedException
{
this(localManager, Util.findPojoCache(Util.getCacheConfigName(localManager)));
this.cacheConfigName_ = Util.getCacheConfigName(localManager);
}
/**
* Create a new FieldBasedJBossCacheService.
*
* @param cache
*/
public FieldBasedJBossCacheService(LocalDistributableSessionManager localManager, PojoCache cache)
{
super(localManager, cache.getCache());
this.pojoCache_ = cache;
if (!isMarshallingAvailable())
{
// BES 16/8/2006 -- throw ISE, not ClusteringNotSupportedException, as a
// misconfig should be treated differently from the absence of clustering
// services
throw new IllegalStateException("replication-granularity value is set to " +
"'FIELD' but is not supported by the cache service configuration. " +
"Must set 'useRegionBasedMarshalling' to 'true' in the cache configuration");
}
}
public boolean getSupportsAttributeOperations()
{
return true;
}
public void putAttribute(String realId, String key, Object value)
{
if(log_.isTraceEnabled())
{
log_.trace("putAttribute(): session id: " + realId + " key: " + key +
" object: " + value.toString());
}
Fqn fqn = getFieldFqn(combinedPath_, realId, key);
try {
pojoCache_.attach(fqn.toString(), value);
}
catch (CacheException e)
{
throw new RuntimeException("Exception occurred in PojoCache attach ... ", e);
}
}
/**
* 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 removeAttribute(String realId, String key)
{
if(log_.isTraceEnabled())
{
log_.trace("removePojo(): session id: " +realId + " key: " +key);
}
// Construct the fqn.
Fqn fqn = getFieldFqn(combinedPath_, realId, key);
try {
return pojoCache_.detach(fqn.toString());
}
catch (CacheException e)
{
throw new RuntimeException("Exception occurred in PojoCache detach ... ", e);
}
}
public void removeAttributeLocal(String realId, String key)
{
if(log_.isTraceEnabled())
{
log_.trace("removePojoLocal(): session id: " + realId + " key: " +key);
}
Fqn fqn = getFieldFqn(combinedPath_, realId, key);
cacheWrapper_.removeLocal(fqn);
}
public Set getAttributeKeys(String realId)
{
Set keys = null;
Fqn fqn = getAttributeFqn(combinedPath_, realId);
try
{
keys = getChildrenNames(fqn);
}
catch (CacheException e)
{
log_.error("getAttributeKeys(): 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 getAttribute(String realId, String key)
{
Fqn fqn = getFieldFqn(combinedPath_, realId, key);
if(log_.isTraceEnabled())
{
log_.trace("getPojo(): session id: " +realId + " key: " + key +
" fqn: " + fqn);
}
try
{
return pojoCache_.find(fqn);
}
catch (CacheException e)
{
throw new RuntimeException("Exception occurred in PojoCache find ... ", e);
}
}
@Override
protected void setupSessionRegion(DistributableSession session, Fqn fqn)
{
getCache().getRegion(fqn, true);
session.createdRegionForSession();
if (log_.isTraceEnabled())
{
log_.trace("Created region for session at " + fqn);
}
}
@Override
protected void removeSessionRegion(String realId, Fqn fqn)
{
getCache().removeRegion(fqn);
if (log_.isTraceEnabled())
{
log_.trace("Removed region for session at " + fqn);
}
}
@Override
protected void releaseCacheToManager(String cacheConfigName)
{
try
{
PojoCacheManager pcm = PojoCacheManagerLocator.getCacheManagerLocator().getCacheManager(null);
pcm.releaseCache(cacheConfigName);
}
catch (Exception e)
{
log_.error("Problem releasing cache to CacheManager -- config is " + cacheConfigName, e);
}
}
@Override
protected boolean getStoreAttributesInSingleKey()
{
return false;
}
public Map<String, Object> getAttributes(String realId)
{
Map<String, Object> attrs = new HashMap<String, Object>();
Set<String> keys = getAttributeKeys(realId);
for (String key : keys)
{
attrs.put(key, getAttribute(realId, key));
}
return attrs;
}
public void putAttribute(String realId, Map<String, Object> map)
{
for (Map.Entry<String, Object> entry : map.entrySet())
{
putAttribute(realId, entry.getKey(), entry.getValue());
}
}
@Override
protected boolean isFieldBased()
{
return true;
}
/**
* Overrides the superclass to pull in attributes via PojoCache API.
*/
@Override
protected Map<String, Object> getSessionAttributes(String realId, Map<Object, Object> distributedCacheData)
{
return getAttributes(realId);
}
}