diff --git a/build.gradle b/build.gradle
index 60a8d1e1..29d044b9 100644
--- a/build.gradle
+++ b/build.gradle
@@ -32,8 +32,8 @@ description = 'Spring Data Geode'
group = 'org.springframework.data'
archivesBaseName = project.name
-sourceCompatibility = 1.6
-targetCompatibility = 1.6
+sourceCompatibility = 1.8
+targetCompatibility = 1.8
sourceSets {
main {
@@ -115,6 +115,7 @@ dependencies {
// Java & 3rd Party Dependencies
optional "javax.enterprise:cdi-api:$cdiVersion"
compile "org.aspectj:aspectjweaver:$aspectjVersion"
+ optional "org.apache.shiro:shiro-spring:$shiroVersion"
compile "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion"
compile "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion"
diff --git a/gradle.properties b/gradle.properties
index 44e211da..05bad395 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -13,6 +13,7 @@ mockitoVersion=1.10.19
multiThreadedtcVersion=1.01
openwebbeansVersion=1.2.8
servletApiVersion=2.5
+shiroVersion=1.3.2
slf4jVersion=1.7.21
spring.range="[4.0.0, 5.0.0)"
springVersion=4.3.3.RELEASE
diff --git a/pom.xml b/pom.xml
index ccf4012e..6dafafe9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,6 +20,7 @@
SGF
2.7.7
+ 1.3.2
2.5.0
1.1.0-incubating-SNAPSHOT
2.0.2
@@ -28,6 +29,7 @@
4.3.3.RELEASE
1.12.4.RELEASE
1.1.0.RELEASE
+ 1.8
@@ -124,6 +126,12 @@
${aspectj}
+
+ org.apache.shiro
+ shiro-spring
+ ${apache-shiro.version}
+
+
com.fasterxml.jackson.core
jackson-annotations
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfiguration.java
index 135bfb68..3ae6c7c0 100644
--- a/src/main/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfiguration.java
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfiguration.java
@@ -88,8 +88,7 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
private static final AtomicBoolean CUSTOM_EDITORS_REGISTERED = new AtomicBoolean(false);
private static final AtomicBoolean DEFINED_INDEXES_APPLICATION_LISTENER_REGISTERED = new AtomicBoolean(false);
private static final AtomicBoolean DISK_STORE_DIRECTORY_BEAN_POST_PROCESSOR_REGISTERED = new AtomicBoolean(false);
- private static final AtomicBoolean PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED =
- new AtomicBoolean(false);
+ private static final AtomicBoolean PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED = new AtomicBoolean(false);
protected static final boolean DEFAULT_CLOSE = true;
protected static final boolean DEFAULT_COPY_ON_READ = false;
@@ -270,7 +269,6 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
registerCustomEditorBeanFactoryPostProcessor(importMetadata);
registerDefinedIndexesApplicationListener(importMetadata);
registerDiskStoreDirectoryBeanPostProcessor(importMetadata);
- registerPdxDiskStoreAwareBeanFactoryPostProcessor(importMetadata);
}
/**
@@ -323,6 +321,8 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
setPdxPersistent(Boolean.TRUE.equals(enablePdxAttributes.get("persistent")));
setPdxReadSerialized(Boolean.TRUE.equals(enablePdxAttributes.get("readSerialized")));
setPdxSerializer(resolvePdxSerializer((String) enablePdxAttributes.get("serializerBeanName")));
+
+ registerPdxDiskStoreAwareBeanFactoryPostProcessor(importMetadata);
}
}
@@ -383,9 +383,13 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
/* (non-Javadoc) */
protected void registerPdxDiskStoreAwareBeanFactoryPostProcessor(AnnotationMetadata importMetadata) {
- if (PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
- register(BeanDefinitionBuilder.rootBeanDefinition(PdxDiskStoreAwareBeanFactoryPostProcessor.class)
- .setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition());
+ if (StringUtils.hasText(pdxDiskStoreName())) {
+ if (PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
+ register(BeanDefinitionBuilder.rootBeanDefinition(PdxDiskStoreAwareBeanFactoryPostProcessor.class)
+ .setRole(BeanDefinition.ROLE_INFRASTRUCTURE)
+ .addConstructorArgValue(pdxDiskStoreName())
+ .getBeanDefinition());
+ }
}
}
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/ApacheShiroSecurityConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/ApacheShiroSecurityConfiguration.java
new file mode 100644
index 00000000..2b0a600c
--- /dev/null
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/ApacheShiroSecurityConfiguration.java
@@ -0,0 +1,255 @@
+/*
+ * 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.Collections;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+
+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.factory.ListableBeanFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+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.context.annotation.ConfigurationCondition;
+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.SecurityManager
+ * @see org.apache.shiro.spring.LifecycleBeanPostProcessor
+ * @see org.springframework.context.annotation.Condition
+ * @see org.springframework.context.annotation.Conditional
+ * @since 1.0.0
+ */
+@Configuration
+@Conditional(ApacheShiroSecurityConfiguration.ApacheShiroPresentCondition.class)
+@SuppressWarnings("unused")
+public class ApacheShiroSecurityConfiguration {
+
+ @Autowired(required = false)
+ private List realms = Collections.emptyList();
+
+ @Autowired(required = false)
+ private org.apache.shiro.mgt.SecurityManager shiroSecurityManager;
+
+ /**
+ * {@link Bean} definition to configure and register an Apache Shiro, Spring {@link LifecycleBeanPostProcessor}
+ * used to automatically call lifecycle callback methods on Shiro security components during Spring container
+ * initialization and destruction phases.
+ *
+ * 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}.
+ *
+ * @return an Apache Shiro, Spring {@link LifecycleBeanPostProcessor} bean.
+ * @see org.apache.shiro.spring.LifecycleBeanPostProcessor
+ */
+ @Bean
+ //@Conditional(ShiroRealmsConfigured.class)
+ public BeanPostProcessor shiroLifecycleBeanPostProcessor() {
+ return new LifecycleBeanPostProcessor();
+ }
+
+ /**
+ * {@link Bean} definition used to 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, thus evaluating any security configuration
+ * logic internally in Apache Geode that may potentially overwrite the Spring configuration.
+ *
+ * @return an Apache Shiro {@link org.apache.shiro.mgt.SecurityManager} implementation used to secure Apache Geode.
+ * @see org.apache.shiro.mgt.SecurityManager
+ * @see #isRealmsPresent()
+ * @see #getRealms()
+ */
+ @Bean
+ //@Conditional(ShiroRealmsConfigured.class)
+ public org.apache.shiro.mgt.SecurityManager shiroSecurityManager(GemFireCache gemfireCache) {
+ return (isRealmsPresent() ? new DefaultSecurityManager(getRealms()) : null);
+ }
+
+ /**
+ * Post processes the Apache Shiro security components by registering the Apach Shiro
+ * {@link org.apache.shiro.mgt.SecurityManager} if present with the Apache Shiro security framework
+ * and proceeds to enable Apache Geode security.
+ *
+ * @throws IllegalStateException if an Apache Shiro {@link org.apache.shiro.mgt.SecurityManager} is present
+ * and Apache Geode security could not be enabled.
+ * @see #registerSecurityManager(org.apache.shiro.mgt.SecurityManager)
+ * @see #enableApacheGeodeSecurity()
+ */
+ @PostConstruct
+ public void postProcess() {
+ if (this.shiroSecurityManager != null) {
+ registerSecurityManager(this.shiroSecurityManager);
+
+ if (!enableApacheGeodeSecurity()) {
+ throw new IllegalStateException("Failed to enable security services in Apache Geode");
+ }
+ }
+ }
+
+ /**
+ * 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) {
+ Field isIntegratedSecurity = ReflectionUtils.findField(securityService.getClass(),
+ "isIntegratedSecurity", Boolean.TYPE);
+
+ if (isIntegratedSecurity != null) {
+ ReflectionUtils.makeAccessible(isIntegratedSecurity);
+ ReflectionUtils.setField(isIntegratedSecurity, securityService, true);
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the {@link List} of Apache Shiro {@link Realm Realms} configured in
+ * this Spring {@link org.springframework.context.ApplicationContext}.
+ *
+ * @return a {@link List} of configured/declared Apache Shiro {@link Realm Realms}.
+ * @see org.apache.shiro.realm.Realm
+ */
+ protected List getRealms() {
+ return this.realms;
+ }
+
+ /**
+ * Determines whether any Apache Shiro {@link Realm Realms} were configured in
+ * this Spring {@link org.springframework.context.ApplicationContext}.
+ *
+ * @return a boolean value indicating whether any Apache Shiro {@link Realm Realms} were declared and configured
+ * in this Spring {@link org.springframework.context.ApplicationContext}.
+ * @see #getRealms()
+ */
+ protected boolean isRealmsPresent() {
+ return !CollectionUtils.isEmpty(getRealms());
+ }
+
+ /**
+ * 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_PROCESOR_CLASS_NAME =
+ "org.apache.shiro.spring.LifecycleBeanPostProcessor";
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+ return ClassUtils.isPresent(APACHE_SHIRO_LIFECYCLE_BEAN_POST_PROCESOR_CLASS_NAME,
+ context.getClassLoader());
+ }
+ }
+
+ /**
+ * A Spring {@link Condition} implementation that determines whether the user declared and configured
+ * any Apache Shiro {@link Realm Realms}, which are necessary to configure the Apache Shiro security framework
+ * with security meta-data used to secure Apache Geode.
+ *
+ * @see org.springframework.context.annotation.ConfigurationCondition
+ */
+ public static class ShiroRealmsConfigured implements ConfigurationCondition {
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public ConfigurationPhase getConfigurationPhase() {
+ return ConfigurationPhase.REGISTER_BEAN;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+ ListableBeanFactory beanFactory = context.getBeanFactory();
+
+ ApacheShiroSecurityConfiguration securityConfiguration =
+ beanFactory.getBean(ApacheShiroSecurityConfiguration.class);
+
+ return (securityConfiguration.isRealmsPresent() || !beanFactory.getBeansOfType(Realm.class).isEmpty());
+ }
+ }
+}
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/AuthConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/AuthConfiguration.java
index 1c27e15f..09e2626f 100644
--- a/src/main/java/org/springframework/data/gemfire/config/annotation/AuthConfiguration.java
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/AuthConfiguration.java
@@ -40,6 +40,18 @@ public class AuthConfiguration extends EmbeddedServiceConfigurationSupport {
public static final String DEFAULT_SECURITY_LOG_LEVEL = "config";
+ 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";
+
/* (non-Javadoc) */
@Override
protected Class getAnnotationType() {
@@ -51,32 +63,32 @@ public class AuthConfiguration extends EmbeddedServiceConfigurationSupport {
protected Properties toGemFireProperties(Map 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();
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/EnableSecurity.java b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableSecurity.java
new file mode 100644
index 00000000..37da4957
--- /dev/null
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableSecurity.java
@@ -0,0 +1,111 @@
+/*
+ * 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
+ * @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 "";
+
+}
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/GeodeIntegratedSecurityConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/GeodeIntegratedSecurityConfiguration.java
new file mode 100644
index 00000000..2d062023
--- /dev/null
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/GeodeIntegratedSecurityConfiguration.java
@@ -0,0 +1,91 @@
+/*
+ * 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_PEER_AUTH_INIT = "security-peer-auth-init";
+ protected static final String SECURITY_MANAGER = "security-manager";
+ 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() {
+ return false;
+ }
+
+ /* (non-Javadoc) */
+ protected boolean isShiroSecurityNotConfigured() {
+ return !isShiroSecurityConfigured();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ protected Properties toGemFireProperties(Map annotationAttributes) {
+ PropertiesBuilder gemfireProperties = new PropertiesBuilder();
+
+ gemfireProperties.setProperty(SECURITY_CLIENT_AUTH_INIT,
+ annotationAttributes.get("clientAuthenticationInitializer"));
+
+ gemfireProperties.setProperty(SECURITY_PEER_AUTH_INIT,
+ annotationAttributes.get("peerAuthenticationInitializer"));
+
+ 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.setPropertyIfNotDefault(SECURITY_POST_PROCESSOR,
+ annotationAttributes.get("securityPostProcessorClass"), Void.class);
+
+ gemfireProperties.setProperty(SECURITY_POST_PROCESSOR,
+ annotationAttributes.get("securityPostProcessorClassName"));
+
+ return gemfireProperties.build();
+ }
+}
diff --git a/src/main/java/org/springframework/data/gemfire/config/support/PdxDiskStoreAwareBeanFactoryPostProcessor.java b/src/main/java/org/springframework/data/gemfire/config/support/PdxDiskStoreAwareBeanFactoryPostProcessor.java
index 85ed5a30..98c1d4d0 100644
--- a/src/main/java/org/springframework/data/gemfire/config/support/PdxDiskStoreAwareBeanFactoryPostProcessor.java
+++ b/src/main/java/org/springframework/data/gemfire/config/support/PdxDiskStoreAwareBeanFactoryPostProcessor.java
@@ -89,7 +89,8 @@ public class PdxDiskStoreAwareBeanFactoryPostProcessor implements BeanFactoryPos
* @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory#getBeanNamesForType(Class)
*/
private void postProcessPdxDiskStoreDependencies(ConfigurableListableBeanFactory beanFactory,
- final Class>... beanTypes) {
+ Class>... beanTypes) {
+
for (Class> beanType : beanTypes) {
for (String beanName : beanFactory.getBeanNamesForType(beanType)) {
if (!beanName.equalsIgnoreCase(getPdxDiskStoreName())) {
diff --git a/src/main/java/org/springframework/data/gemfire/util/ArrayUtils.java b/src/main/java/org/springframework/data/gemfire/util/ArrayUtils.java
index cb49c757..5df4c519 100644
--- a/src/main/java/org/springframework/data/gemfire/util/ArrayUtils.java
+++ b/src/main/java/org/springframework/data/gemfire/util/ArrayUtils.java
@@ -32,6 +32,7 @@ public abstract class ArrayUtils {
* @param elements variable list of arguments to return as an array.
* @return an arry for the given varargs {@code elements}.
*/
+ @SafeVarargs
public static T[] asArray(T... elements) {
return elements;
}
@@ -45,7 +46,7 @@ public abstract class ArrayUtils {
* @return the first element in the array or {@literal null} if the array is null or empty.
* @see #getFirst(Object[], Object)
*/
- public static T getFirst(T... array) {
+ public static T getFirst(T[] array) {
return getFirst(array, null);
}
diff --git a/src/test/java/org/springframework/data/gemfire/GemfireTemplateIntegrationTests.java b/src/test/java/org/springframework/data/gemfire/GemfireTemplateIntegrationTests.java
index 9a35d8ad..9ee185b2 100644
--- a/src/test/java/org/springframework/data/gemfire/GemfireTemplateIntegrationTests.java
+++ b/src/test/java/org/springframework/data/gemfire/GemfireTemplateIntegrationTests.java
@@ -205,7 +205,7 @@ public class GemfireTemplateIntegrationTests {
public void get() {
String key = getKey(getUser("imaPigg"));
- assertThat(usersTemplate.get(key)).isEqualTo(users.get(key));
+ assertThat(usersTemplate.