Close Reader used by MustacheViewResolver when compiling a Template

Previously, MustacheViewResolver would create an InputStreamReader
that wraps the template Resource's InputStream but would fail to close
the Reader. When the InputStream was a FileInputStream, this caused
the resolver to leak file handles.

This commit updates the resolver to close the Reader once the Template
has been compiled, thereby allowing any underlying resources to be
cleaned up immediately, rather than having to wait for the JVM to exit.

Closes gh-4921
This commit is contained in:
Andy Wilkinson 2016-01-15 11:19:24 +00:00
parent 681a866cce
commit b56eef236e
2 changed files with 37 additions and 3 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2016 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.
@ -106,7 +106,13 @@ public class MustacheViewResolver extends UrlBasedViewResolver {
}
private Template createTemplate(Resource resource) throws IOException {
return this.compiler.compile(getReader(resource));
Reader reader = getReader(resource);
try {
return this.compiler.compile(reader);
}
finally {
reader.close();
}
}
private Reader getReader(Resource resource) throws IOException {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2016 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.
@ -16,11 +16,14 @@
package org.springframework.boot.autoconfigure.mustache.web;
import java.io.InputStream;
import java.util.Locale;
import org.fusesource.hawtbuf.ByteArrayInputStream;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.io.Resource;
import org.springframework.mock.web.MockServletContext;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.servlet.View;
@ -29,11 +32,16 @@ import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link MustacheViewResolver}.
*
* @author Dave Syer
* @author Andy Wilkinson
*/
public class MustacheViewResolverTests {
@ -85,4 +93,24 @@ public class MustacheViewResolverTests {
}
@Test
public void templateResourceInputStreamIsClosed() throws Exception {
final Resource resource = mock(Resource.class);
given(resource.exists()).willReturn(true);
InputStream inputStream = new ByteArrayInputStream(new byte[0]);
InputStream spyInputStream = spy(inputStream);
given(resource.getInputStream()).willReturn(spyInputStream);
this.resolver = new MustacheViewResolver();
this.resolver.setApplicationContext(new StaticWebApplicationContext() {
@Override
public Resource getResource(String location) {
return resource;
}
});
this.resolver.loadView("foo", null);
verify(spyInputStream).close();
}
}