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

import com.google.gwt.core.shared.GWT;
import com.google.gwt.user.client.rpc.CustomFieldSerializer;
import com.google.gwt.user.client.rpc.GwtTransient;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.SerializationStreamWriter;
import com.google.gwt.user.server.rpc.RPCServletUtils;
import com.google.gwt.user.server.rpc.SerializationPolicy;
import com.google.gwt.user.server.rpc.ServerCustomFieldSerializer;

import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.zip.CRC32;

/**
 * Serialization utility class used by the server-side RPC code.
 */
public class SerializabilityUtil {
  /**
   * Comparator used to sort fields.
   */
  public static final Comparator<Field> FIELD_COMPARATOR = new Comparator<Field>() {
    @Override
    public int compare(Field f1, Field f2) {
      return f1.getName().compareTo(f2.getName());
    }
  };

  /**
   * A permanent cache of all computed CRCs on classes. This is safe to do
   * because a Class is guaranteed not to change within the lifetime of a
   * ClassLoader (and thus, this Map).
   */
  private static final Map<Class<?>, String> classCRC32Cache =
      new ConcurrentHashMap<Class<?>, String>();

  /**
   * A permanent cache of all serializable fields on classes. This is safe to do
   * because a Class is guaranteed not to change within the lifetime of a
   * ClassLoader (and thus, this Map).
   */
  private static final Map<Class<?>, Field[]> classSerializableFieldsCache =
      new ConcurrentHashMap<Class<?>, Field[]>();

  /**
   * A permanent cache of all which classes onto custom field serializers. This
   * is safe to do because a Class is guaranteed not to change within the
   * lifetime of a ClassLoader (and thus, this Map).
   */
  private static final Map<Class<?>, Class<?>> classCustomSerializerCache =
      new ConcurrentHashMap<Class<?>, Class<?>>();

  /**
   * A permanent cache of all which classes onto server-side custom field
   * serializers. This is safe to do because a Class is guaranteed not to change
   * within the lifetime of a ClassLoader (and thus, this Map).
   */
  private static final Map<Class<?>, Class<?>> classServerCustomSerializerCache =
      new ConcurrentHashMap<Class<?>, Class<?>>();

  /**
   * Map of {@link Class} objects to singleton instances of that
   * {@link CustomFieldSerializer}.
   */
  private static final Map<Class<?>, CustomFieldSerializer<?>> CLASS_TO_SERIALIZER_INSTANCE =
      new ConcurrentHashMap<Class<?>, CustomFieldSerializer<?>>();

  private static final String JRE_SERVER_SERIALIZER_PACKAGE = "com.google.gwt.user.server.rpc.core";
  private static final String JRE_SERIALIZER_PACKAGE = "com.google.gwt.user.client.rpc.core";

  /**
   * A re-usable, non-functional {@link ServerCustomFieldSerializer} for when
   * the Server Custom Field Serializer does not implement the
   * {@link ServerCustomFieldSerializer} interface.
   */
  private static final ServerCustomFieldSerializer<?> NO_SUCH_SERIALIZER =
      new ServerCustomFieldSerializer<Object>() {
        @Override
        public void deserializeInstance(SerializationStreamReader streamReader, Object instance) {
          throw new AssertionError("This should never be called.");
        }

        @Override
        public void deserializeInstance(ServerSerializationStreamReader streamReader,
            Object instance, Type[] expectedParameterTypes,
            DequeMap<TypeVariable<?>, Type> resolvedTypes) throws SerializationException {
          throw new SerializationException("This should never be called.");
        }

        @Override
        public void serializeInstance(SerializationStreamWriter streamWriter, Object instance) {
          throw new AssertionError("This should never be called.");
        }
      };

  private static final Map<String, String> SERIALIZED_PRIMITIVE_TYPE_NAMES =
      new HashMap<String, String>();

  private static final Set<Class<?>> TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES =
      new HashSet<Class<?>>();

  static {

    SERIALIZED_PRIMITIVE_TYPE_NAMES.put(boolean.class.getName(), "Z");
    SERIALIZED_PRIMITIVE_TYPE_NAMES.put(byte.class.getName(), "B");
    SERIALIZED_PRIMITIVE_TYPE_NAMES.put(char.class.getName(), "C");
    SERIALIZED_PRIMITIVE_TYPE_NAMES.put(double.class.getName(), "D");
    SERIALIZED_PRIMITIVE_TYPE_NAMES.put(float.class.getName(), "F");
    SERIALIZED_PRIMITIVE_TYPE_NAMES.put(int.class.getName(), "I");
    SERIALIZED_PRIMITIVE_TYPE_NAMES.put(long.class.getName(), "J");
    SERIALIZED_PRIMITIVE_TYPE_NAMES.put(short.class.getName(), "S");

    TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Boolean.class);
    TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Byte.class);
    TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Character.class);
    TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Double.class);
    TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Exception.class);
    TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Float.class);
    TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Integer.class);
    TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Long.class);
    TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Object.class);
    TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Short.class);
    TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(String.class);
    TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(Throwable.class);

    try {
      /*
       * Work around for incompatible type hierarchy (and therefore signature)
       * between JUnit3 and JUnit4. Do this via reflection so we don't force the
       * server to depend on JUnit.
       */
      Class<?> clazz = Class.forName("junit.framework.AssertionFailedError");
      TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.add(clazz);
    } catch (ClassNotFoundException dontCare) {
      // Empty because we don't care
    }
  }

  /**
   * Returns the fields of a particular class that can be considered for
   * serialization. The returned list will be sorted into a canonical order to
   * ensure consistent answers.
   */
  public static Field[] applyFieldSerializationPolicy(Class<?> clazz) {
    Field[] serializableFields;
    serializableFields = classSerializableFieldsCache.get(clazz);
    if (serializableFields == null) {
      ArrayList<Field> fieldList = new ArrayList<Field>();
      Field[] fields = clazz.getDeclaredFields();
      for (Field field : fields) {
        if (fieldQualifiesForSerialization(field)) {
          fieldList.add(field);
        }
      }
      serializableFields = fieldList.toArray(new Field[fieldList.size()]);

      // sort the fields by name
      Arrays.sort(serializableFields, 0, serializableFields.length, FIELD_COMPARATOR);

      classSerializableFieldsCache.put(clazz, serializableFields);
    }
    return serializableFields;
  }

  public static SerializedInstanceReference decodeSerializedInstanceReference(
      String encodedSerializedInstanceReference) {
    final String[] components =
        encodedSerializedInstanceReference
            .split(SerializedInstanceReference.SERIALIZED_REFERENCE_SEPARATOR);
    return new SerializedInstanceReference() {
      @Override
      public String getName() {
        return components.length > 0 ? components[0] : "";
      }

      @Override
      public String getSignature() {
        return components.length > 1 ? components[1] : "";
      }
    };
  }

  public static String encodeSerializedInstanceReference(Class<?> instanceType,
      SerializationPolicy policy) {
    return instanceType.getName() + SerializedInstanceReference.SERIALIZED_REFERENCE_SEPARATOR
        + getSerializationSignature(instanceType, policy);
  }

  /**
   * Return the concrete type that a generic type maps to, if known.
   *
   * @param genericType The generic type to resolve.
   * @param resolvedTypes A map of generic types to actual types.
   * @return The actual type, which may be of any subclass of Type.
   */
  public static Type findActualType(Type genericType,
      DequeMap<TypeVariable<?>, Type> resolvedTypes) {
    Type result = genericType;
    // Look for things that TypeVariables are mapped to, but stop if mapped
    // to itself. We map a TypeVariable to itself when we wish to explicitly
    // mark it as unmapped.
    while (result instanceof TypeVariable<?> &&
        resolvedTypes.get((TypeVariable<?>) result) != result &&
        resolvedTypes.get((TypeVariable<?>) result) != null) {
      result = resolvedTypes.get((TypeVariable<?>) result);
    }

    return result;
  }

  /**
   * Determine the expected types for any instance type parameters.
   *
   * This method also determines whether or not the instance can be assigned to
   * the expected type. We combine the tasks because they require traversing the
   * same data structures.
   *
   * @param instanceClass The instance for which we want generic parameter types
   * @param expectedType The type we are expecting this instance to be
   * @param resolvedTypes The types that have been resolved to actual values
   * @return The expected types of the instance class' parameters. If null, the
   *     instance class is not assignable to the expected type.
   */
  public static Type[] findExpectedParameterTypes(Class<?> instanceClass,
      Type expectedType, DequeMap<TypeVariable<?>, Type> resolvedTypes) {
    // Make a copy of the instance parameters from its class
    TypeVariable<?>[] instanceTypes = instanceClass.getTypeParameters();
    Type[] expectedParameterTypes = Arrays.copyOf(instanceTypes, instanceTypes.length,
        Type[].class);

    // Determine the type we are really expecting, to the best of our knowledge
    if (expectedType == null) {
      // Match up parameters assuming that the instance class is the best match
      // for the expected class, which we can only do if we have resolved types.
      if (resolvedTypes != null) {
        findInstanceParameters(instanceClass, resolvedTypes, expectedParameterTypes);
      }

      // With no expected type, the instance is assignable and we fall through
    } else {
      // First determine what type we are really expecting. The type may still
      // be a TypeVariable<?> at this time when we are deserializing class
      // fields or components of another data structure.
      Type actualType = findActualType(expectedType, resolvedTypes);

      // Try to match the instanceClass to the expected type, updating the
      // expectedParameterTypes so that we can track them back to the resolved
      // types once we determine what class to treat the instance as. In
      // this method, only type information from the instance is used to resolve
      // types because the information in the resolved types map is only
      // relevant to the expected type(s). We still pass in the resolvedTypes
      // because we may need to resolve expected types.
      // Note that certain expected types may require the instance to extend
      // or implement multiple classes or interfaces, so we may capture multiple
      // types here.
      Set<Class<?>> expectedInstanceClasses = new HashSet<Class<?>>();
      if (!findExpectedInstanceClass(instanceClass, actualType,
          resolvedTypes, expectedInstanceClasses, expectedParameterTypes)) {
        // If we could not match the instance to the expected, it is not assignable
        // and we are done.
        return null;
      }

      // Now that we know what class the instance should be,
      // get any remaining parameters using resolved types.
      if (resolvedTypes != null) {
        for (Class<?> expectedClass : expectedInstanceClasses) {
          findInstanceParameters(expectedClass, resolvedTypes, expectedParameterTypes);
        }
      }
    }

    return expectedParameterTypes;
  }

  /**
   * Find the Class that a given type refers to.
   *
   * @param type The type of interest
   * @return The Class that type represents
   */
  public static Class<?> getClassFromType(Type type,
      DequeMap<TypeVariable<?>, Type> resolvedTypes) {
    Type actualType = findActualType(type, resolvedTypes);
    if (actualType instanceof Class) {
      return (Class<?>) actualType;
    }
    if (type instanceof ParameterizedType) {
      return getClassFromType(((ParameterizedType) actualType).getRawType(), resolvedTypes);
    }
    return null;
  }

  public static String getSerializationSignature(Class<?> instanceType,
      SerializationPolicy policy) {
    String result;
    result = classCRC32Cache.get(instanceType);
    if (result == null) {
      CRC32 crc = new CRC32();
      try {
        generateSerializationSignature(instanceType, crc, policy);
      } catch (UnsupportedEncodingException e) {
        throw new RuntimeException("Could not compute the serialization signature", e);
      }
      result = Long.toString(crc.getValue());
      classCRC32Cache.put(instanceType, result);
    }
    return result;
  }

  public static String getSerializedTypeName(Class<?> instanceType) {
    if (instanceType.isPrimitive()) {
      return SERIALIZED_PRIMITIVE_TYPE_NAMES.get(instanceType.getName());
    }

    return instanceType.getName();
  }

  /**
   * Returns the {@link Class} which can serialize the given instance type, or
   * <code>null</code> if this class has no custom field serializer.
   *
   * Note that arrays never have custom field serializers.
   */
  public static Class<?> hasCustomFieldSerializer(Class<?> instanceType) {
    assert (instanceType != null);
    if (instanceType.isArray()) {
      return null;
    }

    Class<?> result;
    result = classCustomSerializerCache.get(instanceType);
    if (result == null) {
      result = computeHasCustomFieldSerializer(instanceType, false);
      if (result == null) {
        /*
         * Use (result == instanceType) as a sentinel value when the class has
         * no custom field serializer. We avoid using null as the sentinel
         * value, because that would necessitate an additional containsKey()
         * check in the most common case.
         */
        result = instanceType;
      }
      classCustomSerializerCache.put(instanceType, result);
    }
    return (result == instanceType) ? null : result;
  }

  /**
   * Returns the server-side {@link Class} which can serialize the given
   * instance type, or <code>null</code> if this class has no type-checking
   * custom field serializer.
   *
   * Note that arrays never have custom field serializers.
   */
  public static Class<?> hasServerCustomFieldSerializer(Class<?> instanceType) {
    assert (instanceType != null);
    if (instanceType.isArray()) {
      return null;
    }

    Class<?> result;
    result = classServerCustomSerializerCache.get(instanceType);
    if (result == null) {
      result = computeHasCustomFieldSerializer(instanceType, true);
      if (result == null) {
        /*
         * Use (result == instanceType) as a sentinel value when the class has
         * no custom field serializer. We avoid using null as the sentinel
         * value, because that would necessitate an additional containsKey()
         * check in the most common case.
         */
        result = instanceType;
      }
      classServerCustomSerializerCache.put(instanceType, result);
    }
    return (result == instanceType) ? null : result;
  }

  /**
   * Remove all of the actual types that arose from the the given type.
   *
   * This method should always be called after a corresponding call to
   * resolveTypes.
   *
   * @param methodType The type we wish to assign this instance to
   * @param resolvedTypes The types that have been resolved to actual values
   */
  public static void releaseTypes(Type methodType, DequeMap<TypeVariable<?>, Type> resolvedTypes) {
    SerializabilityUtil.resolveTypesWorker(methodType, resolvedTypes, false);
  }

  /**
   * Find all the actual types we can from the information in the given type,
   * and put the mapping from TypeVariable objects to actual types into the
   * resolved types map.
   *
   * The method releaseTypes should always be called after a call to this
   * method, unless the resolved types map is about to be discarded.
   *
   * @param methodType The type we wish to assign this instance to
   * @param resolvedTypes The types that have been resolved to actual values
   */
  public static void resolveTypes(Type methodType, DequeMap<TypeVariable<?>, Type> resolvedTypes) {
    SerializabilityUtil.resolveTypesWorker(methodType, resolvedTypes, true);
  }

  /**
   * Returns true if this field has an annotation named "GwtTransient".
   */
  static boolean hasGwtTransientAnnotation(Field field) {
    for (Annotation a : field.getAnnotations()) {
      if (a.annotationType().getSimpleName().equals(GwtTransient.class.getSimpleName())) {
        return true;
      }
    }
    return false;
  }

  static boolean isNotStaticTransientOrFinal(Field field) {
    /*
     * Only serialize fields that are not static, transient (including
     * @GwtTransient), or final.
     */
    int fieldModifiers = field.getModifiers();
    return !Modifier.isStatic(fieldModifiers) && !Modifier.isTransient(fieldModifiers)
        && !hasGwtTransientAnnotation(field) && !Modifier.isFinal(fieldModifiers);
  }

  /**
   * Loads a {@link CustomFieldSerializer} from a class that may implement that
   * interface.
   *
   * @param customSerializerClass the Custom Field Serializer class
   *
   * @return an instance the class provided if it implements
   *         {@link CustomFieldSerializer} or {@code null} if it does not
   *
   * @throws SerializationException if the load process encounters an unexpected
   *           problem
   */
  static CustomFieldSerializer<?> loadCustomFieldSerializer(final Class<?> customSerializerClass)
      throws SerializationException {
    CustomFieldSerializer<?> customFieldSerializer =
        CLASS_TO_SERIALIZER_INSTANCE.get(customSerializerClass);
    if (customFieldSerializer == null) {
      if (CustomFieldSerializer.class.isAssignableFrom(customSerializerClass)) {
        try {
          customFieldSerializer = (CustomFieldSerializer<?>) customSerializerClass.newInstance();
        } catch (InstantiationException e) {
          throw new SerializationException(e);

        } catch (IllegalAccessException e) {
          throw new SerializationException(e);
        }
      } else {
        customFieldSerializer = NO_SUCH_SERIALIZER;
      }
      CLASS_TO_SERIALIZER_INSTANCE.put(customSerializerClass, customFieldSerializer);
    }
    if (customFieldSerializer == NO_SUCH_SERIALIZER) {
      return null;
    } else {
      return customFieldSerializer;
    }
  }

  /**
   * This method treats arrays in a special way.
   */
  private static Class<?> computeHasCustomFieldSerializer(Class<?> instanceType,
      Boolean typeChecked) {
    assert (instanceType != null);
    String qualifiedTypeName = instanceType.getName();
    /*
     * This class is called from client code running in Development Mode as well
     * as server code running in the servlet container. In Development Mode, we
     * want to load classes through the
     * CompilingClassLoader$MultiParentClassLoader, not the system classloader.
     */
    ClassLoader classLoader =
        GWT.isClient() ? SerializabilityUtil.class.getClassLoader() : Thread.currentThread()
            .getContextClassLoader();

    if (typeChecked) {
      /*
       * Look for a server-specific version of the custom field serializer.
       * Server-side versions do additional type checking before deserializing a
       * class, offering protection against certain malicious attacks on the
       * server via RPC.
       */
      String serverSerializerName = qualifiedTypeName + "_ServerCustomFieldSerializer";
      serverSerializerName = serverSerializerName.replaceFirst("client", "server");
      Class<?> serverCustomSerializer = getCustomFieldSerializer(classLoader, serverSerializerName);
      if (serverCustomSerializer != null) {
        return serverCustomSerializer;
      }

      // Try with the regular name
      serverCustomSerializer =
          getCustomFieldSerializer(classLoader, JRE_SERVER_SERIALIZER_PACKAGE + "."
              + serverSerializerName);
      if (serverCustomSerializer != null) {
        return serverCustomSerializer;
      }
    }

    // Look for client side serializers.
    String simpleSerializerName = qualifiedTypeName + "_CustomFieldSerializer";
    Class<?> customSerializer = getCustomFieldSerializer(classLoader, simpleSerializerName);
    if (customSerializer != null) {
      return customSerializer;
    }

    // Try with the regular name
    customSerializer =
        getCustomFieldSerializer(classLoader, JRE_SERIALIZER_PACKAGE + "." + simpleSerializerName);
    if (customSerializer != null) {
      return customSerializer;
    }

    return null;
  }

  private static boolean excludeImplementationFromSerializationSignature(Class<?> instanceType) {
    if (TYPES_WHOSE_IMPLEMENTATION_IS_EXCLUDED_FROM_SIGNATURES.contains(instanceType)) {
      return true;
    }
    return false;
  }

  private static boolean fieldQualifiesForSerialization(Field field) {
    if (Throwable.class == field.getDeclaringClass()) {
      /**
       * Only serialize Throwable's detailMessage field; all others are ignored.
       *
       * NOTE: Changing the set of fields that we serialize for Throwable will
       * necessitate a change to our JRE emulation's version of Throwable.
       */
      if ("detailMessage".equals(field.getName())) {
        assert (isNotStaticTransientOrFinal(field));
        return true;
      } else {
        return false;
      }
    } else {
      return isNotStaticTransientOrFinal(field);
    }
  }

  private static boolean findExpectedInstanceClass(Class<?> instanceClass,
      Type expectedType, DequeMap<TypeVariable<?>, Type> resolvedTypes,
      Set<Class<?>> expectedInstanceClasses, Type[] expectedParameterTypes) {
    // Check for an exact match for the instance class and the expected type.
    // If found, we can return. For expected types that allow one of several
    // possible class to match (wildcards, type variables) see if this
    // instance matches any of the allowed types.
    if (expectedType instanceof TypeVariable) {
      // Every bound must have a match
      Type[] typeVariableBounds = ((TypeVariable<?>) expectedType).getBounds();
      for (Type boundType : typeVariableBounds) {
        if (!findExpectedInstanceClass(instanceClass, boundType, resolvedTypes,
            expectedInstanceClasses, expectedParameterTypes)) {
          return false;
        }
      }
      return true;
    } else if (expectedType instanceof ParameterizedType) {
      ParameterizedType paramType = (ParameterizedType) expectedType;
      if (paramType.getRawType() == instanceClass) {
        expectedInstanceClasses.add(instanceClass);
        return true;
      }
    } else if (expectedType instanceof GenericArrayType) {
      if (instanceClass.isArray()) {
        expectedInstanceClasses.add(instanceClass);
        return true;
      }
    } else if (expectedType instanceof WildcardType) {
      WildcardType wildcardType = (WildcardType) expectedType;

      Type[] lowerBounds = wildcardType.getLowerBounds();
      for (Type type : lowerBounds) {
        /* Require instance to be a superclass of type, or type itself. */
        Class<?> boundClass = getClassFromType(type, resolvedTypes);

        while (boundClass != null) {
          if (instanceClass == boundClass) {
            expectedInstanceClasses.add(boundClass);
            break;
          }
          boundClass = boundClass.getSuperclass();
        }

        // We fail if the class does not meet any bound, as we should.
        if (boundClass == null) {
          return false;
        }
      }

      Type[] upperBounds = wildcardType.getUpperBounds();
      for (Type type : upperBounds) {
        /* Require instanceClass to be a subclass of type. */
        if (!findExpectedInstanceClass(instanceClass, type, resolvedTypes,
            expectedInstanceClasses, expectedParameterTypes)) {
          return false;
        }
      }
      return true;
    } else if (((Class<?>) expectedType).getComponentType() != null) {
      // Array types just pass through here, and we catch any problems when
      // we try to deserialize the entries.
      if (((Class<?>) expectedType).isAssignableFrom(instanceClass)) {
        expectedInstanceClasses.add(instanceClass);
        return true;
      } else {
        return false;
      }
    } else if (((Class<?>) expectedType) == instanceClass) {
      expectedInstanceClasses.add(instanceClass);
      return true;
    }

    // We know that the instance class does not exactly match the expected type,
    // so try its superclass and its interfaces. At the same time, update any
    // expected types to use the superclass or interface type. We know at this
    // point that the expected type does not involve wildcards or TypeVariables,
    // so we know that the first thing to return true indicates we are done,
    // and failure of anything to return true means the instance does not meet
    // the expected type.
    if (instanceClass.getGenericSuperclass() != null) {
      Type[] localTypes = expectedParameterTypes.clone();
      if (findExpectedInstanceClassFromSuper(instanceClass.getGenericSuperclass(), expectedType,
          resolvedTypes, expectedInstanceClasses, localTypes)) {
        for (int i = 0; i < expectedParameterTypes.length; ++i) {
          expectedParameterTypes[i] = localTypes[i];
        }
        return true;
      }
    }

    Type[] interfaces = instanceClass.getGenericInterfaces();
    for (Type interfaceType : interfaces) {
      Type[] localTypes = expectedParameterTypes.clone();
      if (findExpectedInstanceClassFromSuper(interfaceType, expectedType, resolvedTypes,
          expectedInstanceClasses, localTypes)) {
        for (int i = 0; i < expectedParameterTypes.length; ++i) {
          expectedParameterTypes[i] = localTypes[i];
        }
        return true;
      }
    }

    return false;
  }

  private static boolean findExpectedInstanceClassFromSuper(
      Type superType, Type expectedType, DequeMap<TypeVariable<?>, Type> resolvedTypes,
      Set<Class<?>> expectedInstanceClasses, Type[] expectedParameterTypes) {

    if (superType instanceof GenericArrayType) {
      // Can't use array types as supertypes or interfaces
      return false;
    } else if (superType instanceof Class) {
      // No additional type info from the superclass
      return findExpectedInstanceClass((Class<?>) superType, expectedType, resolvedTypes,
          expectedInstanceClasses, expectedParameterTypes);
    } else if (superType instanceof ParameterizedType) {
      ParameterizedType paramType = (ParameterizedType) superType;
      Type rawType = paramType.getRawType();

      if (rawType instanceof Class) {
        Class<?> rawClass = (Class<?>) rawType;
        TypeVariable<?>[] classGenericTypes = rawClass.getTypeParameters();
        Type[] actualTypes = paramType.getActualTypeArguments();

        for (int i = 0; i < actualTypes.length; ++i) {
          for (int j = 0; j < expectedParameterTypes.length; ++j) {
            if (actualTypes[i] == expectedParameterTypes[j]) {
              expectedParameterTypes[j] = classGenericTypes[i];
            }
          }
        }
        return findExpectedInstanceClass(rawClass, expectedType, resolvedTypes,
            expectedInstanceClasses, expectedParameterTypes);
      }
    } else if (superType instanceof WildcardType) {
      WildcardType wildcardType = (WildcardType) superType;
      Type[] upperBounds = wildcardType.getUpperBounds();
      for (Type boundType : upperBounds) {
        if (findExpectedInstanceClassFromSuper(boundType, expectedType,
            resolvedTypes, expectedInstanceClasses, expectedParameterTypes)) {
          return true;
        }
      }
    }

    return false;
  }

    /**
   * Attempt to find known type for TypeVariable type from an instance.
   *
   * @param foundParameter The currently known parameter, which must be of type
   *          TypeVariable
   * @param instanceType The instance that we need to check for information
   *          about the type
   * @param resolvedTypes The map of known relationships between Type objects
   * @return A new value for the foundParameter, if we find one
   */
  private static Type findInstanceParameter(Type foundParameter, Type instanceType,
      DequeMap<TypeVariable<?>, Type> resolvedTypes) {
    // See what we know about the types that are matched to this type.
    if (instanceType instanceof GenericArrayType) {
      return findInstanceParameter(foundParameter, ((GenericArrayType) instanceType)
          .getGenericComponentType(), resolvedTypes);
    } else if (instanceType instanceof ParameterizedType) {
      ParameterizedType paramType = (ParameterizedType) instanceType;
      Type rawType = paramType.getRawType();

      if (rawType instanceof Class) {
        Class<?> rawClass = (Class<?>) rawType;
        TypeVariable<?>[] classGenericTypes = rawClass.getTypeParameters();
        Type[] actualTypes = paramType.getActualTypeArguments();

        for (int i = 0; i < actualTypes.length; ++i) {
          if (actualTypes[i] == foundParameter) {
            // Check if we already know about this type.
            Type capturedType = findActualType(classGenericTypes[i], resolvedTypes);
            if (capturedType != classGenericTypes[i]) {
              return capturedType;
            }

            if (rawClass.getGenericSuperclass() != null) {
              Type superParameter =
                  findInstanceParameter(classGenericTypes[i], rawClass.getGenericSuperclass(),
                      resolvedTypes);
              if (!(superParameter instanceof TypeVariable)) {
                return superParameter;
              }
            }
            Type[] rawInterfaces = rawClass.getGenericInterfaces();
            for (Type interfaceType : rawInterfaces) {
              Type interfaceParameter =
                  findInstanceParameter(classGenericTypes[i], interfaceType, resolvedTypes);
              if (!(interfaceParameter instanceof TypeVariable)) {
                return interfaceParameter;
              }
            }
          }
        }
      }
    } else if (instanceType instanceof WildcardType) {
      WildcardType wildcardType = (WildcardType) instanceType;
      Type[] upperBounds = wildcardType.getUpperBounds();
      for (Type boundType : upperBounds) {
        Type wildcardParameter = findInstanceParameter(foundParameter, boundType, resolvedTypes);
        if (!(wildcardParameter instanceof TypeVariable)) {
          return wildcardParameter;
        }
      }
    }

    return foundParameter;
  }

  /**
   * Attempt to find the actual types for the generic parameters of an instance,
   * given the types we have resolved from the method signature or class field
   * declaration.
   *
   * @param instanceClass The instance for which we want actual generic
   *          parameter types.
   * @param resolvedTypes The types that have been resolved to actual values
   * @param expectedParameterTypes An array of types representing the actual
   *         declared types for the  parameters of the instanceClass. Some may
   *         be of type TypeVariable, in which case they need to be resolved, if
   *         possible, by this method.
   */
  private static void findInstanceParameters(Class<?> instanceClass,
      DequeMap<TypeVariable<?>, Type> resolvedTypes, Type[] expectedParameterTypes) {
    TypeVariable<?>[] instanceTypes = instanceClass.getTypeParameters();

    for (int i = 0; i < expectedParameterTypes.length; ++i) {
      if (!(expectedParameterTypes[i] instanceof TypeVariable)) {
        // We already have an actual type
        continue;
      }

      // Check if we already know about this type.
      boolean haveMatch = false;
      for (int j = 0; !haveMatch && j < instanceTypes.length; ++j) {
        if (expectedParameterTypes[i] == instanceTypes[j]) {
          Type capturedType = findActualType(instanceTypes[j], resolvedTypes);
          if (!(capturedType instanceof TypeVariable)) {
            expectedParameterTypes[i] = capturedType;
            haveMatch = true;
          }
        }
      }
      if (haveMatch) {
        continue;
      }

      // Check if it is defined by superclasses
      if (instanceClass.getGenericSuperclass() != null) {
        Type superParameter = findInstanceParameter(expectedParameterTypes[i],
                instanceClass.getGenericSuperclass(), resolvedTypes);
        if (!(superParameter instanceof TypeVariable)) {
          expectedParameterTypes[i] = superParameter;
          continue;
        }
      }

      // Check if it is defined by interfaces
      Type[] interfaceTypes = instanceClass.getGenericInterfaces();
      for (Type interfaceType : interfaceTypes) {
        Type interfaceParameter =
            findInstanceParameter(expectedParameterTypes[i], interfaceType, resolvedTypes);
        if (!(interfaceParameter instanceof TypeVariable)) {
          expectedParameterTypes[i] = interfaceParameter;
          break;
        }
      }
    }
  }

  private static void generateSerializationSignature(Class<?> instanceType, CRC32 crc,
      SerializationPolicy policy) throws UnsupportedEncodingException {
    crc.update(getSerializedTypeName(instanceType).getBytes(RPCServletUtils.CHARSET_UTF8));

    if (excludeImplementationFromSerializationSignature(instanceType)) {
      return;
    }

    Class<?> customSerializer = hasCustomFieldSerializer(instanceType);
    if (customSerializer != null) {
      generateSerializationSignature(customSerializer, crc, policy);
    } else if (instanceType.isArray()) {
      generateSerializationSignature(instanceType.getComponentType(), crc, policy);
    } else if (!instanceType.isPrimitive()) {
      Field[] fields = applyFieldSerializationPolicy(instanceType);
      Set<String> clientFieldNames = policy.getClientFieldNamesForEnhancedClass(instanceType);
      for (Field field : fields) {
        assert (field != null);
        /**
         * If clientFieldNames is non-null, use only the fields listed there to
         * generate the signature. Otherwise, use all known fields.
         */
        if ((clientFieldNames == null) || clientFieldNames.contains(field.getName())) {
          crc.update(field.getName().getBytes(RPCServletUtils.CHARSET_UTF8));
          crc.update(getSerializedTypeName(field.getType()).getBytes(RPCServletUtils.CHARSET_UTF8));
        }
      }

      Class<?> superClass = instanceType.getSuperclass();
      if (superClass != null) {
        generateSerializationSignature(superClass, crc, policy);
      }
    }
  }

  private static Class<?> getCustomFieldSerializer(ClassLoader classLoader,
      String qualifiedSerialzierName) {
    try {
      Class<?> customSerializerClass = Class.forName(qualifiedSerialzierName, false, classLoader);
      return customSerializerClass;
    } catch (ClassNotFoundException e) {
      return null;
    }
  }

  private static void resolveTypesWorker(Type methodType,
      DequeMap<TypeVariable<?>, Type> resolvedTypes, boolean addTypes) {
    if (methodType instanceof GenericArrayType) {
      SerializabilityUtil.resolveTypesWorker(((GenericArrayType) methodType)
          .getGenericComponentType(), resolvedTypes, addTypes);
    } else if (methodType instanceof ParameterizedType) {
      ParameterizedType paramType = (ParameterizedType) methodType;
      Type rawType = paramType.getRawType();
      if (rawType instanceof Class) {
        Class<?> rawClass = (Class<?>) paramType.getRawType();
        TypeVariable<?>[] classGenericTypes = rawClass.getTypeParameters();
        Type[] actualTypes = paramType.getActualTypeArguments();

        for (int i = 0; i < actualTypes.length; ++i) {
          TypeVariable<?> variableType = classGenericTypes[i];
          if (addTypes) {
            resolvedTypes.add(variableType, actualTypes[i]);
          } else {
            resolvedTypes.remove(variableType);
          }
        }

        Class<?> superClass = rawClass.getSuperclass();
        if (superClass != null) {
          Type superGenericType = rawClass.getGenericSuperclass();
          SerializabilityUtil.resolveTypesWorker(superGenericType, resolvedTypes, addTypes);
        }

        Type[] interfaceTypes = rawClass.getGenericInterfaces();
        for (Type interfaceType : interfaceTypes) {
          SerializabilityUtil.resolveTypesWorker(interfaceType, resolvedTypes, addTypes);
        }
      }
    } else if (methodType instanceof WildcardType) {
      WildcardType wildcardType = (WildcardType) methodType;
      Type[] lowerBounds = wildcardType.getLowerBounds();
      for (Type type : lowerBounds) {
        SerializabilityUtil.resolveTypesWorker(type, resolvedTypes, addTypes);
      }
      Type[] upperBounds = wildcardType.getUpperBounds();
      for (Type type : upperBounds) {
        SerializabilityUtil.resolveTypesWorker(type, resolvedTypes, addTypes);
      }
    } else if (methodType instanceof TypeVariable) {
      Type[] bounds = ((TypeVariable<?>) methodType).getBounds();
      for (Type type : bounds) {
        SerializabilityUtil.resolveTypesWorker(type, resolvedTypes, addTypes);
      }
    } else if (methodType instanceof Class) {
      Class<?> classType = (Class<?>) methodType;

      // A type that is of instance Class, with TypeParameters, must be a raw
      // class, so strip off any parameters in the map.
      TypeVariable<?>[] classParams = classType.getTypeParameters();
      for (TypeVariable<?> classParamType : classParams) {
        if (addTypes) {
          resolvedTypes.add(classParamType, classParamType);
        } else {
          resolvedTypes.remove(classParamType);
        }
      }

      Type superGenericType = classType.getGenericSuperclass();
      if (superGenericType != null) {
        SerializabilityUtil.resolveTypesWorker(superGenericType, resolvedTypes, addTypes);
      }

      Type[] interfaceTypes = classType.getGenericInterfaces();
      for (Type interfaceType : interfaceTypes) {
        SerializabilityUtil.resolveTypesWorker(interfaceType, resolvedTypes, addTypes);
      }
    }
  }
}
