/*
* 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.classpool.base;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.Properties;
import org.jboss.logging.Logger;
import org.jboss.util.CachePolicy;
import org.jboss.util.LRUCachePolicy;
import org.jboss.util.TimedCachePolicy;
/**
*
* @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
* @version $Revision: 1.1 $
*/
public class CtClassCacheFactory
{
private static final Logger log = Logger.getLogger(Logger.class);
public static final String POLICY_CLASS = "org.jboss.classpool.policy";
public static final String TIMED_POLICY_LIFETIME = "org.jboss.classpool.policy.lifetime";
public static final String TIMED_POLICY_RESOLUTION = "org.jboss.classpool.policy.resolution";
public static final String LRU_POLICY_MIN = "org.jboss.classpool.policy.min";
public static final String LRU_POLICY_MAX = "org.jboss.classpool.policy.max";
public static final int DEFAULT_TIMED_POLICY_LIFETIME = 20;
public static final int DEFAULT_TIMED_POLICY_RESOLUTION = 3;
public static final int DEFAULT_LRU_POLICY_MIN = 10;
public static final int DEFAULT_LRU_POLICY_MAX = 100;
private volatile Class<? extends CachePolicy> policyClass;
private volatile int lifetime;
private volatile int resolution;
private volatile int min;
private volatile int max;
public static CtClassCacheFactory createFromProperties()
{
return createFromProperties(System.getProperties());
}
public static CtClassCacheFactory createFromProperties(Properties properties)
{
CtClassCacheFactory initializer = new CtClassCacheFactory();
String policy = properties.getProperty(POLICY_CLASS, null);
if (policy == null)
return null;
try
{
Class<?> clazz = Class.forName(policy);
if (CachePolicy.class.isAssignableFrom(clazz) == false)
throw new IllegalStateException(clazz + " is not an instance of " + CachePolicy.class.getName());
else
initializer.policyClass = (Class<? extends CachePolicy>)clazz;
}
catch(Exception e)
{
throw new IllegalStateException("Could not load policy class " + policy, e);
}
if (TimedCachePolicy.class.isAssignableFrom(initializer.policyClass))
{
initializer.lifetime = parsePropertyIntoInteger(properties, TIMED_POLICY_LIFETIME, DEFAULT_TIMED_POLICY_LIFETIME);
initializer.resolution = parsePropertyIntoInteger(properties, TIMED_POLICY_RESOLUTION, DEFAULT_TIMED_POLICY_RESOLUTION);
warnUnusedParameters(properties, initializer.policyClass, LRU_POLICY_MIN, LRU_POLICY_MAX);
}
else if (LRUCachePolicy.class.isAssignableFrom(initializer.policyClass))
{
initializer.min = parsePropertyIntoInteger(properties, LRU_POLICY_MIN, DEFAULT_LRU_POLICY_MIN);
initializer.max = parsePropertyIntoInteger(properties, LRU_POLICY_MAX, DEFAULT_LRU_POLICY_MAX);
warnUnusedParameters(properties, initializer.policyClass, TIMED_POLICY_LIFETIME, TIMED_POLICY_RESOLUTION);
}
else
{
try
{
Constructor<?> ctor = initializer.policyClass.getConstructor();
if (!Modifier.isPublic(ctor.getModifiers()))
throw new IllegalStateException("Unknown policy class " + initializer.policyClass.getName() + " has a default constructor, but it is not public");
}
catch(NoSuchMethodException e)
{
throw new IllegalStateException("Unknown policy class " + initializer.policyClass.getName() + " does not have a default constructor");
}
}
return initializer;
}
public CtClassCache createCache()
{
CachePolicy policy = null;
if (policyClass == TimedCachePolicy.class)
policy = new TimedCachePolicy(lifetime, true, resolution);
else if (policyClass == LRUCachePolicy.class)
policy = new LRUCachePolicy(min, max);
else
{
try
{
policy = policyClass.newInstance();
}
catch(Exception e)
{
throw new IllegalStateException("Could not instantiate " + policyClass.getName(), e);
}
}
try
{
policy.create();
policy.start();
}
catch(Exception e)
{
throw new IllegalStateException("Error starting domain cache", e);
}
return new CtClassCache(policy);
}
/**
* Get the policyClass
* @return the policyClass
*/
public Class<? extends CachePolicy> getPolicyClass()
{
return policyClass;
}
/**
* Get the lifetime
* @return the lifetime
*/
public int getLifetime()
{
return lifetime;
}
/**
* Get the resolution
* @return the resolution
*/
public int getResolution()
{
return resolution;
}
/**
* Get the min
* @return the min
*/
public int getMin()
{
return min;
}
/**
* Get the max
* @return the max
*/
public int getMax()
{
return max;
}
private static int parsePropertyIntoInteger(Properties properties, String key, int defaultValue)
{
try
{
return Integer.valueOf(properties.getProperty(key, String.valueOf(defaultValue)));
}
catch(NumberFormatException e)
{
throw new IllegalStateException("The value " + properties.getProperty(key) + " for '" + key + "' is not a number");
}
}
private static void warnUnusedParameters(Properties properties, Class<?> clazz, String...keys)
{
for (String key : keys)
{
if (properties.getProperty(key) != null)
{
log.warn("Ignoring unrecognized property " + key + " for policy class" + clazz);
}
}
}
}