From eeda0a0991048ed901b3de4d417c6005ca605290 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 21 Apr 2020 11:23:45 +0100 Subject: [PATCH 1/3] Ignore STS-generated files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d37eb49a80be..ef6e41f01219 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ .#* .*.md.html .DS_Store +.attach_pid* .classpath .factorypath .gradle From b5f1bd415dea4918f39390d5d679e25648af5d4a Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 21 Apr 2020 11:23:48 +0100 Subject: [PATCH 2/3] Fix MustacheEnvironmentCollector to not ignore native fetcher When the context is a map (as it is in a web View for instance) you can't assume a non-null fetcher actually contains the property you are searching for. This change alters the logic so that the native fetcher is always consulted if it exists, but there is always a fallback. Fixes gh-21045 --- .../MustacheEnvironmentCollector.java | 29 ++++++++++++++++--- .../MustacheStandaloneIntegrationTests.java | 12 ++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheEnvironmentCollector.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheEnvironmentCollector.java index 0a58f4341ded..5698359d3564 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheEnvironmentCollector.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheEnvironmentCollector.java @@ -19,6 +19,7 @@ import com.samskivert.mustache.DefaultCollector; import com.samskivert.mustache.Mustache.Collector; import com.samskivert.mustache.Mustache.VariableFetcher; +import com.samskivert.mustache.Template; import org.springframework.context.EnvironmentAware; import org.springframework.core.env.ConfigurableEnvironment; @@ -35,8 +36,6 @@ public class MustacheEnvironmentCollector extends DefaultCollector implements En private ConfigurableEnvironment environment; - private final VariableFetcher propertyFetcher = new PropertyVariableFetcher(); - @Override public void setEnvironment(Environment environment) { this.environment = (ConfigurableEnvironment) environment; @@ -46,18 +45,40 @@ public void setEnvironment(Environment environment) { public VariableFetcher createFetcher(Object ctx, String name) { VariableFetcher fetcher = super.createFetcher(ctx, name); if (fetcher != null) { - return fetcher; + return new PropertyVariableFetcher(fetcher); } if (this.environment.containsProperty(name)) { - return this.propertyFetcher; + return new PropertyVariableFetcher(); } return null; } private class PropertyVariableFetcher implements VariableFetcher { + private final VariableFetcher nativeFetcher; + + PropertyVariableFetcher() { + this.nativeFetcher = null; + } + + PropertyVariableFetcher(VariableFetcher nativeFetcher) { + this.nativeFetcher = nativeFetcher; + } + @Override public Object get(Object ctx, String name) { + if (this.nativeFetcher != null) { + Object result; + try { + result = this.nativeFetcher.get(ctx, name); + if (result != null && result != Template.NO_FETCHER_FOUND) { + return result; + } + } + catch (Exception ex) { + // fall through + } + } return MustacheEnvironmentCollector.this.environment.getProperty(name); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheStandaloneIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheStandaloneIntegrationTests.java index 85bf79322e4e..26eac25584f2 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheStandaloneIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheStandaloneIntegrationTests.java @@ -60,11 +60,23 @@ void environmentCollectorCompoundKeyStandard() { .isEqualTo("Hello: There"); } + @Test + void environmentCollectorCompoundKeyStandardMap() { + assertThat(this.compiler.standardsMode(true).compile("Hello: {{env.foo}}") + .execute(Collections.singletonMap("world", "World"))).isEqualTo("Hello: There"); + } + @Test void environmentCollectorSimpleKey() { assertThat(this.compiler.compile("Hello: {{foo}}").execute(new Object())).isEqualTo("Hello: World"); } + @Test + void environmentCollectorSimpleKeyMap() { + assertThat(this.compiler.compile("Hello: {{foo}}").execute(Collections.singletonMap("world", "Foo"))) + .isEqualTo("Hello: World"); + } + @Configuration(proxyBeanMethods = false) @Import({ MustacheAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) static class Application { From 554599b252cfff748687f5dd7072a7ceba780d11 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 21 Apr 2020 14:21:29 +0100 Subject: [PATCH 3/3] Fix for _csrf.token style properties --- .../MustacheEnvironmentCollector.java | 8 ++++-- .../MustacheStandaloneIntegrationTests.java | 26 ++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheEnvironmentCollector.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheEnvironmentCollector.java index 5698359d3564..1abe4e3a57e6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheEnvironmentCollector.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheEnvironmentCollector.java @@ -67,8 +67,8 @@ private class PropertyVariableFetcher implements VariableFetcher { @Override public Object get(Object ctx, String name) { + Object result; if (this.nativeFetcher != null) { - Object result; try { result = this.nativeFetcher.get(ctx, name); if (result != null && result != Template.NO_FETCHER_FOUND) { @@ -79,7 +79,11 @@ public Object get(Object ctx, String name) { // fall through } } - return MustacheEnvironmentCollector.this.environment.getProperty(name); + result = MustacheEnvironmentCollector.this.environment.getProperty(name); + if (result == null) { + return Template.NO_FETCHER_FOUND; + } + return result; } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheStandaloneIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheStandaloneIntegrationTests.java index 26eac25584f2..620fe0efb2bb 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheStandaloneIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheStandaloneIntegrationTests.java @@ -37,7 +37,7 @@ * @author Dave Syer */ @DirtiesContext -@SpringBootTest(webEnvironment = WebEnvironment.NONE, properties = { "env.FOO=There", "foo=World" }) +@SpringBootTest(webEnvironment = WebEnvironment.NONE, properties = { "env.FOO=There", "foo=World", "bar.name=Bar" }) class MustacheStandaloneIntegrationTests { @Autowired @@ -66,6 +66,18 @@ void environmentCollectorCompoundKeyStandardMap() { .execute(Collections.singletonMap("world", "World"))).isEqualTo("Hello: There"); } + @Test + void environmentCollectorCompoundKeyWithBean() { + assertThat(this.compiler.compile("Hello: {{foo.name}}") + .execute(Collections.singletonMap("foo", new Foo()))).isEqualTo("Hello: Foo"); + } + + @Test + void environmentCollectorCompoundKeyWithBeanPrefersEnvironment() { + assertThat(this.compiler.compile("Hello: {{bar.name}}") + .execute(Collections.singletonMap("bar", new Foo()))).isEqualTo("Hello: Bar"); + } + @Test void environmentCollectorSimpleKey() { assertThat(this.compiler.compile("Hello: {{foo}}").execute(new Object())).isEqualTo("Hello: World"); @@ -82,5 +94,17 @@ void environmentCollectorSimpleKeyMap() { static class Application { } + + static class Foo { + private String name = "Foo"; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } }