
org.ow2.cmi.lb.util.PolicyFactory Maven / Gradle / Ivy
/**
* CMI : Cluster Method Invocation
* Copyright (C) 2007,2008 Bull S.A.S.
* Contact: [email protected]
*
* This library 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 library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
* --------------------------------------------------------------------------
* $Id:LBPolicyFactory.java 1124 2007-07-27 16:38:35Z loris $
* --------------------------------------------------------------------------
*/
package org.ow2.cmi.lb.util;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import net.jcip.annotations.ThreadSafe;
import org.ow2.cmi.controller.common.ClusterViewManager;
import org.ow2.cmi.controller.common.ClusterViewManagerException;
import org.ow2.cmi.lb.LoadBalanceable;
import org.ow2.cmi.lb.PropertyConfigurationException;
import org.ow2.cmi.lb.data.PropertyData;
import org.ow2.cmi.lb.policy.IPolicy;
import org.ow2.cmi.lb.strategy.IStrategy;
import org.ow2.cmi.reference.ObjectNotFoundException;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;
/**
* Define a factory to construct policies.
* @param the type parameter of the constructed policies
* @author The new CMI team
*/
@ThreadSafe
public final class PolicyFactory {
/**
* Logger.
*/
private static final Log LOGGER = LogFactory.getLog(PolicyFactory.class);
/**
* A manager to retrieve the cluster view.
*/
private final ClusterViewManager clusterViewManager;
/**
* Map each classname of policy with its properties.
*/
private static ConcurrentHashMap> policyClassName2PropertyData =
new ConcurrentHashMap>();
/**
* Constructs a new factory for policies with a given manager of cluster view.
* @param clusterViewManager a manager to retrieve the cluster view
*/
public PolicyFactory(final ClusterViewManager clusterViewManager) {
this.clusterViewManager = clusterViewManager;
}
/**
* Returns a policy to access to the object with the given name.
* @param objectName a name of object
* @return a policy to access to the object with the given name
* @throws PolicyFactoryException if the policy cannot be constructed
* @throws ObjectNotFoundException if none object has the given name
*/
@SuppressWarnings("unchecked")
public IPolicy getPolicy(final String objectName)
throws PolicyFactoryException, ObjectNotFoundException {
Class extends IPolicy> policyClass;
try {
policyClass = (Class extends IPolicy>) clusterViewManager.getPolicyClass(objectName);
} catch (ClusterViewManagerException e) {
LOGGER.error("Error while finding the policy class", e);
throw new PolicyFactoryException("Error while finding the policy class", e);
}
Map properties = clusterViewManager.getPropertiesForPolicy(objectName);
Class extends IStrategy> strategyClass;
try {
strategyClass = (Class extends IStrategy>) clusterViewManager.getStrategyClass(objectName);
} catch (ClusterViewManagerException e) {
LOGGER.error("Error while finding the strategy class", e);
throw new PolicyFactoryException("Error while finding the strategy class", e);
}
return getPolicy(policyClass, strategyClass, properties);
}
/**
* Returns a policy for the given classes of policy, strategy and properties.
* @param policyClass
* @param strategyClass
* @param properties
* @return a policy to access to the object with the given name
* @throws PolicyFactoryException if the policy cannot be constructed
*/
@SuppressWarnings("unchecked")
public IPolicy getPolicy(
final Class extends IPolicy> policyClass, final Class extends IStrategy> strategyClass,
final Map properties)
throws PolicyFactoryException {
IPolicy policy = createPolicy(policyClass);
try {
findProperties(policy.getClass());
} catch (PropertyConfigurationException e) {
LOGGER.error("Error while finding properties", e);
throw new PolicyFactoryException("Error while finding properties", e);
}
if(properties != null) {
try {
setProperties(policy, properties);
} catch (PropertyConfigurationException e) {
LOGGER.error("Error while configuring the properties", e);
throw new PolicyFactoryException("Error while configuring the properties", e);
}
}
IStrategy strategy = createStrategy(strategyClass);
policy.setStrategy(strategy);
return policy;
}
/**
* Find properties in a class defining policy.
* @param policyClass a class defining policy
* @throws PropertyConfigurationException
*/
@SuppressWarnings("unchecked")
private static void findProperties(final Class extends IPolicy> policyClass)
throws PropertyConfigurationException {
String policyClassname = policyClass.getName();
if(policyClassName2PropertyData.containsKey(policyClassname)) {
return;
}
ConcurrentHashMap properties =
new ConcurrentHashMap();
for(Method method : policyClass.getDeclaredMethods()) {
String methodName = method.getName();
if(methodName.startsWith("get") && !methodName.equals("getStrategy")) {
PropertyData propertyData =
new PropertyData(method, (Class extends IPolicy>>) policyClass);
properties.putIfAbsent(
propertyData.getPropertyName(), propertyData);
}
}
policyClassName2PropertyData.putIfAbsent(policyClassname, properties);
}
/**
* Returns a pure policy for a given class.
* @param policyClass a class defining a policy
* @return a pure policy to access to the object with the given name
* @throws PolicyFactoryException if the policy cannot be constructed
*/
@SuppressWarnings("unchecked")
public IPolicy createPolicy(final Class extends IPolicy> policyClass) throws PolicyFactoryException {
IPolicy policy = null;
// Lookup if it exists a constructor with a parameter of type ClusterviewManager
Constructor>[] constructors = policyClass.getDeclaredConstructors();
for(Constructor> constructor : constructors) {
Class>[] paramTypes = constructor.getParameterTypes();
if(paramTypes.length == 1 && paramTypes[0].equals(ClusterViewManager.class)) {
try {
policy = (IPolicy) constructor.newInstance(clusterViewManager);
} catch (Exception e) {
LOGGER.error("Cannot construct the policy with the instance of ClusterViewManager", e);
throw new PolicyFactoryException(
"Cannot construct the policy with the instance of ClusterViewManager", e);
}
break;
}
}
// Use the default constructor
if(policy == null) {
try {
policy = policyClass.newInstance();
} catch (Exception e) {
LOGGER.error("Cannot construct the LB policy", e);
throw new PolicyFactoryException("Cannot construct the LB policy", e);
}
}
// Find a setter for cluster view manager
try {
Method setter = policyClass.getMethod("setClusterViewManager", ClusterViewManager.class);
setter.invoke(policy, clusterViewManager);
} catch (Exception e) {
LOGGER.debug("Cannot set the manager of cluster view", e);
}
return policy;
}
/**
* Sets properties for a given policy.
* @param policy a policy
* @param properties properties of the policy
* @throws PropertyConfigurationException if a property cannot be set
*/
private void setProperties(final IPolicy policy, final Map properties)
throws PropertyConfigurationException {
for(Entry propertyEntry : properties.entrySet()) {
setProperty(policy, propertyEntry.getKey(), propertyEntry.getValue());
}
}
/**
* Set a property for a given policy.
* @param policy a policy
* @param propertyName a name of property
* @param propertyValue a value of property
* @throws PropertyConfigurationException
*/
@SuppressWarnings("unchecked")
private void setProperty(
final IPolicy policy, final String propertyName, final Object propertyValue)
throws PropertyConfigurationException {
Class extends IPolicy> policyClass = policy.getClass();
PropertyData propertyData =
policyClassName2PropertyData.get(policyClass.getName()).get(propertyName);
try {
propertyData.getSetter().invoke(policy, propertyValue);
} catch (Exception e) {
LOGGER.error("Cannot set the property for name {0} with {1}",
propertyName, propertyValue, e);
throw new PropertyConfigurationException(
"Cannot set the property for name "
+ propertyName + " with "
+ propertyValue, e);
}
}
/**
* Returns a strategy for a given class.
* @param strategyClass a class defining a strategy
* @return a strategy to access to the object with the given name
* @throws PolicyFactoryException if the strategy cannot be constructed
*/
@SuppressWarnings("unchecked")
private IStrategy createStrategy(final Class extends IStrategy> strategyClass)
throws PolicyFactoryException {
IStrategy strategy = null;
// Lookup if it exists a constructor with a parameter of type ClusterviewManager
Constructor>[] constructors = strategyClass.getDeclaredConstructors();
for(Constructor> constructor : constructors) {
Class>[] paramTypes = constructor.getParameterTypes();
if(paramTypes.length == 1 && paramTypes[0].equals(ClusterViewManager.class)) {
try {
strategy = (IStrategy) constructor.newInstance(clusterViewManager);
} catch (Exception e) {
LOGGER.error("Cannot construct the strategy with the instance of ClusterViewManager", e);
throw new PolicyFactoryException(
"Cannot construct the strategy with the instance of ClusterViewManager", e);
}
break;
}
}
// Use the default constructor
if(strategy == null) {
try {
strategy = strategyClass.newInstance();
} catch (Exception e) {
LOGGER.error("Cannot construct the strategy with the default constructor", e);
throw new PolicyFactoryException("Cannot construct the strategy with the default constructor", e);
}
}
return strategy;
}
//-------------------- Access to properties ---------------------------------------------------
// TODO Should be externalized in a separate class
@SuppressWarnings("unchecked")
public static Map getProperties(final IPolicy> policy)
throws PropertyConfigurationException {
Class extends IPolicy> policyClass = policy.getClass();
// Check if properties have initialized
findProperties(policyClass);
Map propertyData =
policyClassName2PropertyData.get(policyClass.getName());
Map properties = new HashMap();
Object propertyValue;
for(String propertyName : propertyData.keySet()) {
propertyValue = getProperty(policy, propertyName);
properties.put(propertyName, propertyValue);
}
return properties;
}
@SuppressWarnings("unchecked")
public static Object getProperty(final IPolicy> policy, final String propertyName) throws PropertyConfigurationException {
Class extends IPolicy> policyClass = policy.getClass();
// Check if properties have initialized
findProperties(policyClass);
Map propertyData =
policyClassName2PropertyData.get(policyClass.getName());
PropertyData property = propertyData.get(propertyName);
try {
return property.getGetter().invoke(policy);
} catch (Exception e) {
LOGGER.error("Cannot invoke the getter for property {0}", propertyName, e);
return null;
}
}
@SuppressWarnings("unchecked")
public static Type getPropertyRawType(
final Class extends IPolicy> policyClass, final String propertyName)
throws PropertyConfigurationException {
Type propertyType = getPropertyType(policyClass, propertyName);
if(propertyType instanceof ParameterizedType) {
return ((ParameterizedType) propertyType).getRawType();
} else {
return propertyType;
}
}
@SuppressWarnings("unchecked")
public static Type getPropertyType(
final Class extends IPolicy> policyClass, final String propertyName) throws PropertyConfigurationException {
// Check if properties have initialized
findProperties(policyClass);
return policyClassName2PropertyData.get(policyClass.getName()).get(propertyName).getPropertyType();
}
@SuppressWarnings("unchecked")
public static Map getPropertyData(
final Class extends IPolicy> policyClass)
throws PropertyConfigurationException {
// Check if properties have initialized
findProperties(policyClass);
return policyClassName2PropertyData.get(policyClass.getName());
}
/**
* Converts the given value from String to the given type.
* @param propertyName the property name
* @param svalue a value
* @return an object that has the same that the given field
* @throws PropertyConfigurationException if the conversion is not possible
*/
@SuppressWarnings("unchecked")
public static Object convertString(
final Class extends IPolicy> policyClass,
final String propertyName,
final String svalue) throws PropertyConfigurationException {
Type propertyType = getPropertyType(policyClass, propertyName);
return convertString(propertyType, svalue);
}
public static Object convertString(
final Type propertyType,
final String svalue) throws PropertyConfigurationException {
Type type;
if(propertyType instanceof ParameterizedType) {
type = ((ParameterizedType) propertyType).getRawType();
} else {
type = propertyType;
}
Class> klass = (Class>) type;
Object propertyValue;
// Attempt to cast String forward a primitive type
if(klass.equals(String.class)) {
propertyValue = svalue;
} else if(klass.equals(boolean.class) || klass.equals(Boolean.class)) {
propertyValue = Boolean.valueOf(svalue);
} else if(klass.equals(byte.class) || klass.equals(Byte.class)) {
propertyValue = Byte.valueOf(svalue);
} else if(klass.equals(int.class) || klass.equals(Integer.class)) {
propertyValue = Integer.valueOf(svalue);
} else if(klass.equals(long.class) || klass.equals(Long.class)) {
propertyValue = Long.valueOf(svalue);
} else if(klass.equals(float.class) || klass.equals(Float.class)) {
propertyValue = Float.valueOf(svalue);
} else if(klass.equals(double.class) || klass.equals(Double.class)) {
propertyValue = Double.valueOf(svalue);
} else if(klass.equals(URL.class)){ // Try with some complex type
try {
propertyValue = new URL(svalue);
} catch (MalformedURLException e) {
throw new PropertyConfigurationException("Cannot convert the string " + svalue + " to an URL", e);
}
} else if(klass.equals(File.class)) {
propertyValue = new File(svalue);
} else if(klass.equals(Class.class)) {
try {
propertyValue = Class.forName(svalue);
} catch (ClassNotFoundException e) {
throw new PropertyConfigurationException("Cannot convert the string " + svalue + " to a class", e);
}
} else {
LOGGER.error("Type of field not supported: {0}", klass.getName());
throw new PropertyConfigurationException(
"Type of field not supported: " + klass.getName());
}
return propertyValue;
}
@SuppressWarnings("unchecked")
public static List> convertStrings(
final Class extends IPolicy> policyClass,
final String propertyName,
final List slist)throws PropertyConfigurationException {
Type parameterizedType = getPropertyType(policyClass, propertyName);
if(!(parameterizedType instanceof ParameterizedType)) {
LOGGER.error("{0} is not a parameterized type: cannot convert the elements of this collection", parameterizedType);
throw new PropertyConfigurationException(
parameterizedType + "is not a parameterized type: cannot convert the elements of this collection");
}
Type propertyType = ((ParameterizedType) parameterizedType).getActualTypeArguments()[0];
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy