SGF-569 - Move Off-Heap, Redis Adapter and Security Annotation config from apache-geode to SDG 2.0.x.
This commit is contained in:
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright 2016 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.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.internal.security.SecurityService;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.mgt.DefaultSecurityManager;
|
||||
import org.apache.shiro.realm.Realm;
|
||||
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* The {@link ApacheShiroSecurityConfiguration} class is a Spring {@link Configuration @Configuration} component
|
||||
* responsible for configuring and initializing the Apache Shiro security framework in order to secure Apache Geode
|
||||
* administrative and data access operations.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.internal.security.SecurityService
|
||||
* @see org.apache.shiro.mgt.DefaultSecurityManager
|
||||
* @see org.apache.shiro.realm.Realm
|
||||
* @see org.apache.shiro.spring.LifecycleBeanPostProcessor
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.beans.factory.ListableBeanFactory
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Condition
|
||||
* @see org.springframework.context.annotation.Conditional
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.config.annotation.ApacheShiroSecurityConfiguration.ApacheShiroPresentCondition
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Configuration
|
||||
@Conditional(ApacheShiroSecurityConfiguration.ApacheShiroPresentCondition.class)
|
||||
@SuppressWarnings("unused")
|
||||
public class ApacheShiroSecurityConfiguration implements BeanFactoryAware {
|
||||
|
||||
private ListableBeanFactory beanFactory;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory);
|
||||
this.beanFactory = (ListableBeanFactory) beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Spring {@link BeanFactory}.
|
||||
*
|
||||
* @return a reference to the Spring {@link BeanFactory}.
|
||||
* @throws IllegalStateException if the Spring {@link BeanFactory} was not properly initialized.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected ListableBeanFactory getBeanFactory() {
|
||||
Assert.state(this.beanFactory != null, "BeanFactory was not properly initialized");
|
||||
return this.beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Bean} definition to define, configure and register an Apache Shiro Spring
|
||||
* {@link LifecycleBeanPostProcessor} to automatically call lifecycle callback methods
|
||||
* on Shiro security components during Spring container initialization and destruction phases.
|
||||
*
|
||||
* @return an instance of the Apache Shiro Spring {@link LifecycleBeanPostProcessor} to handle the lifecycle
|
||||
* of Apache Shiro security framework components.
|
||||
* @see org.apache.shiro.spring.LifecycleBeanPostProcessor
|
||||
*/
|
||||
@Bean
|
||||
public BeanPostProcessor shiroLifecycleBeanPostProcessor() {
|
||||
return new LifecycleBeanPostProcessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Bean} definition to define, configure and register an Apache Shiro
|
||||
* {@link org.apache.shiro.mgt.SecurityManager} implementation to secure Apache Geode.
|
||||
*
|
||||
* The registration of this {@link Bean} definition is dependent upon whether the user is using Apache Shiro
|
||||
* to secure Apache Geode, which is determined by the presence of Apache Shiro {@link Realm Realms}
|
||||
* declared in the Spring {@link org.springframework.context.ApplicationContext}.
|
||||
*
|
||||
* This {@link Bean} definition declares a dependency on the Apache Geode {@link GemFireCache} instance
|
||||
* in order to ensure the Geode cache is created and initialized first. This ensures that any internal Geode
|
||||
* security configuration logic is evaluated and processed before SDG attempts to configure Apache Shiro
|
||||
* as Apache Geode's security provider.
|
||||
*
|
||||
* Additionally, this {@link Bean} definition will register the Apache Shiro
|
||||
* {@link org.apache.geode.security.SecurityManager} with the Apache Shiro security framework
|
||||
*
|
||||
* Finally, this method proceeds to enable Apache Geode security.
|
||||
|
||||
* @return an Apache Shiro {@link org.apache.shiro.mgt.SecurityManager} implementation used to secure Apache Geode.
|
||||
* @throws IllegalStateException if an Apache Shiro {@link org.apache.shiro.mgt.SecurityManager} was registered
|
||||
* with the Apache Shiro security framework but Apache Geode security could not be enabled.
|
||||
* @see org.apache.shiro.mgt.SecurityManager
|
||||
* @see #registerSecurityManager(org.apache.shiro.mgt.SecurityManager)
|
||||
* @see #enableApacheGeodeSecurity()
|
||||
* @see #resolveRealms()
|
||||
* @see #registerSecurityManager(org.apache.shiro.mgt.SecurityManager)
|
||||
* @see #enableApacheGeodeSecurity()
|
||||
*/
|
||||
@Bean
|
||||
public org.apache.shiro.mgt.SecurityManager shiroSecurityManager(GemFireCache gemfireCache) {
|
||||
org.apache.shiro.mgt.SecurityManager shiroSecurityManager = null;
|
||||
|
||||
List<Realm> realms = resolveRealms();
|
||||
|
||||
if (!realms.isEmpty()) {
|
||||
shiroSecurityManager = registerSecurityManager(new DefaultSecurityManager(realms));
|
||||
|
||||
if (!enableApacheGeodeSecurity()) {
|
||||
throw new IllegalStateException("Failed to enable security services in Apache Geode");
|
||||
}
|
||||
}
|
||||
|
||||
return shiroSecurityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves all the Apache Shiro {@link Realm Realms} declared and configured as Spring managed beans
|
||||
* in the Spring {@link org.springframework.context.ApplicationContext}.
|
||||
*
|
||||
* This method will order the Realms according to priority order to ensure that the Apache Shiro Realms
|
||||
* are applied in the correct sequence, as declared/configured.
|
||||
*
|
||||
* @return a {@link List} of all Apache Shiro {@link Realm Realms} declared and configured as Spring managed beans
|
||||
* in the Spring {@link org.springframework.context.ApplicationContext}.
|
||||
* @see org.springframework.beans.factory.ListableBeanFactory#getBeansOfType(Class, boolean, boolean)
|
||||
* @see org.springframework.core.OrderComparator
|
||||
* @see org.apache.shiro.realm.Realm
|
||||
*/
|
||||
protected List<Realm> resolveRealms() {
|
||||
try {
|
||||
Map<String, Realm> realmBeans = getBeanFactory().getBeansOfType(Realm.class, false, true);
|
||||
List<Realm> realms = new ArrayList<>(CollectionUtils.nullSafeMap(realmBeans).values());
|
||||
Collections.sort(realms, OrderComparator.INSTANCE);
|
||||
return realms;
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given Apache Shiro {@link org.apache.shiro.mgt.SecurityManager} with the Apache Shiro
|
||||
* security framework.
|
||||
*
|
||||
* @param securityManager {@link org.apache.shiro.mgt.SecurityManager} to register.
|
||||
* @return the given {@link org.apache.shiro.mgt.SecurityManager} reference.
|
||||
* @throws IllegalArgumentException if {@link org.apache.shiro.mgt.SecurityManager} is {@literal null}.
|
||||
* @see org.apache.shiro.SecurityUtils#setSecurityManager(org.apache.shiro.mgt.SecurityManager)
|
||||
* @see org.apache.shiro.mgt.SecurityManager
|
||||
*/
|
||||
protected org.apache.shiro.mgt.SecurityManager registerSecurityManager(
|
||||
org.apache.shiro.mgt.SecurityManager securityManager) {
|
||||
|
||||
Assert.notNull(securityManager, "The Apache Shiro SecurityManager to register must not be null");
|
||||
|
||||
SecurityUtils.setSecurityManager(securityManager);
|
||||
|
||||
return securityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Apache Geode, Integrated Security {@link SecurityService} property {@literal isIntegratedSecurity}
|
||||
* to {@literal true} to indicate that Apache Geode security is enabled.
|
||||
*
|
||||
* @return a boolean value indicating whether Apache Geode's Integrated Security framework services
|
||||
* were successfully enabled.
|
||||
* @see org.apache.geode.internal.security.SecurityService#getSecurityService()
|
||||
*/
|
||||
protected boolean enableApacheGeodeSecurity() {
|
||||
SecurityService securityService = SecurityService.getSecurityService();
|
||||
|
||||
if (securityService != null) {
|
||||
String isIntegratedSecurityFieldName = "isIntegratedSecurity";
|
||||
|
||||
Field isIntegratedSecurity = ReflectionUtils.findField(securityService.getClass(),
|
||||
isIntegratedSecurityFieldName, Boolean.class);
|
||||
|
||||
isIntegratedSecurity = (isIntegratedSecurity != null ? isIntegratedSecurity
|
||||
: ReflectionUtils.findField(securityService.getClass(), isIntegratedSecurityFieldName, Boolean.TYPE));
|
||||
|
||||
if (isIntegratedSecurity != null) {
|
||||
ReflectionUtils.makeAccessible(isIntegratedSecurity);
|
||||
ReflectionUtils.setField(isIntegratedSecurity, securityService, Boolean.TRUE);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Spring {@link Condition} to determine whether the user has included (declared) the 'shiro-spring' dependency
|
||||
* on their application's classpath, which is necessary for configuring Apache Shiro to secure Apache Geode
|
||||
* in a Spring context.
|
||||
*
|
||||
* @see org.springframework.context.annotation.Condition
|
||||
*/
|
||||
public static class ApacheShiroPresentCondition implements Condition {
|
||||
|
||||
protected static final String APACHE_SHIRO_LIFECYCLE_BEAN_POST_PROCESSOR_CLASS_NAME =
|
||||
"org.apache.shiro.spring.LifecycleBeanPostProcessor";
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
return ClassUtils.isPresent(APACHE_SHIRO_LIFECYCLE_BEAN_POST_PROCESSOR_CLASS_NAME,
|
||||
context.getClassLoader());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,43 +40,59 @@ public class AuthConfiguration extends EmbeddedServiceConfigurationSupport {
|
||||
|
||||
public static final String DEFAULT_SECURITY_LOG_LEVEL = "config";
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static final String GEMFIRE_SECURITY_PROPERTY_FILE = "gemfireSecurityPropertyFile";
|
||||
protected static final String SECURITY_CLIENT_ACCESSOR = "security-client-accessor";
|
||||
protected static final String SECURITY_CLIENT_ACCESSOR_POST_PROCESSOR = "security-client-accessor-pp";
|
||||
protected static final String SECURITY_CLIENT_AUTH_INIT = "security-client-auth-init";
|
||||
protected static final String SECURITY_CLIENT_AUTHENTICATOR = "security-client-authenticator";
|
||||
protected static final String SECURITY_CLIENT_DIFFIE_HELLMAN_ALGORITHM = "security-client-dhalgo";
|
||||
protected static final String SECURITY_LOG_FILE = "security-log-file";
|
||||
protected static final String SECURITY_LOG_LEVEL = "security-log-level";
|
||||
protected static final String SECURITY_PEER_AUTH_INIT = "security-peer-auth-init";
|
||||
protected static final String SECURITY_PEER_AUTHENTICATOR = "security-peer-authenticator";
|
||||
protected static final String SECURITY_PEER_VERIFY_MEMBER_TIMEOUT = "security-peer-verifymember-timeout";
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
protected Class getAnnotationType() {
|
||||
return EnableAuth.class;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {
|
||||
PropertiesBuilder gemfireProperties = PropertiesBuilder.create();
|
||||
|
||||
gemfireProperties.setProperty("gemfireSecurityPropertyFile", annotationAttributes.get("securityPropertiesFile"));
|
||||
gemfireProperties.setProperty(GEMFIRE_SECURITY_PROPERTY_FILE, annotationAttributes.get("securityPropertiesFile"));
|
||||
|
||||
gemfireProperties.setProperty("security-client-accessor", annotationAttributes.get("clientAccessor"));
|
||||
gemfireProperties.setProperty(SECURITY_CLIENT_ACCESSOR, annotationAttributes.get("clientAccessor"));
|
||||
|
||||
gemfireProperties.setProperty("security-client-accessor-pp",
|
||||
gemfireProperties.setProperty(SECURITY_CLIENT_ACCESSOR_POST_PROCESSOR,
|
||||
annotationAttributes.get("clientAccessPostOperation"));
|
||||
|
||||
gemfireProperties.setProperty("security-client-auth-init",
|
||||
gemfireProperties.setProperty(SECURITY_CLIENT_AUTH_INIT,
|
||||
annotationAttributes.get("clientAuthenticationInitializer"));
|
||||
|
||||
gemfireProperties.setProperty("security-client-authenticator", annotationAttributes.get("clientAuthenticator"));
|
||||
gemfireProperties.setProperty(SECURITY_CLIENT_AUTHENTICATOR, annotationAttributes.get("clientAuthenticator"));
|
||||
|
||||
gemfireProperties.setProperty("security-client-dhalgo",
|
||||
gemfireProperties.setProperty(SECURITY_CLIENT_DIFFIE_HELLMAN_ALGORITHM,
|
||||
annotationAttributes.get("clientDiffieHellmanAlgorithm"));
|
||||
|
||||
gemfireProperties.setProperty("security-peer-auth-init",
|
||||
gemfireProperties.setProperty(SECURITY_PEER_AUTH_INIT,
|
||||
annotationAttributes.get("peerAuthenticationInitializer"));
|
||||
|
||||
gemfireProperties.setProperty("security-peer-authenticator", annotationAttributes.get("peerAuthenticator"));
|
||||
gemfireProperties.setProperty(SECURITY_PEER_AUTHENTICATOR, annotationAttributes.get("peerAuthenticator"));
|
||||
|
||||
gemfireProperties.setPropertyIfNotDefault("security-peer-verifymember-timeout",
|
||||
gemfireProperties.setPropertyIfNotDefault(SECURITY_PEER_VERIFY_MEMBER_TIMEOUT,
|
||||
annotationAttributes.get("peerVerifyMemberTimeout"), DEFAULT_PEER_VERIFY_MEMBER_TIMEOUT);
|
||||
|
||||
gemfireProperties.setProperty("security-log-file", annotationAttributes.get("securityLogFile"));
|
||||
gemfireProperties.setProperty(SECURITY_LOG_FILE, annotationAttributes.get("securityLogFile"));
|
||||
|
||||
gemfireProperties.setPropertyIfNotDefault("security-log-level",
|
||||
gemfireProperties.setPropertyIfNotDefault(SECURITY_LOG_LEVEL,
|
||||
annotationAttributes.get("securityLogLevel"), DEFAULT_SECURITY_LOG_LEVEL);
|
||||
|
||||
return gemfireProperties.build();
|
||||
|
||||
@@ -34,10 +34,11 @@ import org.springframework.context.annotation.Import;
|
||||
* annotated class to configure and enable GemFire/Geode's Authentication and Authorization framework services.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.config.annotation.AuthConfiguration
|
||||
* @see org.apache.geode.security.AccessControl
|
||||
* @see org.apache.geode.security.AuthInitialize
|
||||
* @see org.apache.geode.security.Authenticator
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.data.gemfire.config.annotation.AuthConfiguration
|
||||
* @see <a href="http://gemfire.docs.pivotal.io/docs-gemfire/latest/managing/security/authentication_overview.html">Authentication</a>
|
||||
* @see <a href="http://gemfire.docs.pivotal.io/docs-gemfire/latest/managing/security/authorization_overview.html">Authorization</a>
|
||||
* @since 1.9.0
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2016 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.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* The EnableOffHeap annotation marks a Spring {@link org.springframework.context.annotation.Configuration @Configuration}
|
||||
* annotated class to configure and enable Apache Geode Off-Heap Memory support and data storage
|
||||
* in Geode's cache {@link org.apache.geode.cache.Region Regions}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.config.annotation.OffHeapConfiguration
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@Import(OffHeapConfiguration.class)
|
||||
@SuppressWarnings("unused")
|
||||
public @interface EnableOffHeap {
|
||||
|
||||
/**
|
||||
* Specifies the size of off-heap memory in megabytes (m) or gigabytes (g). For example:
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* off-heap-memory-size=4096m
|
||||
* off-heap-memory-size=120g
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* Defaults to unset.
|
||||
*/
|
||||
String memorySize();
|
||||
|
||||
/**
|
||||
* Idenfitied the Regions by name in which the off-heap memory setting will be applied.
|
||||
*
|
||||
* Defaults to all Regions.
|
||||
*/
|
||||
String[] regionNames() default {};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2016 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.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* The EnableRedisServer annotation marks a Spring {@link org.springframework.context.annotation.Configuration}
|
||||
* class to embed the Redis service in the GemFire server-side data member node.
|
||||
*
|
||||
* The Redis service implements the Redis server protocol enabling Redis clients to connect and speak
|
||||
* to Pivotal GemFire or Apache Geode.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.config.annotation.MemcachedServerConfiguration
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
@Import(RedisServerConfiguration.class)
|
||||
@SuppressWarnings("unused")
|
||||
public @interface EnableRedisServer {
|
||||
|
||||
/**
|
||||
* Configures the Network bind-address on which the Redis server will accept connections.
|
||||
*
|
||||
* Defaults to {@literal localhost}.
|
||||
*/
|
||||
String bindAddress() default "";
|
||||
|
||||
/**
|
||||
* Configures the Network port on which the Redis server will listen for Redis client connections.
|
||||
*
|
||||
* Defaults to {@literal 6379}.
|
||||
*/
|
||||
int port() default RedisServerConfiguration.DEFAULT_REDIS_PORT;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2016 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.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.apache.geode.security.AuthInitialize;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* The {@link EnableSecurity} annotation marks a Spring {@link org.springframework.context.annotation.Configuration}
|
||||
* annotated class to configure and enable Apache Geode's Security features for authentication, authorization
|
||||
* and post processing.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see GeodeIntegratedSecurityConfiguration
|
||||
* @see org.apache.geode.security.AuthInitialize
|
||||
* @see org.apache.geode.security.SecurityManager
|
||||
* @see org.apache.geode.security.PostProcessor
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.data.gemfire.config.annotation.ApacheShiroSecurityConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.GeodeIntegratedSecurityConfiguration
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@Import({ ApacheShiroSecurityConfiguration.class, GeodeIntegratedSecurityConfiguration.class })
|
||||
@SuppressWarnings({ "unused" })
|
||||
public @interface EnableSecurity {
|
||||
|
||||
/**
|
||||
* Used for authentication. Static creation method returning an {@link AuthInitialize} object,
|
||||
* which obtains credentials for clients.
|
||||
*
|
||||
* Defaults to unset.
|
||||
*/
|
||||
String clientAuthenticationInitializer() default "";
|
||||
|
||||
/**
|
||||
* Used with authentication. Static creation method returning an {@link AuthInitialize} object, which obtains
|
||||
* credentials for peers in a distributed system.
|
||||
*
|
||||
* Defaults to unset.
|
||||
*/
|
||||
String peerAuthenticationInitializer() default "";
|
||||
|
||||
/**
|
||||
* Specifies the application {@link Class} type implementing the Apache Geode
|
||||
* {@link org.apache.geode.security.SecurityManager} interface to enable security in Apache Geode.
|
||||
*
|
||||
* Defaults to {@link Void}.
|
||||
*/
|
||||
Class<?> securityManagerClass() default Void.class;
|
||||
|
||||
/**
|
||||
* Specifies the fully-qualified class name of the application {@link Class} implementing the Apache Geode
|
||||
* {@link org.apache.geode.security.SecurityManager} interface to enable security in Apache Geode.
|
||||
*
|
||||
* Use this Annotation attribute if you are uncertain whether the application class is on the classpath or not.
|
||||
*
|
||||
* Default is unset.
|
||||
*/
|
||||
String securityManagerClassName() default "";
|
||||
|
||||
/**
|
||||
* Specifies the application {@link Class} type implementing the Apache Geode
|
||||
* {@link org.apache.geode.security.PostProcessor} interface, which used to transform sensitive data
|
||||
* returned from secure data access operations.
|
||||
*
|
||||
* Defaults to {@link Void}.
|
||||
*/
|
||||
Class<?> securityPostProcessorClass() default Void.class;
|
||||
|
||||
/**
|
||||
* Specifies the fully-qualified class name of the application {@link Class} implementing the Apache Geode
|
||||
* {@link org.apache.geode.security.PostProcessor} interface, which used to transform sensitive data
|
||||
* returned from secure data access operations.
|
||||
*
|
||||
* Use this Annotation attribute if you are uncertain whether the application class is on the classpath or not.
|
||||
*
|
||||
* Default is unset.
|
||||
*/
|
||||
String securityPostProcessorClassName() default "";
|
||||
|
||||
/**
|
||||
* Sets the Geode System Property referring to the location of an Apache Shiro INI file used to configure
|
||||
* the Apache Shiro Security Framework to secure Apache Geode.
|
||||
*
|
||||
* Default is unset.
|
||||
*/
|
||||
String shiroIniResourcePath() default "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2016 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 java.util.Properties;
|
||||
|
||||
import org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport;
|
||||
import org.springframework.data.gemfire.util.PropertiesBuilder;
|
||||
|
||||
/**
|
||||
* The {@link GeodeIntegratedSecurityConfiguration} class is a {@link EmbeddedServiceConfigurationSupport} implementation
|
||||
* that enables Apache Geode's Integrated Security framework and services.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class GeodeIntegratedSecurityConfiguration extends EmbeddedServiceConfigurationSupport {
|
||||
|
||||
protected static final String SECURITY_CLIENT_AUTH_INIT = "security-client-auth-init";
|
||||
protected static final String SECURITY_MANAGER = "security-manager";
|
||||
protected static final String SECURITY_PEER_AUTH_INIT = "security-peer-auth-init";
|
||||
protected static final String SECURITY_POST_PROCESSOR = "security-post-processor";
|
||||
protected static final String SECURITY_SHIRO_INIT = "security-shiro-init";
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
protected Class getAnnotationType() {
|
||||
return EnableSecurity.class;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected boolean isShiroSecurityConfigured() {
|
||||
try {
|
||||
// NOTE experimental...
|
||||
//return resolveBean(ApacheShiroSecurityConfiguration.class).isRealmsPresent();
|
||||
return false;
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected boolean isShiroSecurityNotConfigured() {
|
||||
return !isShiroSecurityConfigured();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {
|
||||
PropertiesBuilder gemfireProperties = new PropertiesBuilder();
|
||||
|
||||
gemfireProperties.setProperty(SECURITY_CLIENT_AUTH_INIT,
|
||||
annotationAttributes.get("clientAuthenticationInitializer"));
|
||||
|
||||
if (isShiroSecurityNotConfigured()) {
|
||||
gemfireProperties.setPropertyIfNotDefault(SECURITY_MANAGER,
|
||||
annotationAttributes.get("securityManagerClass"), Void.class);
|
||||
|
||||
gemfireProperties.setProperty(SECURITY_MANAGER, annotationAttributes.get("securityManagerClassName"));
|
||||
|
||||
gemfireProperties.setProperty(SECURITY_SHIRO_INIT, annotationAttributes.get("shiroIniResourcePath"));
|
||||
}
|
||||
|
||||
gemfireProperties.setProperty(SECURITY_PEER_AUTH_INIT,
|
||||
annotationAttributes.get("peerAuthenticationInitializer"));
|
||||
|
||||
gemfireProperties.setPropertyIfNotDefault(SECURITY_POST_PROCESSOR,
|
||||
annotationAttributes.get("securityPostProcessorClass"), Void.class);
|
||||
|
||||
gemfireProperties.setProperty(SECURITY_POST_PROCESSOR,
|
||||
annotationAttributes.get("securityPostProcessorClassName"));
|
||||
|
||||
return gemfireProperties.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright 2016 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.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.gemfire.GenericRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.LocalRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.PartitionedRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.ReplicatedRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport;
|
||||
import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
import org.springframework.data.gemfire.util.PropertiesBuilder;
|
||||
|
||||
/**
|
||||
* The OffHeapConfiguration class is a Spring {@link org.springframework.context.annotation.ImportBeanDefinitionRegistrar}
|
||||
* capable of enabling GemFire cache {@link Region Regions} to use Off-Heap memory for data storage.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableOffHeap
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public class OffHeapConfiguration extends EmbeddedServiceConfigurationSupport {
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
protected Class getAnnotationType() {
|
||||
return EnableOffHeap.class;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
protected void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
|
||||
Map<String, Object> annotationAttributes, BeanDefinitionRegistry registry) {
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
OffHeapBeanFactoryPostProcessor.class);
|
||||
|
||||
builder.addConstructorArgValue(annotationAttributes.get("regionNames"));
|
||||
|
||||
registry.registerBeanDefinition(generateBeanName(OffHeapBeanFactoryPostProcessor.class),
|
||||
builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {
|
||||
PropertiesBuilder gemfireProperties = PropertiesBuilder.create();
|
||||
|
||||
gemfireProperties.setProperty("off-heap-memory-size", annotationAttributes.get("memorySize"));
|
||||
|
||||
return gemfireProperties.build();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
protected static class OffHeapBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
|
||||
|
||||
protected static final Set<String> REGION_FACTORY_BEAN_TYPES = new HashSet<String>(5);
|
||||
|
||||
static {
|
||||
REGION_FACTORY_BEAN_TYPES.add(ClientRegionFactoryBean.class.getName());
|
||||
REGION_FACTORY_BEAN_TYPES.add(GenericRegionFactoryBean.class.getName());
|
||||
REGION_FACTORY_BEAN_TYPES.add(LocalRegionFactoryBean.class.getName());
|
||||
REGION_FACTORY_BEAN_TYPES.add(PartitionedRegionFactoryBean.class.getName());
|
||||
REGION_FACTORY_BEAN_TYPES.add(ReplicatedRegionFactoryBean.class.getName());
|
||||
}
|
||||
|
||||
private final Set<String> regionNames;
|
||||
|
||||
protected OffHeapBeanFactoryPostProcessor(String[] regionNames) {
|
||||
this(CollectionUtils.asSet(ArrayUtils.nullSafeArray(regionNames, String.class)));
|
||||
}
|
||||
|
||||
protected OffHeapBeanFactoryPostProcessor(Set<String> regionNames) {
|
||||
this.regionNames = CollectionUtils.nullSafeSet(regionNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
for (String beanName : beanFactory.getBeanDefinitionNames()) {
|
||||
BeanDefinition bean = beanFactory.getBeanDefinition(beanName);
|
||||
|
||||
if (isTargetedRegionBean(beanName, bean, beanFactory)) {
|
||||
bean.getPropertyValues().addPropertyValue("offHeap", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isTargetedRegionBean(String beanName, BeanDefinition bean,
|
||||
ConfigurableListableBeanFactory beanFactory) {
|
||||
|
||||
return (isRegionBean(bean) && isNamedRegion(beanName, bean, beanFactory));
|
||||
}
|
||||
|
||||
boolean isRegionBean(BeanDefinition bean) {
|
||||
return (bean != null && REGION_FACTORY_BEAN_TYPES.contains(bean.getBeanClassName()));
|
||||
}
|
||||
|
||||
boolean isNamedRegion(String beanName, BeanDefinition bean, ConfigurableListableBeanFactory beanFactory) {
|
||||
return (CollectionUtils.isEmpty(regionNames) || CollectionUtils.containsAny(regionNames,
|
||||
getBeanNames(beanName, bean, beanFactory)));
|
||||
}
|
||||
|
||||
Collection<String> getBeanNames(String beanName, BeanDefinition bean, BeanFactory beanFactory) {
|
||||
Collection<String> beanNames = new HashSet<String>();
|
||||
|
||||
beanNames.add(beanName);
|
||||
Collections.addAll(beanNames, beanFactory.getAliases(beanName));
|
||||
|
||||
PropertyValue regionName = bean.getPropertyValues().getPropertyValue("regionName");
|
||||
|
||||
if (regionName != null) {
|
||||
Object regionNameValue = regionName.getValue();
|
||||
|
||||
if (regionNameValue != null) {
|
||||
beanNames.add(regionNameValue.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return beanNames;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2016 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 java.util.Properties;
|
||||
|
||||
import org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport;
|
||||
import org.springframework.data.gemfire.util.PropertiesBuilder;
|
||||
|
||||
/**
|
||||
* The RedisServerConfiguration class is a Spring {@link org.springframework.context.annotation.ImportBeanDefinitionRegistrar}
|
||||
* that applies additional GemFire configuration by way of GemFire System properties to configure
|
||||
* an embedded Redis server.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableRedisServer
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public class RedisServerConfiguration extends EmbeddedServiceConfigurationSupport {
|
||||
|
||||
protected static final int DEFAULT_REDIS_PORT = 6379;
|
||||
|
||||
@Override
|
||||
protected Class getAnnotationType() {
|
||||
return EnableRedisServer.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {
|
||||
return new PropertiesBuilder()
|
||||
.setProperty("redis-bind-address", annotationAttributes.get("bindAddress"))
|
||||
.setProperty("redis-port", resolvePort((Integer)annotationAttributes.get("port"), DEFAULT_REDIS_PORT))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,8 @@ import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -53,8 +53,9 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
|
||||
* @param elements array of objects to add to the {@link Set}.
|
||||
* @return an unmodifiable {@link Set} containing the elements from the given object array.
|
||||
*/
|
||||
@SafeVarargs
|
||||
public static <T> Set<T> asSet(T... elements) {
|
||||
Set<T> set = new HashSet<T>(elements.length);
|
||||
Set<T> set = new HashSet<>(elements.length);
|
||||
Collections.addAll(set, elements);
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
@@ -68,12 +69,8 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
|
||||
* @see java.lang.Iterable
|
||||
* @see java.util.Enumeration
|
||||
*/
|
||||
public static <T> Iterable<T> iterable(final Enumeration<T> enumeration) {
|
||||
return new Iterable<T>() {
|
||||
@Override public Iterator<T> iterator() {
|
||||
return org.springframework.util.CollectionUtils.toIterator(enumeration);
|
||||
}
|
||||
};
|
||||
public static <T> Iterable<T> iterable(Enumeration<T> enumeration) {
|
||||
return () -> org.springframework.util.CollectionUtils.toIterator(enumeration);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,12 +82,8 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
|
||||
* @see java.lang.Iterable
|
||||
* @see java.util.Iterator
|
||||
*/
|
||||
public static <T> Iterable<T> iterable(final Iterator<T> iterator) {
|
||||
return new Iterable<T>() {
|
||||
@Override public Iterator<T> iterator() {
|
||||
return iterator;
|
||||
}
|
||||
};
|
||||
public static <T> Iterable<T> iterable(Iterator<T> iterator) {
|
||||
return () -> iterator;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,7 +98,7 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
|
||||
* @see java.util.Collection
|
||||
*/
|
||||
public static <T> Collection<T> nullSafeCollection(Collection<T> collection) {
|
||||
return (collection != null ? collection : Collections.<T>emptyList());
|
||||
return (collection != null ? collection : Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,23 +112,7 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
|
||||
* @see java.util.Iterator
|
||||
*/
|
||||
public static <T> Iterable<T> nullSafeIterable(Iterable<T> iterable) {
|
||||
return (iterable != null ? iterable : new Iterable<T>() {
|
||||
@Override public Iterator<T> iterator() {
|
||||
return new Iterator<T>() {
|
||||
@Override public boolean hasNext() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override public T next() {
|
||||
throw new NoSuchElementException("No more elements");
|
||||
}
|
||||
|
||||
@Override public void remove() {
|
||||
throw new UnsupportedOperationException("Operation not supported");
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
return (iterable != null ? iterable : Collections::emptyIterator);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,7 +126,7 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
|
||||
* @see java.util.List
|
||||
*/
|
||||
public static <T> List<T> nullSafeList(List<T> list) {
|
||||
return (list != null ? list : Collections.<T>emptyList());
|
||||
return (list != null ? list : Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,7 +141,7 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
|
||||
* @see java.util.Map
|
||||
*/
|
||||
public static <K, V> Map<K, V> nullSafeMap(Map<K, V> map) {
|
||||
return (map != null ? map : Collections.<K, V>emptyMap());
|
||||
return (map != null ? map : Collections.emptyMap());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,7 +155,7 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
|
||||
* @see java.util.Set
|
||||
*/
|
||||
public static <T> Set<T> nullSafeSet(Set<T> set) {
|
||||
return (set != null ? set : Collections.<T>emptySet());
|
||||
return (set != null ? set : Collections.emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,7 +188,7 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
|
||||
public static <T> List<T> subList(List<T> source, int... indices) {
|
||||
Assert.notNull(source, "List must not be null");
|
||||
|
||||
List<T> result = new ArrayList<T>(indices.length);
|
||||
List<T> result = new ArrayList<>(indices.length);
|
||||
|
||||
for (int index : indices) {
|
||||
result.add(source.get(index));
|
||||
@@ -219,4 +196,23 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static String toString(Map<?, ?> map) {
|
||||
StringBuilder builder = new StringBuilder("{\n");
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (Map.Entry<?, ?> entry : new TreeMap<>(map).entrySet()) {
|
||||
builder.append(++count > 1 ? ",\n" : "");
|
||||
builder.append("\t");
|
||||
builder.append(entry.getKey());
|
||||
builder.append(" = ");
|
||||
builder.append(entry.getValue());
|
||||
}
|
||||
|
||||
builder.append("\n}");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ public abstract class DistributedSystemUtils extends SpringUtils {
|
||||
|
||||
public static final String DURABLE_CLIENT_ID_PROPERTY_NAME = DistributionConfig.DURABLE_CLIENT_ID_NAME;
|
||||
public static final String DURABLE_CLIENT_TIMEOUT_PROPERTY_NAME = DistributionConfig.DURABLE_CLIENT_TIMEOUT_NAME;
|
||||
public static final String GEMFIRE_PREFIX = DistributionConfig.GEMFIRE_PREFIX;
|
||||
public static final String NAME_PROPERTY_NAME = DistributionConfig.NAME_NAME;
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static Properties configureDurableClient(Properties gemfireProperties,
|
||||
@@ -85,5 +87,4 @@ public abstract class DistributedSystemUtils extends SpringUtils {
|
||||
public static <T extends DistributedSystem> T getDistributedSystem(GemFireCache gemfireCache) {
|
||||
return (gemfireCache != null ? (T) gemfireCache.getDistributedSystem() : null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user