SGF-729 - Realign SSL configuration using @EnableSsl with Apache Geode's SSL configuration properties.

This commit is contained in:
John Blum
2018-03-30 13:36:26 -07:00
parent d200f8ebfa
commit 989a556c67
18 changed files with 810 additions and 424 deletions

View File

@@ -17,13 +17,17 @@
package org.springframework.data.gemfire.config.annotation;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
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 java.util.Arrays;
import org.apache.shiro.util.Assert;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -47,122 +51,165 @@ import org.springframework.context.annotation.Import;
public @interface EnableSsl {
/**
* A space-separated list of the valid SSL ciphers for secure Socket connections. A setting of 'any'
* uses any ciphers that are enabled by default in the configured JSSE provider.
* Configures the SSL ciphers used for secure Socket connections as an array of valid {@link String cipher names}.
*
* A setting of {@literal any} uses any ciphers that are enabled by default in the configured JSSE provider.
*
* Defaults to {@literal any}.
*
* Use either the {@literal spring.data.gemfire.security.ssl.<component>.ciphers} property
* or the {@literal spring.data.gemfire.security.ssl.ciphers} property
* Use the {@literal spring.data.gemfire.security.ssl.ciphers} property
* in {@literal application.properties}.
*/
String ciphers() default "any";
String[] ciphers() default { "any" };
/**
* An array of Pivotal GemFire/Apache Geode Components in which SSL can be enabled.
* Configures the Pivotal GemFire/Apache Geode components for which SSL will be enabled.
*
* Defaults to {@link EnableSsl.Component#CLUSTER}.
* Defaults to {@link EnableSsl.Component#ALL}.
*
* The value(s) for this attribute are used to configure cluster-wide
* (e.g. {@literal spring.data.gemfire.security.ssl.cluster.keystore} SSL properties
* or individual component {e.g. {@literal spring.data.gemfire.security.ssl.locator.keystore}} SSL properties.
* Use the {@literal spring.data.gemfire.security.ssl.components} property
* in {@literal application.properties}.
*
* E.g. {@literal spring.data.gemfire.security.ssl.components=cluster,gateway,locator,server}.
*/
Component[] components() default { Component.CLUSTER };
Component[] components() default { Component.ALL };
/**
* Pathname to the keystore used for SSL communications.
* Configures the {@link String names} of all the individual {@literal Keystore} certificates to use
* when configuring SSL for each Pivotal GemFire/Apache Geode {@link Component} separately.
*
* Each {@link Component} defaults to the configured value of the {@link #defaultCertificateAlias()}
* if not individually configured with this attribute.
*
* Use {@literal spring.data.gemfire.security.ssl.certificate.alias.<component>}
* in {@literal application.properties}.
*
* E.g. {@literal spring.data.gemfire.security.ssl.certificate.alias.gateway=WanCert}.
*/
ComponentAlias[] componentCertificateAliases() default {};
/**
* Configures the default {@link String name} of a single {@literal Keystore} certificate to use
* when configuring SSL for all Pivotal GemFire/Apache Geode {@link Component components} collectively.
*
* If {@code defaultAlias} is not specified, then the first certificate in the {@literal Keystore}
* acts as the {@literal default} SSL certificate.
*
* Use the {@literal spring.data.gemfire.security.ssl.certificate.alias.default} property
* in {@literal application.properties}.
*/
String defaultCertificateAlias() default "";
/**
* Pathname to the {@literal Keystore} used for SSL communications.
*
* Defaults to unset.
*
* Use either the {@literal spring.data.gemfire.security.ssl.<component>.keystore} property
* or the {@literal spring.data.gemfire.security.ssl.keystore} property
* Use the {@literal spring.data.gemfire.security.ssl.keystore} property
* in {@literal application.properties}.
*/
String keystore() default "";
/**
* Password to access the keys in the keystore used in SSL communications.
* Password to access the keys in the {@literal Keystore} used for SSL communications.
*
* Defaults to unset.
*
* Use either the {@literal spring.data.gemfire.security.ssl.<component>.keystore-password} property
* or the {@literal spring.data.gemfire.security.ssl.keystore-password} property
* Use the {@literal spring.data.gemfire.security.ssl.keystore.password} property
* in {@literal application.properties}.
*/
String keystorePassword() default "";
/**
* TODO change to an enum?
* Identifies the type of {@literal Keystore} used for SSL communications.
*
* Identifies the type of keystore used in SSL communications. For example, JKS, PKCS11, etc.
* For example: {@literal JKS}, {@literal PKCS11}, etc.
*
* Defaults to unset.
* Defaults to {@literal JKS}, or the {@literal Java Keystore}.
*
* Use either the {@literal spring.data.gemfire.security.ssl.<component>.keystore-type} property
* or the {@literal spring.data.gemfire.security.ssl.keystore-type} property
* Use the {@literal spring.data.gemfire.security.ssl.keystore.type} property
* in {@literal application.properties}.
*/
String keystoreType() default "";
String keystoreType() default "JKS";
/**
* A space-separated list of the valid SSL protocols used in secure Socket connections. A setting of 'any'
* uses any protocol that is enabled by default in the configured JSSE provider.
* Configures the SSL protocols used for secure Socket connections as an array of
* valid {@link String protocol names}.
*
* A setting of {@literal any} uses any protocol that is enabled by default in the configured JSSE provider.
*
* Defaults to {@literal any}.
*
* Use either the {@literal spring.data.gemfire.security.ssl.<component>.protocols} property
* or the {@literal spring.data.gemfire.security.ssl.protocols} property
* Use the {@literal spring.data.gemfire.security.ssl.protocols} property
* in {@literal application.properties}.
*/
String protocols() default "any";
String[] protocols() default { "any" };
/**
* Boolean value indicating whether to require authentication for SSL communication between peers,
* clients and servers, gateways, etc.
* Boolean value indicating whether to require authentication for SSL communication between clients, servers,
* gateways, etc.
*
* Defaults to {@literal true}.
*
* Use either the {@literal spring.data.gemfire.security.ssl.<component>.require-authentication} property
* or the {@literal spring.data.gemfire.security.ssl.require-authentication} property
* Use the {@literal spring.data.gemfire.security.ssl.require-authentication} property
* in {@literal application.properties}.
*/
boolean requireAuthentication() default true;
/**
* Pathname to the truststore used in SSL communications.
* Pathname to the truststore used for SSL communications.
*
* Defaults to unset.
*
* Use either the {@literal spring.data.gemfire.security.ssl.<component>.truststore} property
* or the {@literal spring.data.gemfire.security.ssl.truststore} property
* Use the {@literal spring.data.gemfire.security.ssl.truststore} property
* in {@literal application.properties}.
*/
String truststore() default "";
/**
* Password to access the keys in the truststore used in SSL communications.
* Password to access the keys in the truststore used for SSL communications.
*
* Defaults to unset.
*
* Use either the {@literal spring.data.gemfire.security.ssl.<component>.truststore-password} property
* or the {@literal spring.data.gemfire.security.ssl.truststore-password} property
* Use the {@literal spring.data.gemfire.security.ssl.truststore.password} property
* in {@literal application.properties}.
*/
String truststorePassword() default "";
/**
* If {@literal true} then requires two-way authentication for web component.
*
* Defaults to {@literal false}.
*
* Use the {@literal spring.data.gemfire.security.ssl.web-require-authentication}
* in {@literal application.properties}.
*/
boolean webRequireAuthentication() default false;
enum Component {
ALL("all"),
CLUSTER("cluster"),
GATEWAY("gateway"),
HTTP("http-service"),
JMX("jmx-manager"),
JMX("jmx"),
LOCATOR("locator"),
SERVER("server");
SERVER("server"),
WEB("web");
public static Component valueOfName(String name) {
return Arrays.stream(values())
.filter(component -> component.name().equalsIgnoreCase(String.valueOf(name).trim()))
.findFirst()
.orElseThrow(() -> newIllegalArgumentException("Name [%s] is not a valid component", name));
}
private final String prefix;
/* (non-Javadoc) */
Component(String prefix) {
Assert.hasText(prefix, "Prefix is required");
this.prefix = prefix;
}
@@ -174,7 +221,15 @@ public @interface EnableSsl {
*/
@Override
public String toString() {
return prefix;
return this.prefix;
}
}
@interface ComponentAlias {
String alias();
Component component();
}
}

View File

@@ -17,24 +17,27 @@
package org.springframework.data.gemfire.config.annotation;
import static java.util.Arrays.stream;
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport;
import org.springframework.data.gemfire.util.CollectionUtils;
import org.springframework.data.gemfire.util.PropertiesBuilder;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* The {@link SslConfiguration} class is a Spring {@link ImportBeanDefinitionRegistrar} that applies
* additional configuration using Pivotal GemFire/Apache Geode {@link Properties} to configure SSL.
*
* @author John Blum
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar
* @see org.springframework.data.gemfire.config.annotation.EnableSsl
* @see org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport
* @since 1.9.0
@@ -42,77 +45,111 @@ import org.springframework.util.ObjectUtils;
public class SslConfiguration extends EmbeddedServiceConfigurationSupport {
/**
* Returns the {@link EnableSsl} {@link java.lang.annotation.Annotation} {@link Class} type.
* Returns the {@link EnableSsl} {@link Annotation} {@link Class type}.
*
* @return the {@link EnableSsl} {@link java.lang.annotation.Annotation} {@link Class} type.
* @return the {@link EnableSsl} {@link Annotation} {@link Class type}.
* @see org.springframework.data.gemfire.config.annotation.EnableSsl
*/
@Override
protected Class getAnnotationType() {
protected Class<? extends Annotation> getAnnotationType() {
return EnableSsl.class;
}
/* (non-Javadoc) */
@Override
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {
protected Properties toGemFireProperties(Map<String, Object> annotationAttributesMap) {
AnnotationAttributes annotationAttributes = AnnotationAttributes.fromMap(annotationAttributesMap);
PropertiesBuilder gemfireProperties = PropertiesBuilder.create();
EnableSsl.Component[] components = (EnableSsl.Component[]) annotationAttributes.get("components");
Set<EnableSsl.Component> components = resolveComponents(annotationAttributes);
if (ObjectUtils.isEmpty(components)) {
logWarning("SSL will not be configured; No SSL enabled Components %s were specified",
Arrays.toString(EnableSsl.Component.values()));
}
gemfireProperties.setProperty("ssl-enabled-components",
StringUtils.collectionToCommaDelimitedString(components.stream()
.map(EnableSsl.Component::toString)
.collect(Collectors.toSet())))
stream(nullSafeArray(components, EnableSsl.Component.class)).forEach(component ->
.setProperty("ssl-ciphers", resolveProperty(sslProperty("ciphers"),
StringUtils.arrayToCommaDelimitedString(annotationAttributes.getStringArray("ciphers"))))
gemfireProperties.setProperty(String.format("%s-ssl-ciphers", component),
resolveProperty(componentSslProperty(component.toString(), "ciphers"),
resolveProperty(sslProperty("ciphers"),
(String) annotationAttributes.get("ciphers"))))
.setPropertyIfNotDefault("ssl-default-alias",
resolveProperty(sslProperty("certificate.alias.default"),
annotationAttributes.getString("defaultCertificateAlias")), "")
.setProperty(String.format("%s-ssl-enabled", component),
resolveProperty(componentSslProperty(component.toString(), "enabled"),
resolveProperty(sslProperty("enabled"), true)))
.setProperty("ssl-keystore", resolveProperty(sslProperty("keystore"),
annotationAttributes.getString("keystore")))
.setProperty(String.format("%s-ssl-keystore", component),
resolveProperty(componentSslProperty(component.toString(), "keystore"),
resolveProperty(sslProperty("keystore"),
(String) annotationAttributes.get("keystore"))))
.setProperty("ssl-keystore-password", resolveProperty(sslProperty("keystore.password"),
annotationAttributes.getString("keystorePassword")))
.setProperty(String.format("%s-ssl-keystore-password", component),
resolveProperty(componentSslProperty(component.toString(), "keystore-password"),
resolveProperty(sslProperty("keystore-password"),
(String) annotationAttributes.get("keystorePassword"))))
.setProperty("ssl-keystore-type", resolveProperty(sslProperty("keystore.type"),
annotationAttributes.getString("keystoreType")))
.setProperty(String.format("%s-ssl-keystore-type", component),
resolveProperty(componentSslProperty(component.toString(), "keystore-type"),
resolveProperty(sslProperty("keystore-type"),
(String) annotationAttributes.get("keystoreType"))))
.setProperty("ssl-protocols", resolveProperty(sslProperty("protocols"),
StringUtils.arrayToCommaDelimitedString(annotationAttributes.getStringArray("protocols"))))
.setProperty(String.format("%s-ssl-protocols", component),
resolveProperty(componentSslProperty(component.toString(), "protocols"),
resolveProperty(sslProperty("protocols"),
(String) annotationAttributes.get("protocols"))))
.setProperty("ssl-require-authentication",
resolveProperty(sslProperty("require-authentication"),
annotationAttributes.getBoolean("requireAuthentication")))
.setProperty(String.format("%s-ssl-require-authentication", component),
resolveProperty(componentSslProperty(component.toString(), "require-authentication"),
resolveProperty(sslProperty("require-authentication"),
Boolean.TRUE.equals(annotationAttributes.get("requireAuthentication")))))
.setProperty("ssl-truststore", resolveProperty(sslProperty("truststore"),
annotationAttributes.getString("truststore")))
.setProperty(String.format("%s-ssl-truststore", component),
resolveProperty(componentSslProperty(component.toString(), "truststore"),
resolveProperty(sslProperty("truststore"),
(String) annotationAttributes.get("truststore"))))
.setProperty("ssl-truststore-password", resolveProperty(sslProperty("truststore.password"),
annotationAttributes.getString("truststorePassword")))
.setProperty(String.format("%s-ssl-truststore-password", component),
resolveProperty(componentSslProperty(component.toString(), "truststore-password"),
resolveProperty(sslProperty("truststore-password"),
(String) annotationAttributes.get("truststorePassword"))))
.setProperty("ssl-web-require-authentication",
resolveProperty(sslProperty("web-require-authentication"),
annotationAttributes.getBoolean("webRequireAuthentication")));
);
configureComponentCertificateAliases(annotationAttributes, gemfireProperties);
return gemfireProperties.build();
}
private Set<EnableSsl.Component> resolveComponents(AnnotationAttributes annotationAttributes) {
Set<EnableSsl.Component> components =
Arrays.stream(Optional.of(resolveProperty(sslProperty("components"), ""))
.filter(StringUtils::hasText)
.map(StringUtils::commaDelimitedListToStringArray)
.orElseGet(() -> new String[0]))
.map(EnableSsl.Component::valueOfName)
.collect(Collectors.toSet());
components = components.isEmpty()
? CollectionUtils.asSet((EnableSsl.Component[]) annotationAttributes.get("components"))
: components;
components = components.isEmpty() ? Collections.singleton(EnableSsl.Component.ALL) : components;
return components;
}
private void configureComponentCertificateAliases(AnnotationAttributes annotationAttributes,
PropertiesBuilder gemfireProperties) {
AnnotationAttributes[] componentCertificateAliases =
annotationAttributes.getAnnotationArray("componentCertificateAliases");
Arrays.stream(componentCertificateAliases).forEach(aliasAttributes -> {
EnableSsl.Component component = aliasAttributes.getEnum("component");
String alias = aliasAttributes.getString("alias");
gemfireProperties.setProperty(String.format("ssl-%s-alias", component), alias);
});
Arrays.stream(EnableSsl.Component.values()).forEach(component -> {
String propertyNameSuffix = String.format("certificate.alias.%s", component);
Optional.ofNullable(resolveProperty(sslProperty(propertyNameSuffix), ""))
.filter(StringUtils::hasText)
.ifPresent(alias ->
gemfireProperties.setProperty(String.format("ssl-%s-alias", component),
StringUtils.trimWhitespace(alias)));
});
}
}

View File

@@ -435,7 +435,8 @@ public abstract class AbstractAnnotationConfigSupport
* @see #getBeanClassLoader()
*/
protected ClassLoader resolveBeanClassLoader() {
return Optional.ofNullable(getBeanClassLoader()).orElseGet(() -> Thread.currentThread().getContextClassLoader());
return Optional.ofNullable(getBeanClassLoader())
.orElseGet(() -> Thread.currentThread().getContextClassLoader());
}
/**
@@ -640,12 +641,10 @@ public abstract class AbstractAnnotationConfigSupport
return beanDefinition;
}
/* (non-Javadoc) */
protected List<String> arrayOfPropertyNamesFor(String propertyNamePrefix) {
return arrayOfPropertyNamesFor(propertyNamePrefix, null);
}
/* (non-Javadoc) */
protected List<String> arrayOfPropertyNamesFor(String propertyNamePrefix, String propertyNameSuffix) {
List<String> propertyNames = new ArrayList<>();
@@ -666,139 +665,107 @@ public abstract class AbstractAnnotationConfigSupport
return propertyNames;
}
/* (non-Javadoc) */
protected String asArrayProperty(String propertyNamePrefix, int index, String propertyNameSuffix) {
return String.format("%1$s[%2$d]%3$s", propertyNamePrefix, index,
Optional.ofNullable(propertyNameSuffix).filter(StringUtils::hasText).map("."::concat).orElse(""));
}
/* (non-Javadoc) */
protected String cacheProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("cache."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String cacheClientProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("cache.client."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String cacheCompressionProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("cache.compression."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String cacheOffHeapProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("cache.off-heap."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String cachePeerProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("cache.peer."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String cacheServerProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("cache.server."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String namedCacheServerProperty(String name, String propertyNameSuffix) {
return String.format("%1$s%2$s.%3$s", propertyName("cache.server."), name, propertyNameSuffix);
}
/* (non-Javadoc) */
protected String clusterProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("cluster."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String diskStoreProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("disk.store."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String namedDiskStoreProperty(String name, String propertyNameSuffix) {
return String.format("%1$s%2$s.%3$s", propertyName("disk.store."), name, propertyNameSuffix);
}
/* (non-Javadoc) */
protected String entitiesProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("entities."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String locatorProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("locator."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String loggingProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("logging."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String managementProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("management."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String managerProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("manager."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String pdxProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("pdx."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String poolProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("pool."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String namedPoolProperty(String name, String propertyNameSuffix) {
return String.format("%1$s%2$s.%3$s", propertyName("pool."), name, propertyNameSuffix);
}
/* (non-Javadoc) */
protected String securityProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("security."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String sslProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", securityProperty("ssl."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String componentSslProperty(String component, String propertyNameSuffix) {
return String.format("%1$s%2$s.%3$s", securityProperty("ssl."),
component, propertyNameSuffix);
}
/* (non-Javadoc) */
protected String statsProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("stats."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String serviceProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", propertyName("service."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String redisServiceProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", serviceProperty("redis."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String memcachedServiceProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", serviceProperty("memcached."), propertyNameSuffix);
}
/* (non-Javadoc) */
protected String httpServiceProperty(String propertyNameSuffix) {
return String.format("%1$s%2$s", serviceProperty("http."), propertyNameSuffix);
}
@@ -1056,8 +1023,12 @@ public abstract class AbstractAnnotationConfigSupport
return Optional.ofNullable(getEnvironment())
.filter(environment -> environment.containsProperty(propertyName))
.map(environment -> environment.getProperty(environment.resolveRequiredPlaceholders(propertyName),
targetType, defaultValue))
.map(environment -> {
String resolvedPropertyName = environment.resolveRequiredPlaceholders(propertyName);
return environment.getProperty(resolvedPropertyName, targetType, defaultValue);
})
.orElse(defaultValue);
}

View File

@@ -38,8 +38,6 @@ import org.springframework.util.StringUtils;
@SuppressWarnings("unused")
public class PropertiesBuilder implements FactoryBean<Properties> {
private final Properties properties;
/**
* Factory method to create a default {@link PropertiesBuilder} instance.
*
@@ -73,13 +71,14 @@ public class PropertiesBuilder implements FactoryBean<Properties> {
* @see java.util.Properties#load(InputStream)
*/
public static PropertiesBuilder from(InputStream in) {
try {
Properties defaults = new Properties();
defaults.load(in);
return new PropertiesBuilder(defaults);
}
catch (IOException e) {
throw new IllegalArgumentException("Failed to read properties from InputStream", e);
catch (IOException cause) {
throw new IllegalArgumentException("Failed to read properties from InputStream", cause);
}
}
@@ -94,13 +93,14 @@ public class PropertiesBuilder implements FactoryBean<Properties> {
* @see java.util.Properties#load(Reader)
*/
public static PropertiesBuilder from(Reader reader) {
try {
Properties defaults = new Properties();
defaults.load(reader);
return new PropertiesBuilder(defaults);
}
catch (IOException e) {
throw new IllegalArgumentException("Failed to read properties from Reader", e);
catch (IOException cause) {
throw new IllegalArgumentException("Failed to read properties from Reader", cause);
}
}
@@ -116,16 +116,19 @@ public class PropertiesBuilder implements FactoryBean<Properties> {
* @see java.util.Properties#loadFromXML(InputStream)
*/
public static PropertiesBuilder fromXml(InputStream xml) {
try {
Properties defaults = new Properties();
defaults.loadFromXML(xml);
return new PropertiesBuilder(defaults);
}
catch (IOException e) {
throw new IllegalArgumentException("Failed to read properties from XML", e);
catch (IOException cause) {
throw new IllegalArgumentException("Failed to read properties from XML", cause);
}
}
private final Properties properties;
/**
* Constructs an instance of the {@link PropertiesBuilder} class.
*/
@@ -172,7 +175,7 @@ public class PropertiesBuilder implements FactoryBean<Properties> {
*/
@Override
public Class<?> getObjectType() {
return (this.properties != null ? this.properties.getClass() : Properties.class);
return this.properties != null ? this.properties.getClass() : Properties.class;
}
/*
@@ -193,6 +196,7 @@ public class PropertiesBuilder implements FactoryBean<Properties> {
* @see java.util.Properties
*/
public PropertiesBuilder add(Properties properties) {
if (!CollectionUtils.isEmpty(properties)) {
this.properties.putAll(properties);
}
@@ -209,7 +213,7 @@ public class PropertiesBuilder implements FactoryBean<Properties> {
* @see org.springframework.data.gemfire.util.PropertiesBuilder
*/
public PropertiesBuilder add(PropertiesBuilder builder) {
return (builder != null ? add(builder.build()) : this);
return builder != null ? add(builder.build()) : this;
}
/**
@@ -221,7 +225,7 @@ public class PropertiesBuilder implements FactoryBean<Properties> {
* @see #setProperty(String, String)
*/
public PropertiesBuilder setProperty(String name, Object value) {
return (value != null ? setProperty(name, value.toString()) : this);
return value != null ? setProperty(name, value.toString()) : this;
}
/**
@@ -235,8 +239,7 @@ public class PropertiesBuilder implements FactoryBean<Properties> {
* @see #setProperty(String, String)
*/
public PropertiesBuilder setProperty(String name, Object[] values) {
return (!ObjectUtils.isEmpty(values) ? setProperty(name, StringUtils.arrayToCommaDelimitedString(values))
: this);
return !ObjectUtils.isEmpty(values) ? setProperty(name, StringUtils.arrayToCommaDelimitedString(values)) : this;
}
/**
@@ -251,6 +254,7 @@ public class PropertiesBuilder implements FactoryBean<Properties> {
* @see java.util.Properties#setProperty(String, String)
*/
public PropertiesBuilder setProperty(String name, String value) {
Assert.hasText(name, String.format("Name [%s] must be specified", name));
if (isValuable(value)) {
@@ -273,7 +277,7 @@ public class PropertiesBuilder implements FactoryBean<Properties> {
* @see #setProperty(String, Object)
*/
public <T> PropertiesBuilder setPropertyIfNotDefault(String name, Object value, T defaultValue) {
return (defaultValue == null || !defaultValue.equals(value) ? setProperty(name, value) : this);
return defaultValue == null || !defaultValue.equals(value) ? setProperty(name, value) : this;
}
/**
@@ -284,8 +288,11 @@ public class PropertiesBuilder implements FactoryBean<Properties> {
* @throws IllegalArgumentException if the property name is not specified.
*/
public PropertiesBuilder unsetProperty(String name) {
Assert.hasText(name, String.format("Name [%s] mut be specified", name));
this.properties.setProperty(name, "");
return this;
}
@@ -298,7 +305,7 @@ public class PropertiesBuilder implements FactoryBean<Properties> {
* @return a boolean value indicating whether the given {@link String} value is a valid {@link Properties} value.
*/
protected boolean isValuable(String value) {
return (StringUtils.hasText(value) && !"null".equalsIgnoreCase(value.trim()));
return StringUtils.hasText(value) && !"null".equalsIgnoreCase(value.trim());
}
/**