Commit 5199c11e authored by Dave Syer's avatar Dave Syer Committed by Phillip Webb

Fix Mustache to not ignore native fetcher

Alter the logic of `MustacheEnvironmentCollector` so that the
native fetcher is always consulted if it exists.

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.

See gh-21060
parent e9e4a34e
......@@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.mustache;
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,19 +45,45 @@ public class MustacheEnvironmentCollector extends DefaultCollector implements En
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) {
return MustacheEnvironmentCollector.this.environment.getProperty(name);
Object result;
if (this.nativeFetcher != null) {
try {
result = this.nativeFetcher.get(ctx, name);
if (result != null && result != Template.NO_FETCHER_FOUND) {
return result;
}
}
catch (Exception ex) {
// fall through
}
}
result = MustacheEnvironmentCollector.this.environment.getProperty(name);
if (result == null) {
return Template.NO_FETCHER_FOUND;
}
return result;
}
}
......
......@@ -37,7 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @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
......@@ -60,15 +60,51 @@ class MustacheStandaloneIntegrationTests {
.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 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");
}
@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 {
}
static class Foo {
private String name = "Foo";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment