Skip to content

Commit

Permalink
attempt to fix refresh event
Browse files Browse the repository at this point in the history
  • Loading branch information
ulibocchio committed Jun 1, 2020
1 parent 5487d28 commit c6a2e9e
Show file tree
Hide file tree
Showing 11 changed files with 143 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,73 +26,85 @@
@Slf4j
public class EncryptablePropertySourceConverter {

public static void convertPropertySources(InterceptionMode interceptionMode, List<Class<PropertySource<?>>> skipPropertySourceClasses, EncryptablePropertyResolver propertyResolver, EncryptablePropertyFilter propertyFilter, MutablePropertySources propSources) {
private final InterceptionMode interceptionMode;
private final List<Class<PropertySource<?>>> skipPropertySourceClasses;
private final EncryptablePropertyResolver propertyResolver;
private final EncryptablePropertyFilter propertyFilter;

public EncryptablePropertySourceConverter(InterceptionMode interceptionMode, List<Class<PropertySource<?>>> skipPropertySourceClasses, EncryptablePropertyResolver propertyResolver, EncryptablePropertyFilter propertyFilter) {
this.interceptionMode = interceptionMode;
this.skipPropertySourceClasses = skipPropertySourceClasses;
this.propertyResolver = propertyResolver;
this.propertyFilter = propertyFilter;
}

public void convertPropertySources(MutablePropertySources propSources) {
StreamSupport.stream(propSources.spliterator(), false)
.filter(ps -> !(ps instanceof EncryptablePropertySource))
.map(ps -> makeEncryptable(interceptionMode, skipPropertySourceClasses, propertyResolver, propertyFilter, ps))
.map(this::makeEncryptable)
.collect(toList())
.forEach(ps -> propSources.replace(ps.getName(), ps));
}

@SuppressWarnings("unchecked")
public static <T> PropertySource<T> makeEncryptable(InterceptionMode interceptionMode, List<Class<PropertySource<?>>> skipPropertySourceClasses, EncryptablePropertyResolver propertyResolver, EncryptablePropertyFilter propertyFilter, PropertySource<T> propertySource) {
public <T> PropertySource<T> makeEncryptable(PropertySource<T> propertySource) {
if (propertySource instanceof EncryptablePropertySource || skipPropertySourceClasses.stream().anyMatch(skipClass -> skipClass.equals(propertySource.getClass()))) {
log.info("Skipping PropertySource {} [{}", propertySource.getName(), propertySource.getClass());
return propertySource;
}
PropertySource<T> encryptablePropertySource = convertPropertySource(interceptionMode, propertyResolver, propertyFilter, propertySource);
PropertySource<T> encryptablePropertySource = convertPropertySource(propertySource);
log.info("Converting PropertySource {} [{}] to {}", propertySource.getName(), propertySource.getClass().getName(),
AopUtils.isAopProxy(encryptablePropertySource) ? "AOP Proxy" : encryptablePropertySource.getClass().getSimpleName());
return encryptablePropertySource;
}

public static MutablePropertySources proxyPropertySources(InterceptionMode interceptionMode, List<Class<PropertySource<?>>> skipPropertySourceClasses, EncryptablePropertyResolver propertyResolver, EncryptablePropertyFilter propertyFilter, MutablePropertySources propertySources, EnvCopy envCopy) {
public MutablePropertySources proxyPropertySources(MutablePropertySources propertySources, EnvCopy envCopy) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(MutablePropertySources.class);
proxyFactory.setProxyTargetClass(true);
proxyFactory.addInterface(PropertySources.class);
proxyFactory.setTarget(propertySources);
proxyFactory.addAdvice(new EncryptableMutablePropertySourcesInterceptor(interceptionMode, skipPropertySourceClasses, propertyResolver, propertyFilter, envCopy));
proxyFactory.addAdvice(new EncryptableMutablePropertySourcesInterceptor(this, envCopy));
return (MutablePropertySources) proxyFactory.getProxy();
}

private static <T> PropertySource<T> convertPropertySource(InterceptionMode interceptionMode, EncryptablePropertyResolver propertyResolver, EncryptablePropertyFilter propertyFilter, PropertySource<T> propertySource) {
private <T> PropertySource<T> convertPropertySource(PropertySource<T> propertySource) {
return interceptionMode == InterceptionMode.PROXY
? proxyPropertySource(propertySource, propertyResolver, propertyFilter) : instantiatePropertySource(propertySource, propertyResolver, propertyFilter);
? proxyPropertySource(propertySource) : instantiatePropertySource(propertySource);
}

@SuppressWarnings("unchecked")
private static <T> PropertySource<T> proxyPropertySource(PropertySource<T> propertySource, EncryptablePropertyResolver resolver, EncryptablePropertyFilter propertyFilter) {
private <T> PropertySource<T> proxyPropertySource(PropertySource<T> propertySource) {
//Silly Chris Beams for making CommandLinePropertySource getProperty and containsProperty methods final. Those methods
//can't be proxied with CGLib because of it. So fallback to wrapper for Command Line Arguments only.
if (CommandLinePropertySource.class.isAssignableFrom(propertySource.getClass())
// Other PropertySource classes like org.springframework.boot.env.OriginTrackedMapPropertySource
// are final classes as well
|| Modifier.isFinal(propertySource.getClass().getModifiers())) {
return instantiatePropertySource(propertySource, resolver, propertyFilter);
return instantiatePropertySource(propertySource);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTargetClass(propertySource.getClass());
proxyFactory.setProxyTargetClass(true);
proxyFactory.addInterface(EncryptablePropertySource.class);
proxyFactory.setTarget(propertySource);
proxyFactory.addAdvice(new EncryptablePropertySourceMethodInterceptor<>(propertySource, resolver, propertyFilter));
proxyFactory.addAdvice(new EncryptablePropertySourceMethodInterceptor<>(propertySource, propertyResolver, propertyFilter));
return (PropertySource<T>) proxyFactory.getProxy();
}

@SuppressWarnings({"unchecked", "rawtypes"})
private static <T> PropertySource<T> instantiatePropertySource(PropertySource<T> propertySource, EncryptablePropertyResolver resolver, EncryptablePropertyFilter propertyFilter) {
private <T> PropertySource<T> instantiatePropertySource(PropertySource<T> propertySource) {
PropertySource<T> encryptablePropertySource;
if (needsProxyAnyway(propertySource)) {
encryptablePropertySource = proxyPropertySource(propertySource, resolver, propertyFilter);
encryptablePropertySource = proxyPropertySource(propertySource);
} else if (propertySource instanceof SystemEnvironmentPropertySource) {
encryptablePropertySource = (PropertySource<T>) new EncryptableSystemEnvironmentPropertySourceWrapper((SystemEnvironmentPropertySource) propertySource, resolver, propertyFilter);
encryptablePropertySource = (PropertySource<T>) new EncryptableSystemEnvironmentPropertySourceWrapper((SystemEnvironmentPropertySource) propertySource, propertyResolver, propertyFilter);
} else if (propertySource instanceof MapPropertySource) {
encryptablePropertySource = (PropertySource<T>) new EncryptableMapPropertySourceWrapper((MapPropertySource) propertySource, resolver, propertyFilter);
encryptablePropertySource = (PropertySource<T>) new EncryptableMapPropertySourceWrapper((MapPropertySource) propertySource, propertyResolver, propertyFilter);
} else if (propertySource instanceof EnumerablePropertySource) {
encryptablePropertySource = new EncryptableEnumerablePropertySourceWrapper<>((EnumerablePropertySource) propertySource, resolver, propertyFilter);
encryptablePropertySource = new EncryptableEnumerablePropertySourceWrapper<>((EnumerablePropertySource) propertySource, propertyResolver, propertyFilter);
} else {
encryptablePropertySource = new EncryptablePropertySourceWrapper<>(propertySource, resolver, propertyFilter);
encryptablePropertySource = new EncryptablePropertySourceWrapper<>(propertySource, propertyResolver, propertyFilter);
}
return encryptablePropertySource;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,16 @@
*/
public class EncryptableMutablePropertySourcesInterceptor implements MethodInterceptor {

private final InterceptionMode interceptionMode;
private final List<Class<PropertySource<?>>> skipPropertySourceClasses;
private final EncryptablePropertyResolver resolver;
private final EncryptablePropertyFilter filter;
private final EncryptablePropertySourceConverter propertyConverter;
private final EnvCopy envCopy;

public EncryptableMutablePropertySourcesInterceptor(InterceptionMode interceptionMode, List<Class<PropertySource<?>>> skipPropertySourceClasses, EncryptablePropertyResolver resolver, EncryptablePropertyFilter filter, EnvCopy envCopy) {
this.interceptionMode = interceptionMode;
this.skipPropertySourceClasses = skipPropertySourceClasses;
this.resolver = resolver;
this.filter = filter;
public EncryptableMutablePropertySourcesInterceptor(EncryptablePropertySourceConverter propertyConverter, EnvCopy envCopy) {
this.propertyConverter = propertyConverter;
this.envCopy = envCopy;
}

private Object makeEncryptable(Object propertySource) {
return EncryptablePropertySourceConverter.makeEncryptable(interceptionMode, skipPropertySourceClasses, resolver, filter, (PropertySource<?>) propertySource);
return propertyConverter.makeEncryptable((PropertySource<?>) propertySource);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package com.ulisesbocchio.jasyptspringboot.caching;

import com.ulisesbocchio.jasyptspringboot.EncryptablePropertySource;
import com.ulisesbocchio.jasyptspringboot.EncryptablePropertySourceConverter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.PropertySources;
import org.springframework.core.env.*;
import org.springframework.util.ClassUtils;

@Order(Ordered.HIGHEST_PRECEDENCE)
Expand All @@ -20,9 +18,11 @@ public class RefreshScopeRefreshedEventListener implements ApplicationListener<A
public static final String REFRESHED_EVENT_CLASS = "org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent";
public static final String ENVIRONMENT_EVENT_CLASS = "org.springframework.cloud.context.environment.EnvironmentChangeEvent";
private final ConfigurableEnvironment environment;
private final EncryptablePropertySourceConverter converter;

public RefreshScopeRefreshedEventListener(ConfigurableEnvironment environment) {
public RefreshScopeRefreshedEventListener(ConfigurableEnvironment environment, EncryptablePropertySourceConverter converter) {
this.environment = environment;
this.converter = converter;
}

@Override
Expand All @@ -31,9 +31,15 @@ public void onApplicationEvent(ApplicationEvent event) {
if (isAssignable(ENVIRONMENT_EVENT_CLASS, event) || isAssignable(REFRESHED_EVENT_CLASS, event)) {
log.info("Refreshing cached encryptable property sources");
refreshCachedProperties();
decorateNewSources();
}
}

private void decorateNewSources() {
MutablePropertySources propSources = environment.getPropertySources();
converter.convertPropertySources(propSources);
}

boolean isAssignable(String className, Object value) {
try {
return ClassUtils.isAssignableValue(ClassUtils.forName(className, null), value);
Expand All @@ -52,7 +58,7 @@ private void refreshPropertySource(PropertySource<?> propertySource) {
if (propertySource instanceof CompositePropertySource) {
CompositePropertySource cps = (CompositePropertySource) propertySource;
cps.getPropertySources().forEach(this::refreshPropertySource);
} else if (propertySource instanceof EncryptablePropertySource){
} else if (propertySource instanceof EncryptablePropertySource) {
EncryptablePropertySource eps = (EncryptablePropertySource) propertySource;
eps.refresh();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.ulisesbocchio.jasyptspringboot.configuration;

import com.ulisesbocchio.jasyptspringboot.EncryptablePropertySourceConverter;
import com.ulisesbocchio.jasyptspringboot.caching.RefreshScopeRefreshedEventListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand All @@ -8,7 +9,7 @@
@Configuration
public class CachingConfiguration {
@Bean
public RefreshScopeRefreshedEventListener refreshScopeRefreshedEventListener(ConfigurableEnvironment environment) {
return new RefreshScopeRefreshedEventListener(environment);
public RefreshScopeRefreshedEventListener refreshScopeRefreshedEventListener(ConfigurableEnvironment environment, EncryptablePropertySourceConverter converter) {
return new RefreshScopeRefreshedEventListener(environment, converter);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package com.ulisesbocchio.jasyptspringboot.configuration;

import com.ulisesbocchio.jasyptspringboot.EncryptablePropertyFilter;
import com.ulisesbocchio.jasyptspringboot.EncryptablePropertyResolver;
import com.ulisesbocchio.jasyptspringboot.InterceptionMode;
import com.ulisesbocchio.jasyptspringboot.EncryptablePropertySourceConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
Expand All @@ -14,12 +13,6 @@
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;

import java.util.List;

import static com.ulisesbocchio.jasyptspringboot.EncryptablePropertySourceConverter.convertPropertySources;
import static com.ulisesbocchio.jasyptspringboot.configuration.EncryptablePropertyResolverConfiguration.FILTER_BEAN_NAME;
import static com.ulisesbocchio.jasyptspringboot.configuration.EncryptablePropertyResolverConfiguration.RESOLVER_BEAN_NAME;

/**
* <p>{@link BeanFactoryPostProcessor} that wraps all {@link PropertySource} defined in the {@link Environment}
* with {@link com.ulisesbocchio.jasyptspringboot.wrapper.EncryptablePropertySourceWrapper} and defines a default {@link
Expand All @@ -33,23 +26,19 @@
public class EnableEncryptablePropertiesBeanFactoryPostProcessor implements BeanFactoryPostProcessor, Ordered {

private static final Logger LOG = LoggerFactory.getLogger(EnableEncryptablePropertiesBeanFactoryPostProcessor.class);
private ConfigurableEnvironment environment;
private InterceptionMode interceptionMode;
private final List<Class<PropertySource<?>>> skipPropertySourceClasses;
private final ConfigurableEnvironment environment;
private final EncryptablePropertySourceConverter converter;

public EnableEncryptablePropertiesBeanFactoryPostProcessor(ConfigurableEnvironment environment, InterceptionMode interceptionMode, List<Class<PropertySource<?>>> skipPropertySourceClasses) {
public EnableEncryptablePropertiesBeanFactoryPostProcessor(ConfigurableEnvironment environment, EncryptablePropertySourceConverter converter) {
this.environment = environment;
this.interceptionMode = interceptionMode;
this.skipPropertySourceClasses = skipPropertySourceClasses;
this.converter = converter;
}

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
LOG.info("Post-processing PropertySource instances");
EncryptablePropertyResolver propertyResolver = beanFactory.getBean(RESOLVER_BEAN_NAME, EncryptablePropertyResolver.class);
EncryptablePropertyFilter propertyFilter = beanFactory.getBean(FILTER_BEAN_NAME, EncryptablePropertyFilter.class);
MutablePropertySources propSources = environment.getPropertySources();
convertPropertySources(interceptionMode, skipPropertySourceClasses, propertyResolver, propertyFilter, propSources);
converter.convertPropertySources(propSources);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.ulisesbocchio.jasyptspringboot.configuration;

import com.ulisesbocchio.jasyptspringboot.InterceptionMode;
import com.ulisesbocchio.jasyptspringboot.EncryptablePropertySourceConverter;
import lombok.extern.slf4j.Slf4j;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.config.StringPBEConfig;
Expand All @@ -12,10 +12,6 @@
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
* <p>Configuration class that registers a {@link BeanFactoryPostProcessor} that wraps all {@link PropertySource} defined in the {@link Environment}
* with {@link com.ulisesbocchio.jasyptspringboot.wrapper.EncryptablePropertySourceWrapper} and defines a default {@link StringEncryptor} for decrypting properties
Expand Down Expand Up @@ -62,26 +58,8 @@
@Slf4j
public class EnableEncryptablePropertiesConfiguration {

@SuppressWarnings("unchecked")
@Bean
public static EnableEncryptablePropertiesBeanFactoryPostProcessor enableEncryptablePropertySourcesPostProcessor(final ConfigurableEnvironment environment) {
final boolean proxyPropertySources = environment.getProperty("jasypt.encryptor.proxy-property-sources", Boolean.TYPE, false);
final List<String> skipPropertySources = (List<String>) environment.getProperty("jasypt.encryptor.skip-property-sources", List.class, Collections.EMPTY_LIST);
final List<Class<PropertySource<?>>> skipPropertySourceClasses = skipPropertySources.stream().map(EnableEncryptablePropertiesConfiguration::getPropertiesClass).collect(Collectors.toList());
final InterceptionMode interceptionMode = proxyPropertySources ? InterceptionMode.PROXY : InterceptionMode.WRAPPER;
return new EnableEncryptablePropertiesBeanFactoryPostProcessor(environment, interceptionMode, skipPropertySourceClasses);
}

@SuppressWarnings("unchecked")
private static Class<PropertySource<?>> getPropertiesClass(String className) {
try {
Class<?> clazz = Class.forName(className);
if (PropertySource.class.isAssignableFrom(clazz)) {
return (Class<PropertySource<?>>) clazz;
}
throw new IllegalArgumentException(String.format("Invalid jasypt.encryptor.skip-property-sources: Class %s does not implement %s", className, PropertySource.class.getName()));
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException(String.format("Invalid jasypt.encryptor.skip-property-sources: Class %s not found", className), e);
}
public static EnableEncryptablePropertiesBeanFactoryPostProcessor enableEncryptablePropertySourcesPostProcessor(final ConfigurableEnvironment environment, EncryptablePropertySourceConverter converter) {
return new EnableEncryptablePropertiesBeanFactoryPostProcessor(environment, converter);
}
}
Loading

0 comments on commit c6a2e9e

Please sign in to comment.