Rename modules.
Rename geode-spring-boot to spring-geode. Rename geode-spring-boot-autoconfigure to spring-geode-autoconfigure. Rename geode-spring-boot-starter to spring-geode-starter. Rename gemfire-spring-boot-starter to spring-gemfire-starter. Resolves GitHub Issue #6.
This commit is contained in:
40
spring-geode/src/main/java/org/springframework/geode/cache/support/CacheLoaderSupport.java
vendored
Normal file
40
spring-geode/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,131 @@
|
||||
/*
|
||||
* 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.shiro.util.Assert;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
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.config.annotation.ClientCacheConfigurer;
|
||||
import org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer;
|
||||
import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport;
|
||||
|
||||
/**
|
||||
* The {@link DistributedSystemIdConfiguration} class is a Spring {@link Configuration} class used to configure
|
||||
* the {@literal distributed-system-id} for a {@link Cache peer Cache member} in a cluster
|
||||
* when using the P2P topology.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.context.annotation.ImportAware
|
||||
* @see org.springframework.core.annotation.AnnotationAttributes
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @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.UseDistributedSystemId
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@SuppressWarnings("unused")
|
||||
public class DistributedSystemIdConfiguration extends AbstractAnnotationConfigSupport implements ImportAware {
|
||||
|
||||
private static final String GEMFIRE_DISTRIBUTED_SYSTEM_ID_PROPERTY = "distributed-system-id";
|
||||
|
||||
private Integer distributedSystemId;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotationType() {
|
||||
return UseDistributedSystemId.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
|
||||
if (isAnnotationPresent(importMetadata)) {
|
||||
|
||||
AnnotationAttributes distributedSystemIdAttributes = getAnnotationAttributes(importMetadata);
|
||||
|
||||
setDistributedSystemId(distributedSystemIdAttributes.containsKey("value")
|
||||
? distributedSystemIdAttributes.getNumber("value") : null);
|
||||
|
||||
setDistributedSystemId(distributedSystemIdAttributes.containsKey("id")
|
||||
? distributedSystemIdAttributes.getNumber("id") : null);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setDistributedSystemId(Integer distributedSystemId) {
|
||||
|
||||
this.distributedSystemId = Optional.ofNullable(distributedSystemId)
|
||||
.filter(id -> id > -1)
|
||||
.orElse(this.distributedSystemId);
|
||||
}
|
||||
|
||||
protected Optional<Integer> getDistributedSystemId() {
|
||||
|
||||
return Optional.ofNullable(this.distributedSystemId)
|
||||
.filter(id -> id > -1);
|
||||
}
|
||||
|
||||
protected Logger getLogger() {
|
||||
return this.logger;
|
||||
}
|
||||
|
||||
private int validateDistributedSystemId(int distributedSystemId) {
|
||||
|
||||
Assert.isTrue(distributedSystemId >= -1 && distributedSystemId < 256,
|
||||
String.format("Distributed System ID [%d] must be between -1 and 255", distributedSystemId));
|
||||
|
||||
return distributedSystemId;
|
||||
}
|
||||
|
||||
@Bean
|
||||
ClientCacheConfigurer clientCacheDistributedSystemIdConfigurer() {
|
||||
|
||||
return (beanName, clientCacheFactoryBean) -> getDistributedSystemId().ifPresent(distributedSystemId -> {
|
||||
|
||||
Logger logger = getLogger();
|
||||
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Distributed System Id [{}] was set on the ClientCache instance, which will not have any effect",
|
||||
distributedSystemId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Bean
|
||||
PeerCacheConfigurer peerCacheDistributedSystemIdConfigurer() {
|
||||
|
||||
return (beanName, cacheFactoryBean) ->
|
||||
getDistributedSystemId().ifPresent(id -> cacheFactoryBean.getProperties()
|
||||
.setProperty(GEMFIRE_DISTRIBUTED_SYSTEM_ID_PROPERTY,
|
||||
String.valueOf(validateDistributedSystemId(id))));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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.client.ClientCache;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
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.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 DurableClientConfiguration} class is a Spring {@link Configuration} class used to configure
|
||||
* this {@link ClientCache} instance as a {@literal Durable Client} by setting the {@literal durable-client-id}
|
||||
* and {@literal durable-client-timeout} properties in addition to enabling {@literal keepAlive}
|
||||
* on {@link ClientCache} shutdown.
|
||||
*
|
||||
* @author John Blum
|
||||
* @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.core.annotation.AnnotationAttributes
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @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.EnableDurableClient
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@SuppressWarnings("unused")
|
||||
public class DurableClientConfiguration extends AbstractAnnotationConfigSupport implements ImportAware {
|
||||
|
||||
public static final boolean DEFAULT_KEEP_ALIVE = true;
|
||||
public static final boolean DEFAULT_READY_FOR_EVENTS = true;
|
||||
|
||||
public static final int DEFAULT_DURABLE_CLIENT_TIMEOUT = 300;
|
||||
|
||||
private Boolean keepAlive = DEFAULT_KEEP_ALIVE;
|
||||
private Boolean readyForEvents = DEFAULT_READY_FOR_EVENTS;
|
||||
|
||||
private Integer durableClientTimeout = DEFAULT_DURABLE_CLIENT_TIMEOUT;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private String durableClientId;
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotationType() {
|
||||
return EnableDurableClient.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
|
||||
if (isAnnotationPresent(importMetadata)) {
|
||||
|
||||
AnnotationAttributes enableDurableClientAttributes = getAnnotationAttributes(importMetadata);
|
||||
|
||||
this.durableClientId = enableDurableClientAttributes.containsKey("id")
|
||||
? enableDurableClientAttributes.getString("id")
|
||||
: null;
|
||||
|
||||
this.durableClientTimeout = enableDurableClientAttributes.containsKey("timeout")
|
||||
? enableDurableClientAttributes.getNumber("timeout")
|
||||
: DEFAULT_DURABLE_CLIENT_TIMEOUT;
|
||||
|
||||
this.keepAlive = enableDurableClientAttributes.containsKey("keepAlive")
|
||||
? enableDurableClientAttributes.getBoolean("keepAlive")
|
||||
: DEFAULT_KEEP_ALIVE;
|
||||
|
||||
this.readyForEvents = enableDurableClientAttributes.containsKey("readyForEvents")
|
||||
? enableDurableClientAttributes.getBoolean("readyForEvents")
|
||||
: DEFAULT_READY_FOR_EVENTS;
|
||||
}
|
||||
}
|
||||
|
||||
protected Optional<String> getDurableClientId() {
|
||||
|
||||
return Optional.ofNullable(this.durableClientId)
|
||||
.filter(StringUtils::hasText);
|
||||
}
|
||||
|
||||
protected Integer getDurableClientTimeout() {
|
||||
|
||||
return Optional.ofNullable(this.durableClientTimeout)
|
||||
.orElse(DEFAULT_DURABLE_CLIENT_TIMEOUT);
|
||||
}
|
||||
|
||||
protected Boolean getKeepAlive() {
|
||||
|
||||
return Optional.ofNullable(this.keepAlive)
|
||||
.orElse(DEFAULT_KEEP_ALIVE);
|
||||
}
|
||||
|
||||
protected Boolean getReadyForEvents() {
|
||||
|
||||
return Optional.ofNullable(this.readyForEvents)
|
||||
.orElse(DEFAULT_READY_FOR_EVENTS);
|
||||
}
|
||||
|
||||
protected Logger getLogger() {
|
||||
return this.logger;
|
||||
}
|
||||
|
||||
@Bean
|
||||
ClientCacheConfigurer clientCacheDurableClientConfigurer() {
|
||||
|
||||
return (beanName, clientCacheFactoryBean) -> getDurableClientId().ifPresent(durableClientId -> {
|
||||
|
||||
clientCacheFactoryBean.setDurableClientId(durableClientId);
|
||||
clientCacheFactoryBean.setDurableClientTimeout(getDurableClientTimeout());
|
||||
clientCacheFactoryBean.setKeepAlive(getKeepAlive());
|
||||
clientCacheFactoryBean.setReadyForEvents(getReadyForEvents());
|
||||
});
|
||||
}
|
||||
|
||||
@Bean
|
||||
PeerCacheConfigurer peerCacheDurableClientConfigurer() {
|
||||
|
||||
return (beanName, cacheFactoryBean) -> getDurableClientId().ifPresent(durableClientId -> {
|
||||
|
||||
Logger logger = getLogger();
|
||||
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Durable Client ID [{}] was set on a peer Cache instance, which will not have any effect",
|
||||
durableClientId);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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.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.client.ClientCache;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* The {@link EnableDurableClient} annotation configures a {@link ClientCache} instance as a {@literal Durable Client}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.annotation.Documented
|
||||
* @see java.lang.annotation.Inherited
|
||||
* @see java.lang.annotation.Retention
|
||||
* @see java.lang.annotation.Target
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.geode.config.annotation.DurableClientConfiguration
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@Import(DurableClientConfiguration.class)
|
||||
@SuppressWarnings("unused")
|
||||
public @interface EnableDurableClient {
|
||||
|
||||
/**
|
||||
* Used only for clients in a client/server installation. If set, this indicates that the client is durable
|
||||
* and identifies the client. The ID is used by servers to reestablish any messaging that was interrupted
|
||||
* by client downtime.
|
||||
*/
|
||||
String id();
|
||||
|
||||
/**
|
||||
* Configure whether the server should keep the durable client's queues alive for the timeout period.
|
||||
*
|
||||
* Defaults to {@literal true}.
|
||||
*/
|
||||
boolean keepAlive() default DurableClientConfiguration.DEFAULT_KEEP_ALIVE;
|
||||
|
||||
/**
|
||||
* Configures whether the {@link ClientCache} is ready to recieve events on startup.
|
||||
*
|
||||
* Defaults to {@literal true}.
|
||||
*/
|
||||
boolean readyForEvents() default DurableClientConfiguration.DEFAULT_READY_FOR_EVENTS;
|
||||
|
||||
/**
|
||||
* Used only for clients in a client/server installation. Number of seconds this client can remain disconnected
|
||||
* from its server and have the server continue to accumulate durable events for it.
|
||||
*
|
||||
* Defaults to {@literal 300 seconds}, or {@literal 5 minutes}.
|
||||
*/
|
||||
int timeout() default DurableClientConfiguration.DEFAULT_DURABLE_CLIENT_TIMEOUT;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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 GroupsConfiguration} class is a Spring {@link Configuration} class used to configure the {@literal groups}
|
||||
* in which is member belongs in an Apache Geode/Pivotal GemFire distributed system, whether the member
|
||||
* is a {@link ClientCache} in a client/server topology or a {@link Cache peer Cache} in a cluster
|
||||
* using the P2P topology.
|
||||
*
|
||||
* @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.core.annotation.AnnotationAttributes
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @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.UseGroups
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@SuppressWarnings("unused")
|
||||
public class GroupsConfiguration extends AbstractAnnotationConfigSupport implements ImportAware {
|
||||
|
||||
private static final String GEMFIRE_GROUPS_PROPERTY = "groups";
|
||||
|
||||
private String[] groups = {};
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotationType() {
|
||||
return UseGroups.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
|
||||
if (isAnnotationPresent(importMetadata)) {
|
||||
|
||||
AnnotationAttributes inGroupsAttributes = getAnnotationAttributes(importMetadata);
|
||||
|
||||
setGroups(inGroupsAttributes.containsKey("value")
|
||||
? inGroupsAttributes.getStringArray("value") : null);
|
||||
|
||||
setGroups(inGroupsAttributes.containsKey("groups")
|
||||
? inGroupsAttributes.getStringArray("groups") : null);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setGroups(String[] groups) {
|
||||
|
||||
this.groups = Optional.ofNullable(groups)
|
||||
.filter(it -> it.length > 0)
|
||||
.orElse(this.groups);
|
||||
}
|
||||
|
||||
protected Optional<String[]> getGroups() {
|
||||
|
||||
return Optional.ofNullable(this.groups)
|
||||
.filter(it -> it.length > 0);
|
||||
}
|
||||
|
||||
@Bean
|
||||
ClientCacheConfigurer clientCacheGroupsConfigurer() {
|
||||
return (beaName, clientCacheFactoryBean) -> configureGroups(clientCacheFactoryBean);
|
||||
}
|
||||
|
||||
@Bean
|
||||
PeerCacheConfigurer peerCacheGroupsConfigurer() {
|
||||
return (beaName, peerCacheFactoryBean) -> configureGroups(peerCacheFactoryBean);
|
||||
}
|
||||
|
||||
private void configureGroups(CacheFactoryBean cacheFactoryBean) {
|
||||
getGroups().ifPresent(groups -> cacheFactoryBean.getProperties()
|
||||
.setProperty(GEMFIRE_GROUPS_PROPERTY, StringUtils.arrayToCommaDelimitedString(groups)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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 configure
|
||||
* an Apache Geode or Pivotal GemFire's member name in the distributed system, whether the member
|
||||
* is a {@link ClientCache client} in the client/server topology or a {@link Cache peer} in a cluster
|
||||
* using the P2P topology.
|
||||
*
|
||||
* @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.core.annotation.AnnotationAttributes
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @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
|
||||
@SuppressWarnings("all")
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
|
||||
if (isAnnotationPresent(importMetadata)) {
|
||||
|
||||
AnnotationAttributes memberNameAttributes = getAnnotationAttributes(importMetadata);
|
||||
|
||||
setMemberName(memberNameAttributes.containsKey("value")
|
||||
? memberNameAttributes.getString("value") : null);
|
||||
|
||||
setMemberName(memberNameAttributes.containsKey("name")
|
||||
? memberNameAttributes.getString("name") : null);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setMemberName(String memberName) {
|
||||
|
||||
this.memberName = Optional.ofNullable(memberName)
|
||||
.filter(StringUtils::hasText)
|
||||
.orElse(this.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,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.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 UseDistributedSystemId} annotation configures the {@literal distributed-system-id} property
|
||||
* of a {@link Cache peer Cache member} in an Apache Geode/Pivotal GemFire P2P topology.
|
||||
*
|
||||
* This configuration annotation is only applicable on {@link Cache peer Cache members}
|
||||
* and has no effect on {@link ClientCache} instances.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.annotation.Documented
|
||||
* @see java.lang.annotation.Inherited
|
||||
* @see java.lang.annotation.Retention
|
||||
* @see java.lang.annotation.Target
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.core.annotation.AliasFor
|
||||
* @see org.springframework.geode.config.annotation.DistributedSystemIdConfiguration
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@Import(DistributedSystemIdConfiguration.class)
|
||||
@SuppressWarnings("unused")
|
||||
public @interface UseDistributedSystemId {
|
||||
|
||||
/**
|
||||
* Configures the identifier used to distinguish messages from different distributed systems.
|
||||
*
|
||||
* This is required for Portable Data eXchange (PDX) data serialization.
|
||||
*
|
||||
* Set distributed-system-id to different values for different systems in a multi-site (WAN) configuration,
|
||||
* and to different values for production vs. development environments. This setting must be the same
|
||||
* for every member of a given distributed system and unique to each distributed system within a WAN installation.
|
||||
*
|
||||
* Valid values are integers in the range -1…255. -1 means no setting.
|
||||
*
|
||||
* Defaults to {@literal -1}.
|
||||
*/
|
||||
@AliasFor("id")
|
||||
int value() default -1;
|
||||
|
||||
/**
|
||||
* Configures the identifier used to distinguish messages from different distributed systems.
|
||||
*
|
||||
* Alias for {@literal #value()}.
|
||||
*/
|
||||
@AliasFor("value")
|
||||
int id() default -1;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 UseGroups} annotation configures the groups in which the member belongs in an Apache Geode
|
||||
* or Pivotal GemFire distributed system, whether the member is a {@link ClientCache} in a client/server topology
|
||||
* or a {@link Cache peer Cache} in a cluster using the P2P topology.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.annotation.Documented
|
||||
* @see java.lang.annotation.Inherited
|
||||
* @see java.lang.annotation.Retention
|
||||
* @see java.lang.annotation.Target
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.core.annotation.AliasFor
|
||||
* @see org.springframework.geode.config.annotation.GroupsConfiguration
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@Import(GroupsConfiguration.class)
|
||||
@SuppressWarnings("unused")
|
||||
public @interface UseGroups {
|
||||
|
||||
@AliasFor("groups")
|
||||
String[] value() default {};
|
||||
|
||||
@AliasFor("value")
|
||||
String[] groups() default {};
|
||||
|
||||
}
|
||||
@@ -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.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 Cache member} in the cluster using the P2P topology.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.annotation.Documented
|
||||
* @see java.lang.annotation.Inherited
|
||||
* @see java.lang.annotation.Retention
|
||||
* @see java.lang.annotation.Target
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.core.annotation.AliasFor
|
||||
* @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
spring-geode/src/main/java/org/springframework/geode/core/env/VcapPropertySource.java
vendored
Normal file
239
spring-geode/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
spring-geode/src/main/java/org/springframework/geode/core/env/support/CloudCacheService.java
vendored
Normal file
345
spring-geode/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
spring-geode/src/main/java/org/springframework/geode/core/env/support/Service.java
vendored
Normal file
70
spring-geode/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
spring-geode/src/main/java/org/springframework/geode/core/env/support/User.java
vendored
Normal file
182
spring-geode/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,85 @@
|
||||
/*
|
||||
* 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.config;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.execute.Execution;
|
||||
import org.apache.geode.cache.execute.Function;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.StandardAnnotationMetadata;
|
||||
import org.springframework.data.gemfire.function.config.AbstractFunctionExecutionConfigurationSource;
|
||||
import org.springframework.data.gemfire.function.config.AnnotationFunctionExecutionConfigurationSource;
|
||||
import org.springframework.data.gemfire.function.config.FunctionExecutionBeanDefinitionRegistrar;
|
||||
|
||||
/**
|
||||
* The {@link AbstractFunctionExecutionAutoConfigurationExtension} class extends SDG's {@link FunctionExecutionBeanDefinitionRegistrar}
|
||||
* to redefine the location of application POJO {@link Function} {@link Execution} interfaces.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.execute.Execution
|
||||
* @see org.apache.geode.cache.execute.Function
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.boot.autoconfigure.AutoConfigurationPackages
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @see org.springframework.data.gemfire.function.config.FunctionExecutionBeanDefinitionRegistrar
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public abstract class AbstractFunctionExecutionAutoConfigurationExtension
|
||||
extends FunctionExecutionBeanDefinitionRegistrar implements BeanFactoryAware {
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@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();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
protected AbstractFunctionExecutionConfigurationSource newAnnotationBasedFunctionExecutionConfigurationSource(
|
||||
AnnotationMetadata annotationMetadata) {
|
||||
|
||||
StandardAnnotationMetadata metadata =
|
||||
new StandardAnnotationMetadata(getConfiguration(), true);
|
||||
|
||||
return new AnnotationFunctionExecutionConfigurationSource(metadata) {
|
||||
|
||||
@Override
|
||||
public Iterable<String> getBasePackages() {
|
||||
return AutoConfigurationPackages.get(getBeanFactory());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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.function.config;
|
||||
|
||||
import org.apache.geode.cache.execute.Execution;
|
||||
import org.apache.geode.cache.execute.Function;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.data.gemfire.function.config.EnableGemfireFunctionExecutions;
|
||||
|
||||
/**
|
||||
* The {@link GemFireFunctionExecutionAutoConfigurationRegistrar} class is a Spring {@link ImportBeanDefinitionRegistrar}
|
||||
* used to register SDG POJO interfaces defining Apache Geode/Pivotal GemFire
|
||||
* {@link Function} {@link Execution Executions}
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.execute.Execution
|
||||
* @see org.apache.geode.cache.execute.Function
|
||||
* @see org.springframework.data.gemfire.function.config.EnableGemfireFunctionExecutions
|
||||
* @see org.springframework.geode.function.config.AbstractFunctionExecutionAutoConfigurationExtension
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class GemFireFunctionExecutionAutoConfigurationRegistrar
|
||||
extends AbstractFunctionExecutionAutoConfigurationExtension {
|
||||
|
||||
@Override
|
||||
protected Class<?> getConfiguration() {
|
||||
return EnableGemfireFunctionExecutionsConfiguration.class;
|
||||
}
|
||||
|
||||
@EnableGemfireFunctionExecutions
|
||||
private static class EnableGemfireFunctionExecutionsConfiguration { }
|
||||
|
||||
}
|
||||
@@ -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,163 @@
|
||||
/*
|
||||
* 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.DisposableBean;
|
||||
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, DisposableBean {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
super.destroy();
|
||||
INSTANCE.set(null);
|
||||
}
|
||||
}
|
||||
@@ -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.security.support;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.security.AuthenticationFailedException;
|
||||
import org.apache.geode.security.ResourcePermission;
|
||||
|
||||
/**
|
||||
* {@link SecurityManagerSupport} is an abstract base class implementing Apache Geode/Pivotal GemFire's
|
||||
* {@link org.apache.geode.security.SecurityManager} interface, providing default implementations of the
|
||||
* {@literal SecurityManager's} auth methods.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.security.SecurityManager
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class SecurityManagerSupport implements org.apache.geode.security.SecurityManager {
|
||||
|
||||
protected static final boolean DEFAULT_AUTHORIZATION = false;
|
||||
|
||||
@Override
|
||||
public void init(Properties securityProperties) { }
|
||||
|
||||
@Override
|
||||
public Object authenticate(Properties credentials) throws AuthenticationFailedException {
|
||||
return new AuthenticationFailedException("Authentication Provider Not Present");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authorize(Object principal, ResourcePermission permission) {
|
||||
return DEFAULT_AUTHORIZATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() { }
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user