/*
 * Copyright (C) 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.inject.servlet;

import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;

import com.google.common.collect.Sets;
import com.google.inject.Binding;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.spi.BindingScopingVisitor;
import java.io.IOException;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;

/**
 * Ensures servlet spec compliance for CGI-style variables and general path/pattern matching.
 *
 * @author Dhanji R. Prasanna (dhanji@gmail com)
 */
public class ServletDefinitionPathsTest extends TestCase {

  // Data-driven test.
  public final void testServletPathMatching() throws IOException, ServletException {
    servletPath("/index.html", "*.html", "/index.html");
    servletPath("/somewhere/index.html", "*.html", "/somewhere/index.html");
    servletPath("/somewhere/index.html", "/*", "");
    servletPath("/index.html", "/*", "");
    servletPath("/", "/*", "");
    servletPath("//", "/*", "");
    servletPath("/////", "/*", "");
    servletPath("", "/*", "");
    servletPath("/thing/index.html", "/thing/*", "/thing");
    servletPath("/thing/wing/index.html", "/thing/*", "/thing");
  }

  private void servletPath(
      final String requestPath, String mapping, final String expectedServletPath)
      throws IOException, ServletException {

    Injector injector = createMock(Injector.class);
    Binding binding = createMock(Binding.class);
    HttpServletRequest request = createMock(HttpServletRequest.class);
    HttpServletResponse response = createMock(HttpServletResponse.class);

    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true);
    expect(injector.getBinding(Key.get(HttpServlet.class))).andReturn(binding);

    final boolean[] run = new boolean[1];
    //get an instance of this servlet
    expect(injector.getInstance(Key.get(HttpServlet.class)))
        .andReturn(
            new HttpServlet() {

              @Override
              protected void service(
                  HttpServletRequest servletRequest, HttpServletResponse httpServletResponse)
                  throws ServletException, IOException {

                final String path = servletRequest.getServletPath();
                assertEquals(
                    String.format("expected [%s] but was [%s]", expectedServletPath, path),
                    expectedServletPath,
                    path);
                run[0] = true;
              }
            });

    expect(request.getServletPath()).andReturn(requestPath);

    replay(injector, binding, request);

    ServletDefinition servletDefinition =
        new ServletDefinition(
            Key.get(HttpServlet.class),
            UriPatternType.get(UriPatternType.SERVLET, mapping),
            new HashMap<String, String>(),
            null);

    servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
    servletDefinition.doService(request, response);

    assertTrue("Servlet did not run!", run[0]);

    verify(injector, binding, request);
  }

  // Data-driven test.
  public final void testPathInfoWithServletStyleMatching() throws IOException, ServletException {
    pathInfoWithServletStyleMatching("/path/index.html", "/path", "/*", "/index.html", "");
    pathInfoWithServletStyleMatching(
        "/path//hulaboo///index.html", "/path", "/*", "/hulaboo/index.html", "");
    pathInfoWithServletStyleMatching("/path/", "/path", "/*", "/", "");
    pathInfoWithServletStyleMatching("/path////////", "/path", "/*", "/", "");

    // a servlet mapping of /thing/*
    pathInfoWithServletStyleMatching("/path/thing////////", "/path", "/thing/*", "/", "/thing");
    pathInfoWithServletStyleMatching("/path/thing/stuff", "/path", "/thing/*", "/stuff", "/thing");
    pathInfoWithServletStyleMatching(
        "/path/thing/stuff.html", "/path", "/thing/*", "/stuff.html", "/thing");
    pathInfoWithServletStyleMatching("/path/thing", "/path", "/thing/*", null, "/thing");

    // see external issue 372
    pathInfoWithServletStyleMatching(
        "/path/some/path/of.jsp", "/path", "/thing/*", null, "/some/path/of.jsp");

    // *.xx style mapping
    pathInfoWithServletStyleMatching("/path/thing.thing", "/path", "*.thing", null, "/thing.thing");
    pathInfoWithServletStyleMatching("/path///h.thing", "/path", "*.thing", null, "/h.thing");
    pathInfoWithServletStyleMatching(
        "/path///...//h.thing", "/path", "*.thing", null, "/.../h.thing");
    pathInfoWithServletStyleMatching("/path/my/h.thing", "/path", "*.thing", null, "/my/h.thing");

    // Encoded URLs
    pathInfoWithServletStyleMatching("/path/index%2B.html", "/path", "/*", "/index+.html", "");
    pathInfoWithServletStyleMatching(
        "/path/a%20file%20with%20spaces%20in%20name.html",
        "/path", "/*", "/a file with spaces in name.html", "");
    pathInfoWithServletStyleMatching(
        "/path/Tam%C3%A1s%20nem%20m%C3%A1s.html", "/path", "/*", "/Tamás nem más.html", "");
  }

  private void pathInfoWithServletStyleMatching(
      final String requestUri,
      final String contextPath,
      String mapping,
      final String expectedPathInfo,
      final String servletPath)
      throws IOException, ServletException {

    Injector injector = createMock(Injector.class);
    Binding binding = createMock(Binding.class);
    HttpServletRequest request = createMock(HttpServletRequest.class);
    HttpServletResponse response = createMock(HttpServletResponse.class);

    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true);
    expect(injector.getBinding(Key.get(HttpServlet.class))).andReturn(binding);

    final boolean[] run = new boolean[1];
    //get an instance of this servlet
    expect(injector.getInstance(Key.get(HttpServlet.class)))
        .andReturn(
            new HttpServlet() {

              @Override
              protected void service(
                  HttpServletRequest servletRequest, HttpServletResponse httpServletResponse)
                  throws ServletException, IOException {

                final String path = servletRequest.getPathInfo();

                if (null == expectedPathInfo) {
                  assertNull(
                      String.format("expected [%s] but was [%s]", expectedPathInfo, path), path);
                } else {
                  assertEquals(
                      String.format("expected [%s] but was [%s]", expectedPathInfo, path),
                      expectedPathInfo,
                      path);
                }

                //assert memoizer
                //noinspection StringEquality
                assertSame("memo field did not work", path, servletRequest.getPathInfo());

                run[0] = true;
              }
            });

    expect(request.getRequestURI()).andReturn(requestUri);

    expect(request.getServletPath()).andReturn(servletPath).anyTimes();

    expect(request.getContextPath()).andReturn(contextPath);

    expect(request.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(null);

    replay(injector, binding, request);

    ServletDefinition servletDefinition =
        new ServletDefinition(
            Key.get(HttpServlet.class),
            UriPatternType.get(UriPatternType.SERVLET, mapping),
            new HashMap<String, String>(),
            null);

    servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
    servletDefinition.doService(request, response);

    assertTrue("Servlet did not run!", run[0]);

    verify(injector, binding, request);
  }

  // Data-driven test.
  public final void testPathInfoWithRegexMatching() throws IOException, ServletException {
    // first a mapping of /*
    pathInfoWithRegexMatching("/path/index.html", "/path", "/(.)*", "/index.html", "");
    pathInfoWithRegexMatching(
        "/path//hulaboo///index.html", "/path", "/(.)*", "/hulaboo/index.html", "");
    pathInfoWithRegexMatching("/path/", "/path", "/(.)*", "/", "");
    pathInfoWithRegexMatching("/path////////", "/path", "/(.)*", "/", "");

    // a servlet mapping of /thing/*
    pathInfoWithRegexMatching("/path/thing////////", "/path", "/thing/(.)*", "/", "/thing");
    pathInfoWithRegexMatching("/path/thing/stuff", "/path", "/thing/(.)*", "/stuff", "/thing");
    pathInfoWithRegexMatching(
        "/path/thing/stuff.html", "/path", "/thing/(.)*", "/stuff.html", "/thing");
    pathInfoWithRegexMatching("/path/thing", "/path", "/thing/(.)*", null, "/thing");

    // *.xx style mapping
    pathInfoWithRegexMatching("/path/thing.thing", "/path", ".*\\.thing", null, "/thing.thing");
    pathInfoWithRegexMatching("/path///h.thing", "/path", ".*\\.thing", null, "/h.thing");
    pathInfoWithRegexMatching("/path///...//h.thing", "/path", ".*\\.thing", null, "/.../h.thing");
    pathInfoWithRegexMatching("/path/my/h.thing", "/path", ".*\\.thing", null, "/my/h.thing");

    // path
    pathInfoWithRegexMatching(
        "/path/test.com/com.test.MyServletModule",
        "",
        "/path/[^/]+/(.*)",
        "com.test.MyServletModule",
        "/path/test.com/com.test.MyServletModule");

    // Encoded URLs
    pathInfoWithRegexMatching("/path/index%2B.html", "/path", "/(.)*", "/index+.html", "");
    pathInfoWithRegexMatching(
        "/path/a%20file%20with%20spaces%20in%20name.html",
        "/path", "/(.)*", "/a file with spaces in name.html", "");
    pathInfoWithRegexMatching(
        "/path/Tam%C3%A1s%20nem%20m%C3%A1s.html", "/path", "/(.)*", "/Tamás nem más.html", "");
  }

  public final void pathInfoWithRegexMatching(
      final String requestUri,
      final String contextPath,
      String mapping,
      final String expectedPathInfo,
      final String servletPath)
      throws IOException, ServletException {

    Injector injector = createMock(Injector.class);
    Binding binding = createMock(Binding.class);
    HttpServletRequest request = createMock(HttpServletRequest.class);
    HttpServletResponse response = createMock(HttpServletResponse.class);

    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true);
    expect(injector.getBinding(Key.get(HttpServlet.class))).andReturn(binding);

    final boolean[] run = new boolean[1];
    //get an instance of this servlet
    expect(injector.getInstance(Key.get(HttpServlet.class)))
        .andReturn(
            new HttpServlet() {

              @Override
              protected void service(
                  HttpServletRequest servletRequest, HttpServletResponse httpServletResponse)
                  throws ServletException, IOException {

                final String path = servletRequest.getPathInfo();

                if (null == expectedPathInfo) {
                  assertNull(
                      String.format("expected [%s] but was [%s]", expectedPathInfo, path), path);
                } else {
                  assertEquals(
                      String.format("expected [%s] but was [%s]", expectedPathInfo, path),
                      expectedPathInfo,
                      path);
                }

                //assert memoizer
                //noinspection StringEquality
                assertSame("memo field did not work", path, servletRequest.getPathInfo());

                run[0] = true;
              }
            });

    expect(request.getRequestURI()).andReturn(requestUri);

    expect(request.getServletPath()).andReturn(servletPath).anyTimes();

    expect(request.getContextPath()).andReturn(contextPath);

    expect(request.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(null);

    replay(injector, binding, request);

    ServletDefinition servletDefinition =
        new ServletDefinition(
            Key.get(HttpServlet.class),
            UriPatternType.get(UriPatternType.REGEX, mapping),
            new HashMap<String, String>(),
            null);

    servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
    servletDefinition.doService(request, response);

    assertTrue("Servlet did not run!", run[0]);

    verify(injector, binding, request);
  }
}
