com.legstar.config.commons.LegStarConfigCommons.java Source code

Java tutorial

Introduction

Here is the source code for com.legstar.config.commons.LegStarConfigCommons.java

Source

/*******************************************************************************
 * Copyright (c) 2010 LegSem.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     LegSem - initial API and implementation
 ******************************************************************************/
package com.legstar.config.commons;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.DefaultConfigurationBuilder;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.legstar.config.LegStarConfigurationException;
import com.legstar.coxb.util.ClassLoadingException;
import com.legstar.coxb.util.ClassUtil;
import com.legstar.config.PoolingEngineConfig;
import com.legstar.messaging.ConnectionFactory;
import com.legstar.messaging.HostEndpoint;
import com.legstar.messaging.LegStarAddress;
import com.legstar.messaging.HostEndpoint.AccessStrategy;

/**
 * A configuration system based on apache commons configuration.
 * 
 */
public class LegStarConfigCommons {

    /** XML Configuration. */
    private HierarchicalConfiguration _generalConfig;

    /** Configuration XPath location for an endpoint. */
    public static final String HOST_ENDPOINT_KEY = "hostEndPoints/hostEndPoint";

    /** Configuration key giving the work manager JNDI location. */
    private static final String WORK_MANAGER_LOCATION_KEY = "engine/workManager/threadPool/JNDILocation";

    /** Configuration key giving the work manager thread pool size. */
    private static final String WORK_MANAGER_THREAD_POOL_SIZE_KEY = "engine/workManager/defaultThreadPool/size";

    /**
     * Configuration key giving maximum number of requests waiting to
     * be serviced.
     */
    private static final String POOLING_MAXIMUM_REQUESTS_KEY = "engine/maxRequests";

    /**
     * the maximum time (milliseconds) to wait for a pooled connection to become
     * available.
     */
    private static final String TAKE_TIMEOUT_KEY = "engine/takeTimeout";

    /** Logger. */
    private final Log _log = LogFactory.getLog(getClass());

    /**
     * Construct from a configuration file.
     * 
     * @param generalConfigFileName the configuration file name
     * @throws LegStarConfigurationException if configuration file cannot be
     *             found or is invalid
     */
    public LegStarConfigCommons(final String generalConfigFileName) throws LegStarConfigurationException {
        _generalConfig = loadGeneralConfig(generalConfigFileName);
    }

    /**
     * Lookup and endpoint by name.
     * 
     * @param endpointName the endpoint name and identifier
     *            matches the requested endpoint name
     * @return a host endpoint
     * @throws LegStarConfigurationException if endpoint not found
     */
    public HostEndpoint getHostEndpoint(final String endpointName) throws LegStarConfigurationException {
        if (_log.isDebugEnabled()) {
            _log.debug("Looking up endpoint: " + endpointName);
        }
        String strXPath = HOST_ENDPOINT_KEY + "[@name='" + endpointName + "']";
        List<?> endpoints = _generalConfig.configurationsAt(strXPath);
        if (endpoints == null || endpoints.isEmpty()) {
            throw new LegStarConfigurationException("The requested endpoint:" + endpointName + " is not defined.");
        }
        return getHostEndpoint((HierarchicalConfiguration) endpoints.get(0));
    }

    /**
     * lookup an endpoint corresponding to a given address. If the address
     * is empty or does not specify an endpoint name, we return a default.
     * 
     * @param address the address to match with an endpoint
     * @return the matching endpoint or the default one
     * @throws LegStarConfigurationException if no endpoint can be returned
     */
    public HostEndpoint getHostEndpoint(final LegStarAddress address) throws LegStarConfigurationException {
        if (_log.isDebugEnabled()) {
            _log.debug("Searching for an endpoint matching address: " + address);
        }
        if (address == null || address.getEndPointName() == null || address.getEndPointName().length() == 0) {
            return getDefaultHostEndpoint();
        } else {
            return getHostEndpoint(address.getEndPointName());
        }
    }

    /**
     * Lookup the default endpoint configuration.
     * 
     * @return the default host endpoint
     * @throws LegStarConfigurationException if no endpoints found
     */
    public HostEndpoint getDefaultHostEndpoint() throws LegStarConfigurationException {
        if (_log.isDebugEnabled()) {
            _log.debug("Searching for default endpoint");
        }
        String strXPath = HOST_ENDPOINT_KEY;
        List<?> endpoints = _generalConfig.configurationsAt(strXPath);
        if (endpoints == null || endpoints.isEmpty()) {
            throw new LegStarConfigurationException("There are no endpoints defined.");
        }
        return getHostEndpoint((HierarchicalConfiguration) endpoints.get(0));
    }

    /**
     * @return the list of all available host endpoints.
     * @throws LegStarConfigurationException if configuration is invalid
     */
    @SuppressWarnings("unchecked")
    public List<HostEndpoint> getHostEndpoints() throws LegStarConfigurationException {
        if (_log.isDebugEnabled()) {
            _log.debug("Searching for all endpoints");
        }
        List<HostEndpoint> endpoints = new ArrayList<HostEndpoint>();
        String strXPath = HOST_ENDPOINT_KEY;
        List<HierarchicalConfiguration> endpointConfigs = (List<HierarchicalConfiguration>) _generalConfig
                .configurationsAt(strXPath);
        for (HierarchicalConfiguration endpointConfig : endpointConfigs) {
            endpoints.add(getHostEndpoint(endpointConfig));
        }

        return endpoints;
    }

    /**
     * @return the pooling engine configuration
     * @throws LegStarConfigurationException if cannot be created
     */
    public PoolingEngineConfig getPoolingEngineConfig() throws LegStarConfigurationException {
        if (_log.isDebugEnabled()) {
            _log.debug("Searching for pooling engine configuration");
        }
        PoolingEngineConfig poolingEngineConfig = new PoolingEngineConfig();
        poolingEngineConfig.setMaxRequests(
                _generalConfig.getInt(POOLING_MAXIMUM_REQUESTS_KEY, PoolingEngineConfig.DEFAULT_MAXIMUM_REQUESTS));
        poolingEngineConfig.setThreadPoolSize(_generalConfig.getInt(WORK_MANAGER_THREAD_POOL_SIZE_KEY,
                PoolingEngineConfig.DEFAULT_THREAD_POOL_SIZE));
        poolingEngineConfig.setWorkManagerJNDILocation(_generalConfig.getString(WORK_MANAGER_LOCATION_KEY));
        poolingEngineConfig.setHostEndpoints(getHostEndpoints());
        poolingEngineConfig
                .setTakeTimeout(_generalConfig.getInt(TAKE_TIMEOUT_KEY, PoolingEngineConfig.DEFAULT_TAKE_TIMEOUT));
        return poolingEngineConfig;
    }

    /**
     * Loads an XML configuration from file.
     * 
     * @param configFileName the configuration file name
     * @return the in-memory XML configuration
     * @throws LegStarConfigurationException if configuration failed to load
     */
    protected HierarchicalConfiguration loadGeneralConfig(final String configFileName)
            throws LegStarConfigurationException {
        try {
            if (_log.isDebugEnabled()) {
                _log.debug("Loading configuration file: " + configFileName);
            }
            /* First try as if it is a single configuration file */
            HierarchicalConfiguration generalConfig = new XMLConfiguration(configFileName);
            /*
             * If the first tag is additional, then this is a combined
             * configuration
             * that needs to be loaded in a specific way.
             */
            if (generalConfig.configurationsAt("additional").size() > 0) {
                DefaultConfigurationBuilder dcb = new DefaultConfigurationBuilder();
                dcb.setFileName(configFileName);
                generalConfig = (HierarchicalConfiguration) dcb.getConfiguration(true)
                        .getConfiguration(DefaultConfigurationBuilder.ADDITIONAL_NAME);
            }
            generalConfig.setExpressionEngine(new XPathExpressionEngine());
            return generalConfig;
        } catch (ConfigurationException e) {
            throw new LegStarConfigurationException(e);
        }
    }

    /**
     * Turn a commons configuration tree into a bean.
     * 
     * @param endpointConfig the commons configuration subtree
     * @return a host endpoint bean
     * @throws LegStarConfigurationException if bean cannot be created
     */
    protected HostEndpoint getHostEndpoint(final HierarchicalConfiguration endpointConfig)
            throws LegStarConfigurationException {
        ConnectionFactory connectionFactory = loadConnectionFactory(endpointConfig);
        HostEndpoint endpoint = connectionFactory.createEndpoint();
        setValues(endpoint, endpointConfig);
        return endpoint;
    }

    /**
     * The connection factory shields the client from transport. To
     * achieve this we use the abstract factory pattern to load a
     * connection factory dynamically.
     * 
     * @param endpointConfig the endpoint configuration
     * @return a new connection factory
     * @throws LegStarConfigurationException if connection factory cannot be
     *             created
     */
    protected ConnectionFactory loadConnectionFactory(final HierarchicalConfiguration endpointConfig)
            throws LegStarConfigurationException {

        /* Get the name of the connection factory from the configuration */
        String factoryClass = endpointConfig.getString(HostEndpoint.HOST_CONNECTION_FACTORY_CLASS_LABEL);
        if (factoryClass == null || factoryClass.length() == 0) {
            throw new LegStarConfigurationException("There are no connection factories in the configuration.");
        }

        if (_log.isDebugEnabled()) {
            _log.debug("Loading connection factory class: " + factoryClass);
        }
        try {
            return (ConnectionFactory) ClassUtil.newObject(factoryClass);
        } catch (SecurityException e) {
            throw new LegStarConfigurationException(e);
        } catch (IllegalArgumentException e) {
            throw new LegStarConfigurationException(e);
        } catch (ClassLoadingException e) {
            throw new LegStarConfigurationException(e);
        }
    }

    /**
     * Sets bean members using configuration attributes.
     * 
     * @param endpoint the bean
     * @param endpointConfig the configuration hierarchy
     * @throws LegStarConfigurationException if setting value on bean fails
     */
    protected void setValues(final Object endpoint, final HierarchicalConfiguration endpointConfig)
            throws LegStarConfigurationException {
        for (Iterator<?> iterator = endpointConfig.getKeys(); iterator.hasNext();) {
            String key = (String) iterator.next();
            setValue(endpoint, key, endpointConfig.getString(key));
        }
    }

    /**
     * For a given configuration key and value locate a corresponding
     * setter method and use it.
     * 
     * @param o the bean to set
     * @param key the configuration key
     * @param value the configuration value
     * @throws LegStarConfigurationException if setting value on bean fails
     */
    protected void setValue(final Object o, final String key, final String value)
            throws LegStarConfigurationException {
        String setterName = getSetterName(key);
        if (_log.isDebugEnabled()) {
            _log.debug("Using setter method: " + setterName + ", for value: " + value);
        }
        try {
            Method[] allMethods = o.getClass().getMethods();
            for (Method method : allMethods) {
                if (method.getName().equals(setterName)) {
                    method.setAccessible(true);
                    Class<?> parm = (Class<?>) method.getGenericParameterTypes()[0];
                    if (parm.isAssignableFrom(String.class)) {
                        method.invoke(o, value);
                        break;
                    }
                    if (parm.isAssignableFrom(boolean.class)) {
                        method.invoke(o, Boolean.parseBoolean(value));
                        break;
                    }
                    if (parm.isAssignableFrom(int.class)) {
                        method.invoke(o, Integer.parseInt(value));
                        break;
                    }
                    if (parm.isAssignableFrom(long.class)) {
                        method.invoke(o, Long.parseLong(value));
                        break;
                    }
                    if (parm.isAssignableFrom(HostEndpoint.AccessStrategy.class)) {
                        method.invoke(o, AccessStrategy.valueOf(value));
                        break;
                    }
                    _log.warn("Setter method: " + setterName + ", parameter type: " + parm
                            + ", not compatible with value: " + value);
                }
            }
        } catch (SecurityException e) {
            throw new LegStarConfigurationException(e);
        } catch (IllegalArgumentException e) {
            throw new LegStarConfigurationException(e);
        } catch (IllegalAccessException e) {
            throw new LegStarConfigurationException(e);
        } catch (InvocationTargetException e) {
            throw new LegStarConfigurationException(e);
        }
    }

    /**
     * Return a setter method name corresponding of a configuration parameter.
     * 
     * @param key the configuration parameter key
     * @return a bean setter method name
     */
    protected static String getSetterName(final String key) {
        String setterName = key;
        if (setterName == null || setterName.length() == 0) {
            return null;
        }
        if (setterName.charAt(0) == '@') {
            setterName = setterName.substring(1);
        }
        String prefix = "set" + setterName.substring(0, 1).toUpperCase(Locale.getDefault());
        return prefix + setterName.substring(1);

    }
}