/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.hadoop.hbase.security.access;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NavigableSet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configurable;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.hbase.ClusterStatus;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Action;
import org.apache.hadoop.hbase.client.Append;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Increment;
import org.apache.hadoop.hbase.client.MultiAction;
import org.apache.hadoop.hbase.client.MultiResponse;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Row;
import org.apache.hadoop.hbase.client.RowMutations;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.filter.BinaryComparator;
import org.apache.hadoop.hbase.filter.BitComparator;
import org.apache.hadoop.hbase.filter.ByteArrayComparable;
import org.apache.hadoop.hbase.filter.ColumnCountGetFilter;
import org.apache.hadoop.hbase.filter.ColumnPrefixFilter;
import org.apache.hadoop.hbase.filter.ColumnRangeFilter;
import org.apache.hadoop.hbase.filter.CompareFilter;
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
import org.apache.hadoop.hbase.filter.DependentColumnFilter;
import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
import org.apache.hadoop.hbase.filter.InclusiveStopFilter;
import org.apache.hadoop.hbase.filter.KeyOnlyFilter;
import org.apache.hadoop.hbase.filter.PageFilter;
import org.apache.hadoop.hbase.filter.PrefixFilter;
import org.apache.hadoop.hbase.filter.QualifierFilter;
import org.apache.hadoop.hbase.filter.RandomRowFilter;
import org.apache.hadoop.hbase.filter.RowFilter;
import org.apache.hadoop.hbase.filter.SingleColumnValueExcludeFilter;
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
import org.apache.hadoop.hbase.filter.SkipFilter;
import org.apache.hadoop.hbase.filter.ValueFilter;
import org.apache.hadoop.hbase.filter.WhileMatchFilter;
import org.apache.hadoop.hbase.io.WritableWithSize;
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
import org.apache.hadoop.hbase.regionserver.RegionOpeningState;
import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
import org.apache.hadoop.hbase.wal.WAL.Entry;
import org.apache.hadoop.hbase.wal.WALKey;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.ProtoUtil;
import org.apache.hadoop.io.DataOutputOutputStream;
import org.apache.hadoop.io.MapWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableFactories;
import org.apache.hadoop.io.WritableUtils;

import com.google.protobuf.Message;
import com.google.protobuf.RpcController;

/**
 * <p>This is a customized version of the polymorphic hadoop
 * {@link ObjectWritable}.  It removes UTF8 (HADOOP-414).
 * Using {@link Text} intead of UTF-8 saves ~2% CPU between reading and writing
 * objects running a short sequentialWrite Performance Evaluation test just in
 * ObjectWritable alone; more when we're doing randomRead-ing.  Other
 * optimizations include our passing codes for classes instead of the
 * actual class names themselves.  This makes it so this class needs amendment
 * if non-Writable classes are introduced -- if passed a Writable for which we
 * have no code, we just do the old-school passing of the class name, etc. --
 * but passing codes the  savings are large particularly when cell
 * data is small (If < a couple of kilobytes, the encoding/decoding of class
 * name and reflection to instantiate class was costing in excess of the cell
 * handling).
 * @deprecated This class is needed migrating TablePermissions written with
 * Writables.  It is needed to read old permissions written pre-0.96.  This
 * class is to be removed after HBase 0.96 ships since then all permissions
 * will have been migrated and written with protobufs.
 */
@Deprecated
@InterfaceAudience.Private
class HbaseObjectWritableFor96Migration implements Writable, WritableWithSize, Configurable {
  private final static Log LOG = LogFactory.getLog(HbaseObjectWritableFor96Migration.class);

  // Here we maintain two static maps of classes to code and vice versa.
  // Add new classes+codes as wanted or figure way to auto-generate these
  // maps.
  static final Map<Integer, Class<?>> CODE_TO_CLASS =
    new HashMap<Integer, Class<?>>();
  static final Map<Class<?>, Integer> CLASS_TO_CODE =
    new HashMap<Class<?>, Integer>();
  // Special code that means 'not-encoded'; in this case we do old school
  // sending of the class name using reflection, etc.
  private static final byte NOT_ENCODED = 0;
  //Generic array means that the array type is not one of the pre-defined arrays
  //in the CLASS_TO_CODE map, but we have to still encode the array since it's
  //elements are serializable by this class.
  private static final int GENERIC_ARRAY_CODE;
  private static final int NEXT_CLASS_CODE;
  static {
    ////////////////////////////////////////////////////////////////////////////
    // WARNING: Please do not insert, remove or swap any line in this static  //
    // block.  Doing so would change or shift all the codes used to serialize //
    // objects, which makes backwards compatibility very hard for clients.    //
    // New codes should always be added at the end. Code removal is           //
    // discouraged because code is a short now.                               //
    ////////////////////////////////////////////////////////////////////////////

    int code = NOT_ENCODED + 1;
    // Primitive types.
    addToMap(Boolean.TYPE, code++);
    addToMap(Byte.TYPE, code++);
    addToMap(Character.TYPE, code++);
    addToMap(Short.TYPE, code++);
    addToMap(Integer.TYPE, code++);
    addToMap(Long.TYPE, code++);
    addToMap(Float.TYPE, code++);
    addToMap(Double.TYPE, code++);
    addToMap(Void.TYPE, code++);

    // Other java types
    addToMap(String.class, code++);
    addToMap(byte [].class, code++);
    addToMap(byte [][].class, code++);

    // Hadoop types
    addToMap(Text.class, code++);
    addToMap(Writable.class, code++);
    addToMap(Writable [].class, code++);
    code++; // Removed
    addToMap(NullInstance.class, code++);

    // Hbase types
    addToMap(HColumnDescriptor.class, code++);
    addToMap(HConstants.Modify.class, code++);

    // We used to have a class named HMsg but its been removed.  Rather than
    // just axe it, use following random Integer class -- we just chose any
    // class from java.lang -- instead just so codes that follow stay
    // in same relative place.
    addToMap(Integer.class, code++);
    addToMap(Integer[].class, code++);

    //HRegion shouldn't be pushed across the wire.
    code++; //addToMap(HRegion.class, code++);
    code++; //addToMap(HRegion[].class, code++);

    addToMap(HRegionInfo.class, code++);
    addToMap(HRegionInfo[].class, code++);
    code++; // Removed
    code++; // Removed
    addToMap(HTableDescriptor.class, code++);
    addToMap(MapWritable.class, code++);

    //
    // HBASE-880
    //
    addToMap(ClusterStatus.class, code++);
    addToMap(Delete.class, code++);
    addToMap(Get.class, code++);
    addToMap(KeyValue.class, code++);
    addToMap(KeyValue[].class, code++);
    addToMap(Put.class, code++);
    addToMap(Put[].class, code++);
    addToMap(Result.class, code++);
    addToMap(Result[].class, code++);
    addToMap(Scan.class, code++);

    addToMap(WhileMatchFilter.class, code++);
    addToMap(PrefixFilter.class, code++);
    addToMap(PageFilter.class, code++);
    addToMap(InclusiveStopFilter.class, code++);
    addToMap(ColumnCountGetFilter.class, code++);
    addToMap(SingleColumnValueFilter.class, code++);
    addToMap(SingleColumnValueExcludeFilter.class, code++);
    addToMap(BinaryComparator.class, code++);
    addToMap(BitComparator.class, code++);
    addToMap(CompareFilter.class, code++);
    addToMap(RowFilter.class, code++);
    addToMap(ValueFilter.class, code++);
    addToMap(QualifierFilter.class, code++);
    addToMap(SkipFilter.class, code++);
    addToMap(ByteArrayComparable.class, code++);
    addToMap(FirstKeyOnlyFilter.class, code++);
    addToMap(DependentColumnFilter.class, code++);

    addToMap(Delete [].class, code++);

    addToMap(Entry.class, code++);
    addToMap(Entry[].class, code++);
    addToMap(HLogKey.class, code++);

    addToMap(List.class, code++);

    addToMap(NavigableSet.class, code++);
    addToMap(ColumnPrefixFilter.class, code++);

    // Multi
    addToMap(Row.class, code++);
    addToMap(Action.class, code++);
    addToMap(MultiAction.class, code++);
    addToMap(MultiResponse.class, code++);

    // coprocessor execution
    // Exec no longer exists --> addToMap(Exec.class, code++);
    code++;
    addToMap(Increment.class, code++);

    addToMap(KeyOnlyFilter.class, code++);

    // serializable
    addToMap(Serializable.class, code++);

    addToMap(RandomRowFilter.class, code++);

    addToMap(CompareOp.class, code++);

    addToMap(ColumnRangeFilter.class, code++);

    // HServerLoad no longer exists; increase code so other classes stay the same.
    code++;
    //addToMap(HServerLoad.class, code++);

    addToMap(RegionOpeningState.class, code++);

    addToMap(HTableDescriptor[].class, code++);

    addToMap(Append.class, code++);

    addToMap(RowMutations.class, code++);

    addToMap(Message.class, code++);

    //java.lang.reflect.Array is a placeholder for arrays not defined above
    GENERIC_ARRAY_CODE = code++;
    addToMap(Array.class, GENERIC_ARRAY_CODE);

    addToMap(RpcController.class, code++);

    // make sure that this is the last statement in this static block
    NEXT_CLASS_CODE = code;
  }

  private Class<?> declaredClass;
  private Object instance;
  private Configuration conf;

  /** default constructor for writable */
  HbaseObjectWritableFor96Migration() {
    super();
  }

  /**
   * @param instance
   */
  HbaseObjectWritableFor96Migration(Object instance) {
    set(instance);
  }

  /**
   * @param declaredClass
   * @param instance
   */
  HbaseObjectWritableFor96Migration(Class<?> declaredClass, Object instance) {
    this.declaredClass = declaredClass;
    this.instance = instance;
  }

  /** @return the instance, or null if none. */
  Object get() { return instance; }

  /** @return the class this is meant to be. */
  Class<?> getDeclaredClass() { return declaredClass; }

  /**
   * Reset the instance.
   * @param instance
   */
  void set(Object instance) {
    this.declaredClass = instance.getClass();
    this.instance = instance;
  }

  /**
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    return "OW[class=" + declaredClass + ",value=" + instance + "]";
  }


  public void readFields(DataInput in) throws IOException {
    readObject(in, this, this.conf);
  }

  public void write(DataOutput out) throws IOException {
    writeObject(out, instance, declaredClass, conf);
  }

  public long getWritableSize() {
    return getWritableSize(instance, declaredClass, conf);
  }

  private static class NullInstance extends Configured implements Writable {
    Class<?> declaredClass;
    /** default constructor for writable */
    @SuppressWarnings("unused")
    public NullInstance() { super(null); }

    /**
     * @param declaredClass
     * @param conf
     */
    public NullInstance(Class<?> declaredClass, Configuration conf) {
      super(conf);
      this.declaredClass = declaredClass;
    }

    public void readFields(DataInput in) throws IOException {
      this.declaredClass = CODE_TO_CLASS.get(WritableUtils.readVInt(in));
    }

    public void write(DataOutput out) throws IOException {
      writeClassCode(out, this.declaredClass);
    }
  }

  static Integer getClassCode(final Class<?> c)
  throws IOException {
    Integer code = CLASS_TO_CODE.get(c);
    if (code == null ) {
      if (List.class.isAssignableFrom(c)) {
        code = CLASS_TO_CODE.get(List.class);
      } else if (Writable.class.isAssignableFrom(c)) {
        code = CLASS_TO_CODE.get(Writable.class);
      } else if (c.isArray()) {
        code = CLASS_TO_CODE.get(Array.class);
      } else if (Message.class.isAssignableFrom(c)) {
        code = CLASS_TO_CODE.get(Message.class);
      } else if (Serializable.class.isAssignableFrom(c)){
        code = CLASS_TO_CODE.get(Serializable.class);
      } else if (Scan.class.isAssignableFrom(c)) {
        code = CLASS_TO_CODE.get(Scan.class);
      }
    }
    return code;
  }

  /**
   * @return the next object code in the list.  Used in testing to verify that additional fields are not added 
   */
  static int getNextClassCode(){
    return NEXT_CLASS_CODE;
  }

  /**
   * Write out the code for passed Class.
   * @param out
   * @param c
   * @throws IOException
   */
  static void writeClassCode(final DataOutput out, final Class<?> c)
      throws IOException {
    Integer code = getClassCode(c);

    if (code == null) {
      LOG.error("Unsupported type " + c);
      StackTraceElement[] els = new Exception().getStackTrace();
      for(StackTraceElement elem : els) {
        LOG.error(elem.getMethodName());
      }
      throw new UnsupportedOperationException("No code for unexpected " + c);
    }
    WritableUtils.writeVInt(out, code);
  }

  static long getWritableSize(Object instance, Class declaredClass,
                                     Configuration conf) {
    return 0L; // no hint is the default.
  }
  /**
   * Write a {@link Writable}, {@link String}, primitive type, or an array of
   * the preceding.
   * @param out
   * @param instance
   * @param declaredClass
   * @param conf
   * @throws IOException
   */
  @SuppressWarnings("unchecked")
  static void writeObject(DataOutput out, Object instance,
                                 Class declaredClass,
                                 Configuration conf)
  throws IOException {

    Object instanceObj = instance;
    Class declClass = declaredClass;

    if (instanceObj == null) {                       // null
      instanceObj = new NullInstance(declClass, conf);
      declClass = Writable.class;
    }
    writeClassCode(out, declClass);
    if (declClass.isArray()) {                // array
      // If bytearray, just dump it out -- avoid the recursion and
      // byte-at-a-time we were previously doing.
      if (declClass.equals(byte [].class)) {
        Bytes.writeByteArray(out, (byte [])instanceObj);
      } else {
        //if it is a Generic array, write the element's type
        if (getClassCode(declaredClass) == GENERIC_ARRAY_CODE) {
          Class<?> componentType = declaredClass.getComponentType();
          writeClass(out, componentType);
        }

        int length = Array.getLength(instanceObj);
        out.writeInt(length);
        for (int i = 0; i < length; i++) {
          Object item = Array.get(instanceObj, i);
          writeObject(out, item,
                    item.getClass(), conf);
        }
      }
    } else if (List.class.isAssignableFrom(declClass)) {
      List list = (List)instanceObj;
      int length = list.size();
      out.writeInt(length);
      for (int i = 0; i < length; i++) {
        Object elem = list.get(i);
        writeObject(out, elem,
                  elem == null ? Writable.class : elem.getClass(), conf);
      }
    } else if (declClass == String.class) {   // String
      Text.writeString(out, (String)instanceObj);
    } else if (declClass.isPrimitive()) {     // primitive type
      if (declClass == Boolean.TYPE) {        // boolean
        out.writeBoolean(((Boolean)instanceObj).booleanValue());
      } else if (declClass == Character.TYPE) { // char
        out.writeChar(((Character)instanceObj).charValue());
      } else if (declClass == Byte.TYPE) {    // byte
        out.writeByte(((Byte)instanceObj).byteValue());
      } else if (declClass == Short.TYPE) {   // short
        out.writeShort(((Short)instanceObj).shortValue());
      } else if (declClass == Integer.TYPE) { // int
        out.writeInt(((Integer)instanceObj).intValue());
      } else if (declClass == Long.TYPE) {    // long
        out.writeLong(((Long)instanceObj).longValue());
      } else if (declClass == Float.TYPE) {   // float
        out.writeFloat(((Float)instanceObj).floatValue());
      } else if (declClass == Double.TYPE) {  // double
        out.writeDouble(((Double)instanceObj).doubleValue());
      } else if (declClass == Void.TYPE) {    // void
      } else {
        throw new IllegalArgumentException("Not a primitive: "+declClass);
      }
    } else if (declClass.isEnum()) {         // enum
      Text.writeString(out, ((Enum)instanceObj).name());
    } else if (Message.class.isAssignableFrom(declaredClass)) {
      Text.writeString(out, instanceObj.getClass().getName());
      ((Message)instance).writeDelimitedTo(
          DataOutputOutputStream.constructOutputStream(out));
    } else if (Writable.class.isAssignableFrom(declClass)) { // Writable
      Class <?> c = instanceObj.getClass();
      Integer code = CLASS_TO_CODE.get(c);
      if (code == null) {
        out.writeByte(NOT_ENCODED);
        Text.writeString(out, c.getName());
      } else {
        writeClassCode(out, c);
      }
      ((Writable)instanceObj).write(out);
    } else if (Serializable.class.isAssignableFrom(declClass)) {
      Class <?> c = instanceObj.getClass();
      Integer code = CLASS_TO_CODE.get(c);
      if (code == null) {
        out.writeByte(NOT_ENCODED);
        Text.writeString(out, c.getName());
      } else {
        writeClassCode(out, c);
      }
      ByteArrayOutputStream bos = null;
      ObjectOutputStream oos = null;
      try{
        bos = new ByteArrayOutputStream();
        oos = new ObjectOutputStream(bos);
        oos.writeObject(instanceObj);
        byte[] value = bos.toByteArray();
        out.writeInt(value.length);
        out.write(value);
      } finally {
        if(bos!=null) bos.close();
        if(oos!=null) oos.close();
      }
    } else if (Scan.class.isAssignableFrom(declClass)) {
      Scan scan = (Scan)instanceObj;
      byte [] scanBytes = ProtobufUtil.toScan(scan).toByteArray();
      out.writeInt(scanBytes.length);
      out.write(scanBytes);
    } else if (Entry.class.isAssignableFrom(declClass)) {
      // Entry is no longer Writable, maintain compatible serialization.
      // Writables write their exact runtime class
      Class <?> c = instanceObj.getClass();
      Integer code = CLASS_TO_CODE.get(c);
      if (code == null) {
        out.writeByte(NOT_ENCODED);
        Text.writeString(out, c.getName());
      } else {
        writeClassCode(out, c);
      }
      final Entry entry = (Entry)instanceObj;
      // We only support legacy HLogKey
      WALKey key = entry.getKey();
      if (!(key instanceof HLogKey)) {
        throw new IOException("Can't write Entry '" + instanceObj + "' due to key class '" +
            key.getClass() + "'");
      }
      ((HLogKey)key).write(out);
      entry.getEdit().write(out);
    } else {
      throw new IOException("Can't write: "+instanceObj+" as "+declClass);
    }
  }

  /** Writes the encoded class code as defined in CLASS_TO_CODE, or
   * the whole class name if not defined in the mapping.
   */
  static void writeClass(DataOutput out, Class<?> c) throws IOException {
    Integer code = CLASS_TO_CODE.get(c);
    if (code == null) {
      WritableUtils.writeVInt(out, NOT_ENCODED);
      Text.writeString(out, c.getName());
    } else {
      WritableUtils.writeVInt(out, code);
    }
  }

  /** Reads and returns the class as written by {@link #writeClass(DataOutput, Class)} */
  static Class<?> readClass(Configuration conf, DataInput in) throws IOException {
    Class<?> instanceClass = null;
    int b = (byte)WritableUtils.readVInt(in);
    if (b == NOT_ENCODED) {
      String className = Text.readString(in);
      try {
        instanceClass = getClassByName(conf, className);
      } catch (ClassNotFoundException e) {
        LOG.error("Can't find class " + className, e);
        throw new IOException("Can't find class " + className, e);
      }
    } else {
      instanceClass = CODE_TO_CLASS.get(b);
    }
    return instanceClass;
  }

  /**
   * Read a {@link Writable}, {@link String}, primitive type, or an array of
   * the preceding.
   * @param in
   * @param conf
   * @return the object
   * @throws IOException
   */
  static Object readObject(DataInput in, Configuration conf)
    throws IOException {
    return readObject(in, null, conf);
  }

  /**
   * Read a {@link Writable}, {@link String}, primitive type, or an array of
   * the preceding.
   * @param in
   * @param objectWritable
   * @param conf
   * @return the object
   * @throws IOException
   */
  @SuppressWarnings("unchecked")
  static Object readObject(DataInput in,
      HbaseObjectWritableFor96Migration objectWritable, Configuration conf)
  throws IOException {
    Class<?> declaredClass = CODE_TO_CLASS.get(WritableUtils.readVInt(in));
    Object instance;
    if (declaredClass.isPrimitive()) {            // primitive types
      if (declaredClass == Boolean.TYPE) {             // boolean
        instance = Boolean.valueOf(in.readBoolean());
      } else if (declaredClass == Character.TYPE) {    // char
        instance = Character.valueOf(in.readChar());
      } else if (declaredClass == Byte.TYPE) {         // byte
        instance = Byte.valueOf(in.readByte());
      } else if (declaredClass == Short.TYPE) {        // short
        instance = Short.valueOf(in.readShort());
      } else if (declaredClass == Integer.TYPE) {      // int
        instance = Integer.valueOf(in.readInt());
      } else if (declaredClass == Long.TYPE) {         // long
        instance = Long.valueOf(in.readLong());
      } else if (declaredClass == Float.TYPE) {        // float
        instance = Float.valueOf(in.readFloat());
      } else if (declaredClass == Double.TYPE) {       // double
        instance = Double.valueOf(in.readDouble());
      } else if (declaredClass == Void.TYPE) {         // void
        instance = null;
      } else {
        throw new IllegalArgumentException("Not a primitive: "+declaredClass);
      }
    } else if (declaredClass.isArray()) {              // array
      if (declaredClass.equals(byte [].class)) {
        instance = Bytes.readByteArray(in);
      } else {
        int length = in.readInt();
        instance = Array.newInstance(declaredClass.getComponentType(), length);
        for (int i = 0; i < length; i++) {
          Array.set(instance, i, readObject(in, conf));
        }
      }
    } else if (declaredClass.equals(Array.class)) { //an array not declared in CLASS_TO_CODE
      Class<?> componentType = readClass(conf, in);
      int length = in.readInt();
      instance = Array.newInstance(componentType, length);
      for (int i = 0; i < length; i++) {
        Array.set(instance, i, readObject(in, conf));
      }
    } else if (List.class.isAssignableFrom(declaredClass)) {            // List
      int length = in.readInt();
      instance = new ArrayList(length);
      for (int i = 0; i < length; i++) {
        ((ArrayList)instance).add(readObject(in, conf));
      }
    } else if (declaredClass == String.class) {        // String
      instance = Text.readString(in);
    } else if (declaredClass.isEnum()) {         // enum
      instance = Enum.valueOf((Class<? extends Enum>) declaredClass,
        Text.readString(in));
    } else if (declaredClass == Message.class) {
      String className = Text.readString(in);
      try {
        declaredClass = getClassByName(conf, className);
        instance = tryInstantiateProtobuf(declaredClass, in);
      } catch (ClassNotFoundException e) {
        LOG.error("Can't find class " + className, e);
        throw new IOException("Can't find class " + className, e);
      }
    } else if (Scan.class.isAssignableFrom(declaredClass)) {
      int length = in.readInt();
      byte [] scanBytes = new byte[length];
      in.readFully(scanBytes);
      ClientProtos.Scan.Builder scanProto = ClientProtos.Scan.newBuilder();
      ProtobufUtil.mergeFrom(scanProto, scanBytes);
      instance = ProtobufUtil.toScan(scanProto.build());
    } else {                                      // Writable or Serializable
      Class instanceClass = null;
      int b = (byte)WritableUtils.readVInt(in);
      if (b == NOT_ENCODED) {
        String className = Text.readString(in);
        if ("org.apache.hadoop.hbase.regionserver.wal.HLog$Entry".equals(className)) {
          className = Entry.class.getName();
        }
        try {
          instanceClass = getClassByName(conf, className);
        } catch (ClassNotFoundException e) {
          LOG.error("Can't find class " + className, e);
          throw new IOException("Can't find class " + className, e);
        }
      } else {
        instanceClass = CODE_TO_CLASS.get(b);
      }
      if(Writable.class.isAssignableFrom(instanceClass)){
        Writable writable = WritableFactories.newInstance(instanceClass, conf);
        try {
          writable.readFields(in);
        } catch (Exception e) {
          LOG.error("Error in readFields", e);
          throw new IOException("Error in readFields" , e);
        }
        instance = writable;
        if (instanceClass == NullInstance.class) {  // null
          declaredClass = ((NullInstance)instance).declaredClass;
          instance = null;
        }
      } else if (Entry.class.isAssignableFrom(instanceClass)) {
        // Entry stopped being Writable; maintain serialization support.
        final HLogKey key = new HLogKey();
        final WALEdit edit = new WALEdit();
        key.readFields(in);
        edit.readFields(in);
        instance = new Entry(key, edit);
      } else {
        int length = in.readInt();
        byte[] objectBytes = new byte[length];
        in.readFully(objectBytes);
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        try {
          bis = new ByteArrayInputStream(objectBytes);
          ois = new ObjectInputStream(bis);
          instance = ois.readObject();
        } catch (ClassNotFoundException e) {
          LOG.error("Class not found when attempting to deserialize object", e);
          throw new IOException("Class not found when attempting to " +
              "deserialize object", e);
        } finally {
          if(bis!=null) bis.close();
          if(ois!=null) ois.close();
        }
      }
    }
    if (objectWritable != null) {                 // store values
      objectWritable.declaredClass = declaredClass;
      objectWritable.instance = instance;
    }
    return instance;
  }

  /**
   * Try to instantiate a protocol buffer of the given message class
   * from the given input stream.
   *
   * @param protoClass the class of the generated protocol buffer
   * @param dataIn the input stream to read from
   * @return the instantiated Message instance
   * @throws IOException if an IO problem occurs
   */
  static Message tryInstantiateProtobuf(
      Class<?> protoClass,
      DataInput dataIn) throws IOException {

    try {
      if (dataIn instanceof InputStream) {
        // We can use the built-in parseDelimitedFrom and not have to re-copy
        // the data
        Method parseMethod = getStaticProtobufMethod(protoClass,
            "parseDelimitedFrom", InputStream.class);
        return (Message)parseMethod.invoke(null, (InputStream)dataIn);
      } else {
        // Have to read it into a buffer first, since protobuf doesn't deal
        // with the DataInput interface directly.

        // Read the size delimiter that writeDelimitedTo writes
        int size = ProtoUtil.readRawVarint32(dataIn);
        if (size < 0) {
          throw new IOException("Invalid size: " + size);
        }

        byte[] data = new byte[size];
        dataIn.readFully(data);
        Method parseMethod = getStaticProtobufMethod(protoClass,
            "parseFrom", byte[].class);
        return (Message)parseMethod.invoke(null, data);
      }
    } catch (InvocationTargetException e) {

      if (e.getCause() instanceof IOException) {
        throw (IOException)e.getCause();
      } else {
        throw new IOException(e.getCause());
      }
    } catch (IllegalAccessException iae) {
      throw new AssertionError("Could not access parse method in " +
          protoClass);
    }
  }

  static Method getStaticProtobufMethod(Class<?> declaredClass, String method,
      Class<?> ... args) {

    try {
      return declaredClass.getMethod(method, args);
    } catch (Exception e) {
      // This is a bug in Hadoop - protobufs should all have this static method
      throw new AssertionError("Protocol buffer class " + declaredClass +
          " does not have an accessible parseFrom(InputStream) method!");
    }
  }

  @SuppressWarnings("unchecked")
  private static Class getClassByName(Configuration conf, String className)
  throws ClassNotFoundException {
    if(conf != null) {
      return conf.getClassByName(className);
    }
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    if(cl == null) {
      cl = HbaseObjectWritableFor96Migration.class.getClassLoader();
    }
    return Class.forName(className, true, cl);
  }

  private static void addToMap(final Class<?> clazz, final int code) {
    CLASS_TO_CODE.put(clazz, code);
    CODE_TO_CLASS.put(code, clazz);
  }

  public void setConf(Configuration conf) {
    this.conf = conf;
  }

  public Configuration getConf() {
    return this.conf;
  }
}
