/atlassian-plugins-servlet/src/test/java/com/atlassian/plugin/servlet/filter/TestDelegatingPluginFilter.java
https://bitbucket.org/purewind/atlassian-plugins · Java · 199 lines · 174 code · 21 blank · 4 comment · 0 complexity · d90b8e71a98d3a6fd5ded1e8c4f23151 MD5 · raw file
- package com.atlassian.plugin.servlet.filter;
- import com.atlassian.plugin.IllegalPluginStateException;
- import com.atlassian.plugin.Plugin;
- import com.atlassian.plugin.PluginArtifact;
- import com.atlassian.plugin.classloader.PluginClassLoader;
- import com.atlassian.plugin.impl.DefaultDynamicPlugin;
- import com.atlassian.plugin.servlet.descriptors.ServletFilterModuleDescriptor;
- import com.atlassian.plugin.servlet.descriptors.ServletFilterModuleDescriptorBuilder;
- import com.atlassian.plugin.servlet.filter.FilterTestUtils.FilterAdapter;
- import com.atlassian.plugin.test.PluginJarBuilder;
- import org.junit.Before;
- import org.junit.Rule;
- import org.junit.Test;
- import org.junit.rules.ExpectedException;
- import org.junit.runner.RunWith;
- import org.mockito.Mock;
- import org.mockito.runners.MockitoJUnitRunner;
- import javax.servlet.Filter;
- import javax.servlet.FilterChain;
- import javax.servlet.ServletException;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.File;
- import java.io.IOException;
- import static com.atlassian.plugin.servlet.filter.FilterTestUtils.emptyChain;
- import static com.atlassian.plugin.servlet.filter.FilterTestUtils.newList;
- import static com.atlassian.plugin.test.PluginTestUtils.getFileForResource;
- import static org.hamcrest.MatcherAssert.assertThat;
- import static org.hamcrest.Matchers.is;
- import static org.mockito.Mockito.mock;
- import static org.mockito.Mockito.when;
- @RunWith(MockitoJUnitRunner.class)
- public class TestDelegatingPluginFilter {
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
- @Mock
- private HttpServletRequest httpServletRequest;
- @Mock
- private HttpServletResponse httpServletResponse;
- @Before
- public void setUp() throws Exception {
- when(httpServletRequest.getPathInfo()).thenReturn("/servlet");
- }
- @Test
- public void testPluginClassLoaderIsThreadContextClassLoaderWhenFiltering() throws Exception {
- createClassLoaderCheckingFilter("filter").doFilter(httpServletRequest, httpServletResponse, emptyChain);
- }
- @Test
- public void testClassLoaderResetDuringFilterChainExecution() throws Exception {
- final ClassLoader initialClassLoader = Thread.currentThread().getContextClassLoader();
- final FilterChain chain = new FilterChain() {
- public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse)
- throws IOException, ServletException {
- assertThat(Thread.currentThread().getContextClassLoader(), is(initialClassLoader));
- }
- };
- createClassLoaderCheckingFilter("filter").doFilter(httpServletRequest, httpServletResponse, chain);
- }
- @Test
- public void testPluginClassLoaderIsThreadContextLoaderWhenFiltersInChainAreFromDifferentPlugins() throws Exception {
- final Iterable<Filter> filters = newList(
- createClassLoaderCheckingFilter("filter-1"),
- createClassLoaderCheckingFilter("filter-2"),
- createClassLoaderCheckingFilter("filter-3")
- );
- final FilterChain chain = new IteratingFilterChain(filters.iterator(), emptyChain);
- chain.doFilter(httpServletRequest, httpServletResponse);
- }
- @Test
- public void testPluginClassLoaderIsRestoredProperlyWhenAnExceptionIsThrownFromFilter() throws Exception {
- final Iterable<Filter> filters = newList(
- createClassLoaderCheckingFilter("filter-1"),
- createClassLoaderCheckingFilter("filter-2"),
- createExceptionThrowingFilter("exception-filter"),
- createClassLoaderCheckingFilter("filter-3")
- );
- final FilterChain chain = new IteratingFilterChain(filters.iterator(), new FilterChain() {
- public void doFilter(final ServletRequest request, final ServletResponse response)
- throws IOException, ServletException {
- throw new ServletException("Exception should be thrown before reaching here.");
- }
- });
- expectedException.expect(ServletException.class);
- expectedException.expectMessage("exception-filter");
- chain.doFilter(httpServletRequest, httpServletResponse);
- }
- @Test
- public void pluginCanBeUninstalledFromFilterChain() throws Exception {
- final Plugin plugin = mock(Plugin.class);
- when(plugin.getClassLoader()).thenReturn(Thread.currentThread().getContextClassLoader());
- final FilterAdapter filter = new FilterAdapter() {
- @Override
- public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
- throws IOException, ServletException {
- chain.doFilter(request, response);
- }
- };
- final ServletFilterModuleDescriptor servletFilterModuleDescriptor = mock(ServletFilterModuleDescriptor.class);
- when(servletFilterModuleDescriptor.getPlugin()).thenReturn(plugin);
- when(servletFilterModuleDescriptor.getModule()).thenReturn(filter);
- // This boolean is a poor man's spy to check that the meat of the test is called. There doesn't seem to be a
- // natural mock to verify, and adding a spy for it feels perverse when the code is just here.
- final boolean chainCalled[] = {false};
- final FilterChain chain = new FilterChain() {
- public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse)
- throws IOException, ServletException {
- // Pretend this chain uninstalls the plugin, which means, among other things, that you
- // can't get the classloader any more
- when(plugin.getClassLoader()).thenThrow(new IllegalPluginStateException("Plugin Uninstalled"));
- chainCalled[0] = true;
- }
- };
- final DelegatingPluginFilter delegatingPluginFilter = new DelegatingPluginFilter(servletFilterModuleDescriptor);
- delegatingPluginFilter.doFilter(httpServletRequest, httpServletResponse, chain);
- assertThat(chainCalled[0], is(true));
- }
- private Filter createClassLoaderCheckingFilter(final String name) throws Exception {
- final File pluginFile = new PluginJarBuilder()
- .addFormattedJava("my.SimpleFilter",
- "package my;" +
- "import java.io.IOException;" +
- "import javax.servlet.Filter;" +
- "import javax.servlet.FilterChain;" +
- "import javax.servlet.FilterConfig;" +
- "import javax.servlet.ServletException;" +
- "import javax.servlet.ServletRequest;" +
- "import javax.servlet.ServletResponse;" +
- "" +
- "public class SimpleFilter implements Filter" +
- "{" +
- " String name;" +
- " public void init(FilterConfig filterConfig) throws ServletException" +
- " {" +
- " name = filterConfig.getInitParameter('name');" +
- " }" +
- "" +
- " public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException" +
- " {" +
- " response.getWriter().write('entered: ' + name + '\');" +
- " chain.doFilter(request, response);" +
- " response.getWriter().write('exiting: ' + name + '\');" +
- " }" +
- " public void destroy() {}" +
- "}")
- .addFile("atlassian-plugin.xml", getFileForResource("com/atlassian/plugin/servlet/filter/atlassian-plugin-filter.xml"))
- .build();
- final PluginClassLoader pluginClassLoader = new PluginClassLoader(pluginFile);
- final PluginArtifact pluginArtifact = mock(PluginArtifact.class);
- final Plugin plugin = new DefaultDynamicPlugin(pluginArtifact, pluginClassLoader);
- final FilterAdapter testFilter = new FilterAdapter() {
- @Override
- public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
- throws IOException, ServletException {
- assertThat(name + " plugin ClassLoader should be current when entering",
- Thread.currentThread().getContextClassLoader(), is((ClassLoader) pluginClassLoader));
- chain.doFilter(request, response);
- assertThat(name + " plugin ClassLoader should be current when exiting",
- Thread.currentThread().getContextClassLoader(), is((ClassLoader) pluginClassLoader));
- }
- };
- final ServletFilterModuleDescriptor filterDescriptor = new ServletFilterModuleDescriptorBuilder()
- .with(testFilter)
- .with(plugin)
- .build();
- return new DelegatingPluginFilter(filterDescriptor);
- }
- private Filter createExceptionThrowingFilter(final String name) {
- return new FilterAdapter() {
- @Override
- public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
- throws IOException, ServletException {
- throw new ServletException(name);
- }
- };
- }
- }