Rename gemfire-spring-boot-starter module to gemfire-spring-boot.
Rename geode-spring-boot-starter module to geode-spring-boot.
This commit is contained in:
38
geode-spring-boot/geode-spring-boot.gradle
Normal file
38
geode-spring-boot/geode-spring-boot.gradle
Normal file
@@ -0,0 +1,38 @@
|
||||
apply plugin: 'io.spring.convention.spring-module'
|
||||
|
||||
apply from: IDE_GRADLE
|
||||
|
||||
description = "Spring Boot for Apache Geode"
|
||||
|
||||
repositories {
|
||||
maven { url "https://repo.spring.io/libs-snapshot" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
compile "org.springframework:spring-context-support"
|
||||
compile "org.springframework:spring-jcl"
|
||||
compile "org.springframework.data:spring-data-geode:$springDataGeodeVersion"
|
||||
|
||||
compile("org.springframework.boot:spring-boot-starter") {
|
||||
exclude group: "org.springframework.boot", module: "spring-boot-starter-logging";
|
||||
}
|
||||
|
||||
testCompile "org.assertj:assertj-core"
|
||||
testCompile "junit:junit"
|
||||
testCompile "org.mockito:mockito-core"
|
||||
testCompile "org.projectlombok:lombok"
|
||||
testCompile "edu.umd.cs.mtc:multithreadedtc"
|
||||
|
||||
testCompile("org.springframework.boot:spring-boot-starter-test") {
|
||||
exclude group: "org.springframework.boot", module: "spring-boot-starter-logging";
|
||||
}
|
||||
|
||||
testCompile slf4jDependencies
|
||||
testCompile "org.springframework.data:spring-test-data-geode"
|
||||
|
||||
testRuntime "javax.cache:cache-api"
|
||||
|
||||
// integrationTestRuntime "org.springframework.shell:spring-shell"
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2018 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.function.config;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.StandardAnnotationMetadata;
|
||||
|
||||
/**
|
||||
* The AbstractFunctionExecutionAutoConfigurationExtension class...
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
*/
|
||||
// TODO replace this class once SD Lovelace is GA and SBDG is rebased on SD Lovelace
|
||||
public abstract class AbstractFunctionExecutionAutoConfigurationExtension
|
||||
extends FunctionExecutionBeanDefinitionRegistrar implements BeanFactoryAware {
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
|
||||
registerBeanDefinitions(newAnnotationBasedFunctionExecutionConfigurationSource(annotationMetadata), registry);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private AbstractFunctionExecutionConfigurationSource newAnnotationBasedFunctionExecutionConfigurationSource(
|
||||
AnnotationMetadata annotationMetadata) {
|
||||
|
||||
StandardAnnotationMetadata metadata =
|
||||
new StandardAnnotationMetadata(getConfiguration(), true);
|
||||
|
||||
return new AnnotationFunctionExecutionConfigurationSource(metadata) {
|
||||
|
||||
@Override
|
||||
public Iterable<String> getBasePackages() {
|
||||
return AutoConfigurationPackages.get(getBeanFactory());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
protected BeanFactory getBeanFactory() {
|
||||
|
||||
return Optional.ofNullable(this.beanFactory)
|
||||
.orElseThrow(() -> newIllegalStateException("BeanFactory was not properly configured"));
|
||||
}
|
||||
|
||||
protected abstract Class<?> getConfiguration();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2018 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.function.config;
|
||||
|
||||
/**
|
||||
* The GemFireFunctionExecutionAutoConfigurationRegistrar class...
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class GemFireFunctionExecutionAutoConfigurationRegistrar
|
||||
extends AbstractFunctionExecutionAutoConfigurationExtension {
|
||||
|
||||
@Override
|
||||
protected Class<?> getConfiguration() {
|
||||
return EnableGemfireFunctionExecutionsConfiguration.class;
|
||||
}
|
||||
|
||||
@EnableGemfireFunctionExecutions
|
||||
private static class EnableGemfireFunctionExecutionsConfiguration { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizers;
|
||||
import org.springframework.boot.autoconfigure.cache.CacheProperties;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.gemfire.cache.GemfireCacheManager;
|
||||
import org.springframework.data.gemfire.cache.config.EnableGemfireCaching;
|
||||
|
||||
/**
|
||||
* Spring Boot {@link EnableAutoConfiguration auto-configuration} for Spring's Cache Abstraction
|
||||
* using Apache Geode as the caching provider.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see javax.annotation.PostConstruct
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
* @see org.springframework.boot.autoconfigure.cache.CacheManagerCustomizers
|
||||
* @see org.springframework.boot.autoconfigure.cache.CacheProperties
|
||||
* @see org.springframework.cache.CacheManager
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.cache.GemfireCacheManager
|
||||
* @see org.springframework.data.gemfire.cache.config.EnableGemfireCaching
|
||||
* @see org.springframework.geode.boot.autoconfigure.ClientCacheAutoConfiguration
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureAfter(ClientCacheAutoConfiguration.class)
|
||||
@ConditionalOnBean(GemFireCache.class)
|
||||
@ConditionalOnClass({ GemfireCacheManager.class, GemFireCache.class })
|
||||
@ConditionalOnMissingBean(CacheManager.class)
|
||||
@EnableGemfireCaching
|
||||
@SuppressWarnings("all")
|
||||
public class CachingProviderAutoConfiguration {
|
||||
|
||||
private final CacheManagerCustomizers cacheManagerCustomizers;
|
||||
|
||||
private final CacheProperties cacheProperties;
|
||||
|
||||
@Autowired
|
||||
private GemfireCacheManager cacheManager;
|
||||
|
||||
CachingProviderAutoConfiguration(
|
||||
@Autowired(required = false) CacheProperties cacheProperties,
|
||||
@Autowired(required = false) CacheManagerCustomizers cacheManagerCustomizers) {
|
||||
|
||||
this.cacheProperties = cacheProperties;
|
||||
this.cacheManagerCustomizers = cacheManagerCustomizers;
|
||||
}
|
||||
|
||||
GemfireCacheManager getCacheManager() {
|
||||
return Optional.ofNullable(this.cacheManager)
|
||||
.orElseThrow(() -> newIllegalStateException("GemfireCacheManager was not properly configured"));
|
||||
}
|
||||
|
||||
Optional<CacheManagerCustomizers> getCacheManagerCustomizers() {
|
||||
return Optional.ofNullable(this.cacheManagerCustomizers);
|
||||
}
|
||||
|
||||
Optional<CacheProperties> getCacheProperties() {
|
||||
return Optional.ofNullable(this.cacheProperties);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void onGeodeCachingInitialization() {
|
||||
getCacheManagerCustomizers()
|
||||
.ifPresent(cacheManagerCustomizers -> cacheManagerCustomizers.customize(getCacheManager()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
|
||||
import org.springframework.data.gemfire.config.annotation.EnablePdx;
|
||||
|
||||
/**
|
||||
* Spring Boot {@link EnableAutoConfiguration auto-configuration} for bootstrapping an Apache Geode {@link ClientCache}
|
||||
* instance constructed, configured and initialized with Spring Data for Apache Geode.
|
||||
*
|
||||
* Additionally, this configuration automatically enables Apache Geode PDX serialization to serialize data sent
|
||||
* between the client and server(s) in the cluster when using the client/server topology.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnablePdx
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ ClientCacheFactoryBean.class, ClientCache.class })
|
||||
@ConditionalOnMissingBean(GemFireCache.class)
|
||||
@ClientCacheApplication
|
||||
@EnablePdx
|
||||
public class ClientCacheAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.cloud.CloudPlatform;
|
||||
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertiesPropertySource;
|
||||
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableSecurity;
|
||||
import org.springframework.data.gemfire.config.annotation.support.AutoConfiguredAuthenticationInitializer;
|
||||
import org.springframework.geode.core.env.VcapPropertySource;
|
||||
import org.springframework.geode.core.env.support.CloudCacheService;
|
||||
import org.springframework.geode.core.env.support.Service;
|
||||
|
||||
/**
|
||||
* Spring Boot {@link EnableAutoConfiguration auto-configuration} enabling Apache Geode's Security functionality,
|
||||
* and specifically Authentication between a client and server using Spring Data Geode Security annotations.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.Properties
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.boot.SpringApplication
|
||||
* @see org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
* @see org.springframework.boot.cloud.CloudPlatform
|
||||
* @see org.springframework.boot.env.EnvironmentPostProcessor
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.core.env.ConfigurableEnvironment
|
||||
* @see org.springframework.core.env.Environment
|
||||
* @see org.springframework.core.env.PropertiesPropertySource
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableSecurity
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.AutoConfiguredAuthenticationInitializer
|
||||
* @see org.springframework.geode.boot.autoconfigure.ClientCacheAutoConfiguration
|
||||
* @see org.springframework.geode.core.env.VcapPropertySource
|
||||
* @see org.springframework.geode.core.env.support.CloudCacheService
|
||||
* @see org.springframework.geode.core.env.support.Service
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureBefore(ClientCacheAutoConfiguration.class)
|
||||
@Conditional(ClientSecurityAutoConfiguration.EnableSecurityCondition.class)
|
||||
@ConditionalOnClass({ ClientCacheFactoryBean.class, ClientCache.class })
|
||||
@ConditionalOnMissingBean(GemFireCache.class)
|
||||
@EnableSecurity
|
||||
@SuppressWarnings("unused")
|
||||
public class ClientSecurityAutoConfiguration {
|
||||
|
||||
public static final String SECURITY_CLOUD_ENVIRONMENT_POST_PROCESSOR_DISABLED_PROPERTY =
|
||||
"spring.boot.data.gemfire.security.auth.environment.post-processor.disabled";
|
||||
|
||||
private static final String CLOUD_CACHE_PROPERTY_SOURCE_NAME = "cloudcache-configuration";
|
||||
|
||||
private static final String MANAGEMENT_HTTP_HOST_PROPERTY = "spring.data.gemfire.management.http.host";
|
||||
private static final String MANAGEMENT_HTTP_PORT_PROPERTY = "spring.data.gemfire.management.http.port";
|
||||
private static final String MANAGEMENT_USE_HTTP_PROPERTY = "spring.data.gemfire.management.use-http";
|
||||
|
||||
private static final String POOL_LOCATORS_PROPERTY = "spring.data.gemfire.pool.locators";
|
||||
|
||||
private static final String SECURITY_USERNAME_PROPERTY =
|
||||
AutoConfiguredAuthenticationInitializer.SDG_SECURITY_USERNAME_PROPERTY;
|
||||
|
||||
private static final String SECURITY_PASSWORD_PROPERTY =
|
||||
AutoConfiguredAuthenticationInitializer.SDG_SECURITY_PASSWORD_PROPERTY;
|
||||
|
||||
private static final String VCAP_PROPERTY_SOURCE_NAME = "vcap";
|
||||
|
||||
static class AutoConfiguredCloudSecurityEnvironmentPostProcessor implements EnvironmentPostProcessor {
|
||||
|
||||
@Override
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
||||
|
||||
Optional.of(environment)
|
||||
.filter(this::isEnabled)
|
||||
.filter(this::isCloudFoundryEnvironment)
|
||||
.ifPresent(env -> {
|
||||
|
||||
VcapPropertySource propertySource = VcapPropertySource.from(env);
|
||||
|
||||
Properties cloudCacheProperties = new Properties();
|
||||
|
||||
CloudCacheService cloudCache = propertySource.findFirstCloudCacheService();
|
||||
|
||||
configureAuthentication(env, cloudCacheProperties, propertySource, cloudCache);
|
||||
configureLocators(env, cloudCacheProperties, propertySource, cloudCache);
|
||||
configureManagementRestApiAccess(env, cloudCacheProperties, propertySource, cloudCache);
|
||||
|
||||
environment.getPropertySources()
|
||||
.addFirst(new PropertiesPropertySource(CLOUD_CACHE_PROPERTY_SOURCE_NAME, cloudCacheProperties));
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isCloudFoundryEnvironment(Environment environment) {
|
||||
return Optional.ofNullable(environment).filter(CloudPlatform.CLOUD_FOUNDRY::isActive).isPresent();
|
||||
}
|
||||
|
||||
private boolean isDisabled(Environment environment) {
|
||||
return Boolean.getBoolean(SECURITY_CLOUD_ENVIRONMENT_POST_PROCESSOR_DISABLED_PROPERTY);
|
||||
}
|
||||
|
||||
private boolean isEnabled(Environment environment) {
|
||||
return !isDisabled(environment);
|
||||
}
|
||||
|
||||
private boolean isSecurityPropertiesSet(Environment environment) {
|
||||
return environment.containsProperty(SECURITY_USERNAME_PROPERTY)
|
||||
&& environment.containsProperty(SECURITY_PASSWORD_PROPERTY);
|
||||
}
|
||||
|
||||
private boolean isSecurityPropertiesNotSet(Environment environment) {
|
||||
return !isSecurityPropertiesSet(environment);
|
||||
}
|
||||
|
||||
private void configureAuthentication(Environment environment, Properties cloudCacheProperties,
|
||||
VcapPropertySource propertySource, Service cloudCache) {
|
||||
|
||||
propertySource.findFirstUserByRoleClusterOperator(cloudCache)
|
||||
.filter(user -> isSecurityPropertiesNotSet(environment))
|
||||
.ifPresent(user -> {
|
||||
cloudCacheProperties.setProperty(SECURITY_USERNAME_PROPERTY, user.getName());
|
||||
user.getPassword().ifPresent(password ->
|
||||
cloudCacheProperties.setProperty(SECURITY_PASSWORD_PROPERTY, password));
|
||||
});
|
||||
}
|
||||
|
||||
private void configureLocators(Environment environment, Properties cloudCacheProperties,
|
||||
VcapPropertySource propertySource, CloudCacheService cloudCache) {
|
||||
|
||||
cloudCache.getLocators().ifPresent(locators ->
|
||||
cloudCacheProperties.setProperty(POOL_LOCATORS_PROPERTY, locators));
|
||||
}
|
||||
|
||||
private void configureManagementRestApiAccess(Environment environment, Properties cloudCacheProperties,
|
||||
VcapPropertySource propertySource, CloudCacheService cloudCache) {
|
||||
|
||||
cloudCache.getGfshUrl().ifPresent(url -> {
|
||||
cloudCacheProperties.setProperty(MANAGEMENT_USE_HTTP_PROPERTY, Boolean.TRUE.toString());
|
||||
cloudCacheProperties.setProperty(MANAGEMENT_HTTP_HOST_PROPERTY, url.getHost());
|
||||
cloudCacheProperties.setProperty(MANAGEMENT_HTTP_PORT_PROPERTY, String.valueOf(url.getPort()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static class EnableSecurityCondition extends AnyNestedCondition {
|
||||
|
||||
public EnableSecurityCondition() {
|
||||
super(ConfigurationPhase.PARSE_CONFIGURATION);
|
||||
}
|
||||
|
||||
@ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY)
|
||||
static class CloudSecurityContextCondition { }
|
||||
|
||||
@ConditionalOnProperty({
|
||||
"spring.data.gemfire.security.username",
|
||||
"spring.data.gemfire.security.password",
|
||||
})
|
||||
static class SpringDataGeodeSecurityContextCondition { }
|
||||
|
||||
@ConditionalOnProperty({
|
||||
"gemfire.security-username",
|
||||
"gemfire.security-password",
|
||||
})
|
||||
static class StandaloneApacheGeodeSecurityContextCondition { }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure;
|
||||
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableContinuousQueries;
|
||||
|
||||
/**
|
||||
* Spring Boot {@link EnableAutoConfiguration auto-configuration} enabling Apache Geode's Continuous Query (CQ)
|
||||
* functionality in a {@link ClientCache} application.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableContinuousQueries
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnBean(ClientCacheFactoryBean.class)
|
||||
@ConditionalOnMissingBean(name = "continuousQueryBeanPostProcessor")
|
||||
@EnableContinuousQueries
|
||||
@SuppressWarnings("unused")
|
||||
public class ContinuousQueryAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public ClientCacheConfigurer enableSubscriptionClientCacheConfigurer() {
|
||||
return (beanName, clientCacheFactoryBean) -> clientCacheFactoryBean.setSubscriptionEnabled(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.gemfire.function.config.EnableGemfireFunctions;
|
||||
import org.springframework.data.gemfire.function.config.GemFireFunctionExecutionAutoConfigurationRegistrar;
|
||||
import org.springframework.data.gemfire.function.execution.GemfireFunctionOperations;
|
||||
|
||||
/**
|
||||
* Spring Boot {@link EnableAutoConfiguration auto-configuration} enabling Apache Geode's Function Execution
|
||||
* functionality in a {@link GemFireCache} application.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.data.gemfire.function.config.EnableGemfireFunctions
|
||||
* @see org.springframework.data.gemfire.function.config.EnableGemfireFunctionExecutions
|
||||
* @see org.springframework.data.gemfire.function.config.GemFireFunctionExecutionAutoConfigurationRegistrar
|
||||
* @see org.springframework.data.gemfire.function.execution.GemfireFunctionOperations
|
||||
* @see org.springframework.geode.boot.autoconfigure.ClientCacheAutoConfiguration
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureAfter(ClientCacheAutoConfiguration.class)
|
||||
@ConditionalOnBean(GemFireCache.class)
|
||||
@ConditionalOnClass({ GemfireFunctionOperations.class, GemFireCache.class })
|
||||
@EnableGemfireFunctions
|
||||
@Import(GemFireFunctionExecutionAutoConfigurationRegistrar.class)
|
||||
@SuppressWarnings("unused")
|
||||
public class FunctionExecutionAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
|
||||
import org.springframework.data.gemfire.repository.config.GemfireRepositoryConfigurationExtension;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||
|
||||
/**
|
||||
* Spring {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data Geode Repositories.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport
|
||||
* @see org.springframework.data.gemfire.repository.config.EnableGemfireRepositories
|
||||
* @see org.springframework.data.gemfire.repository.config.GemfireRepositoryConfigurationExtension
|
||||
* @see org.springframework.geode.boot.autoconfigure.RepositoriesAutoConfiguration
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class GemFireRepositoriesAutoConfigurationRegistrar extends AbstractRepositoryConfigurationSourceSupport {
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotation() {
|
||||
return EnableGemfireRepositories.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getConfiguration() {
|
||||
return EnableGemFireRepositoriesConfiguration.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() {
|
||||
return new GemfireRepositoryConfigurationExtension();
|
||||
}
|
||||
|
||||
@EnableGemfireRepositories
|
||||
private static class EnableGemFireRepositoriesConfiguration { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure;
|
||||
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.ApacheShiroSecurityConfiguration;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableBeanFactoryLocator;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableSecurity;
|
||||
import org.springframework.data.gemfire.config.annotation.GeodeIntegratedSecurityConfiguration;
|
||||
|
||||
/**
|
||||
* Spring Boot {@link EnableAutoConfiguration auto-configuration} enabling Apache Geode's Security functionality,
|
||||
* and specifically Authentication between a client and server using Spring Data Geode Security annotations.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.security.SecurityManager
|
||||
* @see org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.ApacheShiroSecurityConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableBeanFactoryLocator
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableSecurity
|
||||
* @see org.springframework.data.gemfire.config.annotation.GeodeIntegratedSecurityConfiguration
|
||||
* @see org.springframework.geode.security.support.SecurityManagerProxy
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnBean(org.apache.geode.security.SecurityManager.class)
|
||||
@ConditionalOnMissingBean({
|
||||
ClientCacheFactoryBean.class,
|
||||
ApacheShiroSecurityConfiguration.class,
|
||||
GeodeIntegratedSecurityConfiguration.class
|
||||
})
|
||||
@EnableBeanFactoryLocator
|
||||
@EnableSecurity(securityManagerClassName = "org.springframework.geode.security.support.SecurityManagerProxy")
|
||||
@SuppressWarnings("unused")
|
||||
public class PeerSecurityAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.gemfire.repository.GemfireRepository;
|
||||
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
|
||||
import org.springframework.data.gemfire.repository.config.GemfireRepositoryConfigurationExtension;
|
||||
import org.springframework.data.gemfire.repository.support.GemfireRepositoryFactoryBean;
|
||||
|
||||
/**
|
||||
* Spring Boot {@link EnableAutoConfiguration auto-configuration} for Spring Data Geode
|
||||
* and Spring Data GemFire Repositories.
|
||||
*
|
||||
* Activates when there is a bean of type {@link Cache} or {@link ClientCache} configured in the Spring context,
|
||||
* the Spring Data Geode {@link GemfireRepository} type is on the classpath, and no other existing
|
||||
* {@link GemfireRepository GemfireRepositories} are configured.
|
||||
*
|
||||
* Once in effect, the auto-configuration is the equivalent of enabling Geode Repositories using the
|
||||
* {@link EnableGemfireRepositories} annotation.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.data.gemfire.repository.GemfireRepository
|
||||
* @see org.springframework.data.gemfire.repository.config.EnableGemfireRepositories
|
||||
* @see org.springframework.data.gemfire.repository.config.GemfireRepositoryConfigurationExtension
|
||||
* @see org.springframework.data.gemfire.repository.support.GemfireRepositoryFactoryBean
|
||||
* @see org.springframework.geode.boot.autoconfigure.ClientCacheAutoConfiguration
|
||||
* @see org.springframework.geode.boot.autoconfigure.GemFireRepositoriesAutoConfigurationRegistrar
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureAfter(ClientCacheAutoConfiguration.class)
|
||||
@ConditionalOnBean(GemFireCache.class)
|
||||
@ConditionalOnClass(GemfireRepository.class)
|
||||
@ConditionalOnMissingBean({ GemfireRepositoryConfigurationExtension.class, GemfireRepositoryFactoryBean.class })
|
||||
@ConditionalOnProperty(prefix = "spring.data.gemfire.repositories", name = "enabled", havingValue = "true",
|
||||
matchIfMissing = true)
|
||||
@Import(GemFireRepositoriesAutoConfigurationRegistrar.class)
|
||||
public class RepositoriesAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure;
|
||||
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||
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.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertiesPropertySource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableSsl;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Spring Boot {@link EnableAutoConfiguration auto-configuration} enabling Apache Geode's SSL transport
|
||||
* between client and servers when using the client/server topology.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.io.File
|
||||
* @see java.net.URL
|
||||
* @see java.util.Properties
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.springframework.boot.SpringApplication
|
||||
* @see org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
* @see org.springframework.geode.boot.autoconfigure.ClientCacheAutoConfiguration
|
||||
* @see org.springframework.boot.env.EnvironmentPostProcessor
|
||||
* @see org.springframework.context.annotation.Condition
|
||||
* @see org.springframework.context.annotation.Conditional
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.core.env.ConfigurableEnvironment
|
||||
* @see org.springframework.core.env.Environment
|
||||
* @see org.springframework.core.env.PropertiesPropertySource
|
||||
* @see org.springframework.core.io.Resource
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableSsl
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureBefore(ClientCacheAutoConfiguration.class)
|
||||
@Conditional(SslAutoConfiguration.EnableSslCondition.class)
|
||||
@ConditionalOnClass({ CacheFactoryBean.class, GemFireCache.class })
|
||||
@EnableSsl
|
||||
@SuppressWarnings("unused")
|
||||
public class SslAutoConfiguration {
|
||||
|
||||
public static final String SECURITY_SSL_ENVIRONMENT_POST_PROCESSOR_DISABLED_PROPERTY =
|
||||
"spring.boot.data.gemfire.security.ssl.environment.post-processor.disabled";
|
||||
|
||||
private static final String CURRENT_WORKING_DIRECTORY = System.getProperty("user.dir");
|
||||
private static final String GEMFIRE_SSL_KEYSTORE_PROPERTY = "gemfire.ssl-keystore";
|
||||
private static final String GEMFIRE_SSL_PROPERTY_SOURCE_NAME = "gemfire-ssl";
|
||||
private static final String GEMFIRE_SSL_TRUSTSTORE_PROPERTY = "gemfire.ssl-truststore";
|
||||
private static final String SECURITY_SSL_KEYSTORE_PROPERTY = "spring.data.gemfire.security.ssl.keystore";
|
||||
private static final String SECURITY_SSL_TRUSTSTORE_PROPERTY = "spring.data.gemfire.security.ssl.truststore";
|
||||
private static final String SSL_KEYSTORE_PROPERTY = "ssl-keystore";
|
||||
private static final String SSL_TRUSTSTORE_PROPERTY = "ssl-truststore";
|
||||
private static final String TRUSTED_KEYSTORE_FILENAME = "trusted.keystore";
|
||||
private static final String TRUSTED_KEYSTORE_FILENAME_PROPERTY = "spring.boot.data.gemfire.security.ssl.keystore.name";
|
||||
private static final String USER_HOME_DIRECTORY = System.getProperty("user.home");
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SslAutoConfiguration.class);
|
||||
|
||||
private static boolean isSslConfigured(Environment environment) {
|
||||
|
||||
return (environment.containsProperty(SECURITY_SSL_KEYSTORE_PROPERTY)
|
||||
&& environment.containsProperty(SECURITY_SSL_TRUSTSTORE_PROPERTY))
|
||||
|| (environment.containsProperty(GEMFIRE_SSL_KEYSTORE_PROPERTY)
|
||||
&& environment.containsProperty(GEMFIRE_SSL_TRUSTSTORE_PROPERTY))
|
||||
|| (environment.containsProperty(SSL_KEYSTORE_PROPERTY)
|
||||
&& environment.containsProperty(SSL_TRUSTSTORE_PROPERTY));
|
||||
}
|
||||
|
||||
private static boolean isSslNotConfigured(Environment environment) {
|
||||
return !isSslConfigured(environment);
|
||||
}
|
||||
|
||||
private static String resolveTrustedKeyStore(Environment environment) {
|
||||
|
||||
return locateKeyStoreInFileSystem(environment)
|
||||
.map(File::getAbsolutePath)
|
||||
.orElseGet(() -> locateKeyStoreInUserHome(environment)
|
||||
.map(File::getAbsolutePath)
|
||||
.orElseGet(() -> resolveKeyStoreFromClassPathAsPathname(environment)
|
||||
.orElse(null)));
|
||||
}
|
||||
|
||||
private static String resolveTrustedKeystoreName(Environment environment) {
|
||||
|
||||
return Optional.ofNullable(environment)
|
||||
.filter(it -> environment.containsProperty(TRUSTED_KEYSTORE_FILENAME_PROPERTY))
|
||||
.map(it -> environment.getProperty(TRUSTED_KEYSTORE_FILENAME_PROPERTY))
|
||||
.orElse(TRUSTED_KEYSTORE_FILENAME);
|
||||
}
|
||||
|
||||
private static Optional<String> resolveKeyStoreFromClassPathAsPathname(Environment environment) {
|
||||
|
||||
return resolveKeyStoreFromClassPath(environment)
|
||||
.filter(File::isFile)
|
||||
.map(File::getAbsolutePath)
|
||||
.filter(StringUtils::hasText);
|
||||
}
|
||||
|
||||
private static Optional<File> resolveKeyStoreFromClassPath(Environment environment) {
|
||||
|
||||
/*
|
||||
System.err.printf("KEYSTORE LOCATION [%s]%n", ObjectUtils.doOperationSafely(() ->
|
||||
new File(new ClassPathResource(keystoreName).getURL().toURI())).getAbsolutePath());
|
||||
*/
|
||||
|
||||
return locateKeyStoreInClassPath(environment)
|
||||
.map(resource -> {
|
||||
|
||||
File trustedKeyStore = null;
|
||||
|
||||
try {
|
||||
|
||||
URL url = resource.getURL();
|
||||
|
||||
if (ResourceUtils.isFileURL(url)) {
|
||||
trustedKeyStore = new File(url.toURI());
|
||||
}
|
||||
else if (ResourceUtils.isJarURL(url)) {
|
||||
trustedKeyStore = new File(CURRENT_WORKING_DIRECTORY, resolveTrustedKeystoreName(environment));
|
||||
FileCopyUtils.copy(url.openStream(), new FileOutputStream(trustedKeyStore));
|
||||
}
|
||||
}
|
||||
catch (IOException | URISyntaxException cause) {
|
||||
|
||||
if (logger.isWarnEnabled()) {
|
||||
|
||||
logger.warn("Trusted KeyStore {} found in Class Path but is not resolvable as a File: {}",
|
||||
resource, cause.getMessage());
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Caused by:", cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return trustedKeyStore;
|
||||
});
|
||||
}
|
||||
|
||||
private static Optional<ClassPathResource> locateKeyStoreInClassPath(Environment environment) {
|
||||
return locateKeyStoreInClassPath(resolveTrustedKeystoreName(environment));
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
private static Optional<ClassPathResource> locateKeyStoreInClassPath(String keystoreName) {
|
||||
|
||||
return Optional.of(new ClassPathResource(keystoreName))
|
||||
.filter(Resource::exists);
|
||||
}
|
||||
|
||||
private static Optional<File> locateKeyStoreInFileSystem(Environment environment) {
|
||||
return locateKeyStoreInFileSystem(environment, new File(CURRENT_WORKING_DIRECTORY));
|
||||
}
|
||||
|
||||
private static Optional<File> locateKeyStoreInFileSystem(Environment environment, File directory) {
|
||||
return locateKeyStoreInFileSystem(directory, resolveTrustedKeystoreName(environment));
|
||||
}
|
||||
|
||||
private static Optional<File> locateKeyStoreInFileSystem(String keystoreName) {
|
||||
return locateKeyStoreInFileSystem(new File(CURRENT_WORKING_DIRECTORY), keystoreName);
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
private static Optional<File> locateKeyStoreInFileSystem(File directory, String keystoreFilename) {
|
||||
|
||||
assertDirectory(directory);
|
||||
|
||||
//System.err.printf("Searching [%s]...%n", directory);
|
||||
|
||||
for (File file : nullSafeListFiles(directory)) {
|
||||
|
||||
//System.err.printf("Testing [%s]...%n", file);
|
||||
|
||||
if (isDirectory(file)) {
|
||||
|
||||
Optional<File> theFile = locateKeyStoreInFileSystem(file, keystoreFilename);
|
||||
|
||||
if (theFile.isPresent()) {
|
||||
return theFile;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (file.getName().equals(keystoreFilename)) {
|
||||
return Optional.of(file);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static Optional<File> locateKeyStoreInUserHome(Environment environment) {
|
||||
return locateKeyStoreInUserHome(resolveTrustedKeystoreName(environment));
|
||||
}
|
||||
|
||||
private static Optional<File> locateKeyStoreInUserHome(String keystoreFilename) {
|
||||
|
||||
return Optional.of(new File(USER_HOME_DIRECTORY, keystoreFilename))
|
||||
.filter(File::isFile);
|
||||
}
|
||||
|
||||
private static void assertDirectory(File path) {
|
||||
Assert.isTrue(isDirectory(path), String.format("[%s] is not a valid directory", path));
|
||||
}
|
||||
|
||||
private static boolean isDirectory(File path) {
|
||||
return path != null && path.isDirectory();
|
||||
}
|
||||
|
||||
private static File[] nullSafeListFiles(File directory) {
|
||||
return nullSafeArray(directory.listFiles(), File.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
static class EnableSslCondition extends AnyNestedCondition {
|
||||
|
||||
public EnableSslCondition() {
|
||||
super(ConfigurationPhase.PARSE_CONFIGURATION);
|
||||
}
|
||||
|
||||
@Conditional(TrustedKeyStoreIsPresentCondition.class)
|
||||
static class TrustedKeyStoreCondition {}
|
||||
|
||||
@ConditionalOnProperty(prefix = "spring.data.gemfire.security.ssl", name = { "keystore", "truststore", })
|
||||
static class SpringDataGeodeSslContextCondition {}
|
||||
|
||||
// TODO: ;-)
|
||||
@ConditionalOnProperty({
|
||||
GEMFIRE_SSL_KEYSTORE_PROPERTY,
|
||||
GEMFIRE_SSL_TRUSTSTORE_PROPERTY,
|
||||
SSL_KEYSTORE_PROPERTY,
|
||||
SSL_TRUSTSTORE_PROPERTY,
|
||||
})
|
||||
static class StandaloneApacheGeodeSslContextCondition {}
|
||||
|
||||
}
|
||||
|
||||
static class SslEnvironmentPostProcessor implements EnvironmentPostProcessor {
|
||||
|
||||
@Override
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
||||
|
||||
Optional.of(environment)
|
||||
.filter(this::isEnabled)
|
||||
.filter(SslAutoConfiguration::isSslNotConfigured)
|
||||
.map(SslAutoConfiguration::resolveTrustedKeyStore)
|
||||
.filter(StringUtils::hasText)
|
||||
.ifPresent(trustedKeyStore -> {
|
||||
|
||||
Properties gemfireSslProperties = new Properties();
|
||||
|
||||
gemfireSslProperties.setProperty(SECURITY_SSL_KEYSTORE_PROPERTY, trustedKeyStore);
|
||||
gemfireSslProperties.setProperty(SECURITY_SSL_TRUSTSTORE_PROPERTY, trustedKeyStore);
|
||||
|
||||
environment.getPropertySources()
|
||||
.addFirst(new PropertiesPropertySource(GEMFIRE_SSL_PROPERTY_SOURCE_NAME, gemfireSslProperties));
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isEnabled(Environment environment) {
|
||||
return !isDisabled(environment);
|
||||
}
|
||||
|
||||
private boolean isDisabled(Environment environment) {
|
||||
return Boolean.getBoolean(SECURITY_SSL_ENVIRONMENT_POST_PROCESSOR_DISABLED_PROPERTY);
|
||||
}
|
||||
}
|
||||
|
||||
static class TrustedKeyStoreIsPresentCondition implements Condition {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
|
||||
Environment environment = context.getEnvironment();
|
||||
|
||||
return locateKeyStoreInClassPath(environment).isPresent()
|
||||
|| locateKeyStoreInUserHome(environment).isPresent()
|
||||
|| locateKeyStoreInFileSystem(environment).isPresent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2018 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Spring Boot auto-configuration for Apache Geode & Pivotal GemFire.
|
||||
*/
|
||||
package org.springframework.geode.boot.autoconfigure;
|
||||
40
geode-spring-boot/src/main/java/org/springframework/geode/cache/support/CacheLoaderSupport.java
vendored
Normal file
40
geode-spring-boot/src/main/java/org/springframework/geode/cache/support/CacheLoaderSupport.java
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.cache.support;
|
||||
|
||||
import org.apache.geode.cache.CacheLoader;
|
||||
|
||||
/**
|
||||
* The {@link CacheLoaderSupport} interface is an extension of {@link CacheLoader} and a {@link FunctionalInterface}
|
||||
* useful in Lambda expressions.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.CacheLoader
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface CacheLoaderSupport<K, V> extends CacheLoader<K, V> {
|
||||
|
||||
/**
|
||||
* Closes any resources opened and used by this {@link CacheLoader}.
|
||||
*
|
||||
* @see org.apache.geode.cache.CacheLoader#close()
|
||||
*/
|
||||
@Override
|
||||
default void close() {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.config.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer;
|
||||
import org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer;
|
||||
import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link MemberNameConfiguration} class is a Spring {@link Configuration} class used to set
|
||||
* an Apache Geode or Pivotal GemFire's name in the distributed system, whether the member
|
||||
* is a {@link ClientCache client} in the client/server topology or a {@link Cache peer} member
|
||||
* of the cluster.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.context.annotation.ImportAware
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
|
||||
* @see org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport
|
||||
* @see org.springframework.geode.config.annotation.UseMemberName
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@SuppressWarnings("unused")
|
||||
public class MemberNameConfiguration extends AbstractAnnotationConfigSupport implements ImportAware {
|
||||
|
||||
private static final String GEMFIRE_NAME_PROPERTY = "name";
|
||||
|
||||
private String memberName;
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotationType() {
|
||||
return UseMemberName.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
|
||||
if (isAnnotationPresent(importMetadata)) {
|
||||
|
||||
AnnotationAttributes memberNameAttributes = getAnnotationAttributes(importMetadata);
|
||||
|
||||
setMemberNameIfNotSet(memberNameAttributes.containsKey("name")
|
||||
? memberNameAttributes.getString("name") : null);
|
||||
|
||||
setMemberNameIfNotSet(memberNameAttributes.containsKey("value")
|
||||
? memberNameAttributes.getString("value") : null);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setMemberName(String memberName) {
|
||||
this.memberName = memberName;
|
||||
}
|
||||
|
||||
protected void setMemberNameIfNotSet(String memberName) {
|
||||
setMemberName(this.memberName != null ? this.memberName : memberName);
|
||||
}
|
||||
|
||||
protected Optional<String> getMemberName() {
|
||||
|
||||
return Optional.ofNullable(this.memberName)
|
||||
.filter(StringUtils::hasText);
|
||||
}
|
||||
|
||||
@Bean
|
||||
ClientCacheConfigurer clientCacheMemberNameConfigurer() {
|
||||
return (beaName, clientCacheFactoryBean) -> configureMemberName(clientCacheFactoryBean);
|
||||
}
|
||||
|
||||
@Bean
|
||||
PeerCacheConfigurer peerCacheMemberNameConfigurer() {
|
||||
return (beaName, peerCacheFactoryBean) -> configureMemberName(peerCacheFactoryBean);
|
||||
}
|
||||
|
||||
private void configureMemberName(CacheFactoryBean cacheFactoryBean) {
|
||||
getMemberName().ifPresent(memberName ->
|
||||
cacheFactoryBean.getProperties().setProperty(GEMFIRE_NAME_PROPERTY, memberName));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.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.cache.Cache;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
/**
|
||||
* The {@link UseMemberName} annotation configures the {@literal name} of the member in the Apache Geode
|
||||
* or Pivotal GemFire distributed system, whether the member is a {@link ClientCache client} in
|
||||
* the client/server topology or a {@link Cache peer} member of the cluster.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.geode.config.annotation.MemberNameConfiguration
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@Import(MemberNameConfiguration.class)
|
||||
public @interface UseMemberName {
|
||||
|
||||
/**
|
||||
* {@link String Name} used for the Apache Geode/Pivotal GemFire distributed system member.
|
||||
* @see #name()
|
||||
*/
|
||||
@AliasFor("name")
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* Alias for the {@link String name} of the Apache Geode/Pivotal GemFire distributed system member.
|
||||
* @see #value()
|
||||
*/
|
||||
@AliasFor("value")
|
||||
String name() default "";
|
||||
|
||||
}
|
||||
239
geode-spring-boot/src/main/java/org/springframework/geode/core/env/VcapPropertySource.java
vendored
Normal file
239
geode-spring-boot/src/main/java/org/springframework/geode/core/env/VcapPropertySource.java
vendored
Normal file
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.core.env;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertiesPropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.geode.core.env.support.CloudCacheService;
|
||||
import org.springframework.geode.core.env.support.Service;
|
||||
import org.springframework.geode.core.env.support.User;
|
||||
import org.springframework.geode.core.util.ObjectUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link VcapPropertySource} class is a Spring {@link PropertySource} to process
|
||||
* {@literal VCAP} environment properties in Pivotal CloudFoundry.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.Iterable
|
||||
* @see java.net.URL
|
||||
* @see java.util.Properties
|
||||
* @see java.util.function.Predicate
|
||||
* @see org.springframework.core.env.EnumerablePropertySource
|
||||
* @see org.springframework.core.env.Environment
|
||||
* @see org.springframework.core.env.PropertiesPropertySource
|
||||
* @see org.springframework.core.env.PropertySource
|
||||
* @see org.springframework.geode.core.env.support.CloudCacheService
|
||||
* @see org.springframework.geode.core.env.support.Service
|
||||
* @see org.springframework.geode.core.env.support.User
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class VcapPropertySource extends PropertySource<EnumerablePropertySource<?>> implements Iterable<String> {
|
||||
|
||||
private static final String CLOUD_CACHE_TAG_NAME = "cloudcache";
|
||||
private static final String GEMFIRE_TAG_NAME = "gemfire";
|
||||
private static final String THIS_PROPERTY_SOURCE_NAME = "boot.data.gemfire.vcap";
|
||||
private static final String VCAP_APPLICATION_PROPERTY = "vcap.application.";
|
||||
private static final String VCAP_APPLICATION_NAME_PROPERTY = VCAP_APPLICATION_PROPERTY + "name";
|
||||
private static final String VCAP_APPLICATION_URIS_PROPERTY = VCAP_APPLICATION_PROPERTY + "uris";
|
||||
private static final String VCAP_PROPERTY_SOURCE_NAME = "vcap";
|
||||
private static final String VCAP_SERVICES_PROPERTY = "vcap.services.";
|
||||
private static final String VCAP_SERVICES_SERVICE_NAME_GFSH_URL_PROPERTY = "vcap.services.%s.credentials.urls.gfsh";
|
||||
private static final String VCAP_SERVICES_SERVICE_NAME_LOCATORS_PROPERTY = "vcap.services.%s.credentials.locators";
|
||||
private static final String VCAP_SERVICES_SERVICE_NAME_USERS_PROPERTY = "vcap.services.%s.credentials.users[%d]";
|
||||
|
||||
private static final Predicate<Object> CLOUD_CACHE_SERVICE_PREDICATE =
|
||||
propertyValue -> String.valueOf(propertyValue).toLowerCase().contains(CLOUD_CACHE_TAG_NAME);
|
||||
|
||||
private static final Predicate<Object> GEMFIRE_SERVICE_PREDICATE =
|
||||
propertyValue -> String.valueOf(propertyValue).toLowerCase().contains(GEMFIRE_TAG_NAME);
|
||||
|
||||
private static final Predicate<Object> CLOUD_CACHE_AND_GEMFIRE_SERVICE_PREDICATE =
|
||||
CLOUD_CACHE_SERVICE_PREDICATE.and(GEMFIRE_SERVICE_PREDICATE);
|
||||
|
||||
private static final Predicate<String> VCAP_APPLICATION_PROPERTIES_PREDICATE =
|
||||
propertyName -> String.valueOf(propertyName).trim().toLowerCase().startsWith(VCAP_APPLICATION_PROPERTY);
|
||||
|
||||
private static final Predicate<PropertySource> VCAP_REQUIRED_PROPERTIES_PREDICATE =
|
||||
propertySource -> propertySource.containsProperty(VCAP_APPLICATION_NAME_PROPERTY)
|
||||
&& propertySource.containsProperty(VCAP_APPLICATION_URIS_PROPERTY);
|
||||
|
||||
private static final Predicate<String> VCAP_SERVICES_PROPERTIES_PREDICATE =
|
||||
propertyName -> String.valueOf(propertyName).trim().toLowerCase().startsWith(VCAP_SERVICES_PROPERTY);
|
||||
|
||||
public static VcapPropertySource from(Environment environment) {
|
||||
|
||||
return Optional.ofNullable(environment)
|
||||
.filter(env -> env instanceof ConfigurableEnvironment)
|
||||
.map(env -> ((ConfigurableEnvironment) env).getPropertySources())
|
||||
.map(propertySources -> propertySources.get(VCAP_PROPERTY_SOURCE_NAME))
|
||||
.map(VcapPropertySource::from)
|
||||
.orElseThrow(() -> newIllegalArgumentException(
|
||||
"Environment was not configurable or does not contain an enumerable [%s] PropertySource",
|
||||
VCAP_PROPERTY_SOURCE_NAME));
|
||||
}
|
||||
|
||||
public static VcapPropertySource from(Properties properties) {
|
||||
|
||||
return Optional.ofNullable(properties)
|
||||
.map(it -> new PropertiesPropertySource(THIS_PROPERTY_SOURCE_NAME, properties))
|
||||
.filter(VCAP_REQUIRED_PROPERTIES_PREDICATE)
|
||||
.map(VcapPropertySource::new)
|
||||
.orElseThrow(() -> newIllegalArgumentException("Properties are required"));
|
||||
}
|
||||
|
||||
public static VcapPropertySource from(PropertySource<?> propertySource) {
|
||||
|
||||
return Optional.ofNullable(propertySource)
|
||||
.filter(it -> VCAP_PROPERTY_SOURCE_NAME.equals(it.getName()))
|
||||
.filter(it -> it instanceof EnumerablePropertySource)
|
||||
.filter(VCAP_REQUIRED_PROPERTIES_PREDICATE)
|
||||
.map(it -> (EnumerablePropertySource) it)
|
||||
.map(VcapPropertySource::new)
|
||||
.orElseThrow(() -> newIllegalArgumentException(
|
||||
"A valid EnumerablePropertySource named [%s] with VCAP properties is required",
|
||||
VCAP_PROPERTY_SOURCE_NAME));
|
||||
}
|
||||
|
||||
private VcapPropertySource(EnumerablePropertySource<?> propertySource) {
|
||||
super(THIS_PROPERTY_SOURCE_NAME, propertySource);
|
||||
}
|
||||
|
||||
protected Set<String> findAllPropertiesByNameMatching(Predicate<String> predicate) {
|
||||
return findAllPropertiesByNameMatching(this, predicate);
|
||||
}
|
||||
|
||||
protected Set<String> findAllPropertiesByNameMatching(Iterable<String> properties, Predicate<String> predicate) {
|
||||
|
||||
return StreamSupport.stream(properties.spliterator(), false)
|
||||
.filter(predicate)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
protected Set<String> findAllPropertiesByValueMatching(Predicate<Object> predicate) {
|
||||
return findAllPropertiesByValueMatching(this, predicate);
|
||||
}
|
||||
|
||||
protected Set<String> findAllPropertiesByValueMatching(Iterable<String> properties, Predicate<Object> predicate) {
|
||||
|
||||
return StreamSupport.stream(properties.spliterator(), false)
|
||||
.filter(propertyName -> predicate.test(getProperty(propertyName)))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public Set<String> findAllVcapApplicationProperties() {
|
||||
return findAllPropertiesByNameMatching(VCAP_APPLICATION_PROPERTIES_PREDICATE);
|
||||
}
|
||||
|
||||
public Set<String> findAllVcapServicesProperties() {
|
||||
return findAllPropertiesByNameMatching(VCAP_SERVICES_PROPERTIES_PREDICATE);
|
||||
}
|
||||
|
||||
public CloudCacheService findFirstCloudCacheService() {
|
||||
|
||||
String serviceName = findFirstCloudCacheServiceName();
|
||||
|
||||
CloudCacheService service = CloudCacheService.with(serviceName);
|
||||
|
||||
Optional.ofNullable(getProperty(String.format(VCAP_SERVICES_SERVICE_NAME_LOCATORS_PROPERTY, serviceName)))
|
||||
.map(String::valueOf)
|
||||
.ifPresent(service::withLocators);
|
||||
|
||||
Optional.ofNullable(getProperty(String.format(VCAP_SERVICES_SERVICE_NAME_GFSH_URL_PROPERTY, service)))
|
||||
.map(String::valueOf)
|
||||
.map(urlString -> ObjectUtils.doOperationSafely(() -> new URL(urlString)))
|
||||
.ifPresent(service::withGfshUrl);
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
public String findFirstCloudCacheServiceName() {
|
||||
|
||||
Iterable<String> vcapServicesProperties = findAllVcapServicesProperties();
|
||||
|
||||
return findAllPropertiesByValueMatching(vcapServicesProperties, CLOUD_CACHE_AND_GEMFIRE_SERVICE_PREDICATE)
|
||||
.stream()
|
||||
.filter(propertyName -> propertyName.endsWith(".tags"))
|
||||
.map(propertyName -> propertyName.substring(VCAP_SERVICES_PROPERTY.length()))
|
||||
.map(propertyName -> propertyName.substring(0, propertyName.indexOf(".")))
|
||||
.filter(StringUtils::hasText)
|
||||
.sorted(String.CASE_INSENSITIVE_ORDER)
|
||||
.findFirst()
|
||||
.orElseThrow(() ->
|
||||
newIllegalStateException("No service with tags [%1$s, %2$s] was found",
|
||||
CLOUD_CACHE_TAG_NAME, GEMFIRE_TAG_NAME));
|
||||
}
|
||||
|
||||
public Optional<User> findFirstUserByRoleClusterOperator(Service service) {
|
||||
|
||||
String serviceName = service.getName();
|
||||
String userPropertyName = String.format(VCAP_SERVICES_SERVICE_NAME_USERS_PROPERTY, serviceName, 0);
|
||||
|
||||
for (int index = 1; containsProperty(userPropertyName+".roles"); index++) {
|
||||
|
||||
String roles = String.valueOf(getProperty(userPropertyName+".roles"));
|
||||
|
||||
if (roles.contains(User.Role.CLUSTER_OPERATOR.name().toLowerCase())) {
|
||||
break;
|
||||
}
|
||||
|
||||
userPropertyName = String.format(VCAP_SERVICES_SERVICE_NAME_USERS_PROPERTY, serviceName, index);
|
||||
}
|
||||
|
||||
if (containsProperty(userPropertyName+".username")) {
|
||||
|
||||
String username = String.valueOf(getProperty(userPropertyName+".username"));
|
||||
String password = String.valueOf(getProperty(userPropertyName+".password"));
|
||||
|
||||
return Optional.of(User.with(username).withPassword(password).withRole(User.Role.CLUSTER_OPERATOR));
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public Object getProperty(String name) {
|
||||
return getSource().getProperty(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public Iterator<String> iterator() {
|
||||
return Collections.unmodifiableList(Arrays.asList(getSource().getPropertyNames())).iterator();
|
||||
}
|
||||
}
|
||||
345
geode-spring-boot/src/main/java/org/springframework/geode/core/env/support/CloudCacheService.java
vendored
Normal file
345
geode-spring-boot/src/main/java/org/springframework/geode/core/env/support/CloudCacheService.java
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.core.env.support;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.data.gemfire.GemfireUtils;
|
||||
import org.springframework.geode.core.util.ObjectUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link CloudCacheService} class is an Abstract Data Type (ADT) modeling the Pivotal Cloud Cache service
|
||||
* in Pivotal CloudFoundry (PCF).
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.net.URL
|
||||
* @see org.springframework.geode.core.env.support.Service
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class CloudCacheService extends Service {
|
||||
|
||||
/**
|
||||
* Factory method used to construct a new {@link CloudCacheService} initialized with the given {@link String name}.
|
||||
*
|
||||
* @param name {@link String} containing the name of the {@link CloudCacheService}.
|
||||
* @throws IllegalArgumentException if the {@link String name} is {@literal null} or empty.
|
||||
* @return the new {@link CloudCacheService} with the given {@link String name}.
|
||||
* @see #CloudCacheService(String)
|
||||
*/
|
||||
public static CloudCacheService with(String name) {
|
||||
return new CloudCacheService(name);
|
||||
}
|
||||
|
||||
private String locators;
|
||||
|
||||
private URL gfshUrl;
|
||||
|
||||
/**
|
||||
* Construct a new instance of {@link CloudCacheService} initialized with the given {@link String name}.
|
||||
*
|
||||
* @param name {@link String} containing the name of the {@link CloudCacheService}.
|
||||
* @throws IllegalArgumentException if the {@link String name} is {@literal null} or empty.
|
||||
*/
|
||||
private CloudCacheService(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Optional} Gfsh {@link URL}, if configured, used to connect to Pivotal GemFire's
|
||||
* Management REST API (service).
|
||||
*
|
||||
* @return an {@link Optional} Gfsh {@link URL} used to connect to Pivotal GemFire's Management REST API (service).
|
||||
* @see #withGfshUrl(URL)
|
||||
* @see java.util.Optional
|
||||
* @see java.net.URL
|
||||
*/
|
||||
public Optional<URL> getGfshUrl() {
|
||||
return Optional.ofNullable(this.gfshUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Optional} {@link String} containing the list of Pivotal GemFire Locator network endpoints.
|
||||
*
|
||||
* The format of the {@link String}, if present, is {@literal host1[port1],host2[port2], ...,hostN[portN]}.
|
||||
*
|
||||
* @return an {@link Optional} {@link String} containing the list of Pivotal GemFire Locator network endpoints.
|
||||
* @see #withLocators(String)
|
||||
*/
|
||||
public Optional<String> getLocators() {
|
||||
return Optional.ofNullable(this.locators).filter(StringUtils::hasText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of Pivotal GemFire Locator network endpoints.
|
||||
*
|
||||
* Returns an {@link Collections#emptyList() empty List} if no Locators were configured.
|
||||
*
|
||||
* @return a {@link List} of Pivotal GemFire Locator network endpoints.
|
||||
* @see #getLocators()
|
||||
*/
|
||||
public List<Locator> getLocatorList() {
|
||||
|
||||
return getLocators()
|
||||
.map(Locator::parseLocators)
|
||||
.orElseGet(Collections::emptyList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder method used to configure the Gfsh {@link URL} to connect to the Pivotal GemFire
|
||||
* Management REST API (service).
|
||||
*
|
||||
* @param gfshUrl {@link URL} used to connect to the Pivotal GemFire Management REST API (service).
|
||||
* @return this {@link CloudCacheService}.
|
||||
* @see #getGfshUrl()
|
||||
*/
|
||||
public CloudCacheService withGfshUrl(URL gfshUrl) {
|
||||
this.gfshUrl = gfshUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder method used to configure the {@link String list of Locator} network endpoints.
|
||||
*
|
||||
* @param locators {@link String} containing a comma-delimited list of Locator network endpoints
|
||||
* of the format: {@literal host1[port1],host2[port2], ...,hostN[portN]}.
|
||||
* @return this {@link CloudCacheService}.
|
||||
* @see #getLocators()
|
||||
*/
|
||||
public CloudCacheService withLocators(String locators) {
|
||||
this.locators = locators;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class Locator implements Comparable<Locator> {
|
||||
|
||||
static final int DEFAULT_LOCATOR_PORT = GemfireUtils.DEFAULT_LOCATOR_PORT;
|
||||
|
||||
static final String DEFAULT_LOCATOR_HOST = "localhost";
|
||||
|
||||
private Integer port;
|
||||
|
||||
private String host;
|
||||
|
||||
/**
|
||||
* Factory method used to construct a new {@link Locator} on the default {@link String host}
|
||||
* and {@link Integer port}.
|
||||
*
|
||||
* @return a new, default {@link Locator}.
|
||||
* @see #newLocator(String, int)
|
||||
*/
|
||||
public static Locator newLocator() {
|
||||
return newLocator(DEFAULT_LOCATOR_HOST, DEFAULT_LOCATOR_PORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method used to construct a new {@link Locator} running on the default {@link String host}
|
||||
* and configured to listen on the given {@link Integer port}.
|
||||
*
|
||||
* @param port {@link Integer} containing the port number on which the {@link Locator} is listening.
|
||||
* @return a new {@link Locator} running on the default {@link String host},
|
||||
* listening on the given {@link Integer port}.
|
||||
* @throws IllegalArgumentException if the {@link Integer port} is less than {@literal 0}.
|
||||
* @see #newLocator(String, int)
|
||||
*/
|
||||
public static Locator newLocator(int port) {
|
||||
return newLocator(DEFAULT_LOCATOR_HOST, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method used to construct a new {@link Locator} configured to run on the given {@link String host}
|
||||
* and listening on the default {@link Integer port}.
|
||||
*
|
||||
* @param host {@link String} containing the name of the host on which the {@link Locator} is running.
|
||||
* @return a new {@link Locator} running on the configured {@link String host},
|
||||
* listening on the default {@link Integer port}.
|
||||
* @throws IllegalArgumentException if {@link String host} is {@literal null} or empty.
|
||||
* @see #newLocator(String, int)
|
||||
*/
|
||||
public static Locator newLocator(String host) {
|
||||
return newLocator(host, DEFAULT_LOCATOR_PORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method used to construct a new {@link Locator} running on the configured {@link String host}
|
||||
* and listening on the configured {@link Integer port}.
|
||||
*
|
||||
* @param host {@link String} containing the name of the host on which the {@link Locator} is running.
|
||||
* @param port {@link Integer} containing the port number on which the {@link Locator} is listening.
|
||||
* @throws IllegalArgumentException if {@link String host} is {@literal null} or empty,
|
||||
* or the {@link Integer port} is less than {@literal 0}.
|
||||
* @return a new {@link Locator} on the configured {@link String host} and {@link Integer port}.
|
||||
*/
|
||||
public static Locator newLocator(String host, int port) {
|
||||
|
||||
Assert.hasText(host, String.format("Host [%s] is required", host));
|
||||
Assert.isTrue(port > -1, String.format("Port [%d] must be greater than equal to 0", port));
|
||||
|
||||
return new Locator(host, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method used to parse a {@link String comma-delimited list of Locator network endpoints}
|
||||
* into a {@link List} of {@link Locator} objects.
|
||||
*
|
||||
* The {@link String comma-delimited list of Locators} must be formatted as
|
||||
* {@literal host1[port1],host2[port2], ...,hostN[portN]}.
|
||||
*
|
||||
* @param locators {@link String} containing a comma-delimited list of Locator network endpoints.
|
||||
* @return a new {@link List} of {@link Locator} objects or an empty {@link List}
|
||||
* if no Locators were specified.
|
||||
* @throws IllegalArgumentException if an individual Locator {@link String host[port]} is not valid.
|
||||
* @see #parse(String)
|
||||
*/
|
||||
public static List<Locator> parseLocators(String locators) {
|
||||
|
||||
return Arrays.stream(String.valueOf(locators).split(","))
|
||||
.filter(StringUtils::hasText)
|
||||
.map(Locator::parse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method used to parse an individual {@link String host[port]} network endpoint for a Locator.
|
||||
*
|
||||
* @param hostPort {@link String} containing the Locator host and port to parse.
|
||||
* @return a new {@link Locator} configured from the given {@link String}.
|
||||
* @throws IllegalArgumentException if the {@link String hostPort} are not valid.
|
||||
* @see #parseHost(String)
|
||||
* @see #parsePort(String)
|
||||
* @see #newLocator(String, int)
|
||||
*/
|
||||
public static Locator parse(String hostPort) {
|
||||
|
||||
return Optional.ofNullable(hostPort)
|
||||
.filter(StringUtils::hasText)
|
||||
.map(it -> {
|
||||
|
||||
String host = parseHost(it);
|
||||
int port = parsePort(it);
|
||||
|
||||
return newLocator(host, port);
|
||||
})
|
||||
.orElseThrow(() -> newIllegalArgumentException("Locator host/port [%s] is not valid", hostPort));
|
||||
}
|
||||
|
||||
private static String parseHost(String value) {
|
||||
|
||||
int index = String.valueOf(value).trim().indexOf("[");
|
||||
|
||||
return index > 0 ? value.trim().substring(0, index).trim()
|
||||
: (index != 0 && StringUtils.hasText(value) ? value.trim() : DEFAULT_LOCATOR_HOST);
|
||||
}
|
||||
|
||||
private static int parsePort(String value) {
|
||||
|
||||
StringBuilder digits = new StringBuilder();
|
||||
|
||||
for (char chr : String.valueOf(value).toCharArray()) {
|
||||
if (Character.isDigit(chr)) {
|
||||
digits.append(chr);
|
||||
}
|
||||
}
|
||||
|
||||
return digits.length() > 0 ? Integer.valueOf(digits.toString()) : DEFAULT_LOCATOR_PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new {@link Locator} initialized with the {@link String host} and {@link Integer port}
|
||||
* on which this {@link Locator} is running and listening for connections.
|
||||
*
|
||||
* @param host {@link String} containing the name of the host on which this {@link Locator} is running.
|
||||
* @param port {@link Integer} specifying the port number on which this {@link Locator} is listening.
|
||||
*/
|
||||
private Locator(String host, Integer port) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link String name} of the host on which this {@link Locator} is running.
|
||||
*
|
||||
* Defaults to {@literal localhost}.
|
||||
*
|
||||
* @return the {@link String name} of the host on which this {@link Locator} is running.
|
||||
*/
|
||||
public String getHost() {
|
||||
return Optional.ofNullable(this.host).filter(StringUtils::hasText).orElse(DEFAULT_LOCATOR_HOST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Integer port} on which this {@link Locator} is listening.
|
||||
*
|
||||
* Defaults to {@literal 10334}.
|
||||
*
|
||||
* @return the {@link Integer port} on which this {@link Locator} is listening.
|
||||
*/
|
||||
public int getPort() {
|
||||
return Optional.ofNullable(this.port).orElse(DEFAULT_LOCATOR_PORT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public int compareTo(Locator other) {
|
||||
|
||||
int result = this.getHost().compareTo(other.getHost());
|
||||
|
||||
return result != 0 ? result : (this.getPort() - other.getPort());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof Locator)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Locator that = (Locator) obj;
|
||||
|
||||
return this.getHost().equals(that.getHost())
|
||||
&& this.getPort() == that.getPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int hashValue = 17;
|
||||
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getHost());
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getPort());
|
||||
|
||||
return hashValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s[%d]", getHost(), getPort());
|
||||
}
|
||||
}
|
||||
}
|
||||
70
geode-spring-boot/src/main/java/org/springframework/geode/core/env/support/Service.java
vendored
Normal file
70
geode-spring-boot/src/main/java/org/springframework/geode/core/env/support/Service.java
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.core.env.support;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* The {@link Service} class is an Abstract Data Type (ADT) modeling a Pivotal CloudFoundry Service.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class Service {
|
||||
|
||||
/**
|
||||
* Factory method to construct a new {@link Service} initialized with a {@link String name}.
|
||||
*
|
||||
* @param name {@link String} containing the name of the {@link Service}.
|
||||
* @return a new {@link Service} configured with the given {@link String name}.
|
||||
* @throws IllegalArgumentException if the {@link String name} is {@literal null} or empty.
|
||||
* @see #Service(String)
|
||||
*/
|
||||
public static Service with(String name) {
|
||||
return new Service(name);
|
||||
}
|
||||
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link Service} initialized with a {@link String name}.
|
||||
*
|
||||
* @param name {@link String} containing the name of the {@link Service}.
|
||||
* @throws IllegalArgumentException if the {@link String name} is {@literal null} or empty.
|
||||
*/
|
||||
Service(String name) {
|
||||
|
||||
Assert.hasText(name, String.format("Service name [%s] is required", name));
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link String name} of this {@link Service}.
|
||||
*
|
||||
* @return this {@link Service Service's} {@link String name}.
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
182
geode-spring-boot/src/main/java/org/springframework/geode/core/env/support/User.java
vendored
Normal file
182
geode-spring-boot/src/main/java/org/springframework/geode/core/env/support/User.java
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.core.env.support;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link User} class is an Abstract Data Type (ADT) modeling a user in Pivotal CloudFoundry (PCF).
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class User implements Comparable<User> {
|
||||
|
||||
private Role role;
|
||||
|
||||
private final String name;
|
||||
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Factory method used to construct a new {@link User} initialized with the given {@link String name}.
|
||||
*
|
||||
* @param name {@link String} containing the name of the {@link User}.
|
||||
* @return a new {@link User} initialized witht he given {@link String name}.
|
||||
* @throws IllegalArgumentException if {@link String name} is {@literal null} or empty.
|
||||
* @see #User(String)
|
||||
*/
|
||||
public static User with(String name) {
|
||||
return new User(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link User} initialized with the given {@link String name}.
|
||||
*
|
||||
* @param name {@link String} containing the name of the {@link User}.
|
||||
* @throws IllegalArgumentException if {@link String name} is {@literal null} or empty.
|
||||
*/
|
||||
private User(String name) {
|
||||
|
||||
Assert.hasText(name, String.format("User name [%s] is required", name));
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link String name} of this {@link User}.
|
||||
*
|
||||
* @return a {@link String} containing the {@link User User's} name.
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Optional} {@link String} containing {@link User User's} password.
|
||||
*
|
||||
* @return an {@link Optional} {@link String} containing {@link User User's} password.
|
||||
* @see java.util.Optional
|
||||
*/
|
||||
public Optional<String> getPassword() {
|
||||
return Optional.ofNullable(this.password).filter(StringUtils::hasText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Optional} {@link Role} for this {@link User}.
|
||||
*
|
||||
* @return an {@link Optional} {@link Role} for this {@link User}.
|
||||
* @see org.springframework.geode.core.env.support.User.Role
|
||||
* @see java.util.Optional
|
||||
*/
|
||||
public Optional<Role> getRole() {
|
||||
return Optional.ofNullable(this.role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder method used to set this {@link User User's} {@link String password}.
|
||||
*
|
||||
* @param password {@link String} containing this {@link User User's} password.
|
||||
* @return this {@link User}.
|
||||
*/
|
||||
public User withPassword(String password) {
|
||||
this.password = password;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder method used to set this {@link User User's} {@link Role}.
|
||||
*
|
||||
* @param role assigned {@link Role} of this {@link User}.
|
||||
* @return this {@link User}.
|
||||
* @see org.springframework.geode.core.env.support.User
|
||||
*/
|
||||
public User withRole(Role role) {
|
||||
this.role = role;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public int compareTo(User other) {
|
||||
return this.getName().compareTo(other.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof User)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
User that = (User) obj;
|
||||
|
||||
return this.getName().equals(that.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int hashValue = 17;
|
||||
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getName());
|
||||
|
||||
return hashValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
public enum Role {
|
||||
|
||||
CLUSTER_OPERATOR,
|
||||
DEVELOPER;
|
||||
|
||||
public static Role of(String name) {
|
||||
|
||||
return Arrays.stream(values())
|
||||
.filter(role -> role.name().equalsIgnoreCase(String.valueOf(name).trim()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public boolean isClusterOperator() {
|
||||
return CLUSTER_OPERATOR.equals(this);
|
||||
}
|
||||
|
||||
public boolean isDeveloper() {
|
||||
return DEVELOPER.equals(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.core.util;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link ObjectUtils} class is an abstract utility class with operations for {@link Object objects}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.Object
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public abstract class ObjectUtils extends org.springframework.util.ObjectUtils {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ObjectUtils.class);
|
||||
|
||||
/**
|
||||
* Executes the given {@link ExceptionThrowingOperation} handling any checked {@link Exception} thrown during
|
||||
* the normal execution of the operation by rethrowing an {@link IllegalStateException} wrapping
|
||||
* the checked {@link Exception}.
|
||||
*
|
||||
* @param <T> {@link Class type} of the operation result.
|
||||
* @param operation {@link ExceptionThrowingOperation} to execute.
|
||||
* @return the result of the given {@link ExceptionThrowingOperation} or throw an {@link IllegalStateException}
|
||||
* wrapping the checked {@link Exception} thrown by the operation.
|
||||
* @see org.springframework.geode.core.util.ObjectUtils.ExceptionThrowingOperation
|
||||
* @see #doOperationSafely(ExceptionThrowingOperation, Object)
|
||||
*/
|
||||
@Nullable
|
||||
public static <T> T doOperationSafely(ExceptionThrowingOperation<T> operation) {
|
||||
return doOperationSafely(operation, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given {@link ExceptionThrowingOperation} handling any checked {@link Exception} thrown
|
||||
* during the normal execution of the operation, returning the {@link Object default value} in its place
|
||||
* or throwing a {@link RuntimeException} if the {@link Object default value} is {@literal null}.
|
||||
*
|
||||
* @param <T> {@link Class type} of the operation result as well as the {@link Object default value}.
|
||||
* @param operation {@link ExceptionThrowingOperation} to execute.
|
||||
* @param defaultValue {@link Object value} to return if the operation results in a checked {@link Exception}.
|
||||
* @return the result of the given {@link ExceptionThrowingOperation}, returning the {@link Object default value}
|
||||
* if the operation throws a checked {@link Exception} or throws an {@link IllegalStateException} wrapping
|
||||
* the checked {@link Exception} if the {@link Object default value} is {@literal null}.
|
||||
* @throws IllegalStateException if the {@link ExceptionThrowingOperation} throws a checked {@link Exception}
|
||||
* and {@link Object default value} is {@literal null}.
|
||||
* @see org.springframework.geode.core.util.ObjectUtils.ExceptionThrowingOperation
|
||||
* @see #returnValueThrowOnNull(Object, RuntimeException)
|
||||
*/
|
||||
@Nullable
|
||||
public static <T> T doOperationSafely(ExceptionThrowingOperation<T> operation, T defaultValue) {
|
||||
|
||||
try {
|
||||
return operation.doExceptionThrowingOperation();
|
||||
}
|
||||
catch (Exception cause) {
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Failed to execute operation [%s]", operation), cause);
|
||||
}
|
||||
|
||||
return returnValueThrowOnNull(defaultValue,
|
||||
newIllegalStateException(cause, "Failed to execute operation"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given {@link Object value} or throws an {@link IllegalArgumentException}
|
||||
* if {@link Object value} is {@literal null}.
|
||||
*
|
||||
* @param <T> {@link Class type} of the {@link Object value}.
|
||||
* @param value {@link Object} to return.
|
||||
* @return the {@link Object value} or throw an {@link IllegalArgumentException}
|
||||
* if {@link Object value} is {@literal null}.
|
||||
* @see #returnValueThrowOnNull(Object, RuntimeException)
|
||||
*/
|
||||
public static <T> T returnValueThrowOnNull(T value) {
|
||||
return returnValueThrowOnNull(value, newIllegalArgumentException("Value must not be null"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given {@link Object value} or throws the given {@link RuntimeException}
|
||||
* if {@link Object value} is {@literal null}.
|
||||
*
|
||||
* @param <T> {@link Class type} of the {@link Object value}.
|
||||
* @param value {@link Object} to return.
|
||||
* @param exception {@link RuntimeException} to throw if {@link Object value} is {@literal null}.
|
||||
* @return the {@link Object value} or throw the given {@link RuntimeException}
|
||||
* if {@link Object value} is {@literal null}.
|
||||
*/
|
||||
public static <T> T returnValueThrowOnNull(T value, RuntimeException exception) {
|
||||
|
||||
if (value == null) {
|
||||
throw exception;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ExceptionThrowingOperation<T> {
|
||||
T doExceptionThrowingOperation() throws Exception;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.function.support;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.apache.geode.cache.execute.FunctionException;
|
||||
import org.apache.geode.cache.execute.ResultCollector;
|
||||
|
||||
/**
|
||||
* The {@link AbstractResultCollector} class is an abstract base implementation of the {@link ResultCollector} interface
|
||||
* encapsulating common functionality for collecting results from a Function execution.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.execute.ResultCollector
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class AbstractResultCollector<T, S> implements ResultCollector<T, S> {
|
||||
|
||||
protected static final String NOT_IMPLEMENTED = "Not Implemented";
|
||||
|
||||
protected static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MILLISECONDS;
|
||||
|
||||
private AtomicBoolean resultsEnded = new AtomicBoolean(false);
|
||||
|
||||
private S result = null;
|
||||
|
||||
@Override
|
||||
public synchronized S getResult() throws FunctionException {
|
||||
return this.result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public S getResult(long duration, TimeUnit unit) throws FunctionException, InterruptedException {
|
||||
|
||||
unit = resolveTimeUnit(unit);
|
||||
|
||||
long durationInMilliseconds = unit.toMillis(duration);
|
||||
long timeout = System.currentTimeMillis() + unit.toMillis(duration);
|
||||
long waitInMilliseconds = Math.max(50, Math.min(durationInMilliseconds / 5, durationInMilliseconds));
|
||||
|
||||
synchronized (this) {
|
||||
while (getResult() == null && System.currentTimeMillis() < timeout) {
|
||||
unit.timedWait(this, waitInMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
return getResult();
|
||||
}
|
||||
|
||||
protected synchronized void setResult(S result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
protected TimeUnit resolveTimeUnit(TimeUnit unit) {
|
||||
return unit != null ? unit : DEFAULT_TIME_UNIT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearResults() {
|
||||
setResult(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endResults() {
|
||||
this.resultsEnded.set(true);
|
||||
}
|
||||
|
||||
protected boolean hasResultsEnded() {
|
||||
return this.resultsEnded.get();
|
||||
}
|
||||
|
||||
protected boolean hasResultsNotEnded() {
|
||||
return !this.resultsEnded.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.function.support;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.execute.ResultCollector;
|
||||
import org.apache.geode.distributed.DistributedMember;
|
||||
|
||||
/**
|
||||
* The {@link SingleResultReturningCollector} class is an implementation of the {@link ResultCollector} interface
|
||||
* which returns a single {@link Object result}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.execute.ResultCollector
|
||||
* @see org.springframework.geode.function.support.AbstractResultCollector
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class SingleResultReturningCollector<T> extends AbstractResultCollector<T, T> {
|
||||
|
||||
@Override
|
||||
public void addResult(DistributedMember memberID, T resultOfSingleExecution) {
|
||||
setResult(extractSingleResult(resultOfSingleExecution));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T extractSingleResult(Object result) {
|
||||
|
||||
return (T) Optional.ofNullable(result)
|
||||
.filter(this::isInstanceOfIterableOrIterator)
|
||||
.map(this::toIterator)
|
||||
.filter(Iterator::hasNext)
|
||||
.map(Iterator::next)
|
||||
.map(this::extractSingleResult)
|
||||
.orElseGet(() -> isInstanceOfIterableOrIterator(result) ? null : result);
|
||||
}
|
||||
|
||||
private boolean isInstanceOfIterableOrIterator(Object obj) {
|
||||
return obj instanceof Iterable || obj instanceof Iterator;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> Iterator<T> toIterator(Object obj) {
|
||||
return obj instanceof Iterator ? (Iterator<T>) obj : toIterator((Iterable<T>) obj);
|
||||
}
|
||||
|
||||
private <T> Iterator<T> toIterator(Iterable<T> iterable) {
|
||||
return iterable != null ? iterable.iterator() : Collections.emptyIterator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.security.support;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.geode.security.AuthenticationFailedException;
|
||||
import org.apache.geode.security.ResourcePermission;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.gemfire.support.LazyWiringDeclarableSupport;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* The {@link SecurityManagerProxy} class is an Apache Geode {@link org.apache.geode.security.SecurityManager}
|
||||
* proxy implementation delegating to a backing {@link org.apache.geode.security.SecurityManager} implementation
|
||||
* which is registered as a managed bean in a Spring context.
|
||||
*
|
||||
* The idea behind this {@link org.apache.geode.security.SecurityManager} is to enable users to be able to configure
|
||||
* and manage the {@code SecurityManager} as a Spring bean. However, Apache Geode/Pivotal GemFire require
|
||||
* the {@link org.apache.geode.security.SecurityManager} to be configured using a System property when launching
|
||||
* Apache Geode Servers with Gfsh, which makes it difficult to "manage" the {@code SecurityManager} instance.
|
||||
*
|
||||
* Therefore, this implementation allows a developer to set the Apache Geode System property using this proxy...
|
||||
*
|
||||
* <code>
|
||||
* gemfire.security-manager=org.springframework.geode.security.support.SecurityManagerProxy
|
||||
* </code>
|
||||
*
|
||||
* And then declare and define a bean in the Spring context implementing the
|
||||
* {@link org.apache.geode.security.SecurityManager} interface...
|
||||
*
|
||||
* <code>
|
||||
* Configuration
|
||||
* class MyApplicationConfiguration {
|
||||
*
|
||||
* Bean
|
||||
* ExampleSecurityManager exampleSecurityManager(Environment environment) {
|
||||
* return new ExampleSecurityManager(environment);
|
||||
* }
|
||||
*
|
||||
* ...
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.security.ResourcePermission
|
||||
* @see org.apache.geode.security.SecurityManager
|
||||
* @see org.springframework.beans.factory.annotation.Autowired
|
||||
* @see org.springframework.data.gemfire.support.LazyWiringDeclarableSupport
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class SecurityManagerProxy extends LazyWiringDeclarableSupport
|
||||
implements org.apache.geode.security.SecurityManager {
|
||||
|
||||
private static final AtomicReference<SecurityManagerProxy> INSTANCE = new AtomicReference<>();
|
||||
|
||||
private org.apache.geode.security.SecurityManager securityManager;
|
||||
|
||||
/**
|
||||
* Returns a reference to the single {@link SecurityManagerProxy} instance configured by
|
||||
* Apache Geode/Pivotal GemFire in startup.
|
||||
*
|
||||
* @return a reference to the single {@link SecurityManagerProxy} instance.
|
||||
*/
|
||||
public static SecurityManagerProxy getInstance() {
|
||||
|
||||
return Optional.ofNullable(INSTANCE.get())
|
||||
.orElseThrow(() -> newIllegalStateException("SecurityManagerProxy was not configured"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new instance of {@link SecurityManagerProxy}, which will delegate all Apache Geode
|
||||
* security operations to a Spring managed {@link org.apache.geode.security.SecurityManager} bean.
|
||||
*/
|
||||
public SecurityManagerProxy() {
|
||||
|
||||
// TODO remove init() call when GEODE-2083 (https://issues.apache.org/jira/browse/GEODE-2083) is resolved!
|
||||
// NOTE: the init(:Properties) call in the constructor is less than ideal since...
|
||||
// 1) it allows the *this* reference to escape, and...
|
||||
// 2) it is Geode's responsibility to identify Geode Declarable objects and invoke their init(:Properties) method
|
||||
// However, the init(:Properties) method invocation in the constructor is necessary to enable this Proxy to be
|
||||
// identified and auto-wired in a Spring context.
|
||||
|
||||
INSTANCE.compareAndSet(null, this);
|
||||
init(new Properties());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a reference to the Apache Geode {@link org.apache.geode.security.SecurityManager} instance
|
||||
* delegated to by this {@link SecurityManagerProxy}.
|
||||
*
|
||||
* @param securityManager reference to the underlying Apache Geode {@link org.apache.geode.security.SecurityManager}
|
||||
* instance delegated to by this {@link SecurityManagerProxy}.
|
||||
* @throws IllegalArgumentException if the {@link org.apache.geode.security.SecurityManager} reference
|
||||
* is {@literal null}.
|
||||
* @see org.apache.geode.security.SecurityManager
|
||||
*/
|
||||
@Autowired
|
||||
public void setSecurityManager(org.apache.geode.security.SecurityManager securityManager) {
|
||||
|
||||
Assert.notNull(securityManager, "SecurityManager must not be null");
|
||||
|
||||
this.securityManager = securityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Apache Geode {@link org.apache.geode.security.SecurityManager} instance
|
||||
* delegated to by this {@link SecurityManagerProxy}.
|
||||
*
|
||||
* @return a reference to the underlying {@link org.apache.geode.security.SecurityManager} instance
|
||||
* delegated to by this {@link SecurityManagerProxy}.
|
||||
* @throws IllegalStateException if the configured {@link org.apache.geode.security.SecurityManager}
|
||||
* was not properly configured.
|
||||
* @see org.apache.geode.security.SecurityManager
|
||||
*/
|
||||
protected org.apache.geode.security.SecurityManager getSecurityManager() {
|
||||
|
||||
Assert.state(this.securityManager != null, "No SecurityManager configured");
|
||||
|
||||
return this.securityManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object authenticate(Properties properties) throws AuthenticationFailedException {
|
||||
return getSecurityManager().authenticate(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authorize(Object principal, ResourcePermission permission) {
|
||||
return getSecurityManager().authorize(principal, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
getSecurityManager().close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# Auto Configuration
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.geode.boot.autoconfigure.ClientCacheAutoConfiguration,\
|
||||
org.springframework.geode.boot.autoconfigure.CachingProviderAutoConfiguration,\
|
||||
org.springframework.geode.boot.autoconfigure.ClientSecurityAutoConfiguration,\
|
||||
org.springframework.geode.boot.autoconfigure.ContinuousQueryAutoConfiguration,\
|
||||
org.springframework.geode.boot.autoconfigure.FunctionExecutionAutoConfiguration,\
|
||||
org.springframework.geode.boot.autoconfigure.PeerSecurityAutoConfiguration,\
|
||||
org.springframework.geode.boot.autoconfigure.RepositoriesAutoConfiguration,\
|
||||
org.springframework.geode.boot.autoconfigure.SslAutoConfiguration
|
||||
|
||||
# Environment Post Processing
|
||||
org.springframework.boot.env.EnvironmentPostProcessor=\
|
||||
org.springframework.geode.boot.autoconfigure.ClientSecurityAutoConfiguration.AutoConfiguredCloudSecurityEnvironmentPostProcessor,\
|
||||
org.springframework.geode.boot.autoconfigure.SslAutoConfiguration.SslEnvironmentPostProcessor
|
||||
27
geode-spring-boot/src/test/java/example/app/NonBeanType.java
Normal file
27
geode-spring-boot/src/test/java/example/app/NonBeanType.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.app;
|
||||
|
||||
/**
|
||||
* The {@link NonBeanType} class is a non-Spring bean, placeholder reference type for classpath component scanning.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class NonBeanType {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.app.model;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.gemfire.mapping.annotation.Region;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* The Author class...
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Data
|
||||
@Region("Authors")
|
||||
@RequiredArgsConstructor(staticName = "newAuthor")
|
||||
@SuppressWarnings("unused")
|
||||
public class Author {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
@NonNull
|
||||
private String name;
|
||||
|
||||
public boolean isNew() {
|
||||
return getId() == null;
|
||||
}
|
||||
|
||||
public Author identifiedBy(Long id) {
|
||||
setId(id);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
60
geode-spring-boot/src/test/java/example/app/model/Book.java
Normal file
60
geode-spring-boot/src/test/java/example/app/model/Book.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.app.model;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.gemfire.mapping.annotation.Region;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* The {@link Book} class is an Abstract Data Type (ADT) modeling a book.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see lombok
|
||||
* @see org.springframework.data.annotation.Id
|
||||
* @see org.springframework.data.gemfire.mapping.annotation.Region
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Region("Books")
|
||||
@Data
|
||||
@RequiredArgsConstructor(staticName = "newBook")
|
||||
public class Book {
|
||||
|
||||
private Author author;
|
||||
|
||||
@Id
|
||||
private ISBN isbn;
|
||||
|
||||
private LocalDate publishedDate;
|
||||
|
||||
@NonNull
|
||||
private String title;
|
||||
|
||||
public boolean isNew() {
|
||||
return getIsbn() == null;
|
||||
}
|
||||
|
||||
public Book identifiedBy(ISBN isbn) {
|
||||
setIsbn(isbn);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
90
geode-spring-boot/src/test/java/example/app/model/ISBN.java
Normal file
90
geode-spring-boot/src/test/java/example/app/model/ISBN.java
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.app.model;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.shiro.util.Assert;
|
||||
|
||||
/**
|
||||
* The {@link ISBN} class is a Abstract Data Type (ADT) modeling either a {@link Book} ISBN-10 or ISBN-13 number.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.Comparable
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ISBN implements Comparable<ISBN> {
|
||||
|
||||
public static ISBN autoGenerated() {
|
||||
return of(UUID.randomUUID().toString());
|
||||
}
|
||||
|
||||
public static ISBN of(String number) {
|
||||
|
||||
Assert.hasText(number, String.format("Number [%s] is required", number));
|
||||
|
||||
return new ISBN(number);
|
||||
}
|
||||
|
||||
private String number;
|
||||
|
||||
private ISBN(String number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public String getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public int compareTo(ISBN other) {
|
||||
return this.getNumber().compareTo(other.getNumber());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof ISBN)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ISBN that = (ISBN) obj;
|
||||
|
||||
return this.getNumber().equals(that.getNumber());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int hashValue = 17;
|
||||
|
||||
hashValue = 37 * hashValue + getNumber().hashCode();
|
||||
|
||||
return hashValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getNumber();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.app.repo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import example.app.model.Author;
|
||||
import example.app.model.Book;
|
||||
import example.app.model.ISBN;
|
||||
|
||||
/**
|
||||
* The {@link BookRepository} interface is a Spring Data {@link CrudRepository} defining basic CRUD
|
||||
* and simple query data access operations on {@link Book} objects to the backing data store.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see example.app.model.Book
|
||||
* @see example.app.model.ISBN
|
||||
* @see org.springframework.data.repository.CrudRepository
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface BookRepository extends CrudRepository<Book, ISBN> {
|
||||
|
||||
List<Book> findByAuthorOrderByAuthorNameAscTitleAsc(Author author);
|
||||
|
||||
Book findByIsbn(ISBN isbn);
|
||||
|
||||
Book findByTitle(String title);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.app.service;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import example.app.model.Author;
|
||||
import example.app.model.Book;
|
||||
import example.app.model.ISBN;
|
||||
import example.app.repo.BookRepository;
|
||||
|
||||
/**
|
||||
* The {@link BookService} class is an application {@link Service service} class for managing {@link Book Books}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see example.app.model.Author
|
||||
* @see example.app.model.Book
|
||||
* @see example.app.model.ISBN
|
||||
* @see example.app.repo.BookRepository
|
||||
* @see org.springframework.stereotype.Service
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Service
|
||||
@SuppressWarnings("unused")
|
||||
public class BookService {
|
||||
|
||||
private final BookRepository bookRepository;
|
||||
|
||||
public BookService(@Autowired(required = false) BookRepository bookRepository) {
|
||||
this.bookRepository = bookRepository;
|
||||
}
|
||||
|
||||
protected BookRepository getBookRepository() {
|
||||
|
||||
return Optional.ofNullable(this.bookRepository)
|
||||
.orElseThrow(() -> newIllegalStateException("BookRepository was not properly configured"));
|
||||
}
|
||||
|
||||
public List<Book> findByAuthor(Author author) {
|
||||
return getBookRepository().findByAuthorOrderByAuthorNameAscTitleAsc(author);
|
||||
}
|
||||
|
||||
public Book findByIsbn(ISBN isbn) {
|
||||
return getBookRepository().findByIsbn(isbn);
|
||||
}
|
||||
|
||||
public Book findByTitle(String title) {
|
||||
return getBookRepository().findByTitle(title);
|
||||
}
|
||||
|
||||
public Book stock(Book book) {
|
||||
|
||||
if (book.isNew()) {
|
||||
book.identifiedBy(ISBN.autoGenerated());
|
||||
}
|
||||
|
||||
return getBookRepository().save(book);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.app.service.support;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import example.app.model.Book;
|
||||
import example.app.model.ISBN;
|
||||
import example.app.repo.BookRepository;
|
||||
import example.app.service.BookService;
|
||||
|
||||
/**
|
||||
* The {@link CachingBookService} class is an implementation and extension of {@link BookService}
|
||||
* with caching capabilities.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see example.app.model.Book
|
||||
* @see example.app.service.BookService
|
||||
* @see org.springframework.cache.annotation.Cacheable
|
||||
* @see org.springframework.stereotype.Service
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Service
|
||||
public class CachingBookService extends BookService {
|
||||
|
||||
private final AtomicBoolean cacheMiss = new AtomicBoolean(false);
|
||||
|
||||
public CachingBookService(@Autowired(required = false) BookRepository bookRepository) {
|
||||
super(bookRepository);
|
||||
}
|
||||
|
||||
public boolean isCacheMiss() {
|
||||
return this.cacheMiss.getAndSet(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(value = "CachedBooks")
|
||||
public Book findByTitle(String title) {
|
||||
this.cacheMiss.set(true);
|
||||
return Book.newBook(title).identifiedBy(ISBN.autoGenerated());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.echo.config;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.gemfire.GemfireTemplate;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.util.RegionUtils;
|
||||
|
||||
/**
|
||||
* The {@link EchoClientConfiguration} class is a Spring {@link Configuration} class used to configure
|
||||
* a {@link ClientCache} {@link Region} for echo messages.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.GemfireTemplate
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@SuppressWarnings("unused")
|
||||
public class EchoClientConfiguration {
|
||||
|
||||
protected static final String REGION_NAME = "Echo";
|
||||
|
||||
@Bean(REGION_NAME)
|
||||
public ClientRegionFactoryBean<String, String> echoRegion(GemFireCache gemfireCache) {
|
||||
|
||||
ClientRegionFactoryBean<String, String> echoRegion = new ClientRegionFactoryBean<>();
|
||||
|
||||
echoRegion.setCache(gemfireCache);
|
||||
echoRegion.setClose(false);
|
||||
echoRegion.setShortcut(ClientRegionShortcut.PROXY);
|
||||
|
||||
return echoRegion;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GemfireTemplate echoTemplate(GemFireCache gemfireCache) {
|
||||
return new GemfireTemplate(gemfireCache.getRegion(RegionUtils.toRegionPath(REGION_NAME)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.echo.config;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.gemfire.GemfireTemplate;
|
||||
import org.springframework.data.gemfire.PartitionedRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.util.RegionUtils;
|
||||
|
||||
import example.geode.cache.EchoCacheLoader;
|
||||
|
||||
/**
|
||||
* The {@link EchoClientConfiguration} class is a Spring {@link Configuration} class used to configure
|
||||
* a peer {@link Cache} {@link Region} for echo messages.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.GemfireTemplate
|
||||
* @see org.springframework.data.gemfire.PartitionedRegionFactoryBean
|
||||
* @see example.geode.cache.EchoCacheLoader
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@SuppressWarnings("unused")
|
||||
public class EchoServerConfiguration {
|
||||
|
||||
@Bean(EchoClientConfiguration.REGION_NAME)
|
||||
public PartitionedRegionFactoryBean<String, String> echoRegion(GemFireCache gemfireCache) {
|
||||
|
||||
PartitionedRegionFactoryBean<String, String> echoRegion = new PartitionedRegionFactoryBean<>();
|
||||
|
||||
echoRegion.setCache(gemfireCache);
|
||||
echoRegion.setCacheLoader(EchoCacheLoader.INSTANCE);
|
||||
echoRegion.setClose(false);
|
||||
echoRegion.setPersistent(false);
|
||||
|
||||
return echoRegion;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GemfireTemplate echoTemplate(GemFireCache gemfireCache) {
|
||||
|
||||
return new GemfireTemplate(gemfireCache.getRegion(
|
||||
RegionUtils.toRegionPath(EchoClientConfiguration.REGION_NAME)));
|
||||
}
|
||||
}
|
||||
40
geode-spring-boot/src/test/java/example/geode/cache/EchoCacheLoader.java
vendored
Normal file
40
geode-spring-boot/src/test/java/example/geode/cache/EchoCacheLoader.java
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.geode.cache;
|
||||
|
||||
import org.apache.geode.cache.CacheLoader;
|
||||
import org.apache.geode.cache.CacheLoaderException;
|
||||
import org.apache.geode.cache.LoaderHelper;
|
||||
import org.springframework.geode.cache.support.CacheLoaderSupport;
|
||||
|
||||
/**
|
||||
* The {@link EchoCacheLoader} class is an implementation of {@link CacheLoader} that echos the key as the value.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.geode.cache.support.CacheLoaderSupport
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class EchoCacheLoader implements CacheLoaderSupport<String, String> {
|
||||
|
||||
public static final EchoCacheLoader INSTANCE = new EchoCacheLoader();
|
||||
|
||||
@Override
|
||||
public String load(LoaderHelper<String, String> helper) throws CacheLoaderException {
|
||||
return helper.getKey();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.geode.query.cq.event;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* The {@link TemperatureReading} class is an Abstract Data Type (ADT) modeling a temperature event,
|
||||
* tracking the recorded temperature, unit and timestamp of the event.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see example.geode.query.cq.event.TemperatureUnit
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(of = { "temperature", "temperatureUnit" })
|
||||
@RequiredArgsConstructor(staticName = "of")
|
||||
public class TemperatureReading {
|
||||
|
||||
@NonNull
|
||||
private Integer temperature;
|
||||
|
||||
private LocalDateTime timestamp = LocalDateTime.now();
|
||||
|
||||
private TemperatureUnit temperatureUnit = TemperatureUnit.defaultTemperatureUnit();
|
||||
|
||||
public TemperatureReading at(LocalDateTime timestamp) {
|
||||
setTimestamp(timestamp);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TemperatureReading in(TemperatureUnit temperatureUnit) {
|
||||
setTemperatureUnit(temperatureUnit);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%d %s", getTemperature(), getTemperatureUnit());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.geode.query.cq.event;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.geode.cache.query.CqEvent;
|
||||
import org.springframework.data.gemfire.listener.annotation.ContinuousQuery;
|
||||
|
||||
/**
|
||||
* The TemperatureReadingsContinuousQueriesHandler class...
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public final class TemperatureReadingsContinuousQueriesHandler {
|
||||
|
||||
private final AtomicInteger temperatureReadingsCounter = new AtomicInteger(0);
|
||||
|
||||
private final List<TemperatureReading> boilingTemperatureReadings = new CopyOnWriteArrayList<>();
|
||||
private final List<TemperatureReading> freezingTemperatureReadings = new CopyOnWriteArrayList<>();
|
||||
|
||||
public List<TemperatureReading> getBoilingTemperatureReadings() {
|
||||
return Collections.unmodifiableList(this.boilingTemperatureReadings);
|
||||
}
|
||||
|
||||
public List<Integer> getBoilingTemperatures() {
|
||||
|
||||
return getBoilingTemperatureReadings().stream()
|
||||
.map(TemperatureReading::getTemperature)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<TemperatureReading> getFreezingTemperatureReadings() {
|
||||
return Collections.unmodifiableList(this.freezingTemperatureReadings);
|
||||
}
|
||||
|
||||
public List<Integer> getFreezingTemperatures() {
|
||||
|
||||
return getFreezingTemperatureReadings().stream()
|
||||
.map(TemperatureReading::getTemperature)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public int getTemperatureReadingCount() {
|
||||
return this.temperatureReadingsCounter.get();
|
||||
}
|
||||
|
||||
@ContinuousQuery(name = "BoilingTemperatures",
|
||||
query = "SELECT * FROM /TemperatureReadings r WHERE r.temperature >= 212")
|
||||
public void boilingTemperatures(CqEvent event) {
|
||||
|
||||
TemperatureReading temperatureReading = (TemperatureReading) event.getNewValue();
|
||||
|
||||
this.boilingTemperatureReadings.add(temperatureReading);
|
||||
this.temperatureReadingsCounter.incrementAndGet();
|
||||
}
|
||||
|
||||
@ContinuousQuery(name = "FreezingTemperatures",
|
||||
query = "SELECT * FROM /TemperatureReadings r WHERE r.temperature <= 32")
|
||||
public void freezingTemperatures(CqEvent event) {
|
||||
|
||||
TemperatureReading temperatureReading = (TemperatureReading) event.getNewValue();
|
||||
|
||||
this.freezingTemperatureReadings.add(temperatureReading);
|
||||
this.temperatureReadingsCounter.incrementAndGet();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.geode.query.cq.event;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The {@link TemperatureUnit} enum is an enumeration of different temperature units
|
||||
* as defined by International System of Units (SI).
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public enum TemperatureUnit {
|
||||
|
||||
CELSIUS("°C"),
|
||||
FAHRENHEIT("°F"),
|
||||
KELVIN("K");
|
||||
|
||||
public static TemperatureUnit defaultTemperatureUnit() {
|
||||
|
||||
return Optional.of(Locale.getDefault())
|
||||
.map(Locale::getISO3Country)
|
||||
.filter(Locale.US.getISO3Country()::equalsIgnoreCase)
|
||||
.map(it -> TemperatureUnit.FAHRENHEIT)
|
||||
.orElse(TemperatureUnit.CELSIUS);
|
||||
}
|
||||
|
||||
private final String symbol;
|
||||
|
||||
TemperatureUnit(String symbol) {
|
||||
this.symbol = symbol;
|
||||
}
|
||||
|
||||
public String getSymbol() {
|
||||
return this.symbol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getSymbol();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.java.net;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
/**
|
||||
* The {@link UrlRevealed} class...
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.net.URL
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class UrlRevealed {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
URL url = new URL("jar:file:///www.foo.com/bar/jar.jar!/baz/entry.txt");
|
||||
|
||||
System.out.printf("URL [%s] {%n \tfile [%s],%n \tpath [%s],%n \tport [%s],%n \tprotocol [%s],%n \tquery [%s]%n}%n%n",
|
||||
url, url.getFile(), url.getPath(), url.getPort(), url.getProtocol(), url.getQuery());
|
||||
|
||||
System.out.printf("URI [%s]%n", new ClassPathResource("trusted.keystore").getURL().toURI());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2018 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.support;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
|
||||
/**
|
||||
* The {@link GemfireBeanFactoryLocatorProxy} class is an extension of {@link GemfireBeanFactoryLocator}
|
||||
* used to clean up all Spring {@link BeanFactory} references, which are stored throughout the runtime
|
||||
* of an application for different purposes, like configuration of non-Spring managed components.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator
|
||||
* @since 1.0.0
|
||||
*/
|
||||
// TODO: remove this class once and refactor the SDG GemfireBeanFactoryLocator!
|
||||
public class GemfireBeanFactoryLocatorProxy extends GemfireBeanFactoryLocator {
|
||||
|
||||
public static void clear() {
|
||||
BEAN_FACTORIES.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure.cache.client;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
import org.apache.geode.internal.cache.GemFireCacheImpl;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableLogging;
|
||||
import org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport;
|
||||
import org.springframework.data.gemfire.util.RegionUtils;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration test testing the auto-configuration of an Apache Geode {@link ClientCache} instance.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
* @see org.springframework.boot.test.context.SpringBootTest
|
||||
* @see org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport
|
||||
* @see org.springframework.geode.boot.autoconfigure.ClientCacheAutoConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@SuppressWarnings("unused")
|
||||
public class SpringBootApacheGeodeClientCacheApplicationIntegrationTests extends IntegrationTestsSupport {
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = "error";
|
||||
|
||||
@Autowired
|
||||
private ClientCache clientCache;
|
||||
|
||||
@Test
|
||||
public void clientCacheAndClientRegionAreAvailable() {
|
||||
|
||||
Optional.ofNullable(this.clientCache)
|
||||
.filter(it -> it instanceof GemFireCacheImpl)
|
||||
.map(it -> (GemFireCacheImpl) it)
|
||||
.map(it -> assertThat(it.isClient()).isTrue())
|
||||
.orElseThrow(() -> newIllegalStateException("ClientCache was null"));
|
||||
|
||||
Region<Object, Object> example = this.clientCache.getRegion("Example");
|
||||
|
||||
assertThat(example).isNotNull();
|
||||
assertThat(example.getName()).isEqualTo("Example");
|
||||
assertThat(example.getFullPath()).isEqualTo(RegionUtils.toRegionPath("Example"));
|
||||
|
||||
example.put(1, "test");
|
||||
|
||||
assertThat(example.get(1)).isEqualTo("test");
|
||||
}
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableLogging(logLevel = GEMFIRE_LOG_LEVEL)
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean("Example")
|
||||
public ClientRegionFactoryBean<Object, Object> exampleRegion(GemFireCache gemfireCache) {
|
||||
|
||||
ClientRegionFactoryBean<Object, Object> clientRegion = new ClientRegionFactoryBean<>();
|
||||
|
||||
clientRegion.setCache(gemfireCache);
|
||||
clientRegion.setClose(false);
|
||||
clientRegion.setShortcut(ClientRegionShortcut.LOCAL);
|
||||
|
||||
return clientRegion;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure.cache.peer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.internal.cache.GemFireCacheImpl;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.gemfire.LocalRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.PeerCacheApplication;
|
||||
import org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport;
|
||||
import org.springframework.data.gemfire.util.RegionUtils;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration test testing the auto-configuration of an Apache Geode peer {@link Cache} instance, overriding
|
||||
* the default {@link ClientCache} instance.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
* @see org.springframework.boot.test.context.SpringBootTest
|
||||
* @see org.springframework.data.gemfire.config.annotation.PeerCacheApplication
|
||||
* @see org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@SuppressWarnings("unused")
|
||||
public class SpringBootApacheGeodePeerCacheApplicationIntegrationTests extends IntegrationTestsSupport {
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = "error";
|
||||
|
||||
@Autowired
|
||||
private GemFireCache peerCache;
|
||||
|
||||
@Test
|
||||
public void peerCacheWithPeerLocalRegionAreAvailable() {
|
||||
|
||||
Optional.ofNullable(this.peerCache)
|
||||
.filter(it -> it instanceof GemFireCacheImpl)
|
||||
.map(it -> (GemFireCacheImpl) it)
|
||||
.map(it -> assertThat(it.isClient()).isFalse())
|
||||
.orElseThrow(() -> newIllegalStateException("Peer cache was null"));
|
||||
|
||||
Region<Object, Object> example = peerCache.getRegion("/Example");
|
||||
|
||||
assertThat(example).isNotNull();
|
||||
assertThat(example.getName()).isEqualTo("Example");
|
||||
assertThat(example.getFullPath()).isEqualTo(RegionUtils.toRegionPath("Example"));
|
||||
|
||||
example.put(1, "test");
|
||||
|
||||
assertThat(example.get(1)).isEqualTo("test");
|
||||
}
|
||||
|
||||
@SpringBootApplication
|
||||
@PeerCacheApplication(logLevel = GEMFIRE_LOG_LEVEL)
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean("Example")
|
||||
public LocalRegionFactoryBean<Object, Object> exampleRegion(GemFireCache gemfireCache) {
|
||||
|
||||
LocalRegionFactoryBean<Object, Object> exampleRegion = new LocalRegionFactoryBean<>();
|
||||
|
||||
exampleRegion.setCache(gemfireCache);
|
||||
exampleRegion.setClose(false);
|
||||
exampleRegion.setPersistent(false);
|
||||
|
||||
return exampleRegion;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure.caching;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableCachingDefinedRegions;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableLogging;
|
||||
import org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport;
|
||||
import org.springframework.data.gemfire.util.RegionUtils;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import example.app.NonBeanType;
|
||||
import example.app.model.Book;
|
||||
import example.app.service.support.CachingBookService;
|
||||
|
||||
/**
|
||||
* Integration tests testing the auto-configuration of Spring's Cache Abstraction with Apache Geode
|
||||
* or Pivotal GemFire as the caching provider.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
* @see org.springframework.boot.test.context.SpringBootTest
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCachingDefinedRegions
|
||||
* @see org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport
|
||||
* @see org.springframework.geode.boot.autoconfigure.CachingProviderAutoConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@SuppressWarnings("unused")
|
||||
public class AutoConfiguredCachingIntegrationTests extends IntegrationTestsSupport {
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = "error";
|
||||
|
||||
@Autowired
|
||||
private CachingBookService bookService;
|
||||
|
||||
@Resource(name = "CachedBooks")
|
||||
private Region<String, Book> cachedBooks;
|
||||
|
||||
private void assertBook(Book book, String title) {
|
||||
|
||||
assertThat(book).isNotNull();
|
||||
assertThat(book.isNew()).isFalse();
|
||||
assertThat(book.getTitle()).isEqualTo(title);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bookServiceWasConfiguredCorrectly() {
|
||||
|
||||
assertThat(this.bookService).isNotNull();
|
||||
assertThat(this.bookService.isCacheMiss()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cachedBooksRegionWasConfiguredCorrectly() {
|
||||
|
||||
assertThat(this.cachedBooks).isNotNull();
|
||||
assertThat(this.cachedBooks.getName()).isEqualTo("CachedBooks");
|
||||
assertThat(this.cachedBooks.getFullPath()).isEqualTo(RegionUtils.toRegionPath("CachedBooks"));
|
||||
assertThat(this.cachedBooks).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void geodeAsTheCachingProviderWasAutoConfiguredCorrectly() {
|
||||
|
||||
assertThat(this.cachedBooks).isEmpty();
|
||||
|
||||
Book bookOne = this.bookService.findByTitle("Star Wars 3 - Revenge of the Sith");
|
||||
|
||||
assertBook(bookOne, "Star Wars 3 - Revenge of the Sith");
|
||||
assertThat(this.bookService.isCacheMiss()).isTrue();
|
||||
assertThat(this.cachedBooks).hasSize(1);
|
||||
assertThat(this.cachedBooks.get(bookOne.getTitle())).isEqualTo(bookOne);
|
||||
|
||||
Book bookOneAgain = this.bookService.findByTitle(bookOne.getTitle());
|
||||
|
||||
assertThat(bookOneAgain).isEqualTo(bookOne);
|
||||
assertThat(this.bookService.isCacheMiss()).isFalse();
|
||||
assertThat(this.cachedBooks).hasSize(1);
|
||||
assertThat(this.cachedBooks.get(bookOne.getTitle())).isEqualTo(bookOne);
|
||||
|
||||
Book bookTwo = this.bookService.findByTitle("Star Wars 6 - Return of the Jedi");
|
||||
|
||||
assertBook(bookTwo, "Star Wars 6 - Return of the Jedi");
|
||||
assertThat(this.bookService.isCacheMiss()).isTrue();
|
||||
assertThat(this.cachedBooks).hasSize(2);
|
||||
assertThat(this.cachedBooks.get(bookOne.getTitle())).isEqualTo(bookOne);
|
||||
assertThat(this.cachedBooks.get(bookTwo.getTitle())).isEqualTo(bookTwo);
|
||||
}
|
||||
|
||||
@SpringBootApplication(scanBasePackageClasses = NonBeanType.class)
|
||||
@EnableLogging(logLevel = GEMFIRE_LOG_LEVEL)
|
||||
@EnableCachingDefinedRegions(clientRegionShortcut = ClientRegionShortcut.LOCAL)
|
||||
static class TestConfiguration { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure.cq;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.apache.geode.cache.CacheLoader;
|
||||
import org.apache.geode.cache.CacheLoaderException;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.LoaderHelper;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.data.gemfire.GemfireTemplate;
|
||||
import org.springframework.data.gemfire.PartitionedRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableLogging;
|
||||
import org.springframework.data.gemfire.config.annotation.EnablePdx;
|
||||
import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport;
|
||||
import org.springframework.data.gemfire.tests.integration.config.SubscriptionEnabledClientServerIntegrationTestsConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import example.geode.query.cq.event.TemperatureReading;
|
||||
import example.geode.query.cq.event.TemperatureReadingsContinuousQueriesHandler;
|
||||
|
||||
/**
|
||||
* Integration tests testing the auto-configuration of Apache Geode/Pivotal GemFire Continuous Query.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
* @see org.springframework.boot.test.context.SpringBootTest
|
||||
* @see org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerApplication
|
||||
* @see org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport
|
||||
* @see org.springframework.data.gemfire.tests.integration.config.SubscriptionEnabledClientServerIntegrationTestsConfiguration
|
||||
* @see org.springframework.geode.boot.autoconfigure.ContinuousQueryAutoConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @see example.geode.query.cq.event.TemperatureReading
|
||||
* @see example.geode.query.cq.event.TemperatureReadingsContinuousQueriesHandler
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE,
|
||||
classes = AutoConfiguredContinuousQueryIntegrationTests.GemFireClientConfiguration.class)
|
||||
@SuppressWarnings("unused")
|
||||
public class AutoConfiguredContinuousQueryIntegrationTests extends ForkingClientServerIntegrationTestsSupport {
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = "error";
|
||||
|
||||
@BeforeClass
|
||||
public static void startGemFireServer() throws IOException {
|
||||
startGemFireServer(GemFireServerConfiguration.class);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private GemfireTemplate temperatureReadingsTemplate;
|
||||
|
||||
@SuppressWarnings("all")
|
||||
@Resource(name = "TemperatureReadings")
|
||||
private Region<Long, TemperatureReading> temperatureReadings;
|
||||
|
||||
@Autowired
|
||||
private TemperatureReadingsContinuousQueriesHandler temperatureReadingsHandler;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
|
||||
assertThat(this.temperatureReadingsTemplate.<Long, TemperatureReading>get(1L))
|
||||
.isEqualTo(TemperatureReading.of(99));
|
||||
|
||||
assertThat(this.temperatureReadings.sizeOnServer()).isEqualTo(8);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertTemperatureReadingsAreCorrect() {
|
||||
|
||||
assertThat(this.temperatureReadingsHandler.getTemperatureReadingCount()).isEqualTo(4);
|
||||
assertThat(this.temperatureReadingsHandler.getBoilingTemperatures()).contains(300, 242);
|
||||
assertThat(this.temperatureReadingsHandler.getFreezingTemperatures()).contains(16, -51);
|
||||
}
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableLogging(logLevel = GEMFIRE_LOG_LEVEL)
|
||||
public static class GemFireClientConfiguration
|
||||
extends SubscriptionEnabledClientServerIntegrationTestsConfiguration {
|
||||
|
||||
@Bean("TemperatureReadings")
|
||||
public ClientRegionFactoryBean<Long, TemperatureReading> temperatureReadingsRegion(GemFireCache gemfireCache) {
|
||||
|
||||
ClientRegionFactoryBean<Long, TemperatureReading> temperatureReadingsRegion =
|
||||
new ClientRegionFactoryBean<>();
|
||||
|
||||
temperatureReadingsRegion.setCache(gemfireCache);
|
||||
temperatureReadingsRegion.setClose(false);
|
||||
temperatureReadingsRegion.setShortcut(ClientRegionShortcut.PROXY);
|
||||
|
||||
return temperatureReadingsRegion;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@DependsOn("TemperatureReadings")
|
||||
GemfireTemplate temperatureReadingsTemplate(GemFireCache gemfireCache) {
|
||||
return new GemfireTemplate(gemfireCache.getRegion("/TemperatureReadings"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@DependsOn("TemperatureReadings")
|
||||
TemperatureReadingsContinuousQueriesHandler temperatureReadingsHandler() {
|
||||
return new TemperatureReadingsContinuousQueriesHandler();
|
||||
}
|
||||
}
|
||||
|
||||
@EnablePdx
|
||||
@CacheServerApplication(name = "AutoConfiguredContinuousQueryIntegrationTests", logLevel = GEMFIRE_LOG_LEVEL)
|
||||
public static class GemFireServerConfiguration {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
AnnotationConfigApplicationContext applicationContext =
|
||||
new AnnotationConfigApplicationContext(GemFireServerConfiguration.class);
|
||||
|
||||
applicationContext.registerShutdownHook();
|
||||
}
|
||||
|
||||
@Bean("TemperatureReadings")
|
||||
public PartitionedRegionFactoryBean<Long, TemperatureReading> temperatureReadingsRegion(GemFireCache gemfireCache) {
|
||||
|
||||
PartitionedRegionFactoryBean<Long, TemperatureReading> temperatureReadingsRegion =
|
||||
new PartitionedRegionFactoryBean<>();
|
||||
|
||||
temperatureReadingsRegion.setCache(gemfireCache);
|
||||
temperatureReadingsRegion.setCacheLoader(temperatureReadingsLoader());
|
||||
temperatureReadingsRegion.setClose(false);
|
||||
temperatureReadingsRegion.setPersistent(false);
|
||||
|
||||
return temperatureReadingsRegion;
|
||||
}
|
||||
|
||||
private CacheLoader<Long, TemperatureReading> temperatureReadingsLoader() {
|
||||
|
||||
return new CacheLoader<Long, TemperatureReading>() {
|
||||
|
||||
@Override
|
||||
public TemperatureReading load(LoaderHelper<Long, TemperatureReading> helper)
|
||||
throws CacheLoaderException {
|
||||
|
||||
long key = helper.getKey();
|
||||
|
||||
Region<Long, TemperatureReading> temperatureReadings = helper.getRegion();
|
||||
|
||||
recordTemperature(temperatureReadings, ++key, 72);
|
||||
recordTemperature(temperatureReadings, ++key, 16);
|
||||
recordTemperature(temperatureReadings, ++key, 101);
|
||||
recordTemperature(temperatureReadings, ++key, 300);
|
||||
recordTemperature(temperatureReadings, ++key, -51);
|
||||
recordTemperature(temperatureReadings, ++key, 242);
|
||||
recordTemperature(temperatureReadings, ++key, 112);
|
||||
|
||||
return TemperatureReading.of(99);
|
||||
}
|
||||
|
||||
private void recordTemperature(Region<Long, TemperatureReading> temperatureReadings,
|
||||
long key, int temperature) {
|
||||
|
||||
sleep(50);
|
||||
temperatureReadings.put(key, TemperatureReading.of(temperature));
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
private void sleep(long milliseconds) {
|
||||
|
||||
try {
|
||||
Thread.sleep(milliseconds);
|
||||
}
|
||||
catch (InterruptedException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() { }
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure.function;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.execute.FunctionService;
|
||||
import org.apache.shiro.util.Assert;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableGemFireProperties;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableLogging;
|
||||
import org.springframework.data.gemfire.function.annotation.GemfireFunction;
|
||||
import org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport;
|
||||
import org.springframework.geode.boot.autoconfigure.function.executions.Calculator;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration tests testing the auto-configuration of Spring Data for Apache Geode/Pivotal GemFire
|
||||
* Function implementations and executions support.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.execute.FunctionService
|
||||
* @see org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
* @see org.springframework.boot.test.context.SpringBootTest
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.data.gemfire.function.annotation.GemfireFunction
|
||||
* @see org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport
|
||||
* @see org.springframework.geode.boot.autoconfigure.function.executions.Calculator
|
||||
* @see org.springframework.geode.boot.autoconfigure.FunctionExecutionAutoConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@SuppressWarnings("unused")
|
||||
public class AutoConfiguredFunctionExecutionsIntegrationTests extends IntegrationTestsSupport {
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = "error";
|
||||
|
||||
@Autowired
|
||||
private GemFireCache gemfireCache;
|
||||
|
||||
@Autowired
|
||||
private Calculator calculator;
|
||||
|
||||
@Test
|
||||
public void cacheClientIsInGroupTest() {
|
||||
|
||||
assertThat(this.gemfireCache).isNotNull();
|
||||
assertThat(this.gemfireCache.getDistributedSystem().getGroupMembers("test"))
|
||||
.contains(this.gemfireCache.getDistributedSystem().getDistributedMember());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void firstFunctionsMustBeRegistered() {
|
||||
|
||||
Arrays.stream(CalculatorFunctions.class.getMethods())
|
||||
.filter(method -> !Object.class.equals(method.getDeclaringClass()))
|
||||
.map(Method::getName)
|
||||
.forEach(methodName -> assertThat(FunctionService.isRegistered(methodName))
|
||||
.describedAs("Function [%s] was not registered", methodName)
|
||||
.isTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void thenCalculationsAreCorrect() {
|
||||
|
||||
assertThat(this.calculator).isNotNull();
|
||||
assertThat(extractResult(this.calculator.add(8.0d, 8.0d))).isEqualTo(16.0d);
|
||||
assertThat(extractResult(this.calculator.divide(16.0d, 4.0d))).isEqualTo(4.0d);
|
||||
assertThat(extractResult(this.calculator.factorial(5L))).isEqualTo(120L);
|
||||
assertThat(extractResult(this.calculator.multiply(4.0d, 4.0d))).isEqualTo(16.0d);
|
||||
assertThat(extractResult(this.calculator.squared(4.0d))).isEqualTo(16.0d);
|
||||
assertThat(extractResult(this.calculator.squareRoot(16.0d))).isEqualTo(4.0d);
|
||||
assertThat(extractResult(this.calculator.subtract(16.0d, 8.0d))).isEqualTo(8.0d);
|
||||
}
|
||||
|
||||
private Object extractResult(Object result) {
|
||||
|
||||
return Optional.ofNullable(result)
|
||||
.filter(it -> it instanceof Iterable)
|
||||
.map(it -> ((Iterable) it).iterator())
|
||||
.filter(Iterator::hasNext)
|
||||
.map(Iterator::next)
|
||||
.map(this::extractResult)
|
||||
.orElse(result);
|
||||
}
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableGemFireProperties(groups = "test")
|
||||
@EnableLogging(logLevel = GEMFIRE_LOG_LEVEL)
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
public CalculatorFunctions calculatorFunctions(GemFireCache gemfireCache) {
|
||||
return new CalculatorFunctions();
|
||||
}
|
||||
}
|
||||
|
||||
public static class CalculatorFunctions {
|
||||
|
||||
@GemfireFunction(id = "add", hasResult = true)
|
||||
public double add(double operandOne, double operandTwo) {
|
||||
return operandOne + operandTwo;
|
||||
}
|
||||
|
||||
@GemfireFunction(id = "divide", hasResult = true)
|
||||
public double divide(double numerator, double divisor) {
|
||||
return numerator / divisor;
|
||||
}
|
||||
|
||||
@GemfireFunction(id = "factorial", hasResult = true)
|
||||
public long factorial(long number) {
|
||||
|
||||
Assert.isTrue(number > -1, "Number be greater than -1");
|
||||
|
||||
long result = number == 2 ? 2 : 1;
|
||||
|
||||
while (number > 1) {
|
||||
result *= number--;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@GemfireFunction(id = "multiply", hasResult = true)
|
||||
public double multiply(double operandOne, double operandTwo) {
|
||||
return operandOne * operandTwo;
|
||||
}
|
||||
|
||||
@GemfireFunction(id = "squareRoot", hasResult = true)
|
||||
public double squareRoot(double number) {
|
||||
return Math.sqrt(number);
|
||||
}
|
||||
|
||||
@GemfireFunction(id = "squared", hasResult = true)
|
||||
public double squared(double number) {
|
||||
return number * number;
|
||||
}
|
||||
|
||||
@GemfireFunction(id = "subtract", hasResult = true)
|
||||
public double subtract(double operandOne, double operandTwo) {
|
||||
return operandOne - operandTwo;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure.function.executions;
|
||||
|
||||
import org.springframework.data.gemfire.function.annotation.OnMember;
|
||||
|
||||
/**
|
||||
* The {@link Calculator} interface defines Apache Geode/Pivotal GemFire Functions.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.function.annotation.OnRegion
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@OnMember(groups = "test")
|
||||
@SuppressWarnings("all")
|
||||
// TODO change Function returns type when SDG properly handles Function method return types/values
|
||||
public interface Calculator {
|
||||
|
||||
Object add(double operandOne, double operandTwo);
|
||||
|
||||
Object divide(double numerator, double divisor);
|
||||
|
||||
Object factorial(long number);
|
||||
|
||||
Object multiply(double operandOne, double operandTwo);
|
||||
|
||||
Object squareRoot(double number);
|
||||
|
||||
Object squared(double number);
|
||||
|
||||
Object subtract(double operandOne, double operandTwo);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure.repository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableLogging;
|
||||
import org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport;
|
||||
import org.springframework.data.gemfire.util.RegionUtils;
|
||||
import org.springframework.geode.boot.autoconfigure.repository.model.Customer;
|
||||
import org.springframework.geode.boot.autoconfigure.repository.service.CustomerService;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration tests testing the auto-configuration of Spring Data Repositories backed by either Apache Geode
|
||||
* or Pivotal GemFire.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
* @see org.springframework.boot.test.context.SpringBootTest
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions
|
||||
* @see org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport
|
||||
* @see org.springframework.geode.boot.autoconfigure.RepositoriesAutoConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@SuppressWarnings("unused")
|
||||
public class AutoConfiguredRepositoriesIntegrationTests extends IntegrationTestsSupport {
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = "error";
|
||||
|
||||
@Autowired
|
||||
private CustomerService customerService;
|
||||
|
||||
@Resource(name = "Customers")
|
||||
private Region<Long, Customer> customers;
|
||||
|
||||
@Test
|
||||
public void customerServiceWasConfiguredCorrectly() {
|
||||
|
||||
assertThat(this.customerService).isNotNull();
|
||||
assertThat(this.customerService.getCustomerRepository()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customersRegionWasConfiguredCorrectly() {
|
||||
|
||||
assertThat(this.customers).isNotNull();
|
||||
assertThat(this.customers.getName()).isEqualTo("Customers");
|
||||
assertThat(this.customers.getFullPath()).isEqualTo(RegionUtils.toRegionPath("Customers"));
|
||||
assertThat(this.customers).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void repositoryWasAutoConfiguredCorrectly() {
|
||||
|
||||
Customer jonDoe = Customer.newCustomer("Jon Doe");
|
||||
|
||||
assertThat(jonDoe).isNotNull();
|
||||
assertThat(jonDoe.getName()).isEqualTo("Jon Doe");
|
||||
assertThat(jonDoe.isNew()).isTrue();
|
||||
|
||||
jonDoe = this.customerService.save(jonDoe);
|
||||
|
||||
assertThat(jonDoe.isNew()).isFalse();
|
||||
assertThat(this.customers.get(jonDoe.getId())).isEqualTo(jonDoe);
|
||||
assertThat(this.customerService.findBy(jonDoe.getName()).orElse(null)).isEqualTo(jonDoe);
|
||||
|
||||
}
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableLogging(logLevel = GEMFIRE_LOG_LEVEL)
|
||||
@EnableEntityDefinedRegions(basePackageClasses = Customer.class,
|
||||
clientRegionShortcut = ClientRegionShortcut.LOCAL)
|
||||
static class TestConfiguration { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure.repository.model;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.gemfire.mapping.annotation.Region;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* {@link Customer} class and Abstract Data Type (ADT) modeling a customer.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.annotation.Id
|
||||
* @see org.springframework.data.gemfire.mapping.annotation.Region
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Data
|
||||
@Region("Customers")
|
||||
@RequiredArgsConstructor(staticName = "newCustomer")
|
||||
public class Customer {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
@NonNull
|
||||
private String name;
|
||||
|
||||
public boolean isNew() {
|
||||
return getId() == null;
|
||||
}
|
||||
|
||||
public Customer identifiedBy(Long id) {
|
||||
setId(id);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure.repository.repo;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.geode.boot.autoconfigure.repository.model.Customer;
|
||||
|
||||
/**
|
||||
* The {@link CustomerRepository} interface defines a Spring Data {@link CrudRepository} for performing basic CRUD
|
||||
* and simple query data access operations on {@link Customer} objects stored in Apache Geode or Pivotal GemFire.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.repository.CrudRepository
|
||||
* @see org.springframework.geode.boot.autoconfigure.repository.model.Customer
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface CustomerRepository extends CrudRepository<Customer, Long> {
|
||||
|
||||
Customer findByName(String name);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure.repository.service;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.springframework.geode.boot.autoconfigure.repository.model.Customer;
|
||||
import org.springframework.geode.boot.autoconfigure.repository.repo.CustomerRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* The {@link CustomerService} class is an application service for managing {@link Customer Customers}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.geode.boot.autoconfigure.repository.model.Customer
|
||||
* @see org.springframework.geode.boot.autoconfigure.repository.repo.CustomerRepository
|
||||
* @see org.springframework.stereotype.Service
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Service
|
||||
public class CustomerService {
|
||||
|
||||
private final CustomerRepository customerRepository;
|
||||
|
||||
private final AtomicLong identifierSequence = new AtomicLong(0L);
|
||||
|
||||
public CustomerService(CustomerRepository customerRepository) {
|
||||
this.customerRepository = customerRepository;
|
||||
}
|
||||
|
||||
public CustomerRepository getCustomerRepository() {
|
||||
|
||||
return Optional.ofNullable(this.customerRepository)
|
||||
.orElseThrow(() -> newIllegalStateException("CustomerRepository was not properly configured"));
|
||||
}
|
||||
|
||||
public Optional<Customer> findBy(String name) {
|
||||
return Optional.ofNullable(getCustomerRepository().findByName(name));
|
||||
}
|
||||
|
||||
protected Long nextId() {
|
||||
return identifierSequence.incrementAndGet();
|
||||
}
|
||||
|
||||
public Customer save(Customer customer) {
|
||||
|
||||
return Optional.ofNullable(customer)
|
||||
.map(it -> {
|
||||
|
||||
if (customer.isNew()) {
|
||||
customer.identifiedBy(nextId());
|
||||
}
|
||||
|
||||
return getCustomerRepository().save(customer);
|
||||
})
|
||||
.orElseThrow(() -> newIllegalArgumentException("Customer is required"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure.security.auth;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.data.gemfire.config.annotation.support.AutoConfiguredAuthenticationInitializer.SECURITY_PASSWORD_PROPERTY;
|
||||
import static org.springframework.data.gemfire.config.annotation.support.AutoConfiguredAuthenticationInitializer.SECURITY_USERNAME_PROPERTY;
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.security.Principal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.security.AuthenticationFailedException;
|
||||
import org.apache.geode.security.ResourcePermission;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.data.gemfire.GemfireTemplate;
|
||||
import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import example.echo.config.EchoClientConfiguration;
|
||||
import example.echo.config.EchoServerConfiguration;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* The {@link AbstractAutoConfiguredSecurityContextIntegrationTests} class is an abstract security context integration test class
|
||||
* encapsulating configuration and functionality common to both cloud and local security context integration tests.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.security.Principal
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.security.ResourcePermission
|
||||
* @see org.springframework.core.env.Environment
|
||||
* @see org.springframework.data.gemfire.GemfireTemplate
|
||||
* @see org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class AbstractAutoConfiguredSecurityContextIntegrationTests
|
||||
extends ForkingClientServerIntegrationTestsSupport {
|
||||
|
||||
private static final String SECURITY_CONTEXT_USERNAME_PROPERTY = "security.context.username.property";
|
||||
private static final String SECURITY_CONTEXT_PASSWORD_PROPERTY = "security.context.password.property";
|
||||
|
||||
@Autowired
|
||||
private GemfireTemplate echoTemplate;
|
||||
|
||||
@Test
|
||||
public void clientServerAuthWasSuccessful() {
|
||||
|
||||
assertThat(this.echoTemplate.<String, String>get("Hello")).isEqualTo("Hello");
|
||||
assertThat(this.echoTemplate.<String, String>get("Test")).isEqualTo("Test");
|
||||
assertThat(this.echoTemplate.<String, String>get("Good-Bye")).isEqualTo("Good-Bye");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(EchoClientConfiguration.class)
|
||||
protected static abstract class BaseGemFireClientConfiguration { }
|
||||
|
||||
@Configuration
|
||||
@Import(EchoServerConfiguration.class)
|
||||
protected static abstract class BaseGemFireServerConfiguration {
|
||||
|
||||
@Bean
|
||||
TestSecurityManager testSecurityManager(Environment environment) {
|
||||
return new TestSecurityManager(environment);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TestSecurityManager implements org.apache.geode.security.SecurityManager {
|
||||
|
||||
private final String username;
|
||||
private final String password;
|
||||
|
||||
public TestSecurityManager(Environment environment) {
|
||||
|
||||
this.username = Optional.ofNullable(environment.getProperty(SECURITY_CONTEXT_USERNAME_PROPERTY))
|
||||
.filter(StringUtils::hasText)
|
||||
.orElseThrow(() -> newIllegalArgumentException("Username is required"));
|
||||
|
||||
this.password = Optional.ofNullable(environment.getProperty(SECURITY_CONTEXT_PASSWORD_PROPERTY))
|
||||
.filter(StringUtils::hasText)
|
||||
.orElseThrow(() -> newIllegalArgumentException("Password is required"));
|
||||
}
|
||||
|
||||
private ClassPathResource resolveApplicationProperties(Environment environment) {
|
||||
|
||||
Assert.notNull(environment, "Environment must not be null");
|
||||
|
||||
return Arrays.stream(nullSafeArray(environment.getActiveProfiles(), String.class))
|
||||
.filter(StringUtils::hasText)
|
||||
.filter(it -> !"default".equalsIgnoreCase(it))
|
||||
.map(it -> String.format("application-%s.properties", it))
|
||||
.map(ClassPathResource::new)
|
||||
.filter(ClassPathResource::exists)
|
||||
.findFirst()
|
||||
.orElseThrow(() ->
|
||||
newIllegalStateException("Unable to resolve application.properties from Environment [%s]",
|
||||
environment));
|
||||
|
||||
}
|
||||
|
||||
String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object authenticate(Properties credentials) throws AuthenticationFailedException {
|
||||
|
||||
String username = credentials.getProperty(SECURITY_USERNAME_PROPERTY);
|
||||
String password = credentials.getProperty(SECURITY_PASSWORD_PROPERTY);
|
||||
|
||||
if (!(getUsername().equals(username) && getPassword().equals(password))) {
|
||||
throw new AuthenticationFailedException(String.format("Failed to authenticate user [%s]", username));
|
||||
}
|
||||
|
||||
return User.with(username).having(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authorize(Object principal, ResourcePermission permission) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@ToString(of = "name")
|
||||
@EqualsAndHashCode(of = "name")
|
||||
@RequiredArgsConstructor(staticName = "with")
|
||||
static class User implements Principal, Serializable {
|
||||
|
||||
@NonNull
|
||||
private String name;
|
||||
|
||||
private String password;
|
||||
|
||||
User having(String password) {
|
||||
setPassword(password);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure.security.auth.cloud;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableLocator;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableLogging;
|
||||
import org.springframework.data.gemfire.support.GemfireBeanFactoryLocatorProxy;
|
||||
import org.springframework.geode.boot.autoconfigure.security.auth.AbstractAutoConfiguredSecurityContextIntegrationTests;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration test testing the auto-configuration of Apache Geode/Pivotal GemFire Security
|
||||
* authentication/authorization in a cloud, managed context (e.g. Pivotal CloudFoundry)
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.security.Principal
|
||||
* @see java.util.Properties
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.springframework.boot.SpringApplication
|
||||
* @see org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
* @see org.springframework.boot.test.context.SpringBootTest
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableLocator
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableSecurity
|
||||
* @see org.springframework.geode.boot.autoconfigure.ClientSecurityAutoConfiguration
|
||||
* @see org.springframework.geode.boot.autoconfigure.PeerSecurityAutoConfiguration
|
||||
* @see org.springframework.geode.boot.autoconfigure.security.auth.AbstractAutoConfiguredSecurityContextIntegrationTests
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = AutoConfiguredCloudSecurityContextIntegrationTests.GemFireClientConfiguration.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@SuppressWarnings("unused")
|
||||
public class AutoConfiguredCloudSecurityContextIntegrationTests
|
||||
extends AbstractAutoConfiguredSecurityContextIntegrationTests {
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = "error";
|
||||
private static final String VCAP_APPLICATION_PROPERTIES = "application-vcap.properties";
|
||||
|
||||
private static Properties vcapApplicationProperties = new Properties();
|
||||
|
||||
@BeforeClass
|
||||
public static void startGemFireServer() throws IOException {
|
||||
|
||||
startGemFireServer(GemFireServerConfiguration.class, "-Dspring.profiles.active=security-cloud");
|
||||
|
||||
loadVcapApplicationProperties();
|
||||
|
||||
GemfireBeanFactoryLocatorProxy.clear();
|
||||
}
|
||||
|
||||
public static void loadVcapApplicationProperties() throws IOException {
|
||||
|
||||
vcapApplicationProperties.load(new ClassPathResource(VCAP_APPLICATION_PROPERTIES).getInputStream());
|
||||
|
||||
vcapApplicationProperties.stringPropertyNames().forEach(property ->
|
||||
System.setProperty(property, vcapApplicationProperties.getProperty(property)));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanUpUsedResources() {
|
||||
|
||||
vcapApplicationProperties.stringPropertyNames().forEach(System::clearProperty);
|
||||
|
||||
GemfireBeanFactoryLocatorProxy.clear();
|
||||
}
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableLogging(logLevel = GEMFIRE_LOG_LEVEL)
|
||||
static class GemFireClientConfiguration extends BaseGemFireClientConfiguration { }
|
||||
|
||||
@SpringBootApplication
|
||||
@CacheServerApplication(name = "AutoConfiguredCloudSecurityContextIntegrationTests", logLevel = GEMFIRE_LOG_LEVEL)
|
||||
@EnableLocator(port = 55221)
|
||||
static class GemFireServerConfiguration extends BaseGemFireServerConfiguration {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(GemFireServerConfiguration.class, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure.security.auth.local;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableLogging;
|
||||
import org.springframework.data.gemfire.support.GemfireBeanFactoryLocatorProxy;
|
||||
import org.springframework.data.gemfire.tests.integration.config.ClientServerIntegrationTestsConfiguration;
|
||||
import org.springframework.geode.boot.autoconfigure.security.auth.AbstractAutoConfiguredSecurityContextIntegrationTests;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration test testing the auto-configuration of Apache Geode/Pivotal GemFire Security
|
||||
* authentication/authorization in a local, non-managed context.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.security.Principal
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.springframework.boot.SpringApplication
|
||||
* @see org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
* @see org.springframework.boot.test.context.SpringBootTest
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableSecurity
|
||||
* @see org.springframework.data.gemfire.tests.integration.config.ClientServerIntegrationTestsConfiguration
|
||||
* @see org.springframework.geode.boot.autoconfigure.ClientSecurityAutoConfiguration
|
||||
* @see org.springframework.geode.boot.autoconfigure.PeerSecurityAutoConfiguration
|
||||
* @see org.springframework.geode.boot.autoconfigure.security.auth.AbstractAutoConfiguredSecurityContextIntegrationTests
|
||||
* @see org.springframework.test.context.ActiveProfiles
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@ActiveProfiles("security-local-client")
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = AutoConfiguredLocalSecurityContextIntegrationTests.GemFireClientConfiguration.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@SuppressWarnings("unused")
|
||||
public class AutoConfiguredLocalSecurityContextIntegrationTests
|
||||
extends AbstractAutoConfiguredSecurityContextIntegrationTests {
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = "error";
|
||||
|
||||
@BeforeClass
|
||||
public static void startGemFireServer() throws IOException {
|
||||
|
||||
GemfireBeanFactoryLocatorProxy.clear();
|
||||
|
||||
startGemFireServer(GemFireServerConfiguration.class,
|
||||
"-Dspring.profiles.active=security-local-server");
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanUpBeanFactoryLocatorReferences() {
|
||||
GemfireBeanFactoryLocatorProxy.clear();
|
||||
}
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableLogging(logLevel = GEMFIRE_LOG_LEVEL)
|
||||
@Import(ClientServerIntegrationTestsConfiguration.class)
|
||||
static class GemFireClientConfiguration extends BaseGemFireClientConfiguration { }
|
||||
|
||||
@SpringBootApplication
|
||||
@CacheServerApplication(name = "AutoConfiguredLocalSecurityContextIntegrationTests", logLevel = GEMFIRE_LOG_LEVEL)
|
||||
static class GemFireServerConfiguration extends BaseGemFireServerConfiguration {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(GemFireServerConfiguration.class, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.boot.autoconfigure.security.ssl;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.gemfire.GemfireTemplate;
|
||||
import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableLogging;
|
||||
import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport;
|
||||
import org.springframework.data.gemfire.tests.integration.config.ClientServerIntegrationTestsConfiguration;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import example.echo.config.EchoClientConfiguration;
|
||||
import example.echo.config.EchoServerConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests testing the auto-configuration of Apache Geode/Pivotal GemFire SSL.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
* @see org.springframework.boot.test.context.SpringBootTest
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.data.gemfire.GemfireTemplate
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableSsl
|
||||
* @see org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport
|
||||
* @see org.springframework.data.gemfire.tests.integration.config.ClientServerIntegrationTestsConfiguration
|
||||
* @see org.springframework.test.context.ActiveProfiles
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@ActiveProfiles("ssl")
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE,
|
||||
classes = AutoConfiguredSslIntegrationTests.GemFireClientConfiguration.class)
|
||||
@SuppressWarnings("unused")
|
||||
public class AutoConfiguredSslIntegrationTests extends ForkingClientServerIntegrationTestsSupport {
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = "error";
|
||||
private static final String TRUSTED_KEYSTORE_FILENAME = "test-trusted.keystore";
|
||||
|
||||
@BeforeClass
|
||||
public static void startGemFireServer() throws IOException {
|
||||
startGemFireServer(GemFireServerConfiguration.class, "-Dspring.profiles.active=ssl");
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void clearSslSystemProperties() {
|
||||
|
||||
List<String> sslSystemProperties = System.getProperties().keySet().stream()
|
||||
.map(String::valueOf)
|
||||
.map(String::toLowerCase)
|
||||
.filter(property -> property.contains("ssl"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
//System.err.printf("SSL System Properties [%s]%n", sslSystemProperties);
|
||||
|
||||
sslSystemProperties.forEach(System::clearProperty);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private GemfireTemplate echoTemplate;
|
||||
|
||||
@Test
|
||||
public void clientServerCommunicationsSuccessful() {
|
||||
|
||||
assertThat(this.echoTemplate).isNotNull();
|
||||
assertThat(this.echoTemplate.<String, String>get("Hello")).isEqualTo("Hello");
|
||||
assertThat(this.echoTemplate.<String, String>get("Test")).isEqualTo("Test");
|
||||
assertThat(this.echoTemplate.<String, String>get("Good-Bye")).isEqualTo("Good-Bye");
|
||||
}
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableLogging(logLevel = GEMFIRE_LOG_LEVEL)
|
||||
@Import(EchoClientConfiguration.class)
|
||||
static class GemFireClientConfiguration extends ClientServerIntegrationTestsConfiguration { }
|
||||
|
||||
@SpringBootApplication
|
||||
@CacheServerApplication(name = "AutoConfiguredSslIntegrationTests", logLevel = GEMFIRE_LOG_LEVEL)
|
||||
@Import(EchoServerConfiguration.class)
|
||||
static class GemFireServerConfiguration {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(GemFireServerConfiguration.class, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
|
||||
import org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport;
|
||||
import org.springframework.data.gemfire.tests.mock.annotation.EnableGemFireMockObjects;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link UseMemberName} and {@link MemberNameConfiguration}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication
|
||||
* @see org.springframework.data.gemfire.tests.mock.annotation.EnableGemFireMockObjects
|
||||
* @see org.springframework.test.context.ContextConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
@SuppressWarnings("unused")
|
||||
public class MemberNameConfigurationIntegrationTests extends IntegrationTestsSupport {
|
||||
|
||||
@Autowired
|
||||
private GemFireCache gemfireCache;
|
||||
|
||||
@Test
|
||||
public void memberNameIsCorrect() {
|
||||
|
||||
assertThat(this.gemfireCache).isNotNull();
|
||||
assertThat(this.gemfireCache.getDistributedSystem()).isNotNull();
|
||||
assertThat(this.gemfireCache.getDistributedSystem().getProperties()).isNotNull();
|
||||
assertThat(this.gemfireCache.getDistributedSystem().getProperties().getProperty("name"))
|
||||
.isEqualTo("TestClient");
|
||||
}
|
||||
|
||||
@ClientCacheApplication
|
||||
@EnableGemFireMockObjects
|
||||
@UseMemberName("TestClient")
|
||||
static class TestConfiguration { }
|
||||
|
||||
}
|
||||
515
geode-spring-boot/src/test/java/org/springframework/geode/core/env/VcapPropertySourceUnitTests.java
vendored
Normal file
515
geode-spring-boot/src/test/java/org/springframework/geode/core/env/VcapPropertySourceUnitTests.java
vendored
Normal file
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.core.env;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertiesPropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.geode.core.env.support.CloudCacheService;
|
||||
import org.springframework.geode.core.env.support.Service;
|
||||
import org.springframework.geode.core.env.support.User;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link VcapPropertySource}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.Properties
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.core.env.Environment
|
||||
* @see org.springframework.core.env.PropertiesPropertySource
|
||||
* @see org.springframework.core.env.PropertySource
|
||||
* @see org.springframework.geode.core.env.VcapPropertySource
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class VcapPropertySourceUnitTests {
|
||||
|
||||
@Test
|
||||
public void fromEnvironmentIsSuccessful() {
|
||||
|
||||
ConfigurableEnvironment mockEnvironment = mock(ConfigurableEnvironment.class);
|
||||
|
||||
MutablePropertySources propertySources = spy(new MutablePropertySources());
|
||||
|
||||
PropertySource mockVcapPropertySource = mock(EnumerablePropertySource.class);
|
||||
|
||||
when(mockEnvironment.getPropertySources()).thenReturn(propertySources);
|
||||
doReturn(mockVcapPropertySource).when(propertySources).get(eq("vcap"));
|
||||
when(mockVcapPropertySource.getName()).thenReturn("vcap");
|
||||
when(mockVcapPropertySource.containsProperty(anyString())).thenReturn(true);
|
||||
|
||||
VcapPropertySource propertySource = VcapPropertySource.from(mockEnvironment);
|
||||
|
||||
assertThat(propertySource).isNotNull();
|
||||
assertThat(propertySource.getSource()).isEqualTo(mockVcapPropertySource);
|
||||
|
||||
verify(mockEnvironment, times(1)).getPropertySources();
|
||||
verify(propertySources, times(1)).get(eq("vcap"));
|
||||
verify(mockVcapPropertySource, times(1))
|
||||
.containsProperty(eq("vcap.application.name"));
|
||||
verify(mockVcapPropertySource, times(1))
|
||||
.containsProperty(eq("vcap.application.uris"));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void fromNonConfigurableEnvironmentThrowsIllegalArgumentException() {
|
||||
|
||||
Environment mockEnvironment = mock(Environment.class);
|
||||
|
||||
try {
|
||||
VcapPropertySource.from(mockEnvironment);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected)
|
||||
.hasMessage("Environment was not configurable or does not contain an enumerable [vcap] PropertySource");
|
||||
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verifyZeroInteractions(mockEnvironment);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void fromConfigurableEnvironmentWithNoVcapPropertySourceThrowsIllegalArgumentException() {
|
||||
|
||||
ConfigurableEnvironment mockEnvironment = mock(ConfigurableEnvironment.class);
|
||||
|
||||
MutablePropertySources propertySources = spy(new MutablePropertySources());
|
||||
|
||||
when(mockEnvironment.getPropertySources()).thenReturn(propertySources);
|
||||
doReturn(null).when(propertySources).get(anyString());
|
||||
|
||||
try {
|
||||
VcapPropertySource.from(mockEnvironment);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected)
|
||||
.hasMessage("Environment was not configurable or does not contain an enumerable [vcap] PropertySource");
|
||||
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockEnvironment, times(1)).getPropertySources();
|
||||
verify(propertySources, times(1)).get(eq("vcap"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void fromConfigurableEnvironmentWithNonEnumerableVcapPropertySourceThrowsIllegalArgumentException() {
|
||||
|
||||
ConfigurableEnvironment mockEnvironment = mock(ConfigurableEnvironment.class);
|
||||
|
||||
MutablePropertySources propertySources = spy(new MutablePropertySources());
|
||||
|
||||
PropertySource mockPropertySource = mock(PropertySource.class);
|
||||
|
||||
when(mockEnvironment.getPropertySources()).thenReturn(propertySources);
|
||||
doReturn(mockPropertySource).when(propertySources).get(eq("vcap"));
|
||||
when(mockPropertySource.getName()).thenReturn("vcap");
|
||||
|
||||
try {
|
||||
VcapPropertySource.from(mockEnvironment);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected)
|
||||
.hasMessage("A valid EnumerablePropertySource named [vcap] with VCAP properties is required",
|
||||
mockEnvironment);
|
||||
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockEnvironment, times(1)).getPropertySources();
|
||||
verify(propertySources, times(1)).get(eq("vcap"));
|
||||
verify(mockPropertySource, times(1)).getName();
|
||||
verifyNoMoreInteractions(mockPropertySource);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void fromConfigurableEnvironmentWithEnumerableVcapPropertySourceHavingNoRequiredPropertiesThrowsIllegalArgumentException() {
|
||||
|
||||
ConfigurableEnvironment mockEnvironment = mock(ConfigurableEnvironment.class);
|
||||
|
||||
MutablePropertySources propertySources = spy(new MutablePropertySources());
|
||||
|
||||
PropertySource mockPropertySource = mock(EnumerablePropertySource.class);
|
||||
|
||||
when(mockEnvironment.getPropertySources()).thenReturn(propertySources);
|
||||
doReturn(mockPropertySource).when(propertySources).get(eq("vcap"));
|
||||
when(mockPropertySource.getName()).thenReturn("vcap");
|
||||
when(mockPropertySource.containsProperty(eq("vcap.application.name"))).thenReturn(true);
|
||||
when(mockPropertySource.containsProperty(eq("vcap.application.uris"))).thenReturn(false);
|
||||
|
||||
try {
|
||||
VcapPropertySource.from(mockEnvironment);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected)
|
||||
.hasMessage("A valid EnumerablePropertySource named [vcap] with VCAP properties is required",
|
||||
mockEnvironment);
|
||||
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockEnvironment, times(1)).getPropertySources();
|
||||
verify(propertySources, times(1)).get(eq("vcap"));
|
||||
verify(mockPropertySource, times(1)).getName();
|
||||
verify(mockPropertySource, times(1))
|
||||
.containsProperty(eq("vcap.application.name"));
|
||||
verify(mockPropertySource, times(1))
|
||||
.containsProperty(eq("vcap.application.uris"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromPropertiesIsSuccessful() {
|
||||
|
||||
Properties vcap = new Properties();
|
||||
|
||||
vcap.setProperty("vcap.application.name", "testApp");
|
||||
vcap.setProperty("vcap.application.uris", "boot-app.apps.cloud.net");
|
||||
|
||||
|
||||
VcapPropertySource propertySource = VcapPropertySource.from(vcap);
|
||||
|
||||
assertThat(propertySource).isNotNull();
|
||||
assertThat(propertySource.getSource()).isInstanceOf(PropertiesPropertySource.class);
|
||||
assertThat(propertySource.getProperty("vcap.application.name")).isEqualTo("testApp");
|
||||
assertThat(propertySource.getProperty("vcap.application.uris")).isEqualTo("boot-app.apps.cloud.net");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void fromPropertiesHavingNoRequiredProperties() {
|
||||
|
||||
try {
|
||||
VcapPropertySource.from(new Properties());
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Properties are required");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void fromNullPropertiesThrowsIllegalArgumentException() {
|
||||
|
||||
try {
|
||||
VcapPropertySource.from((Properties) null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Properties are required");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllVcapApplicationPropertiesIsSuccessful() {
|
||||
|
||||
EnumerablePropertySource mockPropertySource = mock(EnumerablePropertySource.class);
|
||||
|
||||
String[] propertyNames = {
|
||||
"vcap.services.jblum-pcc.credentials.locators",
|
||||
"vcap.services.jblum-pcc.credentials.users",
|
||||
"vcap.application.host",
|
||||
"vcap.application.name",
|
||||
"vcap.services.jblum-pcc.name",
|
||||
"vcap.application.port",
|
||||
"vcap.application.space_name",
|
||||
"vcap.services.jblum-pcc.plan",
|
||||
"vcap.application.uris",
|
||||
"vcap.services.jblum-pcc.tags"
|
||||
};
|
||||
|
||||
when(mockPropertySource.getName()).thenReturn("vcap");
|
||||
|
||||
when(mockPropertySource.containsProperty(anyString())).thenAnswer(invocation ->
|
||||
Arrays.asList(propertyNames).contains(invocation.<String>getArgument(0)));
|
||||
|
||||
when(mockPropertySource.getPropertyNames()).thenReturn(propertyNames);
|
||||
|
||||
VcapPropertySource propertySource = VcapPropertySource.from(mockPropertySource);
|
||||
|
||||
assertThat(propertySource).isNotNull();
|
||||
assertThat(propertySource.getSource()).isEqualTo(mockPropertySource);
|
||||
|
||||
Set<String> vcapApplicationProperties = propertySource.findAllVcapApplicationProperties();
|
||||
|
||||
assertThat(vcapApplicationProperties).isNotNull();
|
||||
assertThat(vcapApplicationProperties).hasSize(5);
|
||||
assertThat(vcapApplicationProperties)
|
||||
.containsExactlyInAnyOrder("vcap.application.host", "vcap.application.name", "vcap.application.port",
|
||||
"vcap.application.space_name", "vcap.application.uris");
|
||||
|
||||
verify(mockPropertySource, times(1)).getName();
|
||||
verify(mockPropertySource, times(1))
|
||||
.containsProperty(eq("vcap.application.name"));
|
||||
verify(mockPropertySource, times(1))
|
||||
.containsProperty(eq("vcap.application.uris"));
|
||||
verify(mockPropertySource, times(1)).getPropertyNames();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllVcapServicesPropertiesIsSuccessful() {
|
||||
|
||||
EnumerablePropertySource mockPropertySource = mock(EnumerablePropertySource.class);
|
||||
|
||||
String[] propertyNames = {
|
||||
"vcap.services.jblum-pcc.credentials.locators",
|
||||
"vcap.services.jblum-pcc.credentials.users",
|
||||
"vcap.application.host",
|
||||
"vcap.application.name",
|
||||
"vcap.services.jblum-pcc.name",
|
||||
"vcap.application.port",
|
||||
"vcap.application.space_name",
|
||||
"vcap.services.jblum-pcc.plan",
|
||||
"vcap.application.uris",
|
||||
"vcap.services.jblum-pcc.tags"
|
||||
};
|
||||
|
||||
when(mockPropertySource.getName()).thenReturn("vcap");
|
||||
|
||||
when(mockPropertySource.containsProperty(anyString())).thenAnswer(invocation ->
|
||||
Arrays.asList(propertyNames).contains(invocation.<String>getArgument(0)));
|
||||
|
||||
when(mockPropertySource.getPropertyNames()).thenReturn(propertyNames);
|
||||
|
||||
VcapPropertySource propertySource = VcapPropertySource.from(mockPropertySource);
|
||||
|
||||
assertThat(propertySource).isNotNull();
|
||||
assertThat(propertySource.getSource()).isEqualTo(mockPropertySource);
|
||||
|
||||
Set<String> vcapApplicationProperties = propertySource.findAllVcapServicesProperties();
|
||||
|
||||
assertThat(vcapApplicationProperties).isNotNull();
|
||||
assertThat(vcapApplicationProperties).hasSize(5);
|
||||
assertThat(vcapApplicationProperties)
|
||||
.containsExactlyInAnyOrder("vcap.services.jblum-pcc.credentials.locators",
|
||||
"vcap.services.jblum-pcc.credentials.users", "vcap.services.jblum-pcc.name",
|
||||
"vcap.services.jblum-pcc.plan", "vcap.services.jblum-pcc.tags");
|
||||
|
||||
verify(mockPropertySource, times(1)).getName();
|
||||
verify(mockPropertySource, times(1))
|
||||
.containsProperty(eq("vcap.application.name"));
|
||||
verify(mockPropertySource, times(1))
|
||||
.containsProperty(eq("vcap.application.uris"));
|
||||
verify(mockPropertySource, times(1)).getPropertyNames();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findFirstCloudCacheServiceNameReturnsServiceName() {
|
||||
|
||||
Properties vcap = new Properties();
|
||||
|
||||
vcap.setProperty("vcap.application.name", "boot-example");
|
||||
vcap.setProperty("vcap.services.test-pcc.name", "test-pcc");
|
||||
vcap.setProperty("vcap.services.test-pcc.plan", "small");
|
||||
vcap.setProperty("vcap.services.test-pcc.tags", "pivotal,database,cloudcache,gemfire");
|
||||
vcap.setProperty("vcap.application.space_name", "outerspace");
|
||||
vcap.setProperty("vcap.services.jblum-pcc.name", "jblum-pcc");
|
||||
vcap.setProperty("vcap.services.jblum-pcc.plan", "small");
|
||||
vcap.setProperty("vcap.services.jblum-pcc.tags", "cloudcache,database,gemfire,pivotal");
|
||||
vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net");
|
||||
vcap.setProperty("vcap.services.a-pcc.name", "a-pcc");
|
||||
vcap.setProperty("vcap.services.a-pcc.plan", "huge");
|
||||
vcap.setProperty("vcap.services.a-pcc.tags", "pivotal,cloudcache,database");
|
||||
|
||||
VcapPropertySource propertySource = VcapPropertySource.from(vcap);
|
||||
|
||||
assertThat(propertySource).isNotNull();
|
||||
assertThat(propertySource.findFirstCloudCacheServiceName()).isEqualTo("jblum-pcc");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void findFirstCloudCacheServiceNameWithInvalidTagsThrowsIllegalStateException() {
|
||||
|
||||
Properties vcap = new Properties();
|
||||
|
||||
vcap.setProperty("vcap.application.name", "boot-example");
|
||||
vcap.setProperty("vcap.services.test-pcc.name", "test-pcc");
|
||||
vcap.setProperty("vcap.services.test-pcc.plan", "small");
|
||||
vcap.setProperty("vcap.services.test-pcc.tags", "pivotal,gemfire,database");
|
||||
vcap.setProperty("vcap.application.space_name", "outerspace");
|
||||
vcap.setProperty("vcap.services.a-pcc.tags", "pivotal,cloudcache,database");
|
||||
vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net");
|
||||
|
||||
VcapPropertySource propertySource = VcapPropertySource.from(vcap);
|
||||
|
||||
assertThat(propertySource).isNotNull();
|
||||
|
||||
try {
|
||||
propertySource.findFirstCloudCacheServiceName();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("No service with tags [cloudcache, gemfire] was found");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void findFirstCloudCacheServiceNameWithNoTagsThrowsIllegalStateException() {
|
||||
|
||||
Properties vcap = new Properties();
|
||||
|
||||
vcap.setProperty("vcap.application.name", "boot-example");
|
||||
vcap.setProperty("vcap.services.test-pcc.name", "test-pcc");
|
||||
vcap.setProperty("vcap.services.test-pcc.plan", "small");
|
||||
vcap.setProperty("vcap.application.space_name", "outerspace");
|
||||
vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net");
|
||||
|
||||
VcapPropertySource propertySource = VcapPropertySource.from(vcap);
|
||||
|
||||
assertThat(propertySource).isNotNull();
|
||||
|
||||
try {
|
||||
propertySource.findFirstCloudCacheServiceName();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("No service with tags [cloudcache, gemfire] was found");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findFirstCloudCacheServiceReturnsCloudCacheService() throws Exception {
|
||||
|
||||
URL gfshUrl = new URL("http://skullbox:7070/v1/gemfire");
|
||||
|
||||
Properties vcap = new Properties();
|
||||
|
||||
vcap.setProperty("vcap.services.test-pcc.name", "test-pcc");
|
||||
vcap.setProperty("vcap.services.test-pcc.plan", "huge");
|
||||
vcap.setProperty("vcap.application.name", "boot-example");
|
||||
vcap.setProperty("vcap.services.test-pcc.credentials.locators", "sandbox[1234],toolbox,xbox[6789]");
|
||||
vcap.setProperty("vcap.application.space_name", "outerspace");
|
||||
vcap.setProperty("vcap.services.test-pcc.credentials.urls.gfsh", gfshUrl.toExternalForm());
|
||||
vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net");
|
||||
vcap.setProperty("vcap.services.test-pcc.tags", "pivotal,cloudcache , database, gemfire ");
|
||||
|
||||
VcapPropertySource propertySource = VcapPropertySource.from(vcap);
|
||||
|
||||
assertThat(propertySource).isNotNull();
|
||||
|
||||
CloudCacheService cloudCacheService = propertySource.findFirstCloudCacheService();
|
||||
|
||||
assertThat(cloudCacheService).isNotNull();
|
||||
assertThat(cloudCacheService.getGfshUrl().orElse(null)).isEqualTo(gfshUrl);
|
||||
assertThat(cloudCacheService.getLocatorList()).containsExactly(
|
||||
CloudCacheService.Locator.newLocator("sandbox", 1234),
|
||||
CloudCacheService.Locator.newLocator("toolbox", 10334),
|
||||
CloudCacheService.Locator.newLocator("xbox", 6789)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findFirstUserByRoleClusterOperatorReturnsUser() {
|
||||
|
||||
Properties vcap = new Properties();
|
||||
|
||||
vcap.setProperty("vcap.application.name", "boot-example");
|
||||
vcap.setProperty("vcap.services.test-pcc.name", "test-pcc");
|
||||
vcap.setProperty("vcap.services.test-pcc.credentials.users[0].username", "jdoe");
|
||||
vcap.setProperty("vcap.services.test-pcc.credentials.users[0].roles", "developer,poweruser,seaswab");
|
||||
vcap.setProperty("vcap.services.test-pcc.credentials.users[0].password", "test");
|
||||
vcap.setProperty("vcap.services.test-pcc.tags", "pivotal,cloudcache , database, gemfire ");
|
||||
vcap.setProperty("vcap.application.space_name", "outerspace");
|
||||
vcap.setProperty("vcap.services.a-pcc.name", "a-pcc");
|
||||
vcap.setProperty("vcap.services.a-pcc.credentials.users[0].username", "admin");
|
||||
vcap.setProperty("vcap.services.a-pcc.credentials.users[0].roles", "cluster_admin");
|
||||
vcap.setProperty("vcap.services.a-pcc.credentials.users[0].password", "p@55w0rd");
|
||||
vcap.setProperty("vcap.services.a-pcc.credentials.users[1].username", "root");
|
||||
vcap.setProperty("vcap.services.a-pcc.credentials.users[1].roles", "cluster_operator");
|
||||
vcap.setProperty("vcap.services.a-pcc.credentials.users[1].password", "p@55w0rd");
|
||||
vcap.setProperty("vcap.services.a-pcc.tags", "pivotal,cloudcache,database");
|
||||
vcap.setProperty("vcap.application.uris", "boot-example.boot-apps.apps.cloud.net");
|
||||
vcap.setProperty("vcap.services.jblum-pcc.name", "jblum-pcc");
|
||||
vcap.setProperty("vcap.services.jblum-pcc.credentials.users[0].username", "majorTom");
|
||||
vcap.setProperty("vcap.services.jblum-pcc.credentials.users[0].roles", "cluster_operator,ground_contoller");
|
||||
vcap.setProperty("vcap.services.jblum-pcc.credentials.users[0].password", "s3cUr3");
|
||||
vcap.setProperty("vcap.services.jblum-pcc.credentials.users[1].username", "jimbo");
|
||||
vcap.setProperty("vcap.services.jblum-pcc.credentials.users[1].roles", "cluster_fuck");
|
||||
vcap.setProperty("vcap.services.jblum-pcc.credentials.users[1].password", "p@55!t");
|
||||
vcap.setProperty("vcap.services.jblum-pcc.credentials.users[2].username", "buster");
|
||||
vcap.setProperty("vcap.services.jblum-pcc.credentials.users[2].roles", "cluster_operator");
|
||||
vcap.setProperty("vcap.services.jblum-pcc.credentials.users[2].password", "p@55!t");
|
||||
vcap.setProperty("vcap.services.jblum-pcc.tags", "pivotal,gemfire,database");
|
||||
|
||||
VcapPropertySource propertySource = VcapPropertySource.from(vcap);
|
||||
|
||||
assertThat(propertySource).isNotNull();
|
||||
assertThat(propertySource.findFirstUserByRoleClusterOperator(Service.with("test-pcc")).isPresent()).isFalse();
|
||||
|
||||
User root = propertySource.findFirstUserByRoleClusterOperator(Service.with("a-pcc")).orElse(null);
|
||||
|
||||
assertThat(root).isNotNull();
|
||||
assertThat(root.getName()).isEqualTo("root");
|
||||
assertThat(root.getPassword().orElse(null)).isEqualTo("p@55w0rd");
|
||||
assertThat(root.getRole().orElse(null).isClusterOperator()).isTrue();
|
||||
|
||||
User majorTom = propertySource.findFirstUserByRoleClusterOperator(Service.with("jblum-pcc")).orElse(null);
|
||||
|
||||
assertThat(majorTom).isNotNull();
|
||||
assertThat(majorTom.getName()).isEqualTo("majorTom");
|
||||
assertThat(majorTom.getPassword().orElse(null)).isEqualTo("s3cUr3");
|
||||
assertThat(majorTom.getRole().orElse(null).isClusterOperator()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.core.env.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link CloudCacheService}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.springframework.geode.core.env.support.CloudCacheService
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class CloudCacheServiceUnitTests {
|
||||
|
||||
@Test
|
||||
public void withServiceNameLocatorsAndUrlReturnsNewCloudCacheService() throws Exception {
|
||||
|
||||
URL gfshUrl = new URL("http://localhost:7070/v1/gemfire");
|
||||
|
||||
CloudCacheService service = CloudCacheService.with("gemfire")
|
||||
.withLocators("boombox[123],cardboardbox[456],mailbox[789],xbox[40404]")
|
||||
.withGfshUrl(gfshUrl);
|
||||
|
||||
assertThat(service).isNotNull();
|
||||
assertThat(service.getName()).isEqualTo("gemfire");
|
||||
assertThat(service.getGfshUrl().orElse(null)).isEqualTo(gfshUrl);
|
||||
assertThat(service.getLocators().orElse(null))
|
||||
.isEqualTo("boombox[123],cardboardbox[456],mailbox[789],xbox[40404]");
|
||||
|
||||
List<CloudCacheService.Locator> locators = service.getLocatorList();
|
||||
|
||||
assertThat(locators).isNotNull();
|
||||
assertThat(locators).hasSize(4);
|
||||
assertThat(locators.get(0)).isEqualTo(CloudCacheService.Locator.newLocator("boombox", 123));
|
||||
assertThat(locators.get(1)).isEqualTo(CloudCacheService.Locator.newLocator("cardboardbox", 456));
|
||||
assertThat(locators.get(2)).isEqualTo(CloudCacheService.Locator.newLocator("mailbox", 789));
|
||||
assertThat(locators.get(3)).isEqualTo(CloudCacheService.Locator.newLocator("xbox", 40404));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseLocatorWithSingleLetterHostnameAndPort() {
|
||||
|
||||
CloudCacheService.Locator locator = CloudCacheService.Locator.parse("x [10336]");
|
||||
|
||||
assertThat(locator).isNotNull();
|
||||
assertThat(locator.getHost()).isEqualTo("x");
|
||||
assertThat(locator.getPort()).isEqualTo(10336);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseLocatorWithNoHostnameAndPort() {
|
||||
|
||||
CloudCacheService.Locator locator = CloudCacheService.Locator.parse(" [1 234] ");
|
||||
|
||||
assertThat(locator).isNotNull();
|
||||
assertThat(locator.getHost()).isEqualTo(CloudCacheService.Locator.DEFAULT_LOCATOR_HOST);
|
||||
assertThat(locator.getPort()).isEqualTo(1234);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseLocatorWithHostnameAndNoPort() {
|
||||
|
||||
CloudCacheService.Locator locator = CloudCacheService.Locator.parse(" chatterbox ");
|
||||
|
||||
assertThat(locator).isNotNull();
|
||||
assertThat(locator.getHost()).isEqualTo("chatterbox");
|
||||
assertThat(locator.getPort()).isEqualTo(CloudCacheService.Locator.DEFAULT_LOCATOR_PORT);
|
||||
}
|
||||
|
||||
private void testParseLocatorWithInvalidHostPort(String hostPort) {
|
||||
|
||||
try {
|
||||
CloudCacheService.Locator.parse(hostPort);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Locator host/port [%s] is not valid", hostPort);
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void parseLocatorWithBlankHostPort() {
|
||||
testParseLocatorWithInvalidHostPort(" ");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void parseLocatorWithEmptyHostPort() {
|
||||
testParseLocatorWithInvalidHostPort("");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void parseLocatorWithNullHostPort() {
|
||||
testParseLocatorWithInvalidHostPort(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseLocatorsWithMultipleLocatorHostsPorts() {
|
||||
|
||||
List<CloudCacheService.Locator> locators =
|
||||
CloudCacheService.Locator.parseLocators(" jukebox[12345], matchbox [6789] ");
|
||||
|
||||
assertThat(locators).isNotNull();
|
||||
assertThat(locators).hasSize(2);
|
||||
assertThat(locators).containsExactly(
|
||||
CloudCacheService.Locator.newLocator("jukebox", 12345),
|
||||
CloudCacheService.Locator.newLocator("matchbox", 6789)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseLocatorsWithNoLocatorHostPort() {
|
||||
|
||||
List<CloudCacheService.Locator> locators = CloudCacheService.Locator.parseLocators(" ");
|
||||
|
||||
assertThat(locators).isNotNull();
|
||||
assertThat(locators).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseLocatorsWithSingleLocatorHostPort() {
|
||||
|
||||
List<CloudCacheService.Locator> locators = CloudCacheService.Locator.parseLocators("skullbox[2345]");
|
||||
|
||||
assertThat(locators).isNotNull();
|
||||
assertThat(locators).hasSize(1);
|
||||
assertThat(locators).containsExactly(CloudCacheService.Locator.newLocator("skullbox", 2345));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newLocatorWithHostAndPort() {
|
||||
|
||||
CloudCacheService.Locator locator = CloudCacheService.Locator.newLocator("toybox", 8008);
|
||||
|
||||
assertThat(locator).isNotNull();
|
||||
assertThat(locator.getHost()).isEqualTo("toybox");
|
||||
assertThat(locator.getPort()).isEqualTo(8008);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newLocatorWithHostname() {
|
||||
|
||||
CloudCacheService.Locator locator = CloudCacheService.Locator.newLocator("unbox");
|
||||
|
||||
assertThat(locator).isNotNull();
|
||||
assertThat(locator.getHost()).isEqualTo("unbox");
|
||||
assertThat(locator.getPort()).isEqualTo(CloudCacheService.Locator.DEFAULT_LOCATOR_PORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newLocatorWithPort() {
|
||||
|
||||
CloudCacheService.Locator locator = CloudCacheService.Locator.newLocator(6789);
|
||||
|
||||
assertThat(locator).isNotNull();
|
||||
assertThat(locator.getHost()).isEqualTo(CloudCacheService.Locator.DEFAULT_LOCATOR_HOST);
|
||||
assertThat(locator.getPort()).isEqualTo(6789);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newLocatorWithDefaultHostPort() {
|
||||
|
||||
CloudCacheService.Locator locator = CloudCacheService.Locator.newLocator();
|
||||
|
||||
assertThat(locator).isNotNull();
|
||||
assertThat(locator.getHost()).isEqualTo(CloudCacheService.Locator.DEFAULT_LOCATOR_HOST);
|
||||
assertThat(locator.getPort()).isEqualTo(CloudCacheService.Locator.DEFAULT_LOCATOR_PORT);
|
||||
}
|
||||
|
||||
private void testNewLocatorWithInvalidHost(String host) {
|
||||
|
||||
try {
|
||||
CloudCacheService.Locator.newLocator(host);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Host [%s] is required", host);
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void newLocatorWithBlankHostnameThrowsIllegalArgumentException() {
|
||||
testNewLocatorWithInvalidHost(" ");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void newLocatorWithEmptyHostnameThrowsIllegalArgumentException() {
|
||||
testNewLocatorWithInvalidHost("");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void newLocatorWithNullHostnameThrowsIllegalArgumentException() {
|
||||
testNewLocatorWithInvalidHost(null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void newLocatorWithInvalidPortNumberThrowsIllegalArgumentException() {
|
||||
|
||||
try {
|
||||
CloudCacheService.Locator.newLocator(-2345);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Port [-2345] must be greater than equal to 0");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void locatorToStringPrintsHostPort() {
|
||||
assertThat(CloudCacheService.Locator.newLocator("skullbox", 1234).toString())
|
||||
.isEqualTo("skullbox[1234]");
|
||||
}
|
||||
}
|
||||
75
geode-spring-boot/src/test/java/org/springframework/geode/core/env/support/ServiceUnitTests.java
vendored
Normal file
75
geode-spring-boot/src/test/java/org/springframework/geode/core/env/support/ServiceUnitTests.java
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.core.env.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link Service}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.springframework.geode.core.env.support.Service
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class ServiceUnitTests {
|
||||
|
||||
@Test
|
||||
public void withNameReturnsNewService() {
|
||||
|
||||
Service service = Service.with("test");
|
||||
|
||||
assertThat(service).isNotNull();
|
||||
assertThat(service.getName()).isEqualTo("test");
|
||||
}
|
||||
|
||||
private void testWithInvalidNameThrowsIllegalArgumentException(String name) {
|
||||
|
||||
try {
|
||||
Service.with(name);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Service name [%s] is required", name);
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void withBlankServiceNameThrowsIllegalArgumentException() {
|
||||
testWithInvalidNameThrowsIllegalArgumentException(" ");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void withEmptyServiceNameThrowsIllegalArgumentException() {
|
||||
testWithInvalidNameThrowsIllegalArgumentException("");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void withNullServiceNameThrowsIllegalArgumentException() {
|
||||
testWithInvalidNameThrowsIllegalArgumentException("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringReturnsServiceName() {
|
||||
assertThat(Service.with("test").toString()).isEqualTo("test");
|
||||
}
|
||||
}
|
||||
206
geode-spring-boot/src/test/java/org/springframework/geode/core/env/support/UserUnitTests.java
vendored
Normal file
206
geode-spring-boot/src/test/java/org/springframework/geode/core/env/support/UserUnitTests.java
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.core.env.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link User}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.springframework.geode.core.env.support.User
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class UserUnitTests {
|
||||
|
||||
@Test
|
||||
public void withNameReturnsNewUser() {
|
||||
|
||||
User user = User.with("root");
|
||||
|
||||
assertThat(user).isNotNull();
|
||||
assertThat(user.getName()).isEqualTo("root");
|
||||
assertThat(user.getPassword().isPresent()).isFalse();
|
||||
assertThat(user.getRole().isPresent()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withNamePasswordAndRoleReturnsNewUser() {
|
||||
|
||||
User jdoe = User.with("jdoe")
|
||||
.withPassword("p@55w0rd!")
|
||||
.withRole(User.Role.CLUSTER_OPERATOR);
|
||||
|
||||
assertThat(jdoe).isNotNull();
|
||||
assertThat(jdoe.getName()).isEqualTo("jdoe");
|
||||
assertThat(jdoe.getPassword().orElse(null)).isEqualTo("p@55w0rd!");
|
||||
assertThat(jdoe.getRole().orElse(null)).isEqualTo(User.Role.CLUSTER_OPERATOR);
|
||||
}
|
||||
|
||||
private void testWithInvalidNameThrowsIllegalArgumentException(String name) {
|
||||
|
||||
try {
|
||||
User.with(name);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("User name [%s] is required", name);
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void withBlankUserNameThrowsIllegalArgumentException() {
|
||||
testWithInvalidNameThrowsIllegalArgumentException(" ");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void withEmptyUserNameThrowsIllegalArgumentException() {
|
||||
testWithInvalidNameThrowsIllegalArgumentException("");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void withNullUserNameThrowsIllegalArgumentException() {
|
||||
testWithInvalidNameThrowsIllegalArgumentException(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToReturnsEqualValue() {
|
||||
assertThat(User.with("root").compareTo(User.with("root"))).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToReturnsNegativeValue() {
|
||||
assertThat(User.with("jdoe").compareTo(User.with("root"))).isLessThan(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToReturnsPositiveValue() {
|
||||
assertThat(User.with("root").compareTo(User.with("jdoe"))).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void equalsObjectsReturnsFalse() {
|
||||
assertThat(User.with("admin").equals("admin")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsWithDifferentObjectsReturnsFalse() {
|
||||
|
||||
User admin = User.with("admin").withRole(User.Role.CLUSTER_OPERATOR);
|
||||
User root = User.with("root").withRole(User.Role.CLUSTER_OPERATOR);
|
||||
|
||||
assertThat(root.equals(admin)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsWithEqualObjectsReturnsTrue() {
|
||||
|
||||
User root = User.with("root").withRole(User.Role.CLUSTER_OPERATOR);
|
||||
User rootToo = User.with("root").withPassword("test").withRole(User.Role.DEVELOPER);
|
||||
|
||||
assertThat(root.equals(rootToo)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void equalsWithIdenticalObjectsReturnsTrue() {
|
||||
|
||||
User root = User.with("root");
|
||||
|
||||
assertThat(root.equals(root)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hashCodeIsCorrect() {
|
||||
|
||||
User user = User.with("root");
|
||||
|
||||
int hashCode = user.hashCode();
|
||||
|
||||
assertThat(hashCode).isNotZero();
|
||||
assertThat(hashCode).isEqualTo(user.hashCode());
|
||||
|
||||
user.withPassword("test").withRole(User.Role.DEVELOPER);
|
||||
|
||||
assertThat(user.hashCode()).isEqualTo(hashCode);
|
||||
assertThat(user.hashCode()).isNotEqualTo(User.with("anotherUser").hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringReturnsUserName() {
|
||||
assertThat(User.with("root").toString()).isEqualTo("root");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roleOfEmptyNameReturnsNull() {
|
||||
assertThat(User.Role.of("")).isNull();
|
||||
assertThat(User.Role.of(" ")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roleOfInvalidNameReturnsNull() {
|
||||
assertThat(User.Role.of("invalid")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roleOfNulReturnsNull() {
|
||||
assertThat(User.Role.of(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roleOfRoleNamesEqualsRole() {
|
||||
Arrays.stream(User.Role.values()).forEach(role -> {
|
||||
assertThat(User.Role.of(role.name())).isEqualTo(role);
|
||||
assertThat(User.Role.of(role.toString())).isEqualTo(role);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isClusterOperator() {
|
||||
assertThat(User.Role.CLUSTER_OPERATOR.isClusterOperator()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotClusterOperator() {
|
||||
assertThat(User.Role.DEVELOPER.isClusterOperator()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isDeveloper() {
|
||||
assertThat(User.Role.DEVELOPER.isDeveloper()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotDeveloper() {
|
||||
assertThat(User.Role.CLUSTER_OPERATOR.isDeveloper()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringReturnsLowercaseName() {
|
||||
Arrays.stream(User.Role.values())
|
||||
.forEach(role -> assertThat(role.toString()).isEqualTo(role.name().toLowerCase()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.core.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newRuntimeException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ObjectUtils}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.springframework.geode.core.util.ObjectUtils
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class ObjectUtilsUnitTests {
|
||||
|
||||
@Test
|
||||
public void doOperationSafelyReturnsResult() {
|
||||
assertThat(ObjectUtils.doOperationSafely(() -> "test")).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doOperationSafelyReturnsDefaultValue() {
|
||||
assertThat(ObjectUtils.doOperationSafely(() -> { throw newRuntimeException("test"); },
|
||||
"default value")).isEqualTo("default value");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void doOperationSafelyThrowsIllegalStateException() {
|
||||
|
||||
try {
|
||||
ObjectUtils.doOperationSafely(() -> { throw newRuntimeException("test"); }, null);
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Failed to execute operation");
|
||||
assertThat(expected).hasCauseInstanceOf(RuntimeException.class);
|
||||
assertThat(expected.getCause()).hasMessage("test");
|
||||
assertThat(expected.getCause()).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnValueThrowOnNullWithNonNullValueReturnsValue() {
|
||||
assertThat(ObjectUtils.returnValueThrowOnNull("test")).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void returnValueThrowOnNullWithNullValueThrowsException() {
|
||||
|
||||
try {
|
||||
ObjectUtils.returnValueThrowOnNull(null, newRuntimeException("test"));
|
||||
}
|
||||
catch (RuntimeException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("test");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.function.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import edu.umd.cs.mtc.MultithreadedTestCase;
|
||||
import edu.umd.cs.mtc.TestFramework;
|
||||
|
||||
import org.apache.geode.cache.execute.FunctionException;
|
||||
import org.apache.geode.distributed.DistributedMember;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractResultCollector}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.springframework.geode.function.support.AbstractResultCollector
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class AbstractResultCollectorUnitTests {
|
||||
|
||||
private AbstractResultCollector<Object, Object> resultCollector;
|
||||
|
||||
private static <T, S> AbstractResultCollector<T, S> newResultCollector() {
|
||||
return newResultCollector(() -> {});
|
||||
}
|
||||
|
||||
private static <T, S> AbstractResultCollector<T, S> newResultCollector(Runnable runnable) {
|
||||
|
||||
return new AbstractResultCollector<T, S>() {
|
||||
|
||||
@Override
|
||||
public synchronized S getResult() throws FunctionException {
|
||||
runnable.run();
|
||||
return super.getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addResult(DistributedMember memberID, T resultOfSingleExecution) {
|
||||
setResult((S) resultOfSingleExecution);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.resultCollector = newResultCollector();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearResultClearsResult() {
|
||||
|
||||
this.resultCollector.setResult("test");
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isEqualTo("test");
|
||||
|
||||
this.resultCollector.clearResults();
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResultReturnsResult() {
|
||||
|
||||
this.resultCollector.setResult("test");
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResultReturnsResultWithinTimeout() throws Throwable {
|
||||
TestFramework.runOnce(new ReturnsResultWithinTimeoutMultithreadedTestCase());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resultsHaveEnded() {
|
||||
|
||||
this.resultCollector.endResults();
|
||||
|
||||
assertThat(this.resultCollector.hasResultsEnded()).isTrue();
|
||||
assertThat(this.resultCollector.hasResultsNotEnded()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resultsHaveNotEnded() {
|
||||
|
||||
assertThat(this.resultCollector.hasResultsEnded()).isFalse();
|
||||
assertThat(this.resultCollector.hasResultsNotEnded()).isTrue();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
static class ReturnsResultWithinTimeoutMultithreadedTestCase extends MultithreadedTestCase {
|
||||
|
||||
private long startTimestamp;
|
||||
|
||||
private AbstractResultCollector<Object, Object> resultCollector;
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
|
||||
super.initialize();
|
||||
|
||||
this.resultCollector = newResultCollector(() -> waitForTick(1));
|
||||
this.startTimestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void thread1() throws InterruptedException {
|
||||
|
||||
Thread.currentThread().setName("ResultCollector.getResult()");
|
||||
|
||||
assertThat(this.resultCollector.getResult(500, TimeUnit.MILLISECONDS)).isEqualTo("test");
|
||||
}
|
||||
|
||||
public void thread2() {
|
||||
|
||||
Thread.currentThread().setName("ResultCollector.setResult(..)");
|
||||
|
||||
waitForTick(1);
|
||||
|
||||
this.resultCollector.setResult("test");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
|
||||
long endTimestamp = System.currentTimeMillis();
|
||||
|
||||
assertThat(endTimestamp).isGreaterThan(this.startTimestamp);
|
||||
assertThat(endTimestamp - this.startTimestamp).isLessThan(TimeUnit.SECONDS.toMillis(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.function.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.geode.distributed.DistributedMember;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SingleResultReturningCollector}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.springframework.geode.function.support.SingleResultReturningCollector
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SingleResultReturningCollectorUnitTests {
|
||||
|
||||
@Mock
|
||||
private DistributedMember mockDistributedMember;
|
||||
|
||||
private SingleResultReturningCollector<Object> resultCollector;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.resultCollector = new SingleResultReturningCollector<>();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addResultWithNullIsSafe() {
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isNull();
|
||||
|
||||
this.resultCollector.addResult(this.mockDistributedMember, null);
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addResultWithSingleObjectReturnsObject() {
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isNull();
|
||||
|
||||
this.resultCollector.addResult(this.mockDistributedMember, "test");
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addResultWithIterableReturnsFirstElement() {
|
||||
|
||||
Iterable<String> list = Arrays.asList("one", "two", "three");
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isNull();
|
||||
|
||||
this.resultCollector.addResult(this.mockDistributedMember, list);
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isEqualTo("one");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addResultWithIterableReturningNullIteratorIsSafe() {
|
||||
|
||||
Iterable<Object> mockIterable = mock(Iterable.class);
|
||||
|
||||
when(mockIterable.iterator()).thenReturn(null);
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isNull();
|
||||
|
||||
this.resultCollector.addResult(mockDistributedMember, mockIterable);
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addResultWithIterableOfListsReturnsFirstElementInListOne() {
|
||||
|
||||
Iterable<String> listOne = Arrays.asList("one", "two", "three");
|
||||
Iterable<String> listTwo = Arrays.asList("four", "five", "six");
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isNull();
|
||||
|
||||
this.resultCollector.addResult(this.mockDistributedMember, Arrays.asList(listOne, listTwo));
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isEqualTo("one");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addResultWithIterableOfListsOfListsReturnsFirstElementInListOne() {
|
||||
|
||||
Iterable<String> listOne = Arrays.asList("one", "two", "three");
|
||||
Iterable<String> listTwo = Arrays.asList("four", "five", "six");
|
||||
Iterable<String> listThree = Arrays.asList("seven", "eight", "nine");
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isNull();
|
||||
|
||||
this.resultCollector.addResult(this.mockDistributedMember,
|
||||
Arrays.asList(Arrays.asList(listOne, listTwo), listThree));
|
||||
|
||||
assertThat(this.resultCollector.getResult()).isEqualTo("one");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.security.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableSecurity;
|
||||
import org.springframework.data.gemfire.config.annotation.PeerCacheApplication;
|
||||
import org.springframework.data.gemfire.support.GemfireBeanFactoryLocatorProxy;
|
||||
import org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link SecurityManagerProxy}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.security.SecurityManager
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableSecurity
|
||||
* @see org.springframework.data.gemfire.config.annotation.PeerCacheApplication
|
||||
* @see org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport
|
||||
* @see org.springframework.test.context.ContextConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
@SuppressWarnings("unused")
|
||||
public class SecurityManagerProxyIntegrationTests extends IntegrationTestsSupport {
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = "error";
|
||||
|
||||
@BeforeClass
|
||||
@AfterClass
|
||||
public static void cleanUpBeanFactoryLocatorReferences() {
|
||||
GemfireBeanFactoryLocatorProxy.clear();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private org.apache.geode.security.SecurityManager mockSecurityManager;
|
||||
|
||||
@Test
|
||||
public void securityManagerProxyWasConfiguredWithMockSecurityManager() {
|
||||
assertThat(SecurityManagerProxy.getInstance().getSecurityManager()).isEqualTo(this.mockSecurityManager);
|
||||
}
|
||||
|
||||
@PeerCacheApplication(logLevel = GEMFIRE_LOG_LEVEL, useBeanFactoryLocator = true)
|
||||
@EnableSecurity(securityManagerClassName =
|
||||
"org.springframework.geode.security.support.SecurityManagerProxy")
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
org.apache.geode.security.SecurityManager mockSecurityManager(GemFireCache gemfireCache) {
|
||||
return mock(org.apache.geode.security.SecurityManager.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright 2018 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.geode.security.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.security.ResourcePermission;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SecurityManagerProxy}
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.security.Principal
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.geode.security.support.SecurityManagerProxy
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class SecurityManagerProxyUnitTests {
|
||||
|
||||
@Test
|
||||
public void setAndGetSecurityManager() {
|
||||
|
||||
org.apache.geode.security.SecurityManager mockSecurityManager =
|
||||
mock(org.apache.geode.security.SecurityManager.class);
|
||||
|
||||
SecurityManagerProxy securityManagerProxy = new SecurityManagerProxy();
|
||||
|
||||
securityManagerProxy.setSecurityManager(mockSecurityManager);
|
||||
|
||||
assertThat(securityManagerProxy.getSecurityManager()).isEqualTo(mockSecurityManager);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setSecurityManagerToNullThrowsIllegalArgumentException() {
|
||||
|
||||
try {
|
||||
new SecurityManagerProxy().setSecurityManager(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("SecurityManager must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getSecurityManagerWhenUninitializedThrowsIllegalStateException() {
|
||||
|
||||
try {
|
||||
new SecurityManagerProxy().getSecurityManager();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("No SecurityManager configured");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateDelegatesToConfiguredSecurityManager() {
|
||||
|
||||
Properties securityProperties = new Properties();
|
||||
|
||||
org.apache.geode.security.SecurityManager mockSecurityManager =
|
||||
mock(org.apache.geode.security.SecurityManager.class);
|
||||
|
||||
when(mockSecurityManager.authenticate(any(Properties.class))).thenReturn("TestUser");
|
||||
|
||||
SecurityManagerProxy securityManagerProxy = new SecurityManagerProxy();
|
||||
|
||||
securityManagerProxy.setSecurityManager(mockSecurityManager);
|
||||
|
||||
assertThat(securityManagerProxy.getSecurityManager()).isEqualTo(mockSecurityManager);
|
||||
assertThat(securityManagerProxy.authenticate(securityProperties)).isEqualTo("TestUser");
|
||||
|
||||
verify(mockSecurityManager, times(1)).authenticate(eq(securityProperties));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authorizeDelegatesToConfiguredSecurityManager() {
|
||||
|
||||
Principal mockPrincipal = mock(Principal.class);
|
||||
|
||||
ResourcePermission resourcePermission =
|
||||
new ResourcePermission(ResourcePermission.Resource.DATA, ResourcePermission.Operation.READ);
|
||||
|
||||
org.apache.geode.security.SecurityManager mockSecurityManager =
|
||||
mock(org.apache.geode.security.SecurityManager.class);
|
||||
|
||||
when(mockSecurityManager.authorize(any(Object.class), any(ResourcePermission.class))).thenReturn(true);
|
||||
|
||||
SecurityManagerProxy securityManagerProxy = new SecurityManagerProxy();
|
||||
|
||||
securityManagerProxy.setSecurityManager(mockSecurityManager);
|
||||
|
||||
assertThat(securityManagerProxy.getSecurityManager()).isEqualTo(mockSecurityManager);
|
||||
assertThat(securityManagerProxy.authorize(mockPrincipal, resourcePermission)).isTrue();
|
||||
|
||||
verify(mockSecurityManager, times(1))
|
||||
.authorize(eq(mockPrincipal), eq(resourcePermission));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void closeDelegatesToConfiguredSecurityManager() {
|
||||
|
||||
org.apache.geode.security.SecurityManager mockSecurityManager =
|
||||
mock(org.apache.geode.security.SecurityManager.class);
|
||||
|
||||
when(mockSecurityManager.authorize(any(Object.class), any(ResourcePermission.class))).thenReturn(true);
|
||||
|
||||
SecurityManagerProxy securityManagerProxy = new SecurityManagerProxy();
|
||||
|
||||
securityManagerProxy.setSecurityManager(mockSecurityManager);
|
||||
|
||||
assertThat(securityManagerProxy.getSecurityManager()).isEqualTo(mockSecurityManager);
|
||||
|
||||
securityManagerProxy.close();
|
||||
|
||||
verify(mockSecurityManager, times(1)).close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
# Spring Boot application.properties for testing Apache Geode/Pivotal GemFire Security in a cloud context.
|
||||
|
||||
vcap.application.application_id=c50bb519-2739-4fa3-8750-02c051e35735
|
||||
vcap.application.application_name=boot-test
|
||||
vcap.application.application_uris=boot-test.apps.tunis.cf-app.com
|
||||
vcap.application.application_uris[0]=boot-test.apps.tunis.cf-app.com
|
||||
vcap.application.cf_api=https://api.sys.tunis.cf-app.com
|
||||
vcap.application.host=0.0.0.0
|
||||
vcap.application.instance_id=babcf301-3b34-4dcf-720e-ccfc
|
||||
vcap.application.instance_index=0
|
||||
vcap.application.limits.disk=1024
|
||||
vcap.application.limits.fds=16384
|
||||
vcap.application.limits.mem=1024
|
||||
vcap.application.name=boot-test
|
||||
vcap.application.port=8080
|
||||
vcap.application.space_id=271cf083-7855-4b5e-be19-65342d099099
|
||||
vcap.application.space_name=jblum-space
|
||||
vcap.application.uris=boot-test.apps.tunis.cf-app.com
|
||||
vcap.application.uris[0]=boot-test.apps.tunis.cf-app.com
|
||||
vcap.application.version=d34bbbbd-c35c-4057-baf2-6300cb9aa2aa
|
||||
vcap.application.application_version=d34bbbbd-c35c-4057-baf2-6300cb9aa2aa
|
||||
|
||||
vcap.services.jblum-pcc.credentials.distributed_system_id=0
|
||||
vcap.services.jblum-pcc.credentials.locators=localhost[55221]
|
||||
vcap.services.jblum-pcc.credentials.locators[0]=10.0.8.19[55221]
|
||||
vcap.services.jblum-pcc.credentials.locators[1]=10.0.8.21[55221]
|
||||
vcap.services.jblum-pcc.credentials.locators[2]=10.0.8.20[55221]
|
||||
#vcap.services.jblum-pcc.credentials.urls.gfsh=http://cloudcache-9defb33a-6b8b-49f0-bd35-cf6f7b2f222f.sys.tunis.cf-app.com/gemfire/v1
|
||||
vcap.services.jblum-pcc.credentials.urls.pulse=http://cloudcache-9defb33a-6b8b-49f0-bd35-cf6f7b2f222f.sys.tunis.cf-app.com/pulse
|
||||
vcap.services.jblum-pcc.credentials.users={password=vaxAi8UuJkBp9csgDvJ5YA, roles=[cluster_operator], username=cluster_operator_CQhqoDaEIT1gobjLryfpBg},{password=egSyyyaM5Q5yUMOVZD6pXA, roles=[developer], username=developer_krCFKddILf8EfWs0laUQ}
|
||||
vcap.services.jblum-pcc.credentials.users[0].username=cluster_operator_CQhqoDaEIT1gobjLryfpBg
|
||||
vcap.services.jblum-pcc.credentials.users[0].password=vaxAi8UuJkBp9csgDvJ5YA
|
||||
vcap.services.jblum-pcc.credentials.users[0].roles=cluster_operator
|
||||
vcap.services.jblum-pcc.credentials.users[0].roles[0]=cluster_operator
|
||||
vcap.services.jblum-pcc.credentials.users[1].username=developer_krCFKddILf8EfWs0laUQ
|
||||
vcap.services.jblum-pcc.credentials.users[1].password=egSyyyaM5Q5yUMOVZD6pXA
|
||||
vcap.services.jblum-pcc.credentials.users[1].roles=developer
|
||||
vcap.services.jblum-pcc.credentials.users[1].roles[0]=developer
|
||||
vcap.services.jblum-pcc.credentials.wan.sender_credentials.active.username=gateway_sender_UJ0YO1pJBEnQP03yt7sVXQ
|
||||
vcap.services.jblum-pcc.credentials.wan.sender_credentials.active.password=tYHFwByaMN675FuBWDZQiQ
|
||||
vcap.services.jblum-pcc.label=p-cloudcache
|
||||
vcap.services.jblum-pcc.name=jblum-pcc
|
||||
vcap.services.jblum-pcc.plan=small
|
||||
vcap.services.jblum-pcc.provider=
|
||||
vcap.services.jblum-pcc.syslog_drain_url=
|
||||
vcap.services.jblum-pcc.tags=gemfire,cloudcache,database,pivotal
|
||||
vcap.services.jblum-pcc.tags[0]=gemfire
|
||||
vcap.services.jblum-pcc.tags[1]=cloudcache
|
||||
vcap.services.jblum-pcc.tags[2]=database
|
||||
vcap.services.jblum-pcc.tags[3]=pivotal
|
||||
vcap.services.jblum-pcc.volume_mounts=
|
||||
|
||||
security.context.username.property=${vcap.services.jblum-pcc.credentials.users[0].username}
|
||||
security.context.password.property=${vcap.services.jblum-pcc.credentials.users[0].password}
|
||||
@@ -0,0 +1,4 @@
|
||||
# Spring Boot application.properties for testing Apache Geode/Pivotal GemFire Security in a local context.
|
||||
|
||||
spring.data.gemfire.security.username=ghostrider
|
||||
spring.data.gemfire.security.password=p@55w0rd
|
||||
@@ -0,0 +1,4 @@
|
||||
# Spring Boot application.properties for testing Apache Geode/Pivotal GemFire Security in a local context.
|
||||
|
||||
security.context.username.property=ghostrider
|
||||
security.context.password.property=p@55w0rd
|
||||
@@ -0,0 +1,5 @@
|
||||
# Spring Boot application.properties for testing Apache Geode/Pivotal GemFire SSL
|
||||
|
||||
spring.boot.data.gemfire.security.ssl.keystore.name=test-trusted.keystore
|
||||
spring.data.gemfire.security.ssl.keystore.password=s3cr3t
|
||||
spring.data.gemfire.security.ssl.truststore.password=s3cr3t
|
||||
@@ -0,0 +1,4 @@
|
||||
# Spring Boot application.properties for testing security in a Pivotal CloudFoundry (PCF) context.
|
||||
|
||||
VCAP_APPLICATION={"application_id":"c50bb519-2739-4fa3-8750-02c051e35735","application_name":"boot-test","application_uris":["boot-example.apps.tunis.cf-app.com"],"application_version":"d34bbbbd-c35c-4057-baf2-6300cb9aa2aa","cf_api":"https://api.sys.tunis.cf-app.com","host":"0.0.0.0","instance_id":"babcf301-3b34-4dcf-720e-ccfc","instance_index":0,"limits":{"disk":1024,"fds":16384,"mem":1024},"name":"boot-example","port":8080,"space_id":"271cf083-7855-4b5e-be19-65342d099099","space_name":"jblum-space","uris":["boot-example.apps.tunis.cf-app.com"],"version":"d34bbbbd-c35c-4057-baf2-6300cb9aa2aa"}
|
||||
VCAP_SERVICES={"p-cloudcache":[{ "credentials": { "distributed_system_id": "0", "locators": [ "localhost[55221]" ], "urls": { "pulse": "http://cloudcache-9defb33a-6b8b-49f0-bd35-cf6f7b2f222f.sys.tunis.cf-app.com/pulse" }, "users": [ { "password": "vaxAi8UuJkBp9csgDvJ5YA", "roles": [ "cluster_operator" ], "username": "cluster_operator_CQhqoDaEIT1gobjLryfpBg" }, { "password": "egSyyyaM5Q5yUMOVZD6pXA", "roles": [ "developer" ], "username": "developer_krCFKddILf8EfWs0laUQ" } ], "wan": { "sender_credentials": { "active": { "password": "tYHFwByaMN675FuBWDZQiQ", "username": "gateway_sender_UJ0YO1pJBEnQP03yt7sVXQ" } } } }, "syslog_drain_url": null, "volume_mounts": [ ], "label": "p-cloudcache", "provider": null, "plan": "small", "name": "jblum-pcc", "tags": [ "gemfire", "cloudcache", "database", "pivotal" ] }]}
|
||||
BIN
geode-spring-boot/src/test/resources/test-trusted.keystore
Normal file
BIN
geode-spring-boot/src/test/resources/test-trusted.keystore
Normal file
Binary file not shown.
Reference in New Issue
Block a user