package org.apache.stratum.jcs.engine.control;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import org.apache.stratum.jcs.auxiliary.behavior.IAuxiliaryCacheAttributes;
import org.apache.stratum.jcs.auxiliary.behavior.IAuxiliaryCacheFactory;
import org.apache.stratum.jcs.config.OptionConverter;
import org.apache.stratum.jcs.config.PropertySetter;
import org.apache.stratum.jcs.engine.ElementAttributes;
import org.apache.stratum.jcs.engine.behavior.IElementAttributes;
import org.apache.stratum.jcs.engine.behavior.ICache;
import org.apache.stratum.jcs.engine.behavior.ICompositeCacheAttributes;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* This class is based on the log4j class org.apache.log4j.PropertyConfigurator
* which was made by: "Luke Blanshard" <Luke@quiq.com> "Mark DONSZELMANN"
* <Mark.Donszelmann@cern.ch> "Anders Kristensen" <akristensen@dynamicsoft.com>
*
* @author asmuts
* @created January 15, 2002
*/
public class CompositeCacheConfigurator
{
private final static Log log =
LogFactory.getLog( CompositeCacheConfigurator.class );
final static String DEFAULT_REGION = "jcs.default";
final static String REGION_PREFIX = "jcs.region.";
final static String SYSTEM_REGION_PREFIX = "jcs.system.";
final static String AUXILIARY_PREFIX = "jcs.auxiliary.";
final static String ATTRIBUTE_PREFIX = ".attributes";
final static String CACHE_ATTRIBUTE_PREFIX = ".cacheattributes";
final static String ELEMENT_ATTRIBUTE_PREFIX = ".elementattributes";
private CompositeCacheManager ccMgr;
/**
* Constructor for the CompositeCacheConfigurator object
*
* @param ccMgr
*/
public CompositeCacheConfigurator( CompositeCacheManager ccMgr )
{
this.ccMgr = ccMgr;
}
/** Configure cached for file name. */
public void doConfigure( String configFileName )
{
Properties props = new Properties();
try
{
FileInputStream istream = new FileInputStream( configFileName );
props.load( istream );
istream.close();
}
catch ( IOException e )
{
log.error( "Could not read configuration file, ignored: " +
configFileName, e );
return;
}
// If we reach here, then the config file is alright.
doConfigure( props );
}
/** Configure cache for properties object */
public void doConfigure( Properties properties )
{
// store props for use by non configured caches
ccMgr.props = properties;
// set default value list
setDefaultAuxValues( properties );
// set default cache attr
setDefaultCompositeCacheAttributes( properties );
// set default element attr
setDefaultElementAttributes( properties );
// set up ssytem caches to be used by non system caches
// need to make sure there is no circuarity of reference
parseSystemRegions( properties );
// setup preconfigured caches
parseRegions( properties );
}
/** Set the default aux list for new caches. */
protected void setDefaultAuxValues( Properties props )
{
String value = OptionConverter.findAndSubst( DEFAULT_REGION, props );
ccMgr.defaultAuxValues = value;
log.info( "setting defaults to " + value );
}
/** Set the default CompositeCacheAttributes for new caches. */
protected void setDefaultCompositeCacheAttributes( Properties props )
{
ICompositeCacheAttributes icca =
parseCompositeCacheAttributes( props, "", this.DEFAULT_REGION );
ccMgr.setDefaultCacheAttributes( icca );
log.info( "setting defaultCompositeCacheAttributes to " + icca );
}
/** Set the default ElementAttributes for new caches. */
protected void setDefaultElementAttributes( Properties props )
{
IElementAttributes iea =
parseElementAttributes( props, "", this.DEFAULT_REGION );
ccMgr.setDefaultElementAttributes( iea );
log.info( "setting defaultElementAttributes to " + iea );
}
/**
* Create caches used internally. System status gives them creation
* priority.
*/
protected void parseSystemRegions( Properties props )
{
Enumeration enum = props.propertyNames();
while ( enum.hasMoreElements() )
{
String key = ( String ) enum.nextElement();
if ( key.startsWith( SYSTEM_REGION_PREFIX )
&& ( key.indexOf( "attributes" ) == -1 ) )
{
String regionName = key.substring( SYSTEM_REGION_PREFIX.length() );
String value = OptionConverter.findAndSubst( key, props );
ICache cache;
synchronized ( regionName )
{
cache = parseRegion( props, regionName, value, null, SYSTEM_REGION_PREFIX );
}
ccMgr.systemCaches.put( regionName, cache );
// to be availiable for remote reference they need to be here as well
ccMgr.caches.put( regionName, cache );
}
}
}
/** Parse region elements. */
protected void parseRegions( Properties props )
{
Enumeration enum = props.propertyNames();
while ( enum.hasMoreElements() )
{
String key = ( String ) enum.nextElement();
if ( key.startsWith( REGION_PREFIX ) && ( key.indexOf( "attributes" ) == -1 ) )
{
String regionName = key.substring( REGION_PREFIX.length() );
String value = OptionConverter.findAndSubst( key, props );
ICache cache;
synchronized ( regionName )
{
cache = parseRegion( props, regionName, value );
}
ccMgr.caches.put( regionName, cache );
}
}
}
/** Create cache region. */
protected ICache parseRegion( Properties props,
String regName,
String value )
{
return parseRegion( props, regName, value, null, REGION_PREFIX );
}
/** */
protected ICache parseRegion( Properties props,
String regName,
String value,
ICompositeCacheAttributes cca )
{
return parseRegion( props, regName, value, cca, REGION_PREFIX );
}
/** */
protected ICache parseRegion( Properties props,
String regName,
String value,
ICompositeCacheAttributes cca,
String regionPrefix )
{
List auxList = new ArrayList();
log.debug( "Parsing region name '" + regName + "', value '" + value + "'" );
// We must skip over ',' but not white space
StringTokenizer st = new StringTokenizer( value, "," );
// If value is not in the form ", appender.." or "", then we should set
// the priority of the category.
if ( !( value.startsWith( "," ) || value.equals( "" ) ) )
{
// just to be on the safe side...
if ( !st.hasMoreTokens() )
{
return null;
}
}
ICache auxCache;
String auxName;
while ( st.hasMoreTokens() )
{
auxName = st.nextToken().trim();
if ( auxName == null || auxName.equals( "," ) )
{
continue;
}
log.debug( "Parsing auxiliary named \"" + auxName + "\"." );
auxCache = parseAuxiliary( props, auxName, regName );
if ( auxCache != null )
{
auxList.add( auxCache );
}
}
ICache[] auxCaches = ( ICache[] ) auxList.toArray( new ICache[0] );
// GET COMPOSITECACHEATTRIBUTES
if ( cca == null )
{
cca = parseCompositeCacheAttributes( props, regName, regionPrefix );
}
IElementAttributes ea = parseElementAttributes( props, regName, regionPrefix );
ICache cache = null;
if ( regionPrefix.equals( SYSTEM_REGION_PREFIX ) )
{
//cache = ccMgr.createSystemCache( regName, auxCaches, cca, new ElementAttributes() );
cache = ccMgr.createSystemCache( regName, auxCaches, cca, ea );
}
else
{
//cache = ccMgr.createCache( regName, auxCaches, cca, new ElementAttributes() );
cache = ccMgr.createCache( regName, auxCaches, cca, ea );
}
return cache;
}
/** Get an compositecacheattributes for the listed region. */
protected ICompositeCacheAttributes
parseCompositeCacheAttributes( Properties props, String regName )
{
return parseCompositeCacheAttributes( props, regName, REGION_PREFIX );
}
/** */
protected ICompositeCacheAttributes
parseCompositeCacheAttributes( Properties props,
String regName,
String regionPrefix )
{
ICompositeCacheAttributes ccAttr;
String attrName = regionPrefix + regName + CACHE_ATTRIBUTE_PREFIX;
// auxFactory was not previously initialized.
//String prefix = regionPrefix + regName + ATTRIBUTE_PREFIX;
ccAttr = ( ICompositeCacheAttributes ) OptionConverter.instantiateByKey( props, attrName,
org.apache.stratum.jcs.engine.behavior.ICompositeCacheAttributes.class,
null );
if ( ccAttr == null )
{
log.warn( "Could not instantiate ccAttr named '" + attrName +
"', using defaults." );
ICompositeCacheAttributes ccAttr2 = ccMgr.getDefaultCacheAttributes();
ccAttr = ccAttr2.copy();
}
log.debug( "Parsing options for '" + attrName + "'" );
PropertySetter.setProperties( ccAttr, props, attrName + "." );
ccAttr.setCacheName( regName );
log.debug( "End of parsing for \"" + attrName + "\"." );
// GET CACHE FROM FACTORY WITH ATTRIBUTES
ccAttr.setCacheName( regName );
return ccAttr;
}
/** */
protected IElementAttributes
parseElementAttributes( Properties props,
String regName,
String regionPrefix )
{
IElementAttributes eAttr;
String attrName = regionPrefix + regName + this.ELEMENT_ATTRIBUTE_PREFIX;
// auxFactory was not previously initialized.
//String prefix = regionPrefix + regName + ATTRIBUTE_PREFIX;
eAttr = ( IElementAttributes ) OptionConverter.instantiateByKey( props, attrName,
org.apache.stratum.jcs.engine.behavior.IElementAttributes.class,
null );
if ( eAttr == null )
{
log.warn( "Could not instantiate eAttr named '" + attrName +
"', using defaults." );
IElementAttributes eAttr2 = ccMgr.getDefaultElementAttributes();
eAttr = eAttr2.copy();
}
log.debug( "Parsing options for '" + attrName + "'" );
PropertySetter.setProperties( eAttr, props, attrName + "." );
//eAttr.setCacheName( regName );
log.debug( "End of parsing for \"" + attrName + "\"." );
// GET CACHE FROM FACTORY WITH ATTRIBUTES
//eAttr.setCacheName( regName );
return eAttr;
}
/** Get an aux cache for the listed aux for a region. */
protected ICache parseAuxiliary( Properties props,
String auxName,
String regName )
{
ICache auxCache;
// GET FACTORY
IAuxiliaryCacheFactory auxFac = ccMgr.registryFacGet( auxName );
if ( auxFac == null )
{
// auxFactory was not previously initialized.
String prefix = AUXILIARY_PREFIX + auxName;
auxFac = ( IAuxiliaryCacheFactory ) OptionConverter.instantiateByKey( props, prefix,
org.apache.stratum.jcs.auxiliary.behavior.IAuxiliaryCacheFactory.class,
null );
if ( auxFac == null )
{
log.error( "Could not instantiate auxFactory named \"" + auxName + "\"." );
return null;
}
auxFac.setName( auxName );
ccMgr.registryFacPut( auxFac );
}
// GET ATTRIBUTES
IAuxiliaryCacheAttributes auxAttr = ccMgr.registryAttrGet( auxName );
String attrName = AUXILIARY_PREFIX + auxName + ATTRIBUTE_PREFIX;
if ( auxAttr == null )
{
// auxFactory was not previously initialized.
String prefix = AUXILIARY_PREFIX + auxName + ATTRIBUTE_PREFIX;
auxAttr = ( IAuxiliaryCacheAttributes ) OptionConverter.instantiateByKey( props, prefix,
org.apache.stratum.jcs.auxiliary.behavior.IAuxiliaryCacheAttributes.class,
null );
if ( auxFac == null )
{
log.error( "Could not instantiate auxAttr named '" + attrName + "'" );
return null;
}
auxAttr.setName( auxName );
ccMgr.registryAttrPut( auxAttr );
}
auxAttr = auxAttr.copy();
log.debug( "Parsing options for '" + attrName + "'" );
PropertySetter.setProperties( auxAttr, props, attrName + "." );
auxAttr.setCacheName( regName );
log.debug( "End of parsing for '" + attrName + "'" );
// GET CACHE FROM FACTORY WITH ATTRIBUTES
auxAttr.setCacheName( regName );
auxCache = auxFac.createCache( auxAttr );
return auxCache;
}
}