/**
 * Copyright (C) 2006 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.Asserts.reserialize;
import static com.google.inject.servlet.ServletScopes.NullObject;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.isA;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;

import com.google.inject.AbstractModule;
import com.google.inject.BindingAnnotation;
import com.google.inject.CreationException;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.internal.util.Maps;
import com.google.inject.servlet.RequestParameters;
import com.google.inject.util.Providers;

import junit.framework.TestCase;

import java.io.IOException;
import java.io.Serializable;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

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 javax.servlet.http.HttpSession;

/**
 * @author crazybob@google.com (Bob Lee)
 */
public class ServletTest extends TestCase {
  private static final Key<HttpServletRequest> HTTP_REQ_KEY = Key.get(HttpServletRequest.class);
  private static final Key<HttpServletResponse> HTTP_RESP_KEY = Key.get(HttpServletResponse.class);
  private static final Key<Map<String, String[]>> REQ_PARAMS_KEY
      = new Key<Map<String, String[]>>(RequestParameters.class) {};

  private static final Key<InRequest> IN_REQUEST_KEY = Key.get(InRequest.class);
  private static final Key<InRequest> IN_REQUEST_NULL_KEY = Key.get(InRequest.class, Null.class);
  private static final Key<InSession> IN_SESSION_KEY = Key.get(InSession.class);
  private static final Key<InSession> IN_SESSION_NULL_KEY = Key.get(InSession.class, Null.class);

  @Override
  public void setUp() {
    //we need to clear the reference to the pipeline every test =(
    GuiceFilter.reset();
  }

  public void testRequestAndResponseBindings() throws Exception {
    final Injector injector = createInjector();
    final HttpServletRequest request = createMock(HttpServletRequest.class);
    final HttpServletResponse response = createMock(HttpServletResponse.class);
    final Map<String, String[]> params = Maps.newHashMap();
    String httpReqKey = HTTP_REQ_KEY.toString();
    expect(request.getAttribute(httpReqKey)).andReturn(null);
    request.setAttribute(httpReqKey, request);
    expect(request.getAttribute(httpReqKey)).andReturn(request).anyTimes();

    String httpRespKey = HTTP_RESP_KEY.toString();
    expect(request.getAttribute(httpRespKey)).andReturn(null);
    request.setAttribute(httpRespKey, response);
    expect(request.getAttribute(httpRespKey)).andReturn(response).anyTimes();

    String reqParamsKey = REQ_PARAMS_KEY.toString();
    expect(request.getAttribute(reqParamsKey)).andReturn(null);
    expect(request.getParameterMap()).andStubReturn(params);
    request.setAttribute(reqParamsKey, params);
    expect(request.getAttribute(reqParamsKey)).andReturn(params).anyTimes();
    replay(request, response);

    final boolean[] invoked = new boolean[1];
    GuiceFilter filter = new GuiceFilter();
    FilterChain filterChain = new FilterChain() {
      public void doFilter(ServletRequest servletRequest,
          ServletResponse servletResponse) {
        invoked[0] = true;
        assertSame(request, servletRequest);
        assertSame(request, injector.getInstance(ServletRequest.class));
        assertSame(request, injector.getInstance(HTTP_REQ_KEY));

        assertSame(response, servletResponse);
        assertSame(response, injector.getInstance(ServletResponse.class));
        assertSame(response, injector.getInstance(HTTP_RESP_KEY));

        assertSame(params, servletRequest.getParameterMap());
        assertSame(params, injector.getInstance(REQ_PARAMS_KEY));
      }
    };
    filter.doFilter(request, response, filterChain);

    assertTrue(invoked[0]);
    verify(request, response);
  }

  public void testNewRequestObject()
      throws CreationException, IOException, ServletException {
    final Injector injector = createInjector();

    GuiceFilter filter = new GuiceFilter();

    final HttpServletRequest request = createMock(HttpServletRequest.class);

    String inRequestKey = IN_REQUEST_KEY.toString();
    expect(request.getAttribute(inRequestKey)).andReturn(null);
    request.setAttribute(eq(inRequestKey), isA(InRequest.class));
    
    String inRequestNullKey = IN_REQUEST_NULL_KEY.toString();
    expect(request.getAttribute(inRequestNullKey)).andReturn(null);
    request.setAttribute(eq(inRequestNullKey), eq(NullObject.INSTANCE));

    final boolean[] invoked = new boolean[1];
    FilterChain filterChain = new FilterChain() {
      public void doFilter(ServletRequest servletRequest,
          ServletResponse servletResponse) {
        invoked[0] = true;
        assertNotNull(injector.getInstance(InRequest.class));
        assertNull(injector.getInstance(IN_REQUEST_NULL_KEY));
      }
    };

    replay(request);

    filter.doFilter(request, null, filterChain);

    verify(request);
    assertTrue(invoked[0]);
  }

  public void testExistingRequestObject()
      throws CreationException, IOException, ServletException {
    final Injector injector = createInjector();

    GuiceFilter filter = new GuiceFilter();

    final HttpServletRequest request = createMock(HttpServletRequest.class);

    final InRequest inRequest = new InRequest();
    String inRequestKey = IN_REQUEST_KEY.toString();
    expect(request.getAttribute(inRequestKey)).andReturn(inRequest).times(2);
    
    String inRequestNullKey = IN_REQUEST_NULL_KEY.toString();
    expect(request.getAttribute(inRequestNullKey)).andReturn(NullObject.INSTANCE).times(2);

    final boolean[] invoked = new boolean[1];
    FilterChain filterChain = new FilterChain() {
      public void doFilter(ServletRequest servletRequest,
          ServletResponse servletResponse) {
        invoked[0] = true;
        
        assertSame(inRequest, injector.getInstance(InRequest.class));
        assertSame(inRequest, injector.getInstance(InRequest.class));

        assertNull(injector.getInstance(IN_REQUEST_NULL_KEY));
        assertNull(injector.getInstance(IN_REQUEST_NULL_KEY));
      }
    };

    replay(request);

    filter.doFilter(request, null, filterChain);

    verify(request);
    assertTrue(invoked[0]);
  }

  public void testNewSessionObject()
      throws CreationException, IOException, ServletException {
    final Injector injector = createInjector();

    GuiceFilter filter = new GuiceFilter();

    final HttpServletRequest request = createMock(HttpServletRequest.class);
    final HttpSession session = createMock(HttpSession.class);

    String inSessionKey = IN_SESSION_KEY.toString();
    String inSessionNullKey = IN_SESSION_NULL_KEY.toString();

    expect(request.getSession()).andReturn(session).times(2);
    expect(session.getAttribute(inSessionKey)).andReturn(null);
    session.setAttribute(eq(inSessionKey), isA(InSession.class));

    expect(session.getAttribute(inSessionNullKey)).andReturn(null);
    session.setAttribute(eq(inSessionNullKey), eq(NullObject.INSTANCE));

    final boolean[] invoked = new boolean[1];
    FilterChain filterChain = new FilterChain() {
      public void doFilter(ServletRequest servletRequest,
          ServletResponse servletResponse) {
        invoked[0] = true;
        assertNotNull(injector.getInstance(InSession.class));
        assertNull(injector.getInstance(IN_SESSION_NULL_KEY));
      }
    };

    replay(request, session);

    filter.doFilter(request, null, filterChain);

    verify(request, session);
    assertTrue(invoked[0]);
  }

  public void testExistingSessionObject()
      throws CreationException, IOException, ServletException {
    final Injector injector = createInjector();

    GuiceFilter filter = new GuiceFilter();

    final HttpServletRequest request = createMock(HttpServletRequest.class);
    final HttpSession session = createMock(HttpSession.class);

    String inSessionKey = IN_SESSION_KEY.toString();
    String inSessionNullKey = IN_SESSION_NULL_KEY.toString();

    final InSession inSession = new InSession();
    expect(request.getSession()).andReturn(session).times(4);
    expect(session.getAttribute(inSessionKey)).andReturn(inSession).times(2);
    
    expect(session.getAttribute(inSessionNullKey)).andReturn(NullObject.INSTANCE).times(2);

    final boolean[] invoked = new boolean[1];
    FilterChain filterChain = new FilterChain() {
      public void doFilter(ServletRequest servletRequest,
          ServletResponse servletResponse) {
        invoked[0] = true;

        assertSame(inSession, injector.getInstance(InSession.class));
        assertSame(inSession, injector.getInstance(InSession.class));

        assertNull(injector.getInstance(IN_SESSION_NULL_KEY));
        assertNull(injector.getInstance(IN_SESSION_NULL_KEY));
      }
    };

    replay(request, session);

    filter.doFilter(request, null, filterChain);

    verify(request, session);
    assertTrue(invoked[0]);
  }

  public void testHttpSessionIsSerializable()
      throws IOException, ClassNotFoundException, ServletException {
    final Injector injector = createInjector();

    GuiceFilter filter = new GuiceFilter();

    final HttpServletRequest request = createMock(HttpServletRequest.class);
    final HttpSession session = newFakeHttpSession();

    String inSessionKey = IN_SESSION_KEY.toString();
    String inSessionNullKey = IN_SESSION_NULL_KEY.toString();

    expect(request.getSession()).andReturn(session).times(2);

    final boolean[] invoked = new boolean[1];
    FilterChain filterChain = new FilterChain() {
      public void doFilter(ServletRequest servletRequest,
          ServletResponse servletResponse) {
        invoked[0] = true;
        assertNotNull(injector.getInstance(InSession.class));
        assertNull(injector.getInstance(IN_SESSION_NULL_KEY));
      }
    };

    replay(request);

    filter.doFilter(request, null, filterChain);

    verify(request);
    assertTrue(invoked[0]);

    HttpSession deserializedSession = reserialize(session);

    assertTrue(deserializedSession.getAttribute(inSessionKey) instanceof InSession);
    assertEquals(NullObject.INSTANCE, deserializedSession.getAttribute(inSessionNullKey));
  }

  private static class FakeHttpSessionHandler implements InvocationHandler, Serializable {
    final Map<String, Object> attributes = Maps.newHashMap();

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      String name = method.getName();
      if ("setAttribute".equals(name)) {
        attributes.put((String) args[0], args[1]);
        return null;
      } else if ("getAttribute".equals(name)) {
        return attributes.get(args[0]);
      } else {
        throw new UnsupportedOperationException();
      }
    }
  }

  /**
   * Returns a fake, serializable HttpSession which stores attributes in a HashMap.
   */
  private HttpSession newFakeHttpSession() {
    return (HttpSession) Proxy.newProxyInstance(HttpSession.class.getClassLoader(),
        new Class[] { HttpSession.class }, new FakeHttpSessionHandler());
  }

  private Injector createInjector() throws CreationException {

    return Guice.createInjector(new AbstractModule() {

      @Override
      protected void configure() {
        install(new ServletModule());
        bind(InSession.class);
        bind(IN_SESSION_NULL_KEY).toProvider(Providers.<InSession>of(null)).in(SessionScoped.class);
        bind(InRequest.class);
        bind(IN_REQUEST_NULL_KEY).toProvider(Providers.<InRequest>of(null)).in(RequestScoped.class);
      }
    });
  }

  @SessionScoped
  static class InSession implements Serializable {}

  @RequestScoped
  static class InRequest {}

  @BindingAnnotation @Retention(RUNTIME) @Target({PARAMETER, METHOD, FIELD})
  @interface Null {}
}
