/*
 * 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.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RpcToken;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.impl.AbstractSerializationStream;
import com.google.gwt.user.server.rpc.impl.DequeMap;
import com.google.gwt.user.server.rpc.impl.LegacySerializationPolicy;
import com.google.gwt.user.server.rpc.impl.SerializabilityUtil;
import com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader;
import com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter;
import com.google.gwt.user.server.rpc.impl.TypeNameObfuscator;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Utility class for integrating with the RPC system. This class exposes methods
 * for decoding of RPC requests, encoding of RPC responses, and invocation of
 * RPC calls on service objects. The operations exposed by this class can be
 * reused by framework implementors such as Spring and G4jsf to support a wide
 * range of service invocation policies.
 * 
 * <h3>Canonical Example</h3> The following example demonstrates the canonical
 * way to use this class.
 * 
 * {@example com.google.gwt.examples.rpc.server.CanonicalExample#processCall(String)}
 * 
 * <h3>Advanced Example</h3> The following example shows a more advanced way of
 * using this class to create an adapter between GWT RPC entities and POJOs.
 * 
 * {@example com.google.gwt.examples.rpc.server.AdvancedExample#doPost}
 */
public final class RPC {

  /**
   * Maps primitive wrapper classes to their corresponding primitive class.
   */
  private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS =
      new HashMap<Class<?>, Class<?>>();

  /**
   * Static map of classes to sets of interfaces (e.g. classes). Optimizes
   * lookup of interfaces for security.
   */
  private static Map<Class<?>, Set<String>> serviceToImplementedInterfacesMap;

  private static final HashMap<String, Class<?>> TYPE_NAMES;

  static {
    PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Boolean.class, Boolean.TYPE);
    PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Byte.class, Byte.TYPE);
    PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Character.class, Character.TYPE);
    PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Double.class, Double.TYPE);
    PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Float.class, Float.TYPE);
    PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Integer.class, Integer.TYPE);
    PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Long.class, Long.TYPE);
    PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Short.class, Short.TYPE);

    TYPE_NAMES = new HashMap<String, Class<?>>();
    TYPE_NAMES.put("Z", boolean.class);
    TYPE_NAMES.put("B", byte.class);
    TYPE_NAMES.put("C", char.class);
    TYPE_NAMES.put("D", double.class);
    TYPE_NAMES.put("F", float.class);
    TYPE_NAMES.put("I", int.class);
    TYPE_NAMES.put("J", long.class);
    TYPE_NAMES.put("S", short.class);

    serviceToImplementedInterfacesMap = new HashMap<Class<?>, Set<String>>();
  }

  /**
   * Returns an {@link RPCRequest} that is built by decoding the contents of an
   * encoded RPC request.
   * 
   * <p>
   * This method is equivalent to calling {@link #decodeRequest(String, Class)}
   * with <code>null</code> for the type parameter.
   * </p>
   * 
   * @param encodedRequest a string that encodes the {@link RemoteService}
   *          interface, the service method to call, and the arguments to for
   *          the service method
   * @return an {@link RPCRequest} instance
   * 
   * @throws IncompatibleRemoteServiceException if any of the following
   *           conditions apply:
   *           <ul>
   *           <li>if the types in the encoded request cannot be deserialized</li>
   *           <li>if the {@link ClassLoader} acquired from
   *           <code>Thread.currentThread().getContextClassLoader()</code>
   *           cannot load the service interface or any of the types specified
   *           in the encodedRequest</li>
   *           <li>the requested interface is not assignable to
   *           {@link RemoteService}</li>
   *           <li>the service method requested in the encodedRequest is not a
   *           member of the requested service interface</li>
   *           <li>the type parameter is not <code>null</code> and is not
   *           assignable to the requested {@link RemoteService} interface
   *           </ul>
   */
  public static RPCRequest decodeRequest(String encodedRequest) {
    return decodeRequest(encodedRequest, null);
  }

  /**
   * Returns an {@link RPCRequest} that is built by decoding the contents of an
   * encoded RPC request and optionally validating that type can handle the
   * request. If the type parameter is not <code>null</code>, the implementation
   * checks that the type is assignable to the {@link RemoteService} interface
   * requested in the encoded request string.
   * 
   * <p>
   * Invoking this method with <code>null</code> for the type parameter,
   * <code>decodeRequest(encodedRequest, null)</code>, is equivalent to calling
   * <code>decodeRequest(encodedRequest)</code>.
   * </p>
   * 
   * @param encodedRequest a string that encodes the {@link RemoteService}
   *          interface, the service method, and the arguments to pass to the
   *          service method
   * @param type if not <code>null</code>, the implementation checks that the
   *          type is assignable to the {@link RemoteService} interface encoded
   *          in the encoded request string.
   * @return an {@link RPCRequest} instance
   * 
   * @throws NullPointerException if the encodedRequest is <code>null</code>
   * @throws IllegalArgumentException if the encodedRequest is an empty string
   * @throws IncompatibleRemoteServiceException if any of the following
   *           conditions apply:
   *           <ul>
   *           <li>if the types in the encoded request cannot be deserialized</li>
   *           <li>if the {@link ClassLoader} acquired from
   *           <code>Thread.currentThread().getContextClassLoader()</code>
   *           cannot load the service interface or any of the types specified
   *           in the encodedRequest</li>
   *           <li>the requested interface is not assignable to
   *           {@link RemoteService}</li>
   *           <li>the service method requested in the encodedRequest is not a
   *           member of the requested service interface</li>
   *           <li>the type parameter is not <code>null</code> and is not
   *           assignable to the requested {@link RemoteService} interface
   *           </ul>
   */
  public static RPCRequest decodeRequest(String encodedRequest, Class<?> type) {
    return decodeRequest(encodedRequest, type, null);
  }

  /**
   * Returns an {@link RPCRequest} that is built by decoding the contents of an
   * encoded RPC request and optionally validating that type can handle the
   * request. If the type parameter is not <code>null</code>, the implementation
   * checks that the type is assignable to the {@link RemoteService} interface
   * requested in the encoded request string.
   * 
   * <p>
   * If the serializationPolicyProvider parameter is not <code>null</code>, it
   * is asked for a {@link SerializationPolicy} to use to restrict the set of
   * types that can be decoded from the request. If this parameter is
   * <code>null</code>, then only subtypes of
   * {@link com.google.gwt.user.client.rpc.IsSerializable IsSerializable} or
   * types which have custom field serializers can be decoded.
   * </p>
   * 
   * <p>
   * Invoking this method with <code>null</code> for the type parameter,
   * <code>decodeRequest(encodedRequest, null)</code>, is equivalent to calling
   * <code>decodeRequest(encodedRequest)</code>.
   * </p>
   * 
   * @param encodedRequest a string that encodes the {@link RemoteService}
   *          interface, the service method, and the arguments to pass to the
   *          service method
   * @param type if not <code>null</code>, the implementation checks that the
   *          type is assignable to the {@link RemoteService} interface encoded
   *          in the encoded request string.
   * @param serializationPolicyProvider if not <code>null</code>, the
   *          implementation asks this provider for a
   *          {@link SerializationPolicy} which will be used to restrict the set
   *          of types that can be decoded from this request
   * @return an {@link RPCRequest} instance
   * 
   * @throws NullPointerException if the encodedRequest is <code>null</code>
   * @throws IllegalArgumentException if the encodedRequest is an empty string
   * @throws IncompatibleRemoteServiceException if any of the following
   *           conditions apply:
   *           <ul>
   *           <li>if the types in the encoded request cannot be deserialized</li>
   *           <li>if the {@link ClassLoader} acquired from
   *           <code>Thread.currentThread().getContextClassLoader()</code>
   *           cannot load the service interface or any of the types specified
   *           in the encodedRequest</li>
   *           <li>the requested interface is not assignable to
   *           {@link RemoteService}</li>
   *           <li>the service method requested in the encodedRequest is not a
   *           member of the requested service interface</li>
   *           <li>the type parameter is not <code>null</code> and is not
   *           assignable to the requested {@link RemoteService} interface
   *           </ul>
   */
  public static RPCRequest decodeRequest(String encodedRequest, Class<?> type,
      SerializationPolicyProvider serializationPolicyProvider) {
    if (encodedRequest == null) {
      throw new NullPointerException("encodedRequest cannot be null");
    }

    if (encodedRequest.length() == 0) {
      throw new IllegalArgumentException("encodedRequest cannot be empty");
    }

    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

    try {
      ServerSerializationStreamReader streamReader =
          new ServerSerializationStreamReader(classLoader, serializationPolicyProvider);
      streamReader.prepareToRead(encodedRequest);

      RpcToken rpcToken = null;
      if (streamReader.hasFlags(AbstractSerializationStream.FLAG_RPC_TOKEN_INCLUDED)) {
        // Read the RPC token
        rpcToken = (RpcToken) streamReader.deserializeValue(RpcToken.class);
      }

      // Read the name of the RemoteService interface
      String serviceIntfName = maybeDeobfuscate(streamReader, streamReader.readString());

      if (type != null) {
        if (!implementsInterface(type, serviceIntfName)) {
          // The service does not implement the requested interface
          throw new IncompatibleRemoteServiceException("Blocked attempt to access interface '"
              + serviceIntfName + "', which is not implemented by '" + printTypeName(type)
              + "'; this is either misconfiguration or a hack attempt");
        }
      }

      SerializationPolicy serializationPolicy = streamReader.getSerializationPolicy();
      Class<?> serviceIntf;
      try {
        serviceIntf = getClassFromSerializedName(serviceIntfName, classLoader);
        if (!RemoteService.class.isAssignableFrom(serviceIntf)) {
          // The requested interface is not a RemoteService interface
          throw new IncompatibleRemoteServiceException(
              "Blocked attempt to access interface '"
                  + printTypeName(serviceIntf)
                  + "', which doesn't extend RemoteService; this is either "
                  + "misconfiguration or a hack attempt");
        }
      } catch (ClassNotFoundException e) {
        throw new IncompatibleRemoteServiceException("Could not locate requested interface '"
            + serviceIntfName + "' in default classloader", e);
      }

      String serviceMethodName = streamReader.readString();

      int paramCount = streamReader.readInt();
      if (paramCount > streamReader.getNumberOfTokens()) {
        throw new IncompatibleRemoteServiceException("Invalid number of parameters");
      }
      Class<?>[] parameterTypes = new Class[paramCount];

      for (int i = 0; i < parameterTypes.length; i++) {
        String paramClassName = maybeDeobfuscate(streamReader, streamReader.readString());

        try {
          parameterTypes[i] = getClassFromSerializedName(paramClassName, classLoader);
        } catch (ClassNotFoundException e) {
          throw new IncompatibleRemoteServiceException("Parameter " + i
              + " of is of an unknown type '" + paramClassName + "'", e);
        }
      }

      try {
        Method method = serviceIntf.getMethod(serviceMethodName, parameterTypes);

        // The parameter types we have are the non-parameterized versions in the
        // RPC stream. For stronger message verification, get the parameterized
        // types from the method declaration.
        Type[] methodParameterTypes = method.getGenericParameterTypes();
        DequeMap<TypeVariable<?>, Type> resolvedTypes = new DequeMap<TypeVariable<?>, Type>();

        TypeVariable<Method>[] methodTypes = method.getTypeParameters();
        for (TypeVariable<Method> methodType : methodTypes) {
          SerializabilityUtil.resolveTypes(methodType, resolvedTypes);
        }

        Object[] parameterValues = new Object[parameterTypes.length];
        for (int i = 0; i < parameterValues.length; i++) {
          parameterValues[i] = streamReader.deserializeValue(parameterTypes[i],
              methodParameterTypes[i], resolvedTypes);
        }

        return new RPCRequest(method, parameterValues, rpcToken, serializationPolicy, streamReader
            .getFlags());
      } catch (NoSuchMethodException e) {
        throw new IncompatibleRemoteServiceException(formatMethodNotFoundErrorMessage(serviceIntf,
            serviceMethodName, parameterTypes));
      }
    } catch (SerializationException ex) {
      throw new IncompatibleRemoteServiceException(ex.getMessage(), ex);
    }
  }

  /**
   * Returns a string that encodes an exception. If <code>rpcRequest</code>
   * is <code>null</code> a default serialization policy and default request
   * flags will be used. Otherwise these information are taken from
   * <code>rpcRequest</code>.
   * <p>
   * This method should be used if the RPC request could not be decoded or
   * could not be executed because of an exception thrown, e.g.
   * {@link IncompatibleRemoteServiceException}, {@link RpcTokenException}
   * </p>
   * @param rpcRequest the RPCRequest that failed to execute, may be null
   * @param cause the {@link Throwable} that was thrown
   * @return a String that encodes the exception
   * @throws SerializationException if the result cannot be serialized
   */
  public static String encodeResponseForFailedRequest(RPCRequest rpcRequest, Throwable cause)
      throws SerializationException {
    if (rpcRequest == null) {
      return RPC.encodeResponseForFailure(null, cause,
          getDefaultSerializationPolicy(), AbstractSerializationStream.DEFAULT_FLAGS);
    } else {
      return RPC.encodeResponseForFailure(null, cause,
          rpcRequest.getSerializationPolicy(), rpcRequest.getFlags());
    }
  }

  /**
   * Returns a string that encodes an exception. If method is not
   * <code>null</code>, it is an error if the exception is not in the method's
   * list of checked exceptions.
   * 
   * @param serviceMethod the method that threw the exception, may be
   *          <code>null</code>
   * @param cause the {@link Throwable} that was thrown
   * @return a string that encodes the exception
   * 
   * @throws NullPointerException if the cause is <code>null</code>
   * @throws SerializationException if the result cannot be serialized
   * @throws UnexpectedException if the result was an unexpected exception (a
   *           checked exception not declared in the serviceMethod's signature)
   */
  public static String encodeResponseForFailure(Method serviceMethod, Throwable cause)
      throws SerializationException {
    return encodeResponseForFailure(serviceMethod, cause, getDefaultSerializationPolicy());
  }

  /**
   * Returns a string that encodes an exception. If method is not
   * <code>null</code>, it is an error if the exception is not in the method's
   * list of checked exceptions.
   * 
   * <p>
   * If the serializationPolicy parameter is not <code>null</code>, it is used
   * to determine what types can be encoded as part of this response. If this
   * parameter is <code>null</code>, then only subtypes of
   * {@link com.google.gwt.user.client.rpc.IsSerializable IsSerializable} or
   * types which have custom field serializers may be encoded.
   * </p>
   * 
   * @param serviceMethod the method that threw the exception, may be
   *          <code>null</code>
   * @param cause the {@link Throwable} that was thrown
   * @param serializationPolicy determines the serialization policy to be used
   * @return a string that encodes the exception
   * 
   * @throws NullPointerException if the cause or the serializationPolicy
   *           are <code>null</code>
   * @throws SerializationException if the result cannot be serialized
   * @throws UnexpectedException if the result was an unexpected exception (a
   *           checked exception not declared in the serviceMethod's signature)
   */
  public static String encodeResponseForFailure(Method serviceMethod, Throwable cause,
      SerializationPolicy serializationPolicy) throws SerializationException {
    return encodeResponseForFailure(serviceMethod, cause, serializationPolicy,
        AbstractSerializationStream.DEFAULT_FLAGS);
  }

  public static String encodeResponseForFailure(Method serviceMethod, Throwable cause,
      SerializationPolicy serializationPolicy, int flags) throws SerializationException {
    if (cause == null) {
      throw new NullPointerException("cause cannot be null");
    }

    if (serializationPolicy == null) {
      throw new NullPointerException("serializationPolicy");
    }

    if (serviceMethod != null && !RPCServletUtils.isExpectedException(serviceMethod, cause)) {
      throw new UnexpectedException("Service method '" + getSourceRepresentation(serviceMethod)
          + "' threw an unexpected exception: " + cause.toString(), cause);
    }

    return encodeResponse(cause.getClass(), cause, true, flags, serializationPolicy);
  }

  /**
   * Returns a string that encodes the object. It is an error to try to encode
   * an object that is not assignable to the service method's return type.
   * 
   * @param serviceMethod the method whose result we are encoding
   * @param object the instance that we wish to encode
   * @return a string that encodes the object, if the object is compatible with
   *         the service method's declared return type
   * 
   * @throws IllegalArgumentException if the result is not assignable to the
   *           service method's return type
   * @throws NullPointerException if the service method is <code>null</code>
   * @throws SerializationException if the result cannot be serialized
   */
  public static String encodeResponseForSuccess(Method serviceMethod, Object object)
      throws SerializationException {
    return encodeResponseForSuccess(serviceMethod, object, getDefaultSerializationPolicy());
  }

  /**
   * Returns a string that encodes the object. It is an error to try to encode
   * an object that is not assignable to the service method's return type.
   * 
   * <p>
   * If the serializationPolicy parameter is not <code>null</code>, it is used
   * to determine what types can be encoded as part of this response. If this
   * parameter is <code>null</code>, then only subtypes of
   * {@link com.google.gwt.user.client.rpc.IsSerializable IsSerializable} or
   * types which have custom field serializers may be encoded.
   * </p>
   * 
   * @param serviceMethod the method whose result we are encoding
   * @param object the instance that we wish to encode
   * @param serializationPolicy determines the serialization policy to be used
   * @return a string that encodes the object, if the object is compatible with
   *         the service method's declared return type
   * 
   * @throws IllegalArgumentException if the result is not assignable to the
   *           service method's return type
   * @throws NullPointerException if the serviceMethod or the
   *           serializationPolicy are <code>null</code>
   * @throws SerializationException if the result cannot be serialized
   */
  public static String encodeResponseForSuccess(Method serviceMethod, Object object,
      SerializationPolicy serializationPolicy) throws SerializationException {
    return encodeResponseForSuccess(serviceMethod, object, serializationPolicy,
        AbstractSerializationStream.DEFAULT_FLAGS);
  }

  public static String encodeResponseForSuccess(Method serviceMethod, Object object,
      SerializationPolicy serializationPolicy, int flags) throws SerializationException {
    if (serviceMethod == null) {
      throw new NullPointerException("serviceMethod cannot be null");
    }

    if (serializationPolicy == null) {
      throw new NullPointerException("serializationPolicy");
    }

    Class<?> methodReturnType = serviceMethod.getReturnType();
    if (methodReturnType != void.class && object != null) {
      Class<?> actualReturnType;
      if (methodReturnType.isPrimitive()) {
        actualReturnType = getPrimitiveClassFromWrapper(object.getClass());
      } else {
        actualReturnType = object.getClass();
      }

      if (actualReturnType == null || !methodReturnType.isAssignableFrom(actualReturnType)) {
        throw new IllegalArgumentException("Type '" + printTypeName(object.getClass())
            + "' does not match the return type in the method's signature: '"
            + getSourceRepresentation(serviceMethod) + "'");
      }
    }

    return encodeResponse(methodReturnType, object, false, flags, serializationPolicy);
  }

  /**
   * Returns a default serialization policy.
   * 
   * @return the default serialization policy.
   */
  public static SerializationPolicy getDefaultSerializationPolicy() {
    return LegacySerializationPolicy.getInstance();
  }

  /**
   * Returns a string that encodes the result of calling a service method, which
   * could be the value returned by the method or an exception thrown by it.
   * 
   * <p>
   * This method does no security checking; security checking must be done on
   * the method prior to this invocation.
   * </p>
   * 
   * @param target instance on which to invoke the serviceMethod
   * @param serviceMethod the method to invoke
   * @param args arguments used for the method invocation
   * @return a string which encodes either the method's return or a checked
   *         exception thrown by the method
   * 
   * @throws SecurityException if the method cannot be accessed or if the number
   *           or type of actual and formal arguments differ
   * @throws SerializationException if an object could not be serialized by the
   *           stream
   * @throws UnexpectedException if the serviceMethod throws a checked exception
   *           that is not declared in its signature
   */
  public static String invokeAndEncodeResponse(Object target, Method serviceMethod, Object[] args)
      throws SerializationException {
    return invokeAndEncodeResponse(target, serviceMethod, args, getDefaultSerializationPolicy());
  }

  /**
   * Returns a string that encodes the result of calling a service method, which
   * could be the value returned by the method or an exception thrown by it.
   * 
   * <p>
   * If the serializationPolicy parameter is not <code>null</code>, it is used
   * to determine what types can be encoded as part of this response. If this
   * parameter is <code>null</code>, then only subtypes of
   * {@link com.google.gwt.user.client.rpc.IsSerializable IsSerializable} or
   * types which have custom field serializers may be encoded.
   * </p>
   * 
   * <p>
   * This method does no security checking; security checking must be done on
   * the method prior to this invocation.
   * </p>
   * 
   * @param target instance on which to invoke the serviceMethod
   * @param serviceMethod the method to invoke
   * @param args arguments used for the method invocation
   * @param serializationPolicy determines the serialization policy to be used
   * @return a string which encodes either the method's return or a checked
   *         exception thrown by the method
   * 
   * @throws NullPointerException if the serviceMethod or the
   *           serializationPolicy are <code>null</code>
   * @throws SecurityException if the method cannot be accessed or if the number
   *           or type of actual and formal arguments differ
   * @throws SerializationException if an object could not be serialized by the
   *           stream
   * @throws UnexpectedException if the serviceMethod throws a checked exception
   *           that is not declared in its signature
   */
  public static String invokeAndEncodeResponse(Object target, Method serviceMethod, Object[] args,
      SerializationPolicy serializationPolicy) throws SerializationException {
    return invokeAndEncodeResponse(target, serviceMethod, args, serializationPolicy,
        AbstractSerializationStream.DEFAULT_FLAGS);
  }

  public static String invokeAndEncodeResponse(Object target, Method serviceMethod, Object[] args,
      SerializationPolicy serializationPolicy, int flags) throws SerializationException {
    if (serviceMethod == null) {
      throw new NullPointerException("serviceMethod");
    }

    if (serializationPolicy == null) {
      throw new NullPointerException("serializationPolicy");
    }

    String responsePayload;
    try {
      Object result = serviceMethod.invoke(target, args);

      responsePayload = encodeResponseForSuccess(serviceMethod, result, serializationPolicy, flags);
    } catch (IllegalAccessException e) {
      SecurityException securityException =
          new SecurityException(formatIllegalAccessErrorMessage(target, serviceMethod));
      securityException.initCause(e);
      throw securityException;
    } catch (IllegalArgumentException e) {
      SecurityException securityException =
          new SecurityException(formatIllegalArgumentErrorMessage(target, serviceMethod, args));
      securityException.initCause(e);
      throw securityException;
    } catch (InvocationTargetException e) {
      // Try to encode the caught exception
      //
      Throwable cause = e.getCause();

      responsePayload = encodeResponseForFailure(serviceMethod, cause, serializationPolicy, flags);
    }

    return responsePayload;
  }

  private static int getRpcVersion() throws SerializationException {
    int version =
        Integer.getInteger("gwt.rpc.version",
            AbstractSerializationStream.SERIALIZATION_STREAM_VERSION);
    if (version < AbstractSerializationStream.SERIALIZATION_STREAM_MIN_VERSION
        || version > AbstractSerializationStream.SERIALIZATION_STREAM_MAX_VERSION) {
      throw new SerializationException("The RPC version " + version + " is not between "
          + AbstractSerializationStream.SERIALIZATION_STREAM_MIN_VERSION + " and "
          + AbstractSerializationStream.SERIALIZATION_STREAM_MAX_VERSION);
    }
    return version;
  }

  /**
   * Returns a string that encodes the results of an RPC call. Private overload
   * that takes a flag signaling the preamble of the response payload.
   * 
   * @param object the object that we wish to send back to the client
   * @param wasThrown if true, the object being returned was an exception thrown
   *          by the service method; if false, it was the result of the service
   *          method's invocation
   * @return a string that encodes the response from a service method
   * @throws SerializationException if the object cannot be serialized
   */
  private static String encodeResponse(Class<?> responseClass, Object object, boolean wasThrown,
      int flags, SerializationPolicy serializationPolicy) throws SerializationException {

    ServerSerializationStreamWriter stream =
        new ServerSerializationStreamWriter(serializationPolicy, getRpcVersion());
    stream.setFlags(flags);

    stream.prepareToWrite();
    if (responseClass != void.class) {
      stream.serializeValue(object, responseClass);
    }

    String bufferStr = (wasThrown ? "//EX" : "//OK") + stream.toString();
    return bufferStr;
  }

  private static String formatIllegalAccessErrorMessage(Object target, Method serviceMethod) {
    StringBuffer sb = new StringBuffer();
    sb.append("Blocked attempt to access inaccessible method '");
    sb.append(getSourceRepresentation(serviceMethod));
    sb.append("'");

    if (target != null) {
      sb.append(" on target '");
      sb.append(printTypeName(target.getClass()));
      sb.append("'");
    }

    sb.append("; this is either misconfiguration or a hack attempt");

    return sb.toString();
  }

  private static String formatIllegalArgumentErrorMessage(Object target, Method serviceMethod,
      Object[] args) {
    StringBuffer sb = new StringBuffer();
    sb.append("Blocked attempt to invoke method '");
    sb.append(getSourceRepresentation(serviceMethod));
    sb.append("'");

    if (target != null) {
      sb.append(" on target '");
      sb.append(printTypeName(target.getClass()));
      sb.append("'");
    }

    sb.append(" with invalid arguments");

    if (args != null && args.length > 0) {
      sb.append(Arrays.asList(args));
    }

    return sb.toString();
  }

  private static String formatMethodNotFoundErrorMessage(Class<?> serviceIntf,
      String serviceMethodName, Class<?>[] parameterTypes) {
    StringBuffer sb = new StringBuffer();

    sb.append("Could not locate requested method '");
    sb.append(serviceMethodName);
    sb.append("(");
    for (int i = 0; i < parameterTypes.length; ++i) {
      if (i > 0) {
        sb.append(", ");
      }
      sb.append(printTypeName(parameterTypes[i]));
    }
    sb.append(")'");

    sb.append(" in interface '");
    sb.append(printTypeName(serviceIntf));
    sb.append("'");

    return sb.toString();
  }

  /**
   * Returns the {@link Class} instance for the named class or primitive type.
   * 
   * @param serializedName the serialized name of a class or primitive type
   * @param classLoader the classLoader used to load {@link Class}es
   * @return Class instance for the given type name
   * @throws ClassNotFoundException if the named type was not found
   */
  private static Class<?> getClassFromSerializedName(String serializedName, ClassLoader classLoader)
      throws ClassNotFoundException {
    Class<?> value = TYPE_NAMES.get(serializedName);
    if (value != null) {
      return value;
    }

    return Class.forName(serializedName, false, classLoader);
  }

  /**
   * Returns the {@link java.lang.Class Class} for a primitive type given its
   * corresponding wrapper {@link java.lang.Class Class}.
   * 
   * @param wrapperClass primitive wrapper class
   * @return primitive class
   */
  private static Class<?> getPrimitiveClassFromWrapper(Class<?> wrapperClass) {
    return PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.get(wrapperClass);
  }

  /**
   * Returns the source representation for a method signature.
   * 
   * @param method method to get the source signature for
   * @return source representation for a method signature
   */
  private static String getSourceRepresentation(Method method) {
    return method.toString().replace('$', '.');
  }

  /**
   * Used to determine whether the specified interface name is implemented by
   * the service class. This is done without loading the class (for security).
   */
  private static boolean implementsInterface(Class<?> service, String intfName) {
    synchronized (serviceToImplementedInterfacesMap) {
      // See if it's cached.
      //
      Set<String> interfaceSet = serviceToImplementedInterfacesMap.get(service);
      if (interfaceSet != null) {
        if (interfaceSet.contains(intfName)) {
          return true;
        }
      } else {
        interfaceSet = new HashSet<String>();
        serviceToImplementedInterfacesMap.put(service, interfaceSet);
      }

      if (!service.isInterface()) {
        while ((service != null) && !RemoteServiceServlet.class.equals(service)) {
          Class<?>[] intfs = service.getInterfaces();
          for (Class<?> intf : intfs) {
            if (implementsInterfaceRecursive(intf, intfName)) {
              interfaceSet.add(intfName);
              return true;
            }
          }

          // did not find the interface in this class so we look in the
          // superclass
          //
          service = service.getSuperclass();
        }
      } else {
        if (implementsInterfaceRecursive(service, intfName)) {
          interfaceSet.add(intfName);
          return true;
        }
      }

      return false;
    }
  }

  /**
   * Only called from implementsInterface().
   */
  private static boolean implementsInterfaceRecursive(Class<?> clazz, String intfName) {
    assert (clazz.isInterface());

    if (clazz.getName().equals(intfName)) {
      return true;
    }

    // search implemented interfaces
    Class<?>[] intfs = clazz.getInterfaces();
    for (Class<?> intf : intfs) {
      if (implementsInterfaceRecursive(intf, intfName)) {
        return true;
      }
    }

    return false;
  }

  /**
   * Given a type identifier in the stream, attempt to deobfuscate it. Retuns
   * the original identifier if deobfuscation is unnecessary or no mapping is
   * known.
   */
  private static String maybeDeobfuscate(ServerSerializationStreamReader streamReader, String name)
      throws SerializationException {
    int index;
    if (streamReader.hasFlags(AbstractSerializationStream.FLAG_ELIDE_TYPE_NAMES)) {
      SerializationPolicy serializationPolicy = streamReader.getSerializationPolicy();
      if (!(serializationPolicy instanceof TypeNameObfuscator)) {
        throw new IncompatibleRemoteServiceException(
            "RPC request was encoded with obfuscated type names, "
                + "but the SerializationPolicy in use does not implement "
                + TypeNameObfuscator.class.getName());
      }

      String maybe = ((TypeNameObfuscator) serializationPolicy).getClassNameForTypeId(name);
      if (maybe != null) {
        return maybe;
      }
    } else if ((index = name.indexOf('/')) != -1) {
      return name.substring(0, index);
    }
    return name;
  }

  /**
   * Straight copy from
   * {@link com.google.gwt.dev.util.TypeInfo#getSourceRepresentation(Class)} to
   * avoid runtime dependency on gwt-dev.
   */
  private static String printTypeName(Class<?> type) {
    // Primitives
    //
    if (type.equals(Integer.TYPE)) {
      return "int";
    } else if (type.equals(Long.TYPE)) {
      return "long";
    } else if (type.equals(Short.TYPE)) {
      return "short";
    } else if (type.equals(Byte.TYPE)) {
      return "byte";
    } else if (type.equals(Character.TYPE)) {
      return "char";
    } else if (type.equals(Boolean.TYPE)) {
      return "boolean";
    } else if (type.equals(Float.TYPE)) {
      return "float";
    } else if (type.equals(Double.TYPE)) {
      return "double";
    }

    // Arrays
    //
    if (type.isArray()) {
      Class<?> componentType = type.getComponentType();
      return printTypeName(componentType) + "[]";
    }

    // Everything else
    //
    return type.getName().replace('$', '.');
  }

  /**
   * Static classes have no constructability.
   */
  private RPC() {
    // Not instantiable
  }
}
