/*
 * 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.user.client.rpc.CustomFieldSerializer;
import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializedTypeViolationException;
import com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader;
import com.google.gwt.user.server.Base64Utils;
import com.google.gwt.user.server.rpc.RPC;
import com.google.gwt.user.server.rpc.SerializationPolicy;
import com.google.gwt.user.server.rpc.SerializationPolicyProvider;
import com.google.gwt.user.server.rpc.ServerCustomFieldSerializer;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * For internal use only. Used for server call serialization. This class is
 * carefully matched with the client-side version.
 */
public final class ServerSerializationStreamReader extends AbstractSerializationStreamReader {

  /**
   * A basic sanity check for strong names. Only allow certain characters to protect serialization
   * policy providers that use it blindly to load files. (This is normally a hex string, but we
   * allow a few more safe characters in case it's useful for testing.)
   * @see com.google.gwt.dev.util.Util#computeStrongName
   */
  private static final Pattern ALLOWED_STRONG_NAME = Pattern.compile("[a-zA-Z0-9_]+");

  /**
   * Used to accumulate elements while deserializing array types. The generic
   * type of the BoundedList will vary from the component type of the array it
   * is intended to create when the array is of a primitive type.
   * 
   * @param <T> The type of object used to hold the data in the buffer
   */
  private static class BoundedList<T> extends LinkedList<T> {
    private final Class<?> componentType;
    private final int expectedSize;

    public BoundedList(Class<?> componentType, int expectedSize) {
      this.componentType = componentType;
      this.expectedSize = expectedSize;
    }

    @Override
    public boolean add(T o) {
      assert size() < getExpectedSize();
      return super.add(o);
    }

    public Class<?> getComponentType() {
      return componentType;
    }

    public int getExpectedSize() {
      return expectedSize;
    }
  }

  /**
   * Enumeration used to provided typed instance readers.
   */
  private enum ValueReader {
    BOOLEAN {
      @Override
      Object readValue(ServerSerializationStreamReader stream) throws SerializationException {
        return stream.readBoolean();
      }
    },
    BYTE {
      @Override
      Object readValue(ServerSerializationStreamReader stream) throws SerializationException {
        return stream.readByte();
      }
    },
    CHAR {
      @Override
      Object readValue(ServerSerializationStreamReader stream) throws SerializationException {
        return stream.readChar();
      }
    },
    DOUBLE {
      @Override
      Object readValue(ServerSerializationStreamReader stream) throws SerializationException {
        return stream.readDouble();
      }
    },
    FLOAT {
      @Override
      Object readValue(ServerSerializationStreamReader stream) throws SerializationException {
        return stream.readFloat();
      }
    },
    INT {
      @Override
      Object readValue(ServerSerializationStreamReader stream) throws SerializationException {
        return stream.readInt();
      }
    },
    LONG {
      @Override
      Object readValue(ServerSerializationStreamReader stream) throws SerializationException {
        return stream.readLong();
      }
    },
    OBJECT {
      @Override
      Object readValue(ServerSerializationStreamReader stream) throws SerializationException {
        return stream.readObject();
      }

      @Override
      Object readValue(ServerSerializationStreamReader stream, Type expectedType,
          DequeMap<TypeVariable<?>, Type> resolvedTypes) throws SerializationException {
        return stream.readObject(expectedType, resolvedTypes);
      }
    },
    SHORT {
      @Override
      Object readValue(ServerSerializationStreamReader stream) throws SerializationException {
        return stream.readShort();
      }
    },
    STRING {
      @Override
      Object readValue(ServerSerializationStreamReader stream) throws SerializationException {
        return stream.readString();
      }
    };

    abstract Object readValue(ServerSerializationStreamReader stream) throws SerializationException;

    @SuppressWarnings("unused")
    Object readValue(ServerSerializationStreamReader stream, Type expectedType,
        DequeMap<TypeVariable<?>, Type> resolvedTypes) throws SerializationException {
      return readValue(stream);
    }
  }

  /**
   * Enumeration used to provided typed instance readers for vectors.
   */
  private enum VectorReader {
    BOOLEAN_VECTOR {
      @Override
      protected Object readSingleValue(ServerSerializationStreamReader stream)
          throws SerializationException {
        return stream.readBoolean();
      }

      @Override
      protected void setSingleValue(Object array, int index, Object value) {
        Array.setBoolean(array, index, (Boolean) value);
      }
    },
    BYTE_VECTOR {
      @Override
      protected Object readSingleValue(ServerSerializationStreamReader stream)
          throws SerializationException {
        return stream.readByte();
      }

      @Override
      protected void setSingleValue(Object array, int index, Object value) {
        Array.setByte(array, index, (Byte) value);
      }
    },
    CHAR_VECTOR {
      @Override
      protected Object readSingleValue(ServerSerializationStreamReader stream)
          throws SerializationException {
        return stream.readChar();
      }

      @Override
      protected void setSingleValue(Object array, int index, Object value) {
        Array.setChar(array, index, (Character) value);
      }
    },
    DOUBLE_VECTOR {
      @Override
      protected Object readSingleValue(ServerSerializationStreamReader stream)
          throws SerializationException {
        return stream.readDouble();
      }

      @Override
      protected void setSingleValue(Object array, int index, Object value) {
        Array.setDouble(array, index, (Double) value);
      }
    },
    FLOAT_VECTOR {
      @Override
      protected Object readSingleValue(ServerSerializationStreamReader stream)
          throws SerializationException {
        return stream.readFloat();
      }

      @Override
      protected void setSingleValue(Object array, int index, Object value) {
        Array.setFloat(array, index, (Float) value);
      }
    },
    INT_VECTOR {
      @Override
      protected Object readSingleValue(ServerSerializationStreamReader stream)
          throws SerializationException {
        return stream.readInt();
      }

      @Override
      protected void setSingleValue(Object array, int index, Object value) {
        Array.setInt(array, index, (Integer) value);
      }
    },
    LONG_VECTOR {
      @Override
      protected Object readSingleValue(ServerSerializationStreamReader stream)
          throws SerializationException {
        return stream.readLong();
      }

      @Override
      protected void setSingleValue(Object array, int index, Object value) {
        Array.setLong(array, index, (Long) value);
      }
    },
    OBJECT_VECTOR {
      @Override
      protected Object readSingleValue(ServerSerializationStreamReader stream)
          throws SerializationException {
        return stream.readObject();
      }

      @Override
      protected Object readSingleValue(ServerSerializationStreamReader stream, Type expectedType,
          DequeMap<TypeVariable<?>, Type> resolvedTypes) throws SerializationException {
        return stream.readObject(expectedType, resolvedTypes);
      }

      @Override
      protected void setSingleValue(Object array, int index, Object value) {
        Array.set(array, index, value);
      }
    },
    SHORT_VECTOR {
      @Override
      protected Object readSingleValue(ServerSerializationStreamReader stream)
          throws SerializationException {
        return stream.readShort();
      }

      @Override
      protected void setSingleValue(Object array, int index, Object value) {
        Array.setShort(array, index, (Short) value);
      }
    },
    STRING_VECTOR {
      @Override
      protected Object readSingleValue(ServerSerializationStreamReader stream)
          throws SerializationException {
        return stream.readString();
      }

      @Override
      protected void setSingleValue(Object array, int index, Object value) {
        Array.set(array, index, value);
      }
    };

    protected abstract Object readSingleValue(ServerSerializationStreamReader stream)
        throws SerializationException;

    @SuppressWarnings("unused")
    protected Object readSingleValue(ServerSerializationStreamReader stream, Type expectedType,
        DequeMap<TypeVariable<?>, Type> resolvedTypes) throws SerializationException {
      return readSingleValue(stream);
    }

    protected abstract void setSingleValue(Object array, int index, Object value);

    /**
     * Convert a BoundedList to an array of the correct type. This
     * implementation consumes the BoundedList.
     */
    protected Object toArray(Class<?> componentType, BoundedList<Object> buffer)
        throws SerializationException {
      if (buffer.getExpectedSize() != buffer.size()) {
        throw new SerializationException("Inconsistent number of elements received. Received "
            + buffer.size() + " but expecting " + buffer.getExpectedSize());
      }

      Object arr = Array.newInstance(componentType, buffer.size());

      for (int i = 0, n = buffer.size(); i < n; i++) {
        setSingleValue(arr, i, buffer.removeFirst());
      }

      return arr;
    }

    Object read(ServerSerializationStreamReader stream, BoundedList<Object> instance)
        throws SerializationException {
      for (int i = 0, n = instance.getExpectedSize(); i < n; ++i) {
        instance.add(readSingleValue(stream));
      }

      return toArray(instance.getComponentType(), instance);
    }

    Object read(ServerSerializationStreamReader stream, BoundedList<Object> instance,
        Type expectedType, DequeMap<TypeVariable<?>, Type> resolvedTypes) throws
        SerializationException {
      for (int i = 0, n = instance.getExpectedSize(); i < n; ++i) {
        instance.add(readSingleValue(stream, expectedType, resolvedTypes));
      }

      return toArray(instance.getComponentType(), instance);
    }
  }

  /**
   * Map of {@link Class} objects to {@link ValueReader}s.
   */
  private static final Map<Class<?>, ValueReader> CLASS_TO_VALUE_READER =
      new IdentityHashMap<Class<?>, ValueReader>();

  /**
   * Map of {@link Class} objects to {@link VectorReader}s.
   */
  private static final Map<Class<?>, VectorReader> CLASS_TO_VECTOR_READER =
      new IdentityHashMap<Class<?>, VectorReader>();

  private final ClassLoader classLoader;

  private SerializationPolicy serializationPolicy = RPC.getDefaultSerializationPolicy();

  private final SerializationPolicyProvider serializationPolicyProvider;

  /**
   * Used to look up setter methods of the form 'void Class.setXXX(T value)'
   * given a Class type and a field name XXX corresponding to a field of type T.
   */
  private final Map<Class<?>, Map<String, Method>> settersByClass =
      new HashMap<Class<?>, Map<String, Method>>();

  private String[] stringTable;

  private final ArrayList<String> tokenList = new ArrayList<String>();

  private int tokenListIndex;

  {
    CLASS_TO_VECTOR_READER.put(boolean[].class, VectorReader.BOOLEAN_VECTOR);
    CLASS_TO_VECTOR_READER.put(byte[].class, VectorReader.BYTE_VECTOR);
    CLASS_TO_VECTOR_READER.put(char[].class, VectorReader.CHAR_VECTOR);
    CLASS_TO_VECTOR_READER.put(double[].class, VectorReader.DOUBLE_VECTOR);
    CLASS_TO_VECTOR_READER.put(float[].class, VectorReader.FLOAT_VECTOR);
    CLASS_TO_VECTOR_READER.put(int[].class, VectorReader.INT_VECTOR);
    CLASS_TO_VECTOR_READER.put(long[].class, VectorReader.LONG_VECTOR);
    CLASS_TO_VECTOR_READER.put(Object[].class, VectorReader.OBJECT_VECTOR);
    CLASS_TO_VECTOR_READER.put(short[].class, VectorReader.SHORT_VECTOR);
    CLASS_TO_VECTOR_READER.put(String[].class, VectorReader.STRING_VECTOR);

    CLASS_TO_VALUE_READER.put(boolean.class, ValueReader.BOOLEAN);
    CLASS_TO_VALUE_READER.put(byte.class, ValueReader.BYTE);
    CLASS_TO_VALUE_READER.put(char.class, ValueReader.CHAR);
    CLASS_TO_VALUE_READER.put(double.class, ValueReader.DOUBLE);
    CLASS_TO_VALUE_READER.put(float.class, ValueReader.FLOAT);
    CLASS_TO_VALUE_READER.put(int.class, ValueReader.INT);
    CLASS_TO_VALUE_READER.put(long.class, ValueReader.LONG);
    CLASS_TO_VALUE_READER.put(Object.class, ValueReader.OBJECT);
    CLASS_TO_VALUE_READER.put(short.class, ValueReader.SHORT);
    CLASS_TO_VALUE_READER.put(String.class, ValueReader.STRING);
  }

  public ServerSerializationStreamReader(ClassLoader classLoader,
      SerializationPolicyProvider serializationPolicyProvider) {
    this.classLoader = classLoader;
    this.serializationPolicyProvider = serializationPolicyProvider;
  }

  public Object deserializeValue(Class<?> rpcType) throws SerializationException {
    ValueReader valueReader = CLASS_TO_VALUE_READER.get(rpcType);
    if (valueReader != null) {
      return valueReader.readValue(this);
    } else {
      // Arrays of primitive or reference types need to go through readObject.
      return ValueReader.OBJECT.readValue(this);
    }
  }

  public Object deserializeValue(Class<?> rpcType, Type methodType,
      DequeMap<TypeVariable<?>, Type> resolvedTypes) throws SerializationException {
    ValueReader valueReader = CLASS_TO_VALUE_READER.get(rpcType);
    if (valueReader != null) {
      return valueReader.readValue(this, methodType, resolvedTypes);
    } else {
      // Arrays of primitive or reference types need to go through readObject.
      return ValueReader.OBJECT.readValue(this, methodType, resolvedTypes);
    }
  }

  public int getNumberOfTokens() {
    return tokenList.size();
  }

  public SerializationPolicy getSerializationPolicy() {
    return serializationPolicy;
  }

  @Override
  public void prepareToRead(String encodedTokens) throws SerializationException {
    tokenList.clear();
    tokenListIndex = 0;
    stringTable = null;

    int idx = 0, nextIdx;
    while (-1 != (nextIdx = encodedTokens.indexOf(RPC_SEPARATOR_CHAR, idx))) {
      String current = encodedTokens.substring(idx, nextIdx);
      tokenList.add(current);
      idx = nextIdx + 1;
    }
    if (idx == 0) {
      // Didn't find any separator, assume an older version with different
      // separators and get the version as the sequence of digits at the
      // beginning of the encoded string.
      while (idx < encodedTokens.length() && Character.isDigit(encodedTokens.charAt(idx))) {
        ++idx;
      }
      if (idx == 0) {
        throw new IncompatibleRemoteServiceException(
            "Malformed or old RPC message received - expecting version between "
                + SERIALIZATION_STREAM_MIN_VERSION + " and " + SERIALIZATION_STREAM_VERSION);
      } else {
        int version = Integer.valueOf(encodedTokens.substring(0, idx));
        throw new IncompatibleRemoteServiceException("Expecting version between "
            + SERIALIZATION_STREAM_MIN_VERSION + " and " + SERIALIZATION_STREAM_VERSION
            + " from client, got " + version + ".");
      }
    }

    super.prepareToRead(encodedTokens);

    // Check the RPC version number sent by the client
    if (getVersion() < SERIALIZATION_STREAM_MIN_VERSION
        || getVersion() > SERIALIZATION_STREAM_VERSION) {
      throw new IncompatibleRemoteServiceException("Expecting version between "
          + SERIALIZATION_STREAM_MIN_VERSION + " and " + SERIALIZATION_STREAM_VERSION
          + " from client, got " + getVersion() + ".");
    }

    // Check the flags
    if (!areFlagsValid()) {
      throw new IncompatibleRemoteServiceException("Got an unknown flag from " + "client: "
          + getFlags());
    }

    // Read the type name table
    deserializeStringTable();

    // Load the serialization policy
    String moduleBaseURL = readString();
    String strongName = readString();
    if (serializationPolicyProvider != null) {
      if (strongName != null && !ALLOWED_STRONG_NAME.matcher(strongName).matches()) {
        throw new SerializationException(
            "GWT-RPC request is invalid because the strong name contains invalid characters");
      }

      serializationPolicy =
          serializationPolicyProvider.getSerializationPolicy(moduleBaseURL, strongName);

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

  @Override
  public boolean readBoolean() throws SerializationException {
    return !extract().equals("0");
  }

  @Override
  public byte readByte() throws SerializationException {
    String value = extract();
    try {
      return Byte.parseByte(value);
    } catch (NumberFormatException e) {
      throw getNumberFormatException(value, "byte", Byte.MIN_VALUE, Byte.MAX_VALUE);
    }
  }

  @Override
  public char readChar() throws SerializationException {
    // just use an int, it's more foolproof
    return (char) readInt();
  }

  @Override
  public double readDouble() throws SerializationException {
    return Double.parseDouble(extract());
  }

  @Override
  public float readFloat() throws SerializationException {
    return (float) Double.parseDouble(extract());
  }

  @Override
  public int readInt() throws SerializationException {
    String value = extract();
    try {
      return Integer.parseInt(value);
    } catch (NumberFormatException e) {
      throw getNumberFormatException(value, "int", Integer.MIN_VALUE, Integer.MAX_VALUE);
    }
  }

  @Override
  public long readLong() throws SerializationException {
    if (getVersion() == SERIALIZATION_STREAM_MIN_VERSION) {
      return (long) readDouble() + (long) readDouble();
    } else {
      return Base64Utils.longFromBase64(extract());
    }
  }

  public Object readObject(Type expectedType, DequeMap<TypeVariable<?>, Type> resolvedTypes)
      throws SerializationException {
    int token = readInt();

    if (token < 0) {
      // Negative means a previous object
      // Transform negative 1-based to 0-based.
      return getDecodedObject(-token);
    }

    // Positive means a new object
    String typeSignature = getString(token);
    if (typeSignature == null) {
      // a null string means a null instance
      return null;
    }

    if (isSimpleClass(expectedType) && !resolvedTypes.isEmpty()) {
      // Start a new scope for resolving type variables. This is a workaround for false sharing
      // because the type checker doesn't implement type variables properly.
      //
      // For example, if expectedType is Serializable and the actual value is a LinkedHashMap, we
      // don't want any of LinkedHashMap, HashMap, or Map to inherit any bindings for their K,V
      // variables from the surrounding content.
      // Fixes issue 7628.
      resolvedTypes = new DequeMap<TypeVariable<?>, Type>();
    }

    return deserialize(typeSignature, expectedType, resolvedTypes);
  }

  @Override
  public short readShort() throws SerializationException {
    String value = extract();
    try {
      return Short.parseShort(value);
    } catch (NumberFormatException e) {
      throw getNumberFormatException(value, "short", Short.MIN_VALUE, Short.MAX_VALUE);
    }
  }

  @Override
  public String readString() throws SerializationException {
    return getString(readInt());
  }

  @Override
  protected Object deserialize(String typeSignature) throws SerializationException {
    return deserialize(typeSignature, null, null);
  }

  protected Object deserialize(String typeSignature, Type expectedType,
      DequeMap<TypeVariable<?>, Type> resolvedTypes) throws SerializationException {
    Object instance = null;
    try {
      Class<?> instanceClass;
      if (hasFlags(FLAG_ELIDE_TYPE_NAMES)) {
        if (getSerializationPolicy() instanceof TypeNameObfuscator) {
          TypeNameObfuscator obfuscator = (TypeNameObfuscator) getSerializationPolicy();
          String instanceClassName = obfuscator.getClassNameForTypeId(typeSignature);
          instanceClass = Class.forName(instanceClassName, false, classLoader);
        } else {
          throw new SerializationException(
              "The GWT module was compiled with RPC type name elision enabled, but "
                  + getSerializationPolicy().getClass().getName() + " does not implement "
                  + TypeNameObfuscator.class.getName());
        }
      } else {
        SerializedInstanceReference serializedInstRef =
            SerializabilityUtil.decodeSerializedInstanceReference(typeSignature);
        instanceClass = Class.forName(serializedInstRef.getName(), false, classLoader);
        validateTypeVersions(instanceClass, serializedInstRef);
      }

      if (resolvedTypes == null) {
        // We can find ourselves with a null resolvedTypes map if a class
        // has a non-type-checking serializer that tries to deserialize a field.
        // In such cases there is field type information from the class, but no
        // resolvedTypes because we did not pass it through the non-type
        // checking serializer. Create a map, so that from this point forward
        // we have some way of type checking.
        resolvedTypes = new DequeMap<TypeVariable<?>, Type>();
      }
      
      // Try to determine the type for the generic type parameters of the
      // instance class, based upon the expected type and any class hierarchy
      // type information.
      // In looking for the expected parameter types, we also find out the
      // way in which the instance meets the expected type, and hence can find
      // out when it does not meet expectations.
      TypeVariable<?>[] instanceParameterTypes = instanceClass.getTypeParameters();
      Type[] expectedParameterTypes = null;
      if (expectedType != null) {
        SerializabilityUtil.resolveTypes(expectedType, resolvedTypes);
        expectedParameterTypes = SerializabilityUtil.findExpectedParameterTypes(
            instanceClass, expectedType, resolvedTypes);
        if (expectedParameterTypes == null) {
          throw new SerializedTypeViolationException("Attempt to deserialize an object of type "
              + instanceClass.toString() + " when an object of type "
              + SerializabilityUtil.findActualType(expectedType, resolvedTypes).toString()
              + " is expected");
        }
        
        // Add mappings from the instance type variables to the resolved types
        // map.
        for (int i = 0; i < instanceParameterTypes.length; ++i) {
          resolvedTypes.add(instanceParameterTypes[i], expectedParameterTypes[i]);
        }
      }

      assert (serializationPolicy != null);

      serializationPolicy.validateDeserialize(instanceClass);

      Class<?> customSerializer = SerializabilityUtil.hasServerCustomFieldSerializer(instanceClass);

      int index = reserveDecodedObjectIndex();

      instance = instantiate(customSerializer, instanceClass, expectedParameterTypes,
          resolvedTypes);

      rememberDecodedObject(index, instance);

      Object replacement = deserializeImpl(customSerializer, instanceClass, instance, expectedType,
          expectedParameterTypes, resolvedTypes);

      // Remove resolved types that were added for this instance.
      if (expectedParameterTypes != null) {
        for (int i = 0; i < instanceParameterTypes.length; ++i) {
          resolvedTypes.remove(instanceParameterTypes[i]);
        }
      }
      SerializabilityUtil.releaseTypes(expectedType, resolvedTypes);

      // It's possible that deserializing an object requires the original proxy
      // object to be replaced.
      if (instance != replacement) {
        rememberDecodedObject(index, replacement);
        instance = replacement;
      }

      return instance;

    } catch (ClassNotFoundException e) {
      throw new SerializationException(e);
    } catch (InstantiationException e) {
      throw new SerializationException(e);
    } catch (IllegalAccessException e) {
      throw new SerializationException(e);
    } catch (IllegalArgumentException e) {
      throw new SerializationException(e);
    } catch (InvocationTargetException e) {
      throw new SerializationException(e.getTargetException());
    } catch (NoSuchMethodException e) {
      throw new SerializationException(e);
    }
  }

  @Override
  protected String getString(int index) {
    if (index == 0) {
      return null;
    }
    // index is 1-based
    assert (index > 0);
    assert (index <= stringTable.length);
    return stringTable[index - 1];
  }

  /**
   * Deserialize an instance that is an array. Will default to deserializing as
   * an Object vector if the instance is not a primitive vector.
   * 
   * @param instanceClass the class we are deserializing
   * @param instance the object to deserialize into
   * @throws SerializationException
   */
  @SuppressWarnings("unchecked")
  private Object deserializeArray(Class<?> instanceClass, Object instance)
      throws SerializationException {
    assert (instanceClass.isArray());

    BoundedList<Object> buffer = (BoundedList<Object>) instance;
    VectorReader instanceReader = CLASS_TO_VECTOR_READER.get(instanceClass);
    if (instanceReader != null) {
      return instanceReader.read(this, buffer);
    } else {
      return VectorReader.OBJECT_VECTOR.read(this, buffer);
    }
  }

  /**
   * Deserialize an instance that is an array, with type checking.
   * 
   * Will default to deserializing as an Object vector if the instance is not a
   * primitive vector.
   * 
   * @param instanceClass the class we are deserializing
   * @param instance the object to deserialize into
   * @param expectedType the parameterized type the system is expected to find
   * @throws SerializationException
   */
  @SuppressWarnings("unchecked")
  private Object deserializeArray(Class<?> instanceClass, Object instance, Type expectedType,
      DequeMap<TypeVariable<?>, Type> resolvedTypes) throws SerializationException {
    assert (instanceClass.isArray());

    BoundedList<Object> buffer = (BoundedList<Object>) instance;
    VectorReader instanceReader = CLASS_TO_VECTOR_READER.get(instanceClass);
    if (instanceReader != null) {
      return instanceReader.read(this, buffer, expectedType, resolvedTypes);
    } else {
      return VectorReader.OBJECT_VECTOR.read(this, buffer, expectedType, resolvedTypes);
    }
  }

  private void deserializeClass(Class<?> instanceClass, Object instance, Type expectedType,
      Type[] expectedParameterTypes, DequeMap<TypeVariable<?>, Type> resolvedTypes) throws
      SerializationException, IllegalAccessException, NoSuchMethodException,
      InvocationTargetException, ClassNotFoundException {
    /**
     * A map from field names to corresponding setter methods. The reference
     * will be null for classes that do not require special handling for
     * server-only fields.
     */
    Map<String, Method> setters = null;

    /**
     * A list of fields of this class known to the client. If null, assume the
     * class is not enhanced and don't attempt to deal with server-only fields.
     */
    Set<String> clientFieldNames =
        serializationPolicy.getClientFieldNamesForEnhancedClass(instanceClass);
    if (clientFieldNames != null) {
      // Read and set server-only instance fields encoded in the RPC data
      try {
        String encodedData = readString();
        if (encodedData != null) {
          byte[] serializedData = Base64Utils.fromBase64(encodedData);
          ByteArrayInputStream baos = new ByteArrayInputStream(serializedData);
          ObjectInputStream ois = new ObjectInputStream(baos);

          int count = ois.readInt();
          for (int i = 0; i < count; i++) {
            String fieldName = (String) ois.readObject();
            Object fieldValue = ois.readObject();
            Field field = instanceClass.getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(instance, fieldValue);
          }
        }
      } catch (IOException e) {
        throw new SerializationException(e);
      } catch (NoSuchFieldException e) {
        throw new SerializationException(e);
      }

      setters = getSetters(instanceClass);
    }

    Field[] serializableFields = SerializabilityUtil.applyFieldSerializationPolicy(instanceClass);
    for (Field declField : serializableFields) {
      assert (declField != null);
      if ((clientFieldNames != null) && !clientFieldNames.contains(declField.getName())) {
        continue;
      }

      Type declGenericType = declField.getGenericType();
      Object value = deserializeValue(declField.getType(), declGenericType, resolvedTypes);

      String fieldName = declField.getName();
      Method setter;
      /*
       * If setters is non-null and there is a setter method for the given
       * field, call the setter. Otherwise, set the field value directly. For
       * persistence APIs such as JDO, the setter methods have been enhanced to
       * manipulate additional object state, causing direct field writes to fail
       * to update the object state properly.
       */
      if ((setters != null) && ((setter = setters.get(fieldName)) != null)) {
        setter.invoke(instance, value);
      } else {
        boolean isAccessible = declField.isAccessible();
        boolean needsAccessOverride = !isAccessible && !Modifier.isPublic(declField.getModifiers());
        if (needsAccessOverride) {
          // Override access restrictions
          declField.setAccessible(true);
        }

        declField.set(instance, value);
      }
    }

    Class<?> superClass = instanceClass.getSuperclass();
    if (serializationPolicy.shouldDeserializeFields(superClass)) {
      Type[] superParameterTypes = SerializabilityUtil.findExpectedParameterTypes(
          superClass, superClass, resolvedTypes);
      deserializeImpl(SerializabilityUtil.hasServerCustomFieldSerializer(superClass), superClass,
          instance, expectedType, superParameterTypes, resolvedTypes);
    }
  }

  private Object deserializeImpl(Class<?> customSerializer, Class<?> instanceClass,
      Object instance, Type expectedType, Type[] expectedParameterTypes,
      DequeMap<TypeVariable<?>, Type> resolvedTypes)
      throws NoSuchMethodException, IllegalArgumentException, IllegalAccessException,
      InvocationTargetException, SerializationException, ClassNotFoundException {

    if (customSerializer != null) {
      @SuppressWarnings("unchecked")
      CustomFieldSerializer<Object> customFieldSerializer =
          (CustomFieldSerializer<Object>) SerializabilityUtil
              .loadCustomFieldSerializer(customSerializer);
      if (customFieldSerializer == null) {
        deserializeWithCustomFieldDeserializer(customSerializer, instanceClass, instance,
            expectedParameterTypes, resolvedTypes);
      } else if (customFieldSerializer instanceof ServerCustomFieldSerializer &&
          expectedParameterTypes != null) {
        ServerCustomFieldSerializer<Object> serverCFS =
            (ServerCustomFieldSerializer<Object>) customFieldSerializer;
        serverCFS.deserializeInstance(this, instance, expectedParameterTypes, resolvedTypes);
      } else {
        customFieldSerializer.deserializeInstance(this, instance);
      }
    } else if (instanceClass.isArray()) {
      if (expectedType == null) {
        return deserializeArray(instanceClass, instance);
      }
      Type actualExpectedType = SerializabilityUtil.findActualType(expectedType, resolvedTypes);
      if (actualExpectedType instanceof GenericArrayType) {
        Type arrayType = ((GenericArrayType) actualExpectedType).getGenericComponentType();
        return deserializeArray(instanceClass, instance, arrayType, resolvedTypes);
      } else if (((Class<?>) actualExpectedType).getComponentType() != null) {
        Class<?> arrayType = ((Class<?>) actualExpectedType).getComponentType();
        return deserializeArray(instanceClass, instance, arrayType, resolvedTypes);
      }
    } else if (instanceClass.isEnum()) {
      // Enums are deserialized when they are instantiated
    } else {
      deserializeClass(instanceClass, instance, expectedType, expectedParameterTypes,
          resolvedTypes);
    }

    return instance;
  }

  private void deserializeStringTable() throws SerializationException {
    int typeNameCount = readInt();
    BoundedList<String> buffer = new BoundedList<String>(String.class, typeNameCount);
    for (int typeNameIndex = 0; typeNameIndex < typeNameCount; ++typeNameIndex) {
      String str = extract();
      // Change quoted characters back.
      int idx = str.indexOf('\\');
      if (idx >= 0) {
        StringBuilder buf = new StringBuilder();
        int pos = 0;
        while (idx >= 0) {
          buf.append(str.substring(pos, idx));
          if (++idx == str.length()) {
            throw new SerializationException("Unmatched backslash: \"" + str + "\"");
          }
          char ch = str.charAt(idx);
          pos = idx + 1;
          switch (ch) {
            case '0':
              buf.append('\u0000');
              break;
            case '!':
              buf.append(RPC_SEPARATOR_CHAR);
              break;
            case '\\':
              buf.append(ch);
              break;
            case 'u':
              try {
                ch = (char) Integer.parseInt(str.substring(idx + 1, idx + 5), 16);
              } catch (NumberFormatException e) {
                throw new SerializationException("Invalid Unicode escape sequence in \"" + str
                    + "\"");
              }
              buf.append(ch);
              pos += 4;
              break;
            default:
              throw new SerializationException("Unexpected escape character " + ch
                  + " after backslash: \"" + str + "\"");
          }
          idx = str.indexOf('\\', pos);
        }
        buf.append(str.substring(pos));
        str = buf.toString();
      }
      buffer.add(str);
    }

    if (buffer.size() != buffer.getExpectedSize()) {
      throw new SerializationException("Expected " + buffer.getExpectedSize()
          + " string table elements; received " + buffer.size());
    }

    stringTable = buffer.toArray(new String[buffer.getExpectedSize()]);
  }

  private void deserializeWithCustomFieldDeserializer(Class<?> customSerializer,
      Class<?> instanceClass, Object instance, Type[] expectedParameterTypes,
      DequeMap<TypeVariable<?>, Type> resolvedTypes)
      throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
    assert (!instanceClass.isArray());

    if (expectedParameterTypes != null) {
      for (Method method : customSerializer.getMethods()) {
        if ("deserializeChecked".equals(method.getName())) {
          method.invoke(null, this, instance, expectedParameterTypes, resolvedTypes);
          return;
        }
      }
    }
    for (Method method : customSerializer.getMethods()) {
      if ("deserialize".equals(method.getName())) {
        method.invoke(null, this, instance);
        return;
      }
    }
    throw new NoSuchMethodException("deserialize");
  }

  private String extract() throws SerializationException {
    try {
      return tokenList.get(tokenListIndex++);
    } catch (IndexOutOfBoundsException e) {
      throw new SerializationException("Too few tokens in RPC request", e);
    }
  }

  /**
   * Returns a suitable NumberFormatException with an explanatory message when a
   * numerical value cannot be parsed according to its expected type.
   * 
   * @param value the value as read from the RPC stream
   * @param type the name of the expected type
   * @param minValue the smallest valid value for the expected type
   * @param maxValue the largest valid value for the expected type
   * @return a NumberFormatException with an explanatory message
   */
  private NumberFormatException getNumberFormatException(String value, String type,
      double minValue, double maxValue) {
    String message = "a non-numerical value";
    try {
      // Check the field contents in order to produce a more comprehensible
      // error message
      double d = Double.parseDouble(value);
      if (d < minValue || d > maxValue) {
        message = "an out-of-range value";
      } else if (d != Math.floor(d)) {
        message = "a fractional value";
      }
    } catch (NumberFormatException e2) {
      // Fall through with the default message.
    }

    return new NumberFormatException("Expected type '" + type + "' but received " + message + ": "
        + value);
  }

  /**
   * Returns a Map from a field name to the setter method for that field, for a
   * given class. The results are computed once for each class and cached.
   * 
   * @param instanceClass the class to query
   * @return a Map from Strings to Methods such that the name <code>XXX</code>
   *         (corresponding to the field <code>T XXX</code>) maps to the method
   *         <code>void setXXX(T value)</code>, or null if no such method
   *         exists.
   */
  private Map<String, Method> getSetters(Class<?> instanceClass) {
    synchronized (settersByClass) {
      Map<String, Method> setters = settersByClass.get(instanceClass);
      if (setters == null) {
        setters = new HashMap<String, Method>();

        // Iterate over each field and locate a suitable setter method
        Field[] fields = instanceClass.getDeclaredFields();
        for (Field field : fields) {
          // Consider non-final, non-static, non-transient (or @GwtTransient)
          // fields only
          if (SerializabilityUtil.isNotStaticTransientOrFinal(field)) {
            String fieldName = field.getName();
            String setterName =
                "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
            try {
              Method setter = instanceClass.getMethod(setterName, field.getType());
              setters.put(fieldName, setter);
            } catch (NoSuchMethodException e) {
              // Just leave this field out of the map
            }
          }
        }

        settersByClass.put(instanceClass, setters);
      }

      return setters;
    }
  }

  private Object instantiate(Class<?> customSerializer, Class<?> instanceClass,
      Type[] expectedParameterTypes, DequeMap<TypeVariable<?>, Type> resolvedTypes) throws
      InstantiationException, IllegalAccessException, IllegalArgumentException,
      InvocationTargetException, NoSuchMethodException, SerializationException {
    if (customSerializer != null) {
      CustomFieldSerializer<?> customFieldSerializer =
          SerializabilityUtil.loadCustomFieldSerializer(customSerializer);
      if (customFieldSerializer == null) {
        Object result = instantiateWithCustomFieldInstantiator(customSerializer,
            expectedParameterTypes, resolvedTypes);
        if (result != null) {
          return result;
        }
        // Ok to not have a custom instantiate.
      } else if (customFieldSerializer.hasCustomInstantiateInstance()) {
        if (expectedParameterTypes != null &&
            (customFieldSerializer instanceof ServerCustomFieldSerializer)) {
          ServerCustomFieldSerializer<?> serverCFS =
              (ServerCustomFieldSerializer<?>) customFieldSerializer;
          return serverCFS.instantiateInstance(this, expectedParameterTypes, resolvedTypes);
        } else {
          return customFieldSerializer.instantiateInstance(this);
        }
      }
    }

    if (instanceClass.isArray()) {
      int length = readInt();
      // We don't pre-allocate the array; this prevents an allocation attack
      return new BoundedList<Object>(instanceClass.getComponentType(), length);
    } else if (instanceClass.isEnum()) {
      Enum<?>[] enumConstants = (Enum[]) instanceClass.getEnumConstants();
      int ordinal = readInt();
      assert (ordinal >= 0 && ordinal < enumConstants.length);
      return enumConstants[ordinal];
    } else {
      Constructor<?> constructor = instanceClass.getDeclaredConstructor();
      constructor.setAccessible(true);
      return constructor.newInstance();
    }
  }

  private Object instantiateWithCustomFieldInstantiator(Class<?> customSerializer,
      Type[] expectedParameterTypes, DequeMap<TypeVariable<?>, Type> resolvedTypes)
      throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    if (expectedParameterTypes != null) {
      for (Method method : customSerializer.getMethods()) {
        if ("instantiateChecked".equals(method.getName())) {
          return method.invoke(null, this, expectedParameterTypes, resolvedTypes);
        }
      }
    }

    for (Method method : customSerializer.getMethods()) {
      if ("instantiate".equals(method.getName())) {
        return method.invoke(null, this);
      }
    }
    return null;
  }

  /**
   * Returns true if the given type is a top-level class or interface with no type parameters.
   */
  private boolean isSimpleClass(Type t) {
    if (!(t instanceof Class)) {
      return false;
    }
    Class cl = (Class) t;
    return cl.getTypeParameters().length == 0 && cl.getEnclosingClass() == null;
  }

  private void validateTypeVersions(Class<?> instanceClass,
      SerializedInstanceReference serializedInstRef) throws SerializationException {
    String clientTypeSignature = serializedInstRef.getSignature();
    if (clientTypeSignature.length() == 0) {
      throw new SerializationException("Missing type signature for " + instanceClass.getName());
    }

    String serverTypeSignature =
        SerializabilityUtil.getSerializationSignature(instanceClass, serializationPolicy);

    if (!clientTypeSignature.equals(serverTypeSignature)) {
      throw new SerializationException("Invalid type signature for " + instanceClass.getName());
    }
  }
}
