diff --git a/servlet/src/main/java/com/twelvemonkeys/servlet/image/IIOProviderContextListener.java b/servlet/src/main/java/com/twelvemonkeys/servlet/image/IIOProviderContextListener.java index 9dde9c09..531a74ea 100644 --- a/servlet/src/main/java/com/twelvemonkeys/servlet/image/IIOProviderContextListener.java +++ b/servlet/src/main/java/com/twelvemonkeys/servlet/image/IIOProviderContextListener.java @@ -37,6 +37,7 @@ import java.util.List; import javax.imageio.ImageIO; import javax.imageio.spi.IIORegistry; import javax.imageio.spi.ServiceRegistry; +import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; @@ -57,31 +58,38 @@ import javax.servlet.ServletContextListener; public final class IIOProviderContextListener implements ServletContextListener { public void contextInitialized(final ServletContextEvent event) { + event.getServletContext().log("Scanning for locally installed ImageIO plugin providers"); + // Registers all locally available IIO plugins. ImageIO.scanForPlugins(); } public void contextDestroyed(final ServletContextEvent event) { + ServletContext servletContext = event.getServletContext(); + // De-register any locally registered IIO plugins. Relies on each web app having its own context class loader. - final IIORegistry registry = IIORegistry.getDefaultInstance(); - final LocalFilter localFilter = new LocalFilter(Thread.currentThread().getContextClassLoader()); // scanForPlugins uses context class loader + LocalFilter localFilter = new LocalFilter(Thread.currentThread().getContextClassLoader()); // scanForPlugins uses context class loader + IIORegistry registry = IIORegistry.getDefaultInstance(); Iterator> categories = registry.getCategories(); - + while (categories.hasNext()) { - Class category = categories.next(); - Iterator providers = registry.getServiceProviders(category, localFilter, false); + deregisterLocalProvidersForCategory(registry, localFilter, categories.next(), servletContext); + } + } - // Copy the providers, as de-registering while iterating over providers will lead to ConcurrentModificationExceptions. - List providersCopy = new ArrayList<>(); - while (providers.hasNext()) { - providersCopy.add(providers.next()); - } + private static void deregisterLocalProvidersForCategory(IIORegistry registry, LocalFilter localFilter, Class category, ServletContext context) { + Iterator providers = registry.getServiceProviders(category, localFilter, false); - for (Object provider : providersCopy) { - registry.deregisterServiceProvider(provider); - event.getServletContext().log(String.format("Unregistered locally installed provider class: %s", provider.getClass())); - } + // Copy the providers, as de-registering while iterating over providers will lead to ConcurrentModificationExceptions. + List providersCopy = new ArrayList<>(); + while (providers.hasNext()) { + providersCopy.add(providers.next()); + } + + for (T provider : providersCopy) { + registry.deregisterServiceProvider(provider, category); + context.log(String.format("Unregistered locally installed provider class: %s", provider.getClass())); } } diff --git a/servlet/src/test/java/com/twelvemonkeys/servlet/image/IIOProviderContextListenerTest.java b/servlet/src/test/java/com/twelvemonkeys/servlet/image/IIOProviderContextListenerTest.java index 06b8c447..44089f4a 100644 --- a/servlet/src/test/java/com/twelvemonkeys/servlet/image/IIOProviderContextListenerTest.java +++ b/servlet/src/test/java/com/twelvemonkeys/servlet/image/IIOProviderContextListenerTest.java @@ -33,7 +33,6 @@ package com.twelvemonkeys.servlet.image; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; import java.util.Locale; @@ -54,32 +53,29 @@ import org.junit.Test; * @version $Id: IIOProviderContextListenerTest.java,v 1.0 02.01.14 12:33 haraldk Exp$ */ public class IIOProviderContextListenerTest { + + private final ServletContext context = mock(ServletContext.class); + private final ServletContextEvent initialized = new ServletContextEvent(context); + private final ServletContextEvent destroyed = new ServletContextEvent(context); + @Test public void testContextInitialized() { ServletContextListener listener = new IIOProviderContextListener(); - listener.contextInitialized(mock(ServletContextEvent.class)); + listener.contextInitialized(initialized); } @Test public void testContextDestroyed() { - ServletContext context = mock(ServletContext.class); - ServletContextEvent destroyed = mock(ServletContextEvent.class); - when(destroyed.getServletContext()).thenReturn(context); - ServletContextListener listener = new IIOProviderContextListener(); - listener.contextInitialized(mock(ServletContextEvent.class)); + listener.contextInitialized(initialized); listener.contextDestroyed(destroyed); } // Regression test for issue #29 @Test public void testDestroyConcurrentModRegression() { - ServletContext context = mock(ServletContext.class); - ServletContextEvent destroyed = mock(ServletContextEvent.class); - when(destroyed.getServletContext()).thenReturn(context); - ServletContextListener listener = new IIOProviderContextListener(); - listener.contextInitialized(mock(ServletContextEvent.class)); + listener.contextInitialized(initialized); ImageReaderSpi provider1 = new MockImageReaderSpiOne(); ImageReaderSpi provider2 = new MockImageReaderSpiToo();