content: /**
   *
   */
  package ro.isdc.wro.model.resource.locator;
  
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertFalse;
  import static org.mockito.Mockito.when;
  
  import java.io.BufferedReader;
  import java.io.ByteArrayInputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.net.URL;
  import java.util.concurrent.atomic.AtomicBoolean;
  
  import javax.servlet.FilterConfig;
  import javax.servlet.ServletContext;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  
  import org.junit.After;
  import org.junit.AfterClass;
  import org.junit.Before;
  import org.junit.BeforeClass;
  import org.junit.Test;
  import org.mockito.Mock;
  import org.mockito.Mockito;
  import org.mockito.MockitoAnnotations;
  
  import ro.isdc.wro.config.Context;
  import ro.isdc.wro.config.jmx.WroConfiguration;
  import ro.isdc.wro.manager.factory.BaseWroManagerFactory;
  import ro.isdc.wro.model.group.Inject;
  import ro.isdc.wro.model.group.processor.Injector;
  import ro.isdc.wro.model.group.processor.InjectorBuilder;
  import ro.isdc.wro.model.resource.locator.ServletContextUriLocator.LocatorStrategy;
  import ro.isdc.wro.model.resource.locator.factory.SimpleUriLocatorFactory;
  import ro.isdc.wro.model.resource.locator.factory.UriLocatorFactory;
  import ro.isdc.wro.model.resource.locator.support.DispatcherStreamLocator;
  import ro.isdc.wro.util.WroUtil;
  
  
  /**
   * Test for {@link ServletContextUriLocator} class.
   *
   * @author Alex Objelean
   */
  public class TestServletContextUriLocator {
    @Mock
    private HttpServletRequest mockRequest;
    @Mock
    private HttpServletResponse mockResponse;
    @Mock
    private FilterConfig mockFilterConfig;
    @Mock
    private ServletContext mockServletContext;
    private ServletContextUriLocator victim;
  
    @BeforeClass
    public static void onBeforeClass() {
      assertEquals(0, Context.countActive());
    }
  
    @AfterClass
    public static void onAfterClass() {
      assertEquals(0, Context.countActive());
    }
  
    @Before
    public void setUp() {
      MockitoAnnotations.initMocks(this);
  
      when(mockRequest.getRequestURL()).thenReturn(new StringBuffer(""));
      when(mockRequest.getServletPath()).thenReturn("");
      when(mockFilterConfig.getServletContext()).thenReturn(mockServletContext);
  
      final Context context = Context.webContext(mockRequest, mockResponse, mockFilterConfig);
      final WroConfiguration config = new WroConfiguration();
      config.setConnectionTimeout(100);
      Context.set(context, config);
  
      victim = new ServletContextUriLocator();
  
      initLocator(victim);
    }
  
    @After
    public void tearDown() {
      Context.unset();
    }
  
    /**
     * Initialize the locator by injecting all required fields.
     */
    private void initLocator(final ServletContextUriLocator locator) {
      final Injector injector = InjectorBuilder.create(new BaseWroManagerFactory()).build();
      injector.inject(locator);
    }
  
    @Test(expected = NullPointerException.class)
    public void cannotAcceptNullUri()
        throws Exception {
      victim.locate(null);
    }
  
    @Test
    public void testWildcard1Resources()
        throws IOException {
      victim.locate(createUri("/css/*.css"));
    }
  
    @Test
    public void testWildcard2Resources()
        throws IOException {
      victim.locate(createUri("/css/*.cs?"));
    }
  
    @Test
    public void testWildcard3Resources()
        throws IOException {
      victim.locate(createUri("/css/*.???"));
    }
  
    @Test
    public void testRecursiveWildcardResources()
        throws IOException {
      victim.locate(createUri("/css/**.css"));
    }
  
    @Test
    public void shouldFindWildcardResourcesForFolderContainingSpaces()
        throws IOException {
      victim.locate(createUri("/folder with spaces/**.css", "test"));
    }
  
    @Test(expected = IOException.class)
    public void testWildcardInexistentResources()
        throws IOException {
      victim.locate(createUri("/css/**.NOTEXIST"));
    }
  
    private String createUri(final String uri)
        throws IOException {
      return createUri(uri, "ro/isdc/wro/model/resource/locator/");
    }
  
    private String createUri(final String uri, final String path)
        throws IOException {
      final URL url = Thread.currentThread().getContextClassLoader().getResource(path);
      when(mockServletContext.getRealPath(Mockito.anyString())).thenReturn(url.getPath());
      return uri;
    }
  
    /**
     * Make this test method to follow a flow which throws IOException
     */
    @Test(expected = IOException.class)
    public void testInvalidUrl()
        throws Exception {
      victim.locate("/invalid/resource.css");
    }
  
    @Test
    public void shouldPreferServletContextBasedResolving()
        throws IOException {
      final InputStream is = new ByteArrayInputStream("a {}".getBytes());
      Mockito.when(Context.get().getServletContext().getResourceAsStream(Mockito.anyString())).thenReturn(is);
  
      final ServletContextUriLocator locator = new ServletContextUriLocator();
      initLocator(locator);
      locator.setLocatorStrategy(ServletContextUriLocator.LocatorStrategy.SERVLET_CONTEXT_FIRST);
  
      final InputStream actualIs = locator.locate("test.css");
  
      final BufferedReader br = new BufferedReader(new InputStreamReader(actualIs));
      assertEquals("a {}", br.readLine());
    }
  
    @Test(expected = IOException.class)
    public void shouldNotInvokeDispatcherWhenServletContextOnlyStrategyIsUsed()
        throws Exception {
      final AtomicBoolean dispatcherInvokedFlag = new AtomicBoolean();
      victim = new ServletContextUriLocator() {
        @Override
        InputStream locateWithDispatcher(final String uri)
            throws IOException {
          dispatcherInvokedFlag.set(true);
          throw new IOException("No resource exist");
        }
      };
      initLocator(victim);
      victim.setLocatorStrategy(LocatorStrategy.SERVLET_CONTEXT_ONLY);
      try {
        victim.locate("/test.css");
      } finally {
        assertFalse(dispatcherInvokedFlag.get());
      }
    }
  
    @Test(expected = NullPointerException.class)
    public void cannotSetNullLocatorStrategy() {
      victim.setLocatorStrategy(null);
    }
  
    @Test
    public void shouldInjectEachLocatorWhenLocatorFactoryIsUsed()
        throws Exception {
      final SimpleUriLocatorFactory locatorFactory = new SimpleUriLocatorFactory();
      final ServletContextUriLocator locator = new ServletContextUriLocator();
      locatorFactory.addLocator(locator);
      final DispatcherStreamLocator dispatcherLocator = Mockito.mock(DispatcherStreamLocator.class);
      when(
          dispatcherLocator.getInputStream(Mockito.any(HttpServletRequest.class), Mockito.any(HttpServletResponse.class),
              Mockito.anyString())).thenReturn(WroUtil.EMPTY_STREAM);
      final Injector injector = InjectorBuilder.create(new BaseWroManagerFactory().setUriLocatorFactory(locatorFactory)).setDispatcherLocator(
          dispatcherLocator).build();
      final LocatorFactoryHolder locatorFactoryHolder = new LocatorFactoryHolder();
      injector.inject(locatorFactoryHolder);
      final String uri = "/style.css";
      locatorFactoryHolder.locatorFactory.locate(uri);
    }
  
    private static final class LocatorFactoryHolder {
      @Inject
      private UriLocatorFactory locatorFactory;
    }
  
  
    @After
    public void resetContext() {
      Context.unset();
    }
  }
  