/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.springframework.data.gemfire.config.annotation;
import java.util.Map;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.client.PoolFactoryBean;
import org.springframework.data.gemfire.support.ConnectionEndpoint;
import org.springframework.data.gemfire.support.ConnectionEndpointList;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* The {@link AddCacheServerConfiguration} class is a Spring {@link ImportBeanDefinitionRegistrar} that registers
* a {@link PoolFactoryBean} definition for the {@link org.apache.geode.cache.client.Pool}
* configuration meta-data defined in {@link EnablePool}.
*
* @author John Blum
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar
* @see org.springframework.data.gemfire.config.annotation.EnablePool
* @since 1.9.0
*/
public class AddPoolConfiguration implements ImportBeanDefinitionRegistrar {
/**
* {@inheritDoc}
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (importingClassMetadata.hasAnnotation(EnablePool.class.getName())) {
Map<String, Object> enablePoolAttributes = importingClassMetadata.getAnnotationAttributes(
EnablePool.class.getName());
registerPoolFactoryBeanDefinition(enablePoolAttributes, registry);
}
}
/**
* Registers a {@link PoolFactoryBean} definition in the Spring application context configured with
* the {@link EnablePool} annotation meta-data.
*
* @param enablePoolAttributes {@link EnablePool} annotation attributes.
* @param registry Spring {@link BeanDefinitionRegistry used to register the {@link PoolFactoryBean} definition.
* @see org.springframework.beans.factory.support.BeanDefinitionRegistry
* @see org.springframework.data.gemfire.client.PoolFactoryBean
* @see org.springframework.data.gemfire.config.annotation.EnablePool
* @see java.util.Map
*/
protected void registerPoolFactoryBeanDefinition(Map<String, Object> enablePoolAttributes,
BeanDefinitionRegistry registry) {
String poolName = getAndValidatePoolName(enablePoolAttributes);
BeanDefinitionBuilder poolFactoryBean = BeanDefinitionBuilder.genericBeanDefinition(PoolFactoryBean.class);
poolFactoryBean.addPropertyValue("freeConnectionTimeout", enablePoolAttributes.get("freeConnectionTimeout"));
poolFactoryBean.addPropertyValue("idleTimeout", enablePoolAttributes.get("idleTimeout"));
poolFactoryBean.addPropertyValue("loadConditioningInterval", enablePoolAttributes.get("loadConditioningInterval"));
poolFactoryBean.addPropertyValue("maxConnections", enablePoolAttributes.get("maxConnections"));
poolFactoryBean.addPropertyValue("minConnections", enablePoolAttributes.get("minConnections"));
poolFactoryBean.addPropertyValue("multiUserAuthentication", enablePoolAttributes.get("multiUserAuthentication"));
poolFactoryBean.addPropertyValue("pingInterval", enablePoolAttributes.get("pingInterval"));
poolFactoryBean.addPropertyValue("prSingleHopEnabled", enablePoolAttributes.get("prSingleHopEnabled"));
poolFactoryBean.addPropertyValue("readTimeout", enablePoolAttributes.get("readTimeout"));
poolFactoryBean.addPropertyValue("retryAttempts", enablePoolAttributes.get("retryAttempts"));
poolFactoryBean.addPropertyValue("serverGroup", enablePoolAttributes.get("serverGroup"));
poolFactoryBean.addPropertyValue("socketBufferSize", enablePoolAttributes.get("socketBufferSize"));
poolFactoryBean.addPropertyValue("statisticInterval", enablePoolAttributes.get("statisticInterval"));
poolFactoryBean.addPropertyValue("subscriptionAckInterval", enablePoolAttributes.get("subscriptionAckInterval"));
poolFactoryBean.addPropertyValue("subscriptionEnabled", enablePoolAttributes.get("subscriptionEnabled"));
poolFactoryBean.addPropertyValue("subscriptionMessageTrackingTimeout", enablePoolAttributes.get("subscriptionMessageTrackingTimeout"));
poolFactoryBean.addPropertyValue("subscriptionRedundancy", enablePoolAttributes.get("subscriptionRedundancy"));
poolFactoryBean.addPropertyValue("threadLocalConnections", enablePoolAttributes.get("threadLocalConnections"));
configurePoolConnections(enablePoolAttributes, poolFactoryBean);
registry.registerBeanDefinition(poolName, poolFactoryBean.getBeanDefinition());
}
protected String getAndValidatePoolName(Map<String, Object> enablePoolAttributes) {
String poolName = (String) enablePoolAttributes.get("name");
Assert.hasText(poolName, "Pool name must be specified");
return poolName;
}
/**
* Uses the list of GemFire Locator and Server connection endpoint definitions and meta-data to configure
* the GemFire client {@link org.apache.geode.cache.client.Pool} used to communicate with the servers
* in the GemFire cluster.
*
* @param enablePoolAttributes {@link EnablePool} annotation containing
* {@link org.apache.geode.cache.client.Pool} Locator/Server connection endpoint meta-data.
* @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication
* @see java.util.Map
*/
protected BeanDefinitionBuilder configurePoolConnections(Map<String, Object> enablePoolAttributes,
BeanDefinitionBuilder poolFactoryBean) {
configureLocators(enablePoolAttributes, poolFactoryBean);
configureServers(enablePoolAttributes, poolFactoryBean);
return poolFactoryBean;
}
protected BeanDefinitionBuilder configureLocators(Map<String, Object> enablePoolAttributes,
BeanDefinitionBuilder poolFactoryBean) {
poolFactoryBean.addPropertyValue("locators", parseConnectionEndpoints(enablePoolAttributes,
"locators", "locatorsString", GemfireUtils.DEFAULT_LOCATOR_PORT));
return poolFactoryBean;
}
protected BeanDefinitionBuilder configureServers(Map<String, Object> enablePoolAttributes,
BeanDefinitionBuilder poolFactoryBean) {
poolFactoryBean.addPropertyValue("servers", parseConnectionEndpoints(enablePoolAttributes,
"servers", "serversString", GemfireUtils.DEFAULT_CACHE_SERVER_PORT));
return poolFactoryBean;
}
protected ConnectionEndpointList parseConnectionEndpoints(Map<String, Object> enablePoolAttributes,
String arrayAttributeName, String stringAttributeName, int defaultPort) {
ConnectionEndpointList connectionEndpoints = new ConnectionEndpointList();
AnnotationAttributes[] connectionEndpointsMetaData =
(AnnotationAttributes[]) enablePoolAttributes.get(arrayAttributeName);
for (AnnotationAttributes annotationAttributes : connectionEndpointsMetaData) {
connectionEndpoints.add(newConnectionEndpoint((String) annotationAttributes.get("host"),
(Integer) annotationAttributes.get("port")));
}
String hostsPorts = (String) enablePoolAttributes.get(stringAttributeName);
if (StringUtils.hasText(hostsPorts)) {
connectionEndpoints.add(ConnectionEndpointList.parse(defaultPort, hostsPorts.split(",")));
}
return connectionEndpoints;
}
protected ConnectionEndpoint newConnectionEndpoint(String host, Integer port) {
return new ConnectionEndpoint(host, port);
}
}