/*
 * Copyright 2007 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.gwt.user.server.rpc;

import com.google.gwt.user.client.rpc.IsSerializable;
import com.google.gwt.user.client.rpc.SerializationException;

import junit.framework.TestCase;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Set;

import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

/**
 * Test some of the failure modes associated with
 * {@link RemoteServiceServlet#doGetSerializationPolicy(HttpServletRequest, String, String)}.
 * 
 * TODO: test caching of policies?
 */
public class RemoteServiceServletTest extends TestCase {

  private static class Bar implements Serializable {
  }

  private static class Baz {
  }

  private static class Foo implements IsSerializable {
  }

  private static class MockHttpServletRequestContextPath extends
      MockHttpServletRequest {
    private String contextPath;

    @Override
    public String getContextPath() {
      return contextPath;
    }
  }

  private static class MockServletConfig implements ServletConfig {
    private ServletContext context;

    public MockServletConfig(ServletContext context) {
      this.context = context;
    }

    public String getInitParameter(String arg0) {
      throw new UnsupportedOperationException();
    }

    public Enumeration<String> getInitParameterNames() {
      throw new UnsupportedOperationException();
    }

    public ServletContext getServletContext() {
      return context;
    }

    public String getServletName() {
      return "MockServlet";
    }
  }

  private class MockServletContext implements ServletContext {
    private String messageLogged;

    public MockServletContext() {
    }

    public Object getAttribute(String arg0) {
      throw new UnsupportedOperationException();
    }

    public Enumeration<String> getAttributeNames() {
      throw new UnsupportedOperationException();
    }

    public ServletContext getContext(String arg0) {
      throw new UnsupportedOperationException();
    }

    public String getContextPath() {
      throw new UnsupportedOperationException();
    }

    public String getInitParameter(String arg0) {
      throw new UnsupportedOperationException();
    }

    public Enumeration<String> getInitParameterNames() {
      throw new UnsupportedOperationException();
    }

    public int getMajorVersion() {
      throw new UnsupportedOperationException();
    }

    public String getMimeType(String arg0) {
      throw new UnsupportedOperationException();
    }

    public int getMinorVersion() {
      throw new UnsupportedOperationException();
    }

    public RequestDispatcher getNamedDispatcher(String arg0) {
      throw new UnsupportedOperationException();
    }

    public String getRealPath(String arg0) {
      throw new UnsupportedOperationException();
    }

    public RequestDispatcher getRequestDispatcher(String arg0) {
      throw new UnsupportedOperationException();
    }

    public URL getResource(String arg0) throws MalformedURLException {
      throw new UnsupportedOperationException();
    }

    public InputStream getResourceAsStream(String arg0) {
      throw new UnsupportedOperationException();
    }

    public Set<String> getResourcePaths(String arg0) {
      throw new UnsupportedOperationException();
    }

    public String getServerInfo() {
      throw new UnsupportedOperationException();
    }

    public Servlet getServlet(String arg0) throws ServletException {
      throw new UnsupportedOperationException();
    }

    public String getServletContextName() {
      throw new UnsupportedOperationException();
    }

    public Enumeration<String> getServletNames() {
      throw new UnsupportedOperationException();
    }

    public Enumeration<String> getServlets() {
      throw new UnsupportedOperationException();
    }

    public void log(Exception arg0, String arg1) {
      log(arg1, arg0);
    }

    public void log(String arg0) {
      log(arg0, null);
    }

    public void log(String arg0, Throwable arg1) {
      messageLogged = arg0;
    }

    public void removeAttribute(String arg0) {
    }

    public void setAttribute(String arg0, Object arg1) {
      throw new UnsupportedOperationException();
    }
  }

  public void testDoGetSerializationPolicy_FailToOpenMD5Resource()
      throws ServletException {
    MockServletContext mockContext = new MockServletContext() {
      public InputStream getResourceAsStream(String resource) {
        return null;
      }
    };
    MockServletConfig mockConfig = new MockServletConfig(mockContext);

    RemoteServiceServlet rss = new RemoteServiceServlet();

    MockHttpServletRequestContextPath mockRequest = new MockHttpServletRequestContextPath();
    rss.init(mockConfig);

    mockRequest.contextPath = "/MyModule";

    SerializationPolicy serializationPolicy = rss.doGetSerializationPolicy(
        mockRequest, "http://www.google.com/MyModule", "12345");
    assertNull(serializationPolicy);
    assertNotNull(mockContext.messageLogged);
  }

  /**
   * Test method for
   * {@link com.google.gwt.user.server.rpc.RemoteServiceServlet#doGetSerializationPolicy(javax.servlet.http.HttpServletRequest, java.lang.String, java.lang.String)}.
   * 
   * This method tests that if the module path is in a different context than
   * the RemoteServiceServlet which is processing the request, a message will be
   * logged and null is returned for the SerializationPolicy.
   */
  public void testDoGetSerializationPolicy_ModuleInSeparateServlet()
      throws ServletException {
    MockServletContext mockContext = new MockServletContext();
    MockServletConfig mockConfig = new MockServletConfig(mockContext);

    RemoteServiceServlet rss = new RemoteServiceServlet();

    MockHttpServletRequestContextPath mockRequest = new MockHttpServletRequestContextPath();
    rss.init(mockConfig);

    mockRequest.contextPath = "/foo";
    SerializationPolicy serializationPolicy = rss.doGetSerializationPolicy(
        mockRequest, "http://www.google.com/MyModule", "");
    assertNotNull(mockContext.messageLogged);
    assertNull(serializationPolicy);
  }

  /**
   * Test method for
   * {@link com.google.gwt.user.server.rpc.RemoteServiceServlet#doGetSerializationPolicy(javax.servlet.http.HttpServletRequest, java.lang.String, java.lang.String)}.
   * 
   * This method tests the success case. The resource exists and is in the same
   * path at the web application.
   */
  public void testDoGetSerializationPolicy_Success() throws ServletException,
      SerializationException {
    final String resourceHash = "12345";
    final String resourcePath = SerializationPolicyLoader.getSerializationPolicyFileName(resourceHash);
    MockServletContext mockContext = new MockServletContext() {
      public InputStream getResourceAsStream(String resource) {
        if (resourcePath.equals(resource)) {
          try {
            String payLoad = Foo.class.getName() + ",true\n"
                + Bar.class.getName() + ",false\n";
            return new ByteArrayInputStream(
                payLoad.getBytes(SerializationPolicyLoader.SERIALIZATION_POLICY_FILE_ENCODING));
          } catch (UnsupportedEncodingException e) {
            return null;
          }
        }

        return null;
      }
    };
    MockServletConfig mockConfig = new MockServletConfig(mockContext);

    RemoteServiceServlet rss = new RemoteServiceServlet();

    MockHttpServletRequestContextPath mockRequest = new MockHttpServletRequestContextPath();
    rss.init(mockConfig);

    mockRequest.contextPath = "/MyModule";

    SerializationPolicy serializationPolicy = rss.doGetSerializationPolicy(
        mockRequest, "http://www.google.com/MyModule", resourceHash);
    assertNotNull(serializationPolicy);

    assertDeserializeFields(serializationPolicy, Foo.class);
    assertValidDeserialize(serializationPolicy, Foo.class);

    assertDeserializeFields(serializationPolicy, Bar.class);
    assertNotValidDeserialize(serializationPolicy, Bar.class);

    assertNotDeserializeFields(serializationPolicy, Baz.class);
    assertNotValidDeserialize(serializationPolicy, Baz.class);
  }

  private void assertDeserializeFields(SerializationPolicy policy,
      Class<?> clazz) {
    assertTrue(policy.shouldDeserializeFields(clazz));
  }

  private void assertNotDeserializeFields(SerializationPolicy policy,
      Class<?> clazz) {
    assertFalse(policy.shouldDeserializeFields(clazz));
  }

  private void assertNotValidDeserialize(SerializationPolicy policy,
      Class<?> clazz) {
    try {
      policy.validateDeserialize(clazz);
      fail("assertNotValidDeserialize: " + clazz.getName()
          + " failed to throw an exception");
    } catch (SerializationException e) {
      // expected
    }
  }

  private void assertValidDeserialize(SerializationPolicy policy, Class<?> clazz)
      throws SerializationException {
    policy.validateDeserialize(clazz);
  }
}
