/*
 * Copyright 2009 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.rpc.server;

import static com.google.gwt.user.client.rpc.RpcRequestBuilder.MODULE_BASE_HEADER;

import com.google.gwt.rpc.client.impl.RemoteException;
import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet;
import com.google.gwt.user.server.rpc.RPCRequest;
import com.google.gwt.user.server.rpc.RPCServletUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.SoftReference;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPOutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * EXPERIMENTAL and subject to change. Do not use this in production code.
 * <p>
 * The servlet base class for your RPC service implementations that
 * automatically deserializes incoming requests from the client and serializes
 * outgoing responses for client/server RPCs.
 */
public class RpcServlet extends AbstractRemoteServiceServlet {

  protected static final String CLIENT_ORACLE_EXTENSION = ".gwt.rpc";
  private static final boolean DUMP_PAYLOAD = Boolean.getBoolean("gwt.rpc.dumpPayload");

  private final Map<String, SoftReference<ClientOracle>> clientOracleCache = new HashMap<String, SoftReference<ClientOracle>>();

  /**
   * The implementation of the service.
   */
  private final Object delegate;

  /**
   * The default constructor used by service implementations that
   * extend this class.  The servlet will delegate AJAX requests to
   * the appropriate method in the subclass.
   */
  public RpcServlet() {
    this.delegate = this;
  }

  /**
   * The wrapping constructor used by service implementations that are
   * separate from this class.  The servlet will delegate AJAX
   * requests to the appropriate method in the given object.
   */
  public RpcServlet(Object delegate) {
    this.delegate = delegate;
  }

  /**
   * This method creates the ClientOracle that will provide data about the
   * remote client. It delegates to
   * {@link #findClientOracleData(String, String)} to obtain access to
   * ClientOracle data emitted by the GWT compiler.
   */
  public ClientOracle getClientOracle() throws SerializationException {
    String permutationStrongName = getPermutationStrongName();
    if (permutationStrongName == null) {
      throw new SecurityException(
          "Blocked request without GWT permutation header (XSRF attack?)");
    }
    String basePath = getRequestModuleBasePath();
    if (basePath == null) {
      throw new SecurityException(
          "Blocked request without GWT base path header (XSRF attack?)");
    }

    ClientOracle toReturn;

    synchronized (clientOracleCache) {
      if (clientOracleCache.containsKey(permutationStrongName)) {
        toReturn = clientOracleCache.get(permutationStrongName).get();
        if (toReturn != null) {
          return toReturn;
        }
      }

      if ("HostedMode".equals(permutationStrongName)) {
        if (!allowHostedModeConnections()) {
          throw new SecurityException("Blocked Development Mode request");
        }
        toReturn = new HostedModeClientOracle();
      } else {
        InputStream in = findClientOracleData(basePath, permutationStrongName);

        try {
          toReturn = WebModeClientOracle.load(in);
        } catch (IOException e) {
          throw new SerializationException(
              "Could not load serialization policy for permutation "
                  + permutationStrongName, e);
        }
      }
      clientOracleCache.put(permutationStrongName,
          new SoftReference<ClientOracle>(toReturn));
    }

    return toReturn;
  }

  /**
   * Process a call originating from the given request. Uses the
   * {@link RPC#invokeAndStreamResponse(Object, java.lang.reflect.Method, Object[], ClientOracle, OutputStream)}
   * method to do the actual work.
   * <p>
   * Subclasses may optionally override this method to handle the payload in any
   * way they desire (by routing the request to a framework component, for
   * instance). The {@link HttpServletRequest} and {@link HttpServletResponse}
   * can be accessed via the {@link #getThreadLocalRequest()} and
   * {@link #getThreadLocalResponse()} methods.
   * </p>
   * This is public so that it can be unit tested easily without HTTP.
   * 
   * @param clientOracle the ClientOracle that will be used to interpret the
   *          request
   * @param payload the UTF-8 request payload
   * @param stream the OutputStream that will receive the encoded response
   * @throws SerializationException if we cannot serialize the response
   */
  public void processCall(ClientOracle clientOracle, String payload,
      OutputStream stream) throws SerializationException {
    assert clientOracle != null : "clientOracle";
    assert payload != null : "payload";
    assert stream != null : "stream";

    try {
      RPCRequest rpcRequest = RPC.decodeRequest(payload, delegate.getClass(),
          clientOracle);
      onAfterRequestDeserialized(rpcRequest);
      RPC.invokeAndStreamResponse(delegate, rpcRequest.getMethod(),
          rpcRequest.getParameters(), clientOracle, stream);
    } catch (RemoteException ex) {
      throw new SerializationException("An exception was sent from the client",
          ex.getCause());
    } catch (IncompatibleRemoteServiceException ex) {
      log(
          "An IncompatibleRemoteServiceException was thrown while processing this call.",
          ex);
      RPC.streamResponseForFailure(clientOracle, stream, ex);
    }
  }

  /**
   * Standard HttpServlet method: handle the POST.
   * 
   * This doPost method swallows ALL exceptions, logs them in the
   * ServletContext, and returns a GENERIC_FAILURE_MSG response with status code
   * 500.
   * 
   * @throws IOException
   * @throws ServletException
   * @throws SerializationException
   */
  @Override
  public final void processPost(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException,
      SerializationException {

    /*
     * Get the ClientOracle before doing anything else, so that if ClientOracle
     * cannot be loaded, we haven't opened the response's OutputStream.
     */
    ClientOracle clientOracle = getClientOracle();

    // Read the request fully.
    String requestPayload = readContent(request);
    if (DUMP_PAYLOAD) {
      System.out.println(requestPayload);
    }

    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");

    // Configure the OutputStream based on configuration and capabilities
    boolean canCompress = RPCServletUtils.acceptsGzipEncoding(request)
        && shouldCompressResponse(request, response);

    OutputStream out;
    if (DUMP_PAYLOAD) {
      out = new ByteArrayOutputStream();

    } else if (canCompress) {
      RPCServletUtils.setGzipEncodingHeader(response);
      out = new GZIPOutputStream(response.getOutputStream());

    } else {
      out = response.getOutputStream();
    }

    // Invoke the core dispatching logic, which returns the serialized result.
    processCall(clientOracle, requestPayload, out);

    if (DUMP_PAYLOAD) {
      byte[] bytes = ((ByteArrayOutputStream) out).toByteArray();
      System.out.println(new String(bytes, "UTF-8"));
      response.getOutputStream().write(bytes);
    } else if (canCompress) {
      /*
       * We want to write the end of the gzip data, but not close the underlying
       * OutputStream in case there are servlet filters that want to write
       * headers after processPost().
       */
      ((GZIPOutputStream) out).finish();
    }
  }

  /**
   * Indicates whether or not an RPC request from a Development Mode client
   * should be serviced. Requests from Development Mode clients will expose
   * unobfuscated identifiers in the payload. It is intended that developers
   * override this method to restrict access based on installation-specific
   * logic (such as a range of IP addresses, checking for certain cookies, etc.)
   * <p>
   * The default implementation allows hosted-mode connections from the local
   * host, loopback addresses (127.*), site local (RFC 1918), link local
   * (169.254/16) addresses, and their IPv6 equivalents.
   *
   * @return <code>true</code> if a Development Mode connection should be
   *         allowed
   * @see #getThreadLocalRequest()
   * @see InetAddress
   */
  protected boolean allowHostedModeConnections() {
    return isRequestFromLocalAddress();
  }

  /**
   * Override this method to control access to permutation-specific data. For
   * instance, the permutation-specific data may be stored in a database in
   * order to support older clients.
   * <p>
   * The default implementation attempts to load the file from the
   * ServletContext as
   * 
   * <code>requestModuleBasePath + permutationStrongName + CLIENT_ORACLE_EXTENSION</code>
   * 
   * @param requestModuleBasePath the module's base path, modulo protocol and
   *          host, as reported by {@link #getRequestModuleBasePath()}
   * @param permutationStrongName the module's strong name as reported by
   *          {@link #getPermutationStrongName()}
   */
  protected InputStream findClientOracleData(String requestModuleBasePath,
      String permutationStrongName) throws SerializationException {
    String resourcePath = requestModuleBasePath + permutationStrongName
        + CLIENT_ORACLE_EXTENSION;
    InputStream in = getServletContext().getResourceAsStream(resourcePath);
    if (in == null) {
      throw new SerializationException(
          "Could not find ClientOracle data for permutation "
              + permutationStrongName);
    }
    return in;
  }

  /**
   * Extract the module's base path from the current request.
   * 
   * @return the module's base path, modulo protocol and host, as reported by
   *         {@link com.google.gwt.core.client.GWT#getModuleBaseURL()} or
   *         <code>null</code> if the request did not contain the
   *         {@value com.google.gwt.user.client.rpc.RpcRequestBuilder#MODULE_BASE_HEADER} header
   */
  protected final String getRequestModuleBasePath() {
    try {
      String header = getThreadLocalRequest().getHeader(MODULE_BASE_HEADER);
      if (header == null) {
        return null;
      }
      String path = new URL(header).getPath();
      String contextPath = getThreadLocalRequest().getContextPath();
      if (!path.startsWith(contextPath)) {
        return null;
      }
      return path.substring(contextPath.length());
    } catch (MalformedURLException e) {
      return null;
    }
  }

  /**
   * Determines whether the response to a given servlet request should or should
   * not be GZIP compressed. This method is only called in cases where the
   * requester accepts GZIP encoding.
   * <p>
   * This implementation currently returns <code>true</code> if the request
   * originates from a non-local address. Subclasses can override this logic.
   * </p>
   * 
   * @param request the request being served
   * @param response the response that will be written into
   * @return <code>true</code> if responsePayload should be GZIP compressed,
   *         otherwise <code>false</code>.
   */
  protected boolean shouldCompressResponse(HttpServletRequest request,
      HttpServletResponse response) {
    return !isRequestFromLocalAddress();
  }

  /**
   * Utility function to determine if the thread-local request originates from a
   * local address.
   */
  private boolean isRequestFromLocalAddress() {
    try {
      InetAddress addr = InetAddress.getByName(getThreadLocalRequest().getRemoteAddr());

      return InetAddress.getLocalHost().equals(addr)
          || addr.isLoopbackAddress() || addr.isSiteLocalAddress()
          || addr.isLinkLocalAddress();
    } catch (UnknownHostException e) {
      return false;
    }
  }
}
