blob: 3fc13c0834bfae871ddad18e3d1479a69a2c8444 [file]
package org.apache.jcs.engine.control;
import java.io.InputStream;
import java.io.IOException;
import java.io.Serializable;
import java.rmi.NotBoundException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import org.apache.jcs.auxiliary.behavior.IAuxiliaryCacheAttributes;
import org.apache.jcs.auxiliary.behavior.IAuxiliaryCacheFactory;
import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheConstants;
import org.apache.jcs.engine.ElementAttributes;
import org.apache.jcs.engine.behavior.IElementAttributes;
import org.apache.jcs.engine.CompositeCacheAttributes;
import org.apache.jcs.engine.behavior.ICache;
import org.apache.jcs.engine.behavior.ICompositeCacheAttributes;
import org.apache.jcs.engine.behavior.ICompositeCacheManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/** Manages a composite cache. */
public class CompositeCacheManager
implements ICompositeCacheManager, IRemoteCacheConstants, Serializable
{
private final static Log log =
LogFactory.getLog( CompositeCacheManager.class );
/** Caches managed by this cache manager */
protected Hashtable caches = new Hashtable();
/** Internal system caches for this cache manager */
protected Hashtable systemCaches = new Hashtable();
/** Number of clients accessing this cache manager */
private int clients;
/** Default cache attributes for this cache manager */
protected ICompositeCacheAttributes defaultCacheAttr =
new CompositeCacheAttributes();
/** Default elemeent attributes for this cache manager */
protected IElementAttributes defaultElementAttr = new ElementAttributes();
/** Defaults the cache service name to the rmi server's class name */
private String remoteServiceName;
/** Used to keep track of configured auxiliaries */
protected Hashtable auxFacs = new Hashtable( 11 );
/** ??? */
protected Hashtable auxAttrs = new Hashtable( 11 );
/** Properties with which this manager was configured */
protected Properties props;
/** The default auxiliary caches to be used if not preconfigured */
protected String defaultAuxValues;
/** Constructor for the CompositeCacheManager object */
protected CompositeCacheManager()
{
this( "/cache.ccf" );
}
/**
* Constructor for the CompositeCacheManager object
*
* @param propFile
*/
protected CompositeCacheManager( String propFile )
{
log.debug( "Creating cache manager from config file: " + propFile );
Properties props = new Properties();
InputStream is = getClass().getResourceAsStream( propFile );
try
{
props.load( is );
if ( log.isDebugEnabled() )
{
log.debug( "File contained " + props.size() + " properties" );
}
}
catch ( IOException ex )
{
log.error( "Failed to load properties", ex );
throw new IllegalStateException( ex.getMessage() );
}
finally
{
try
{
is.close();
}
catch ( Exception ignore )
{
// Ignored
}
}
// FIXME: need to do something for defaults
// create a default entry in the propsfile
// setDefaults( props );
// Create caches
try
{
createCaches( props );
}
catch ( IOException ex )
{
log.error( "Failed to create caches", ex );
throw new IllegalStateException( ex.getMessage() );
}
catch ( NotBoundException ex )
{
log.error( "Failed to create caches", ex );
throw new IllegalStateException( ex.getMessage() );
}
}
/**
* Gets the defaultCacheAttributes attribute of the CompositeCacheManager
* object
*
* @return The defaultCacheAttributes value
*/
public ICompositeCacheAttributes getDefaultCacheAttributes()
{
return this.defaultCacheAttr.copy();
}
/**
* Sets the defaultCacheAttributes attribute of the CompositeCacheManager
* object
*
* @param icca The new defaultCacheAttributes value
*/
public void setDefaultCacheAttributes( ICompositeCacheAttributes icca )
{
this.defaultCacheAttr = icca;
}
/**
* Sets the defaultElementAttributes attribute of the CompositeCacheManager
* object
*
* @param icca The new defaultElementAttributes value
*/
public void setDefaultElementAttributes( IElementAttributes iea )
{
this.defaultElementAttr = iea;
}
/**
* Gets the defaultElementAttributes attribute of the CompositeCacheManager
* object
*
* @return The defaultElementAttributes value
*/
public IElementAttributes getDefaultElementAttributes()
{
return this.defaultElementAttr.copy();
}
/** */
private void createCaches( Properties props )
throws IOException, NotBoundException
{
CompositeCacheConfigurator ccc = new CompositeCacheConfigurator( this );
ccc.doConfigure( props );
}
/** Creates internal system cache */
protected Cache createSystemCache( String cacheName,
ICache[] auxCaches,
ICompositeCacheAttributes cattr,
IElementAttributes attr )
{
return new Cache( cacheName, auxCaches, cattr, attr );
}
/**
* Factory method to create the actual Cache instance. Subclass can override
* this method to create the specific cache.
*/
protected Cache createCache( String cacheName,
ICache[] auxCaches,
ICompositeCacheAttributes cattr,
IElementAttributes attr )
{
return new Cache( cacheName, auxCaches, cattr, attr );
}
/**
* Gets the auxCaches attribute of the CompositeCacheManager object
*/
private ICache[] getAuxCaches( String cacheName,
IAuxiliaryCacheAttributes iaca )
{
List auxList = new ArrayList();
Enumeration enum = auxFacs.elements();
while ( enum.hasMoreElements() )
{
IAuxiliaryCacheFactory iacf = ( IAuxiliaryCacheFactory ) enum.nextElement();
// need default ilca here.
ICache cache = iacf.createCache( iaca );
auxList.add( cache );
}
return ( ICache[] ) auxList.toArray( new ICache[0] );
}
/** Gets the cache attribute of the CompositeCacheManager object */
public ICache getCache( String cacheName )
{
return getCache( cacheName, this.defaultCacheAttr.copy() );
}
/** Gets the cache attribute of the CompositeCacheManager object */
public ICache getCache( String cacheName, ICompositeCacheAttributes cattr )
{
cattr.setCacheName( cacheName );
return getCache( cattr, this.defaultElementAttr );
}
/** Gets the cache attribute of the CompositeCacheManager object */
public ICache getCache( String cacheName,
ICompositeCacheAttributes cattr,
IElementAttributes attr )
{
cattr.setCacheName( cacheName );
return getCache( cattr, this.defaultElementAttr );
}
/** Gets the cache attribute of the CompositeCacheManager object */
public ICache getCache( ICompositeCacheAttributes cattr )
{
return getCache( cattr, this.defaultElementAttr );
}
/**
* If the cache is created the CacheAttributes and the element Attributes
* will be ignored. Currently there is no overiding once it is set up.
* Overriding hte default elemental atributes will require cahnging the way
* the atributes are assigned to elements. Get cache creates a cache with
* defaults if none are specified. We might want to create separate method
* for creating/getting. . .
*/
public ICache getCache( ICompositeCacheAttributes cattr, IElementAttributes attr )
{
ICache cache = ( ICache ) caches.get( cattr.getCacheName() );
if ( cache == null )
{
synchronized ( caches )
{
cache = ( ICache ) caches.get( cattr.getCacheName() );
if ( cache == null )
{
cattr.setCacheName( cattr.getCacheName() );
//ICache[] auxCaches = getAuxCaches(cattr.getCacheName(), cattr );
// need to call parse region of ccc
//cache = createCache(cattr.getCacheName(), auxCaches, cattr, attr );
CompositeCacheConfigurator ccc = new CompositeCacheConfigurator( this );
cache = ccc.parseRegion( this.props, cattr.getCacheName(), this.defaultAuxValues, cattr );
caches.put( cattr.getCacheName(), cache );
}
}
}
if ( log.isDebugEnabled() )
{
log.debug( "At end of getCache, manager stats: " + getStats() );
}
return cache;
}
/** */
public void freeCache( String name )
{
freeCache( name, Cache.LOCAL_INVOKATION );
}
/** */
public void freeCache( String name, boolean fromRemote )
{
Cache cache = ( Cache ) caches.get( name );
if ( cache != null )
{
cache.dispose( fromRemote );
}
}
/** */
public String getStats()
{
StringBuffer stats = new StringBuffer();
Enumeration allCaches = caches.elements();
while ( allCaches.hasMoreElements() )
{
ICache cache = ( ICache ) allCaches.nextElement();
if ( cache != null )
{
stats.append( "Cache stats: " ).append( cache.getStats() )
.append( " clients = " ).append( clients );
}
}
return stats.toString();
}
/** */
protected void incrementClients()
{
clients++;
}
/** */
public void release()
{
release( Cache.LOCAL_INVOKATION );
}
/** */
private void release( boolean fromRemote )
{
synchronized ( CompositeCacheManager.class )
{
// Wait until called by the last client
if ( --clients > 0 )
{
if ( log.isDebugEnabled() )
{
log.debug( "Release called, but " + clients + " remain" );
return;
}
}
// FIXME: Is this really warn or should it be debug?
// if ( log.isWarnEnabled() )
// {
log.warn( "Last client called release. There are "
+ caches.size() + " caches which will be disposed" );
log.warn( "Manager stats: " + getStats() );
// }
Enumeration allCaches = caches.elements();
while ( allCaches.hasMoreElements() )
{
Cache cache = ( Cache ) allCaches.nextElement();
if ( cache != null )
{
cache.dispose( fromRemote );
}
}
}
}
/** Returns a list of the current cache names. */
public String[] getCacheNames()
{
String[] list = new String[caches.size()];
int i = 0;
for ( Iterator itr = caches.keySet().iterator(); itr.hasNext(); )
{
list[i++] = ( String ) itr.next();
}
return list;
}
/** */
public int getCacheType()
{
return COMPOSITE_CACHE;
}
/** */
public ICompositeCacheAttributes getDefaultCattr()
{
return this.defaultCacheAttr;
}
/** */
void registryFacPut( IAuxiliaryCacheFactory auxFac )
{
auxFacs.put( auxFac.getName(), auxFac );
}
/** */
IAuxiliaryCacheFactory registryFacGet( String name )
{
return ( IAuxiliaryCacheFactory ) auxFacs.get( name );
}
/** */
void registryAttrPut( IAuxiliaryCacheAttributes auxAttr )
{
auxAttrs.put( auxAttr.getName(), auxAttr );
}
/** */
IAuxiliaryCacheAttributes registryAttrGet( String name )
{
return ( IAuxiliaryCacheAttributes ) auxAttrs.get( name );
}
}