THRIFT-169. java: Pluggable Serializers
THRIFT-1239. java: TupleProtocol- An extremely compact, temporary protocol

This monster commit is the combination of the two above tickets, providing a new serialization framework and the first new consumer in one go.

Patch: Armaan Sarkar

git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1156728 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc
index f9ed5e2..f368655 100644
--- a/compiler/cpp/src/generate/t_java_generator.cc
+++ b/compiler/cpp/src/generate/t_java_generator.cc
@@ -37,12 +37,12 @@
  *
  */
 class t_java_generator : public t_oop_generator {
- public:
+public:
   t_java_generator(
-      t_program* program,
-      const std::map<std::string, std::string>& parsed_options,
-      const std::string& option_string)
-    : t_oop_generator(program)
+                   t_program* program,
+                   const std::map<std::string, std::string>& parsed_options,
+                   const std::string& option_string)
+  : t_oop_generator(program)
   {
     (void) option_string;
     std::map<std::string, std::string>::const_iterator iter;
@@ -65,7 +65,7 @@
     iter = parsed_options.find("java5");
     java5_ = (iter != parsed_options.end());
     if (java5_) {
-        android_legacy_ = true;
+      android_legacy_ = true;
     }
 
     out_dir_base_ = (bean_style_ ? "gen-javabean" : "gen-java");
@@ -125,7 +125,7 @@
   std::string get_cap_name(std::string name);
   std::string generate_isset_check(t_field* field);
   std::string generate_isset_check(std::string field);
-  void generate_isset_set(ofstream& out, t_field* field);
+  void generate_isset_set(ofstream& out, t_field* field, std::string prefix);
   std::string isset_field_id(t_field* field);
 
   void generate_service_interface (t_service* tservice);
@@ -151,13 +151,23 @@
   void generate_union_comparisons(ofstream& out, t_struct* tstruct);
   void generate_union_hashcode(ofstream& out, t_struct* tstruct);
 
+  void generate_scheme_map(ofstream& out, t_struct* tstruct);
+  void generate_standard_writer(ofstream& out, t_struct* tstruct);
+  void generate_standard_reader(ofstream& out, t_struct* tstruct);
+  void generate_java_struct_standard_scheme(ofstream& out, t_struct* tstruct);
+
+  void generate_java_struct_tuple_scheme(ofstream& out, t_struct* tstruct);
+  void generate_java_struct_tuple_reader(ofstream& out, t_struct* tstruct);
+  void generate_java_struct_tuple_writer(ofstream& out, t_struct* tstruct);
+
   /**
    * Serialization constructs
    */
 
   void generate_deserialize_field        (std::ofstream& out,
                                           t_field*    tfield,
-                                          std::string prefix="");
+                                          std::string prefix="",
+                                          bool has_metadata = true);
 
   void generate_deserialize_struct       (std::ofstream& out,
                                           t_struct*   tstruct,
@@ -165,23 +175,28 @@
 
   void generate_deserialize_container    (std::ofstream& out,
                                           t_type*     ttype,
-                                          std::string prefix="");
+                                          std::string prefix="",
+                                          bool has_metadata = true);
 
   void generate_deserialize_set_element  (std::ofstream& out,
                                           t_set*      tset,
-                                          std::string prefix="");
+                                          std::string prefix="",
+                                          bool has_metadata = true);
 
   void generate_deserialize_map_element  (std::ofstream& out,
                                           t_map*      tmap,
-                                          std::string prefix="");
+                                          std::string prefix="",
+                                          bool has_metadata = true);
 
   void generate_deserialize_list_element (std::ofstream& out,
                                           t_list*     tlist,
-                                          std::string prefix="");
+                                          std::string prefix="",
+                                          bool has_metadata = true);
 
   void generate_serialize_field          (std::ofstream& out,
                                           t_field*    tfield,
-                                          std::string prefix="");
+                                          std::string prefix="",
+                                          bool has_metadata = true);
 
   void generate_serialize_struct         (std::ofstream& out,
                                           t_struct*   tstruct,
@@ -189,20 +204,24 @@
 
   void generate_serialize_container      (std::ofstream& out,
                                           t_type*     ttype,
-                                          std::string prefix="");
+                                          std::string prefix="",
+                                          bool has_metadata = true);
 
   void generate_serialize_map_element    (std::ofstream& out,
                                           t_map*      tmap,
                                           std::string iter,
-                                          std::string map);
+                                          std::string map,
+                                          bool has_metadata = true);
 
   void generate_serialize_set_element    (std::ofstream& out,
                                           t_set*      tmap,
-                                          std::string iter);
+                                          std::string iter,
+                                          bool has_metadata = true);
 
   void generate_serialize_list_element   (std::ofstream& out,
                                           t_list*     tlist,
-                                          std::string iter);
+                                          std::string iter,
+                                          bool has_metadata = true);
 
   void generate_java_doc                 (std::ofstream& out,
                                           t_field*    field);
@@ -270,7 +289,6 @@
   bool gen_hash_code_;
   bool android_legacy_;
   bool java5_;
-
 };
 
 
@@ -327,6 +345,11 @@
   return
     string() +
     hash_builder +
+    "import org.apache.thrift.scheme.IScheme;\n" +
+    "import org.apache.thrift.scheme.SchemeFactory;\n" +
+    "import org.apache.thrift.scheme.StandardScheme;\n\n" +
+    "import org.apache.thrift.scheme.TupleScheme;\n" +
+    "import org.apache.thrift.protocol.TTupleProtocol;\n" +
     "import java.util.List;\n" +
     "import java.util.ArrayList;\n" +
     "import java.util.Map;\n" +
@@ -433,14 +456,14 @@
     indent(f_enum) << "case " << value << ":" << endl;
     indent(f_enum) << "  return " << (*c_iter)->get_name() << ";" << endl;
   }
-  
+
   indent(f_enum) << "default:" << endl;
   indent(f_enum) << "  return null;" << endl;  
 
   indent_down();
 
   indent(f_enum) << "}" << endl;
-  
+
   indent_down();
 
   indent(f_enum) << "}" << endl;
@@ -482,8 +505,7 @@
                       false);
   }
   indent_down();
-  indent(f_consts) <<
-    "}" << endl;
+  indent(f_consts) << "}" << endl;
   f_consts.close();
 }
 
@@ -592,33 +614,33 @@
   if (type->is_base_type()) {
     t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
     switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      render << '"' << get_escaped_string(value) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      render << ((value->get_integer() > 0) ? "true" : "false");
-      break;
-    case t_base_type::TYPE_BYTE:
-      render << "(byte)" << value->get_integer();
-      break;
-    case t_base_type::TYPE_I16:
-      render << "(short)" << value->get_integer();
-      break;
-    case t_base_type::TYPE_I32:
-      render << value->get_integer();
-      break;
-    case t_base_type::TYPE_I64:
-      render << value->get_integer() << "L";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        render << "(double)" << value->get_integer();
-      } else {
-        render << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+      case t_base_type::TYPE_STRING:
+        render << '"' << get_escaped_string(value) << '"';
+        break;
+      case t_base_type::TYPE_BOOL:
+        render << ((value->get_integer() > 0) ? "true" : "false");
+        break;
+      case t_base_type::TYPE_BYTE:
+        render << "(byte)" << value->get_integer();
+        break;
+      case t_base_type::TYPE_I16:
+        render << "(short)" << value->get_integer();
+        break;
+      case t_base_type::TYPE_I32:
+        render << value->get_integer();
+        break;
+      case t_base_type::TYPE_I64:
+        render << value->get_integer() << "L";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        if (value->get_type() == t_const_value::CV_INTEGER) {
+          render << "(double)" << value->get_integer();
+        } else {
+          render << value->get_double();
+        }
+        break;
+      default:
+        throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
     }
   } else if (type->is_enum()) {
     render << type->get_program()->get_namespace("java") << "." << value->get_identifier_with_parent();
@@ -670,7 +692,7 @@
   f_struct <<
     autogen_comment() <<
     java_package() <<
-   java_type_imports();
+    java_type_imports();
 
   generate_java_struct_definition(f_struct,
                                   tstruct,
@@ -732,7 +754,7 @@
   f_struct << endl;
 
   generate_union_is_set_methods(f_struct, tstruct);
-  
+
   f_struct << endl;
 
   generate_union_comparisons(f_struct, tstruct);
@@ -751,6 +773,10 @@
 
   f_struct << endl;
 
+  //  generate_java_struct_standard_scheme(f_struct, tstruct);
+
+  f_struct << endl;
+
   scope_down(f_struct);
 
   f_struct.close();
@@ -797,7 +823,7 @@
 void t_java_generator::generate_union_getters_and_setters(ofstream& out, t_struct* tstruct) {
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter;
-  
+
   bool first = true;
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
     if (first) {
@@ -911,7 +937,7 @@
 
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
     t_field* field = (*m_iter);
-    
+
     indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
     indent(out) << "  if (value instanceof " << type_name(field->get_type(), true, false, true) << ") {" << endl;
     indent(out) << "    break;" << endl;
@@ -921,13 +947,13 @@
       << "', but got \" + value.getClass().getSimpleName());" << endl;
     // do the real check here
   }
-  
+
   indent(out) << "default:" << endl;
   indent(out) << "  throw new IllegalArgumentException(\"Unknown field id \" + setField);" << endl;
 
   indent_down();
   indent(out) << "}" << endl;
-  
+
   indent_down();
   indent(out) << "}" << endl;
 }
@@ -949,7 +975,7 @@
 
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
     t_field* field = (*m_iter);
-    
+
     indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
     indent_up();
     indent(out) << "if (field.type == " << constant_name(field->get_name()) << "_FIELD_DESC.type) {" << endl;
@@ -997,16 +1023,16 @@
 
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
     t_field* field = (*m_iter);
-    
+
     indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
     indent_up();
     indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() 
       << " = (" <<  type_name(field->get_type(), true, false) << ")value_;" << endl;
-    generate_serialize_field(out, field, "");
+    generate_serialize_field(out, field, "", false);
     indent(out) << "return;" << endl;
     indent_down();
   }
-  
+
   indent(out) << "default:" << endl;
   indent(out) << "  throw new IllegalStateException(\"Cannot write union with unknown field \" + setField_);" << endl;
 
@@ -1015,8 +1041,6 @@
 
   indent_down();
 
-
-
   indent(out) << "}" << endl;
 }
 
@@ -1024,7 +1048,7 @@
   indent(out) << "@Override" << endl;
   indent(out) << "protected org.apache.thrift.protocol.TField getFieldDesc(_Fields setField) {" << endl;
   indent_up();
-  
+
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter;
 
@@ -1134,7 +1158,7 @@
 
   indent(out) <<
     "public " << (is_final ? "final " : "") <<
-     (in_class ? "static " : "") << "class " << tstruct->get_name() << " ";
+    (in_class ? "static " : "") << "class " << tstruct->get_name() << " ";
 
   if (is_exception) {
     out << "extends Exception ";
@@ -1157,6 +1181,10 @@
 
   out << endl;
 
+  generate_scheme_map(out, tstruct);
+
+  out << endl;
+
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
     if (bean_style_ || private_members_) {
       indent(out) << "private ";
@@ -1178,7 +1206,11 @@
     indent(out) << "// isset id assignments" << endl;
 
     int i = 0;
+    int optionals = 0;
     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() == t_field::T_OPTIONAL) {
+        optionals++;
+      }
       if (!type_can_be_null((*m_iter)->get_type())) {
         indent(out) << "private static final int " << isset_field_id(*m_iter)
           << " = " << i << ";" <<  endl;
@@ -1189,8 +1221,15 @@
     if (i > 0) {
       indent(out) << "private BitSet __isset_bit_vector = new BitSet(" << i << ");" << endl;
     }
-
-    out << endl;
+    if (optionals > 0) {
+      std::string output_string = "private _Fields optionals[] = {";
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        if ((*m_iter)->get_req() == t_field::T_OPTIONAL) {
+          output_string = output_string + "_Fields." + constant_name((*m_iter)->get_name()) + ",";
+        }
+      }
+      indent(out) << output_string.substr(0, output_string.length() - 1) <<  "};" << endl;
+    }
   }
 
   generate_java_meta_data_map(out, tstruct);
@@ -1238,9 +1277,10 @@
       if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
         indent(out) << "this." << (*m_iter)->get_name() << " = " <<
           (*m_iter)->get_name() << ";" << endl;
-        generate_isset_set(out, (*m_iter));
+        generate_isset_set(out, (*m_iter), "");
       }
     }
+
     indent_down();
     indent(out) << "}" << endl << endl;
   }
@@ -1313,6 +1353,9 @@
   generate_java_struct_write_object(out, tstruct);
   generate_java_struct_read_object(out, tstruct);
 
+  generate_java_struct_standard_scheme(out, tstruct);
+  generate_java_struct_tuple_scheme(out, tstruct);
+
   scope_down(out);
   out << endl;
 }
@@ -1366,15 +1409,15 @@
 
     out <<
       indent() << "boolean this_present_" << name << " = "
-               << this_present << ";" << endl <<
+      << this_present << ";" << endl <<
       indent() << "boolean that_present_" << name << " = "
-               << that_present << ";" << endl <<
+      << that_present << ";" << endl <<
       indent() << "if (" << "this_present_" << name
-               << " || that_present_" << name << ") {" << endl;
+      << " || that_present_" << name << ") {" << endl;
     indent_up();
     out <<
       indent() << "if (!(" << "this_present_" << name
-               << " && that_present_" << name << "))" << endl <<
+      << " && that_present_" << name << "))" << endl <<
       indent() << "  return false;" << endl;
 
     if (t->is_base_type() && ((t_base_type*)t)->is_binary()) {
@@ -1478,105 +1521,18 @@
  */
 void t_java_generator::generate_java_struct_reader(ofstream& out,
                                                    t_struct* tstruct) {
-  out <<
-    indent() << "public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {" << endl;
+  indent(out) << "public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {" << endl;
   indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // Declare stack tmp variables and read struct header
-  out <<
-    indent() << "org.apache.thrift.protocol.TField field;" << endl <<
-    indent() << "iprot.readStructBegin();" << endl;
-
-  // Loop over reading in fields
-  indent(out) <<
-    "while (true)" << endl;
-    scope_up(out);
-
-    // Read beginning field marker
-    indent(out) <<
-      "field = iprot.readFieldBegin();" << endl;
-
-    // Check for field STOP marker and break
-    indent(out) <<
-      "if (field.type == org.apache.thrift.protocol.TType.STOP) { " << endl;
-    indent_up();
-    indent(out) <<
-      "break;" << endl;
-    indent_down();
-    indent(out) <<
-      "}" << endl;
-
-    // Switch statement on the field we are reading
-    indent(out) << "switch (field.id) {" << endl;
-
-    indent_up();
-
-    // Generate deserialization code for known cases
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      indent(out) <<
-        "case " << (*f_iter)->get_key() << ": // " << constant_name((*f_iter)->get_name()) << endl;
-      indent_up();
-      indent(out) <<
-        "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
-      indent_up();
-
-      generate_deserialize_field(out, *f_iter, "this.");
-      generate_isset_set(out, *f_iter);
-      indent_down();
-      out <<
-        indent() << "} else { " << endl <<
-        indent() << "  org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);" << endl <<
-        indent() << "}" << endl <<
-        indent() << "break;" << endl;
-      indent_down();
-    }
-
-    indent(out) << "default:" << endl;
-    indent(out) << "  org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);" << endl;
-
-    indent_down();
-    indent(out) << "}" << endl;
-
-    // Read field end marker
-    indent(out) <<
-      "iprot.readFieldEnd();" << endl;
-
-    indent_down();
-    indent(out) << "}" << endl;
-
-    out <<
-      indent() << "iprot.readStructEnd();" << endl;
-
-    // in non-beans style, check for required fields of primitive type
-    // (which can be checked here but not in the general validate method)
-    if (!bean_style_){
-      out << endl << indent() << "// check for required fields of primitive type, which can't be checked in the validate method" << endl;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_req() == t_field::T_REQUIRED && !type_can_be_null((*f_iter)->get_type())) {
-          out <<
-            indent() << "if (!" << generate_isset_check(*f_iter) << ") {" << endl <<
-            indent() << "  throw new org.apache.thrift.protocol.TProtocolException(\"Required field '" << (*f_iter)->get_name() << "' was not found in serialized data! Struct: \" + toString());" << endl <<
-            indent() << "}" << endl;
-        }
-      }
-    }
-
-    // performs various checks (e.g. check that all required fields are set)
-    indent(out) << "validate();" << endl;
-
+  indent(out) << "schemes.get(iprot.getScheme()).getScheme().read(iprot, this);" << endl; 
   indent_down();
-  out <<
-    indent() << "}" << endl <<
-    endl;
+  indent(out) << "}" << endl <<
+  endl;	
 }
 
 // generates java method to perform various checks
 // (e.g. check that all required fields are set)
 void t_java_generator::generate_java_validator(ofstream& out,
-                                                   t_struct* tstruct){
+                                               t_struct* tstruct){
   indent(out) << "public void validate() throws org.apache.thrift.TException {" << endl;
   indent_up();
 
@@ -1614,59 +1570,12 @@
  */
 void t_java_generator::generate_java_struct_writer(ofstream& out,
                                                    t_struct* tstruct) {
-  out <<
-    indent() << "public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {" << endl;
+  indent(out) << "public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {" << endl;
   indent_up();
-
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // performs various checks (e.g. check that all required fields are set)
-  indent(out) << "validate();" << endl << endl;
-
-  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    bool null_allowed = type_can_be_null((*f_iter)->get_type());
-    if (null_allowed) {
-      out <<
-        indent() << "if (this." << (*f_iter)->get_name() << " != null) {" << endl;
-      indent_up();
-    }
-    bool optional = (*f_iter)->get_req() == t_field::T_OPTIONAL;
-    if (optional) {
-      indent(out) << "if (" << generate_isset_check((*f_iter)) << ") {" << endl;
-      indent_up();
-    }
-
-    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name()) << "_FIELD_DESC);" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "this.");
-
-    // Write field closer
-    indent(out) <<
-      "oprot.writeFieldEnd();" << endl;
-
-    if (optional) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    if (null_allowed) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-  }
-  // Write the struct map
-  out <<
-    indent() << "oprot.writeFieldStop();" << endl <<
-    indent() << "oprot.writeStructEnd();" << endl;
+  indent(out) << "schemes.get(oprot.getScheme()).getScheme().write(oprot, this);" << endl;
 
   indent_down();
-  out <<
-    indent() << "}" << endl <<
-    endl;
+  indent(out) << "  }" << endl << endl;	
 }
 
 /**
@@ -1679,53 +1588,12 @@
  */
 void t_java_generator::generate_java_struct_result_writer(ofstream& out,
                                                           t_struct* tstruct) {
-  out <<
-    indent() << "public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {" << endl;
+  indent(out) << "public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {" << endl;
   indent_up();
-
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
-
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-      out <<
-        endl <<
-        indent() << "if ";
-    } else {
-      out << " else if ";
-    }
-
-    out << "(this." << generate_isset_check(*f_iter) << ") {" << endl;
-
-    indent_up();
-    
-    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name()) << "_FIELD_DESC);" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "this.");
-
-    // Write field closer
-    indent(out) <<
-      "oprot.writeFieldEnd();" << endl;
-
-    indent_down();
-    indent(out) << "}";
-  }
-  // Write the struct map
-  out <<
-    endl <<
-    indent() << "oprot.writeFieldStop();" << endl <<
-    indent() << "oprot.writeStructEnd();" << endl;
-
+  indent(out) << "schemes.get(oprot.getScheme()).getScheme().write(oprot, this);" << endl;
+  
   indent_down();
-  out <<
-    indent() << "}" << endl <<
-    endl;
+  indent(out) << "  }" << endl << endl;	
 }
 
 void t_java_generator::generate_java_struct_field_by_id(ofstream& out, t_struct* tstruct) {
@@ -1764,7 +1632,6 @@
 }
 
 void t_java_generator::generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct) {
-
   std::ostringstream getter_stream;
   std::ostringstream setter_stream;
 
@@ -1861,7 +1728,6 @@
     }
 
     if (type->is_set() || type->is_list()) {
-
       t_type* element_type;
       if (type->is_set()) {
         element_type = ((t_set*)type)->get_elem_type();
@@ -1895,7 +1761,6 @@
       indent(out) << "this." << field_name << ".add(elem);" << endl;
       indent_down();
       indent(out) << "}" << endl << endl;
-
     } else if (type->is_map()) {
       // Put to map
       t_type* key_type = ((t_map*)type)->get_key_type();
@@ -1968,9 +1833,8 @@
     }
     out << " set" << cap_name << "(" << type_name(type) << " " << field_name << ") {" << endl;
     indent_up();
-    indent(out) << "this." << field_name << " = " << field_name << ";" <<
-      endl;
-    generate_isset_set(out, field);
+    indent(out) << "this." << field_name << " = " << field_name << ";" << endl;
+    generate_isset_set(out, field, "");
     if (!bean_style_) {
       indent(out) << "return this;" << endl;
     }
@@ -2053,13 +1917,13 @@
       indent(out) << "} else {" << endl;
       indent_up();
     }
-    
+
     if (field->get_type()->is_base_type() && ((t_base_type*)(field->get_type()))->is_binary()) {
       indent(out) << "org.apache.thrift.TBaseHelper.toString(this." << field->get_name() << ", sb);" << endl;
     } else {
       indent(out) << "sb.append(this." << (*f_iter)->get_name() << ");" << endl;
     }
-    
+
     if (can_be_null) {
       indent_down();
       indent(out) << "}" << endl;
@@ -2077,8 +1941,7 @@
     indent() << "return sb.toString();" << endl;
 
   indent_down();
-  indent(out) << "}" << endl <<
-    endl;
+  indent(out) << "}" << endl << endl;
 }
 
 /**
@@ -2217,9 +2080,7 @@
     java_package() <<
     java_type_imports();
 
-  f_service_ <<
-    "public class " << service_name_ << " {" << endl <<
-    endl;
+  f_service_ << "public class " << service_name_ << " {" << endl << endl;
   indent_up();
 
   // Generate the three main parts of the service
@@ -2332,11 +2193,9 @@
   indent_down();
   indent(f_service_) << "}" << endl << endl;
 
-  indent(f_service_) <<
-    "public Client(org.apache.thrift.protocol.TProtocol prot)" << endl;
+  indent(f_service_) << "public Client(org.apache.thrift.protocol.TProtocol prot)" << endl;
   scope_up(f_service_);
-  indent(f_service_) <<
-    "super(prot, prot);" << endl;
+  indent(f_service_) << "super(prot, prot);" << endl;
   scope_down(f_service_);
   f_service_ << endl;
 
@@ -2352,11 +2211,9 @@
     string funname = (*f_iter)->get_name();
 
     // Open function
-    indent(f_service_) <<
-      "public " << function_signature(*f_iter) << endl;
+    indent(f_service_) << "public " << function_signature(*f_iter) << endl;
     scope_up(f_service_);
-    indent(f_service_) <<
-      "send_" << funname << "(";
+    indent(f_service_) << "send_" << funname << "(";
 
     // Get the struct of function call params
     t_struct* arg_struct = (*f_iter)->get_arglist();
@@ -2401,8 +2258,7 @@
     indent(f_service_) << argsname << " args = new " << argsname << "();" << endl;
 
     for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ <<
-        indent() << "args.set" << get_cap_name((*fld_iter)->get_name()) << "(" << (*fld_iter)->get_name() << ");" << endl;
+      indent(f_service_) << "args.set" << get_cap_name((*fld_iter)->get_name()) << "(" << (*fld_iter)->get_name() << ");" << endl;
     }
 
     indent(f_service_) << "sendBase(\"" << funname << "\", args);" << endl;
@@ -2447,8 +2303,7 @@
 
       // If you get here it's an exception, unless a void function
       if ((*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) <<
-          "return;" << endl;
+        indent(f_service_) << "return;" << endl;
       } else {
         f_service_ <<
           indent() << "throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, \"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
@@ -2461,8 +2316,7 @@
   }
 
   indent_down();
-  indent(f_service_) <<
-    "}" << endl;
+  indent(f_service_) << "}" << endl;
 }
 
 void t_java_generator::generate_service_async_client(t_service* tservice) {
@@ -2715,8 +2569,7 @@
 
   // Try block for a function with exceptions
   if (xceptions.size() > 0) {
-    f_service_ <<
-      indent() << "try {" << endl;
+    f_service_ << indent() << "try {" << endl;
     indent_up();
   }
 
@@ -2729,8 +2582,7 @@
   if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
     f_service_ << "result.success = ";
   }
-  f_service_ <<
-    "iface." << tfunction->get_name() << "(";
+  f_service_ << "iface." << tfunction->get_name() << "(";
   bool first = true;
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
     if (first) {
@@ -2744,8 +2596,7 @@
 
   // Set isset on success field
   if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void() && !type_can_be_null(tfunction->get_returntype())) {
-    f_service_ <<
-      indent() << "result.set" << get_cap_name("success") << get_cap_name("isSet") << "(true);" << endl;
+    indent(f_service_) << "result.set" << get_cap_name("success") << get_cap_name("isSet") << "(true);" << endl;
   }
 
   if (!tfunction->is_oneway() && xceptions.size() > 0) {
@@ -2779,9 +2630,7 @@
 
   // Close class
   indent_down();
-  f_service_ <<
-    indent() << "}" << endl <<
-    endl;
+  f_service_ << indent() << "}" << endl << endl;
 }
 
 /**
@@ -2792,12 +2641,11 @@
  */
 void t_java_generator::generate_deserialize_field(ofstream& out,
                                                   t_field* tfield,
-                                                  string prefix) {
+                                                  string prefix, bool has_metadata) {
   t_type* type = get_true_type(tfield->get_type());
 
   if (type->is_void()) {
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " +
-      prefix + tfield->get_name();
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
   }
 
   string name = prefix + tfield->get_name();
@@ -2807,15 +2655,15 @@
                                 (t_struct*)type,
                                 name);
   } else if (type->is_container()) {
-    generate_deserialize_container(out, type, name);
+    generate_deserialize_container(out, type, name, has_metadata);
   } else if (type->is_base_type()) {
     indent(out) << name << " = iprot.";
 
+
     t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
     switch (tbase) {
       case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " +
-          name;
+        throw "compiler error: cannot serialize void field in a struct: " + name;
         break;
       case t_base_type::TYPE_STRING:
         if (((t_base_type*)type)->is_binary()) {
@@ -2870,7 +2718,8 @@
  */
 void t_java_generator::generate_deserialize_container(ofstream& out,
                                                       t_type* ttype,
-                                                      string prefix) {
+                                                      string prefix, bool has_metadata) {
+
   scope_up(out);
 
   string obj;
@@ -2883,19 +2732,32 @@
     obj = tmp("_list");
   }
 
-  // Declare variables, read header
-  if (ttype->is_map()) {
-    indent(out) << "org.apache.thrift.protocol.TMap " << obj << " = iprot.readMapBegin();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "org.apache.thrift.protocol.TSet " << obj << " = iprot.readSetBegin();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "org.apache.thrift.protocol.TList " << obj << " = iprot.readListBegin();" << endl;
+  if (has_metadata) {
+    // Declare variables, read header
+    if (ttype->is_map()) {
+      indent(out) << "org.apache.thrift.protocol.TMap " << obj << " = iprot.readMapBegin();" << endl;
+    } else if (ttype->is_set()) {
+      indent(out) << "org.apache.thrift.protocol.TSet " << obj << " = iprot.readSetBegin();" << endl;
+    } else if (ttype->is_list()) {
+      indent(out) << "org.apache.thrift.protocol.TList " << obj << " = iprot.readListBegin();" << endl;
+    }
+  } else {
+    // Declare variables, read header
+    if (ttype->is_map()) {
+      indent(out) << "org.apache.thrift.protocol.TMap " << obj << " = new org.apache.thrift.protocol.TMap(" << 
+      type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << "iprot.readI32());" << endl;
+    } else if (ttype->is_set()) {
+      indent(out) << "org.apache.thrift.protocol.TSet " << obj << " = new org.apache.thrift.protocol.TSet(" << 
+      type_to_enum(((t_set*)ttype)->get_elem_type()) << ", iprot.readI32());" << endl;
+    } else if (ttype->is_list()) {
+      indent(out) << "org.apache.thrift.protocol.TList " << obj << " = new org.apache.thrift.protocol.TList(" << 
+      type_to_enum(((t_set*)ttype)->get_elem_type()) << ", iprot.readI32());" << endl;
+    }
   }
 
-  indent(out)
-    << prefix << " = new " << type_name(ttype, false, true)
-    // size the collection correctly
-    << "("
+  indent(out) << prefix << " = new " << type_name(ttype, false, true);
+  // size the collection correctly
+  out << "("
     << (ttype->is_list() ? "" : "2*" )
     << obj << ".size"
     << ");" << endl;
@@ -2907,28 +2769,29 @@
     i << " < " << obj << ".size" << "; " <<
     "++" << i << ")" << endl;
 
-    scope_up(out);
+  scope_up(out);
 
-    if (ttype->is_map()) {
-      generate_deserialize_map_element(out, (t_map*)ttype, prefix);
-    } else if (ttype->is_set()) {
-      generate_deserialize_set_element(out, (t_set*)ttype, prefix);
-    } else if (ttype->is_list()) {
-      generate_deserialize_list_element(out, (t_list*)ttype, prefix);
-    }
-
-    scope_down(out);
-
-  // Read container end
   if (ttype->is_map()) {
-    indent(out) << "iprot.readMapEnd();" << endl;
+    generate_deserialize_map_element(out, (t_map*)ttype, prefix, has_metadata);
   } else if (ttype->is_set()) {
-    indent(out) << "iprot.readSetEnd();" << endl;
+    generate_deserialize_set_element(out, (t_set*)ttype, prefix, has_metadata);
   } else if (ttype->is_list()) {
-    indent(out) << "iprot.readListEnd();" << endl;
+    generate_deserialize_list_element(out, (t_list*)ttype, prefix, has_metadata);
   }
 
   scope_down(out);
+
+  if (has_metadata) {
+    // Read container end
+    if (ttype->is_map()) {
+      indent(out) << "iprot.readMapEnd();" << endl;
+    } else if (ttype->is_set()) {
+      indent(out) << "iprot.readSetEnd();" << endl;
+    } else if (ttype->is_list()) {
+      indent(out) << "iprot.readListEnd();" << endl;
+    }
+  }
+  scope_down(out);
 }
 
 
@@ -2937,22 +2800,19 @@
  */
 void t_java_generator::generate_deserialize_map_element(ofstream& out,
                                                         t_map* tmap,
-                                                        string prefix) {
+                                                        string prefix, bool has_metadata) {
   string key = tmp("_key");
   string val = tmp("_val");
   t_field fkey(tmap->get_key_type(), key);
   t_field fval(tmap->get_val_type(), val);
 
-  indent(out) <<
-    declare_field(&fkey) << endl;
-  indent(out) <<
-    declare_field(&fval) << endl;
+  indent(out) << declare_field(&fkey) << endl;
+  indent(out) << declare_field(&fval) << endl;
 
-  generate_deserialize_field(out, &fkey);
-  generate_deserialize_field(out, &fval);
+  generate_deserialize_field(out, &fkey, "", has_metadata);
+  generate_deserialize_field(out, &fval, "", has_metadata);
 
-  indent(out) <<
-    prefix << ".put(" << key << ", " << val << ");" << endl;
+  indent(out) << prefix << ".put(" << key << ", " << val << ");" << endl;
 }
 
 /**
@@ -2960,17 +2820,15 @@
  */
 void t_java_generator::generate_deserialize_set_element(ofstream& out,
                                                         t_set* tset,
-                                                        string prefix) {
+                                                        string prefix, bool has_metadata) {
   string elem = tmp("_elem");
   t_field felem(tset->get_elem_type(), elem);
 
-  indent(out) <<
-    declare_field(&felem) << endl;
+  indent(out) << declare_field(&felem) << endl;
 
-  generate_deserialize_field(out, &felem);
+  generate_deserialize_field(out, &felem, "", has_metadata);
 
-  indent(out) <<
-    prefix << ".add(" << elem << ");" << endl;
+  indent(out) << prefix << ".add(" << elem << ");" << endl;
 }
 
 /**
@@ -2978,20 +2836,17 @@
  */
 void t_java_generator::generate_deserialize_list_element(ofstream& out,
                                                          t_list* tlist,
-                                                         string prefix) {
+                                                         string prefix, bool has_metadata) {
   string elem = tmp("_elem");
   t_field felem(tlist->get_elem_type(), elem);
 
-  indent(out) <<
-    declare_field(&felem) << endl;
+  indent(out) << declare_field(&felem) << endl;
 
-  generate_deserialize_field(out, &felem);
+  generate_deserialize_field(out, &felem, "", has_metadata);
 
-  indent(out) <<
-    prefix << ".add(" << elem << ");" << endl;
+  indent(out) << prefix << ".add(" << elem << ");" << endl;
 }
 
-
 /**
  * Serializes a field of any type.
  *
@@ -3000,13 +2855,12 @@
  */
 void t_java_generator::generate_serialize_field(ofstream& out,
                                                 t_field* tfield,
-                                                string prefix) {
+                                                string prefix, bool has_metadata) {
   t_type* type = get_true_type(tfield->get_type());
 
   // Do nothing for void types
   if (type->is_void()) {
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " +
-      prefix + tfield->get_name();
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
   }
 
   if (type->is_struct() || type->is_xception()) {
@@ -3016,51 +2870,49 @@
   } else if (type->is_container()) {
     generate_serialize_container(out,
                                  type,
-                                 prefix + tfield->get_name());
+                                 prefix + tfield->get_name(), has_metadata);
   } else if (type->is_enum()){
     indent(out) << "oprot.writeI32(" << prefix + tfield->get_name() << ".getValue());" << endl;
   } else if (type->is_base_type()) {
     string name = prefix + tfield->get_name();
-    indent(out) <<
-      "oprot.";
+    indent(out) << "oprot.";
 
     if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();  
       switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw
-          "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        if (((t_base_type*)type)->is_binary()) {
-          out << "writeBinary(" << name << ");";
-        } else {
-          out << "writeString(" << name << ");";
-        }
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "writeBool(" << name << ");";
-        break;
-      case t_base_type::TYPE_BYTE:
-        out << "writeByte(" << name << ");";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "writeI16(" << name << ");";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "writeI32(" << name << ");";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "writeI64(" << name << ");";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "writeDouble(" << name << ");";
-        break;
-      default:
-        throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase);
+        case t_base_type::TYPE_VOID:
+          throw "compiler error: cannot serialize void field in a struct: " + name;
+          break;
+        case t_base_type::TYPE_STRING:
+          if (((t_base_type*)type)->is_binary()) {
+            out << "writeBinary(" << name << ");";
+          } else {
+            out << "writeString(" << name << ");";
+          }
+          break;
+        case t_base_type::TYPE_BOOL:
+          out << "writeBool(" << name << ");";
+          break;
+        case t_base_type::TYPE_BYTE:
+          out << "writeByte(" << name << ");";
+          break;
+        case t_base_type::TYPE_I16:
+          out << "writeI16(" << name << ");";
+          break;
+        case t_base_type::TYPE_I32:
+          out << "writeI32(" << name << ");";
+          break;
+        case t_base_type::TYPE_I64:
+          out << "writeI64(" << name << ");";
+          break;
+        case t_base_type::TYPE_DOUBLE:
+          out << "writeDouble(" << name << ");";
+          break;
+        default:
+          throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase);
       }
     } else if (type->is_enum()) {
-      out << "writeI32(" << name << ");";
+      out << "writeI32(struct." << name << ");";
     }
     out << endl;
   } else {
@@ -3081,8 +2933,7 @@
                                                  t_struct* tstruct,
                                                  string prefix) {
   (void) tstruct;
-  out <<
-    indent() << prefix << ".write(oprot);" << endl;
+  out << indent() << prefix << ".write(oprot);" << endl;
 }
 
 /**
@@ -3093,25 +2944,29 @@
  */
 void t_java_generator::generate_serialize_container(ofstream& out,
                                                     t_type* ttype,
-                                                    string prefix) {
+                                                    string prefix, bool has_metadata) {
   scope_up(out);
 
-  if (ttype->is_map()) {
-    indent(out) <<
-      "oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(" <<
-      type_to_enum(((t_map*)ttype)->get_key_type()) << ", " <<
-      type_to_enum(((t_map*)ttype)->get_val_type()) << ", " <<
-      prefix << ".size()));" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) <<
-      "oprot.writeSetBegin(new org.apache.thrift.protocol.TSet(" <<
-      type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " <<
-      prefix << ".size()));" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) <<
-      "oprot.writeListBegin(new org.apache.thrift.protocol.TList(" <<
-      type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " <<
-      prefix << ".size()));" << endl;
+  if (has_metadata) {
+    if (ttype->is_map()) {
+      indent(out) <<
+        "oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(" <<
+        type_to_enum(((t_map*)ttype)->get_key_type()) << ", " <<
+        type_to_enum(((t_map*)ttype)->get_val_type()) << ", " <<
+        prefix << ".size()));" << endl;
+    } else if (ttype->is_set()) {
+      indent(out) <<
+        "oprot.writeSetBegin(new org.apache.thrift.protocol.TSet(" <<
+        type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " <<
+        prefix << ".size()));" << endl;
+    } else if (ttype->is_list()) {
+      indent(out) <<
+        "oprot.writeListBegin(new org.apache.thrift.protocol.TList(" <<
+        type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " <<
+        prefix << ".size()));" << endl;
+    }
+  } else {
+    indent(out) << "oprot.writeI32(" << prefix << ".size());" << endl;
   }
 
   string iter = tmp("_iter");
@@ -3139,23 +2994,22 @@
   out << endl;
   scope_up(out);
   if (ttype->is_map()) {
-    generate_serialize_map_element(out, (t_map*)ttype, iter, prefix);
+    generate_serialize_map_element(out, (t_map*)ttype, iter, prefix, has_metadata);
   } else if (ttype->is_set()) {
-    generate_serialize_set_element(out, (t_set*)ttype, iter);
+    generate_serialize_set_element(out, (t_set*)ttype, iter, has_metadata);
   } else if (ttype->is_list()) {
-    generate_serialize_list_element(out, (t_list*)ttype, iter);
+    generate_serialize_list_element(out, (t_list*)ttype, iter, has_metadata);
   }
   scope_down(out);
 
-  if (ttype->is_map()) {
-    indent(out) <<
-      "oprot.writeMapEnd();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) <<
-      "oprot.writeSetEnd();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) <<
-      "oprot.writeListEnd();" << endl;
+  if (has_metadata) {
+    if (ttype->is_map()) {
+      indent(out) << "oprot.writeMapEnd();" << endl;
+    } else if (ttype->is_set()) {
+      indent(out) << "oprot.writeSetEnd();" << endl;
+    } else if (ttype->is_list()) {
+      indent(out) << "oprot.writeListEnd();" << endl;
+    }
   }
 
   scope_down(out);
@@ -3167,12 +3021,12 @@
 void t_java_generator::generate_serialize_map_element(ofstream& out,
                                                       t_map* tmap,
                                                       string iter,
-                                                      string map) {
+                                                      string map, bool has_metadata) {
   (void) map;
   t_field kfield(tmap->get_key_type(), iter + ".getKey()");
-  generate_serialize_field(out, &kfield, "");
+  generate_serialize_field(out, &kfield, "", has_metadata);
   t_field vfield(tmap->get_val_type(), iter + ".getValue()");
-  generate_serialize_field(out, &vfield, "");
+  generate_serialize_field(out, &vfield, "", has_metadata);
 }
 
 /**
@@ -3180,9 +3034,10 @@
  */
 void t_java_generator::generate_serialize_set_element(ofstream& out,
                                                       t_set* tset,
-                                                      string iter) {
+                                                      string iter,
+                                                      bool has_metadata) {
   t_field efield(tset->get_elem_type(), iter);
-  generate_serialize_field(out, &efield, "");
+  generate_serialize_field(out, &efield, "", has_metadata);
 }
 
 /**
@@ -3190,9 +3045,10 @@
  */
 void t_java_generator::generate_serialize_list_element(ofstream& out,
                                                        t_list* tlist,
-                                                       string iter) {
+                                                       string iter,
+                                                       bool has_metadata) {
   t_field efield(tlist->get_elem_type(), iter);
-  generate_serialize_field(out, &efield, "");
+  generate_serialize_field(out, &efield, "", has_metadata);
 }
 
 /**
@@ -3217,8 +3073,8 @@
       prefix = "Map";
     }
     return prefix + (skip_generic ? "" : "<" +
-      type_name(tmap->get_key_type(), true) + "," +
-      type_name(tmap->get_val_type(), true) + ">");
+                     type_name(tmap->get_key_type(), true) + "," +
+                     type_name(tmap->get_val_type(), true) + ">");
   } else if (ttype->is_set()) {
     t_set* tset = (t_set*) ttype;
     if (in_init) {
@@ -3260,28 +3116,28 @@
   t_base_type::t_base tbase = type->get_base();
 
   switch (tbase) {
-  case t_base_type::TYPE_VOID:
-    return "void";
-  case t_base_type::TYPE_STRING:
-    if (type->is_binary()) {
-      return "ByteBuffer";
-    } else {
-      return "String";
-    }
-  case t_base_type::TYPE_BOOL:
-    return (in_container ? "Boolean" : "boolean");
-  case t_base_type::TYPE_BYTE:
-    return (in_container ? "Byte" : "byte");
-  case t_base_type::TYPE_I16:
-    return (in_container ? "Short" : "short");
-  case t_base_type::TYPE_I32:
-    return (in_container ? "Integer" : "int");
-  case t_base_type::TYPE_I64:
-    return (in_container ? "Long" : "long");
-  case t_base_type::TYPE_DOUBLE:
-    return (in_container ? "Double" : "double");
-  default:
-    throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase);
+    case t_base_type::TYPE_VOID:
+      return "void";
+    case t_base_type::TYPE_STRING:
+      if (type->is_binary()) {
+        return "ByteBuffer";
+      } else {
+        return "String";
+      }
+    case t_base_type::TYPE_BOOL:
+      return (in_container ? "Boolean" : "boolean");
+    case t_base_type::TYPE_BYTE:
+      return (in_container ? "Byte" : "byte");
+    case t_base_type::TYPE_I16:
+      return (in_container ? "Short" : "short");
+    case t_base_type::TYPE_I32:
+      return (in_container ? "Integer" : "int");
+    case t_base_type::TYPE_I64:
+      return (in_container ? "Long" : "long");
+    case t_base_type::TYPE_DOUBLE:
+      return (in_container ? "Double" : "double");
+    default:
+      throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase);
   }
 }
 
@@ -3302,25 +3158,24 @@
     } else if (ttype->is_base_type()) {
       t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
       switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "NO T_VOID CONSTRUCT";
-      case t_base_type::TYPE_STRING:
-        result += " = null";
-        break;
-      case t_base_type::TYPE_BOOL:
-        result += " = false";
-        break;
-      case t_base_type::TYPE_BYTE:
-      case t_base_type::TYPE_I16:
-      case t_base_type::TYPE_I32:
-      case t_base_type::TYPE_I64:
-        result += " = 0";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        result += " = (double)0";
-        break;
-    }
-
+        case t_base_type::TYPE_VOID:
+          throw "NO T_VOID CONSTRUCT";
+        case t_base_type::TYPE_STRING:
+          result += " = null";
+          break;
+        case t_base_type::TYPE_BOOL:
+          result += " = false";
+          break;
+        case t_base_type::TYPE_BYTE:
+        case t_base_type::TYPE_I16:
+        case t_base_type::TYPE_I32:
+        case t_base_type::TYPE_I64:
+          result += " = 0";
+          break;
+        case t_base_type::TYPE_DOUBLE:
+          result += " = (double)0";
+          break;
+      }
     } else if (ttype->is_enum()) {
       result += " = 0";
     } else if (ttype->is_container()) {
@@ -3360,11 +3215,11 @@
 }
 
 /**
-  * Renders a function signature of the form 'void name(args, resultHandler)'
-  *
-  * @params tfunction Function definition
-  * @return String of rendered function definition
-  */
+ * Renders a function signature of the form 'void name(args, resultHandler)'
+ *
+ * @params tfunction Function definition
+ * @return String of rendered function definition
+ */
 string t_java_generator::function_signature_async(t_function* tfunction, bool use_base_method, string prefix) {
   std::string arglist = async_function_call_arglist(tfunction, use_base_method, true);
 
@@ -3457,22 +3312,22 @@
   if (type->is_base_type()) {
     t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
     switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "NO T_VOID CONSTRUCT";
-    case t_base_type::TYPE_STRING:
-      return "org.apache.thrift.protocol.TType.STRING";
-    case t_base_type::TYPE_BOOL:
-      return "org.apache.thrift.protocol.TType.BOOL";
-    case t_base_type::TYPE_BYTE:
-      return "org.apache.thrift.protocol.TType.BYTE";
-    case t_base_type::TYPE_I16:
-      return "org.apache.thrift.protocol.TType.I16";
-    case t_base_type::TYPE_I32:
-      return "org.apache.thrift.protocol.TType.I32";
-    case t_base_type::TYPE_I64:
-      return "org.apache.thrift.protocol.TType.I64";
-    case t_base_type::TYPE_DOUBLE:
-      return "org.apache.thrift.protocol.TType.DOUBLE";
+      case t_base_type::TYPE_VOID:
+        throw "NO T_VOID CONSTRUCT";
+      case t_base_type::TYPE_STRING:
+        return "org.apache.thrift.protocol.TType.STRING";
+      case t_base_type::TYPE_BOOL:
+        return "org.apache.thrift.protocol.TType.BOOL";
+      case t_base_type::TYPE_BYTE:
+        return "org.apache.thrift.protocol.TType.BYTE";
+      case t_base_type::TYPE_I16:
+        return "org.apache.thrift.protocol.TType.I16";
+      case t_base_type::TYPE_I32:
+        return "org.apache.thrift.protocol.TType.I32";
+      case t_base_type::TYPE_I64:
+        return "org.apache.thrift.protocol.TType.I64";
+      case t_base_type::TYPE_DOUBLE:
+        return "org.apache.thrift.protocol.TType.DOUBLE";
     }
   } else if (type->is_enum()) {
     return "org.apache.thrift.protocol.TType.I32";
@@ -3525,9 +3380,9 @@
 
 void t_java_generator::generate_java_docstring_comment(ofstream &out, string contents) {
   generate_docstring_comment(out,
-    "/**\n",
-    " * ", contents,
-    " */\n");
+                             "/**\n",
+                             " * ", contents,
+                             " */\n");
 }
 
 void t_java_generator::generate_java_doc(ofstream &out,
@@ -3568,9 +3423,9 @@
       }
     }
     generate_docstring_comment(out,
-      "/**\n",
-      " * ", ss.str(),
-      " */\n");
+                               "/**\n",
+                               " * ", ss.str(),
+                               " */\n");
   }
 }
 
@@ -3580,9 +3435,9 @@
   t_container* container = (t_container*)type;
   std::string source_name;
   if (source_name_p2 == "")
-      source_name = source_name_p1;
+    source_name = source_name_p1;
   else
-      source_name = source_name_p1 + "." + source_name_p2;
+    source_name = source_name_p1 + "." + source_name_p2;
 
   indent(out) << type_name(type, true, false) << " " << result_name << " = new " << type_name(container, false, true) << "();" << endl;
 
@@ -3654,8 +3509,7 @@
         generate_deep_copy_non_container(out, iterator_element_name, "temp_binary_element", elem_type);
         out << ";" << endl;
         indent(out) << result_name << ".add(temp_binary_element);" << endl;
-      }
-      else{
+      } else{
         indent(out) << result_name << ".add(";
         generate_deep_copy_non_container(out, iterator_element_name, result_name, elem_type);
         out << ");" << endl;
@@ -3695,9 +3549,9 @@
   return "is" + get_cap_name("set") + get_cap_name(field_name) + "()";
 }
 
-void t_java_generator::generate_isset_set(ofstream& out, t_field* field) {
+void t_java_generator::generate_isset_set(ofstream& out, t_field* field, string prefix) {
   if (!type_can_be_null(field->get_type())) {
-    indent(out) << "set" << get_cap_name(field->get_name()) << get_cap_name("isSet") << "(true);" << endl;
+    indent(out) << prefix << "set" << get_cap_name(field->get_name()) << get_cap_name("isSet") << "(true);" << endl;
   }
 }
 
@@ -3712,7 +3566,7 @@
 
 void t_java_generator::generate_struct_desc(ofstream& out, t_struct* tstruct) {
   indent(out) <<
-    "private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct(\"" << tstruct->get_name() << "\");" << endl;
+  "private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct(\"" << tstruct->get_name() << "\");" << endl;
 }
 
 void t_java_generator::generate_field_descs(ofstream& out, t_struct* tstruct) {
@@ -3728,6 +3582,14 @@
   }
 }
 
+void t_java_generator::generate_scheme_map(ofstream& out, t_struct* tstruct) {
+  indent(out) << "private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();" << endl;
+  indent(out) << "static {" << endl;
+  indent(out) << "  schemes.put(StandardScheme.class, new " << tstruct->get_name() << "StandardSchemeFactory());" << endl;  
+  indent(out) << "  schemes.put(TupleScheme.class, new " << tstruct->get_name() << "TupleSchemeFactory());" << endl;  
+  indent(out) << "}" << endl;
+}
+
 void t_java_generator::generate_field_name_constants(ofstream& out, t_struct* tstruct) {
   indent(out) << "/** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */" << endl;
   indent(out) << "public enum _Fields implements org.apache.thrift.TFieldIdEnum {" << endl;
@@ -3830,7 +3692,7 @@
 
 void t_java_generator::generate_java_struct_clear(std::ofstream& out, t_struct* tstruct) {
   if (!java5_) {
-     indent(out) << "@Override" << endl;
+    indent(out) << "@Override" << endl;
   }
   indent(out) << "public void clear() {" << endl;
 
@@ -3906,6 +3768,274 @@
   indent(out) << "}" << endl << endl;
 }
 
+void t_java_generator::generate_standard_reader(ofstream& out, t_struct* tstruct) {
+  out <<
+    indent() << "public void read(org.apache.thrift.protocol.TProtocol iprot, " <<  tstruct->get_name() << " struct) throws org.apache.thrift.TException {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Declare stack tmp variables and read struct header
+  out <<
+    indent() << "org.apache.thrift.protocol.TField schemeField;" << endl <<
+    indent() << "iprot.readStructBegin();" << endl;
+
+  // Loop over reading in fields
+  indent(out) << "while (true)" << endl;
+  scope_up(out);
+
+  // Read beginning field marker
+  indent(out) << "schemeField = iprot.readFieldBegin();" << endl;
+
+  // Check for field STOP marker and break
+  indent(out) << "if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { " << endl;
+  indent_up();
+  indent(out) << "break;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+
+  // Switch statement on the field we are reading
+  indent(out) << "switch (schemeField.id) {" << endl;
+
+  indent_up();
+
+  // Generate deserialization code for known cases
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent(out) <<
+      "case " << (*f_iter)->get_key() << ": // " << constant_name((*f_iter)->get_name()) << endl;
+    indent_up();
+    indent(out) <<
+      "if (schemeField.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+    indent_up();
+
+    generate_deserialize_field(out, *f_iter, "struct.", false);
+    indent(out) << "struct." << "set" << get_cap_name((*f_iter)->get_name()) << get_cap_name("isSet") << "(true);" << endl;
+    indent_down();
+    out <<
+      indent() << "} else { " << endl <<
+      indent() << "  org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);" << endl <<
+      indent() << "}" << endl <<
+      indent() << "break;" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+
+  // Read field end marker
+  indent(out) << "iprot.readFieldEnd();" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+
+  out <<
+    indent() << "iprot.readStructEnd();" << endl;
+
+  // in non-beans style, check for required fields of primitive type
+  // (which can be checked here but not in the general validate method)
+  if (!bean_style_){
+    out << endl << indent() << "// check for required fields of primitive type, which can't be checked in the validate method" << endl;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if ((*f_iter)->get_req() == t_field::T_REQUIRED && !type_can_be_null((*f_iter)->get_type())) {
+        out <<
+        indent() << "if (!struct."  << generate_isset_check(*f_iter) << ") {" << endl <<
+        indent() << "  throw new org.apache.thrift.protocol.TProtocolException(\"Required field '" << (*f_iter)->get_name() << "' was not found in serialized data! Struct: \" + toString());" << endl <<
+        indent() << "}" << endl;
+      }
+    }
+  }
+
+  // performs various checks (e.g. check that all required fields are set)
+  indent(out) << "struct.validate();" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl;	
+}
+
+void t_java_generator::generate_standard_writer(ofstream& out, t_struct* tstruct) {
+  indent_up();
+  out <<
+    indent() << "public void write(org.apache.thrift.protocol.TProtocol oprot, " << 
+    tstruct->get_name() << " struct) throws org.apache.thrift.TException {" << endl;
+  indent_up();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // performs various checks (e.g. check that all required fields are set)
+  indent(out) << "struct.validate();" << endl << endl;
+
+  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool null_allowed = type_can_be_null((*f_iter)->get_type());
+    if (null_allowed) {
+      out <<
+      indent() << "if (struct." << (*f_iter)->get_name() << " != null) {" << endl;
+      indent_up();
+    }
+    bool optional = (*f_iter)->get_req() == t_field::T_OPTIONAL;
+    if (optional) {
+      indent(out) << "if (" << "struct." << generate_isset_check((*f_iter)) << ") {" << endl;
+      indent_up();
+    }
+
+    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name()) << "_FIELD_DESC);" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "struct.", false);
+
+    // Write field closer
+    indent(out) << "oprot.writeFieldEnd();" << endl;
+
+    if (optional) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    if (null_allowed) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+  }
+  // Write the struct map
+  out << 
+    indent() << "oprot.writeFieldStop();" << endl <<
+    indent() << "oprot.writeStructEnd();" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+  indent_down();
+}
+
+void t_java_generator::generate_java_struct_standard_scheme(ofstream& out, t_struct* tstruct){
+  indent(out) << "private static class " << tstruct->get_name() << "StandardSchemeFactory implements SchemeFactory {" << endl;
+  indent_up();
+  indent(out) << "public " << tstruct->get_name() << "StandardScheme getScheme() {" << endl;
+  indent_up();
+  indent(out) << "return new " << tstruct->get_name() << "StandardScheme();" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  out << indent() << "private static class " << tstruct->get_name() << "StandardScheme extends StandardScheme<" << tstruct->get_name() << "> {" << endl << endl;
+  indent_up();
+  generate_standard_reader(out, tstruct);
+  indent_down();
+  out << endl;
+  generate_standard_writer(out, tstruct);
+
+  out <<
+  indent() << "}" << endl <<
+  endl;
+}
+
+void t_java_generator::generate_java_struct_tuple_reader(ofstream& out, t_struct* tstruct) {
+  indent(out) << "@Override" << endl;
+  indent(out) << "public void read(org.apache.thrift.protocol.TProtocol prot, " << tstruct->get_name() << " struct) throws org.apache.thrift.TException {" << endl;
+  indent_up();
+  indent(out) << "TTupleProtocol iprot = (TTupleProtocol) prot;" << endl;
+  int optional_count = 0;
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) {
+      optional_count++;
+    }
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      generate_deserialize_field(out, (*f_iter), "struct.", false);
+      indent(out) << "struct.set" << get_cap_name((*f_iter)->get_name()) << get_cap_name("isSet") << "(true);" << endl;
+    }
+  }
+  if (optional_count > 0) {
+    indent(out) << "BitSet incoming = iprot.readBitSet(" << optional_count << ");" << endl;
+    int i = 0;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) {
+        indent(out) << "if (incoming.get(" << i << ")) {" << endl;
+        indent_up();
+        generate_deserialize_field(out, (*f_iter), "struct.", false);
+        indent(out) << "struct.set" << get_cap_name((*f_iter)->get_name()) << get_cap_name("isSet") << "(true);" << endl;
+        indent_down();
+        indent(out) << "}" << endl;
+        i++;
+      }
+    }
+  }
+  indent_down();
+  indent(out) << "}" << endl;  
+}
+
+void t_java_generator::generate_java_struct_tuple_writer(ofstream& out, t_struct* tstruct) {
+  indent(out) << "@Override" << endl;
+  indent(out) << "public void write(org.apache.thrift.protocol.TProtocol prot, " << tstruct->get_name() << " struct) throws org.apache.thrift.TException {" << endl;
+  indent_up();
+  indent(out) << "TTupleProtocol oprot = (TTupleProtocol) prot;" << endl;
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool has_optional = false;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) {
+      has_optional = true;
+    }
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      generate_serialize_field(out, (*f_iter), "struct.", false);
+    }
+  }
+  if (has_optional) {
+    indent(out) << "BitSet optionals = new BitSet();" << endl;
+    int i = 0;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) {
+        indent(out) << "if (struct." << generate_isset_check((*f_iter)) << ") {" << endl;
+        indent_up();
+        indent(out) << "optionals.set(" << i << ");" << endl;
+        indent_down();
+        indent(out) << "}" << endl;
+        i++;
+      }
+    }
+
+    indent(out) << "oprot.writeBitSet(optionals);" << endl;
+    int j = 0;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) {
+        indent(out) << "if (struct." << generate_isset_check(*f_iter) << ") {" << endl;
+        indent_up();
+        generate_serialize_field(out, (*f_iter), "struct.", false);
+        indent_down();
+        indent(out) << "}" << endl;
+        j++;
+      }
+    }
+  }
+  indent_down();
+  indent(out) << "}" << endl;
+}
+
+void t_java_generator::generate_java_struct_tuple_scheme(ofstream& out, t_struct* tstruct){
+  indent(out) << "private static class " << tstruct->get_name() << "TupleSchemeFactory implements SchemeFactory {" << endl;
+  indent_up();
+  indent(out) << "public " << tstruct->get_name() << "TupleScheme getScheme() {" << endl;
+  indent_up();
+  indent(out) << "return new " << tstruct->get_name() << "TupleScheme();" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+  indent_down();
+  indent(out) << "}" << endl << endl;
+  out << indent() << "private static class " << tstruct->get_name() << "TupleScheme extends TupleScheme<" << tstruct->get_name() << "> {" << endl << endl;
+  indent_up();
+  generate_java_struct_tuple_writer(out, tstruct);
+  out << endl;
+  generate_java_struct_tuple_reader(out, tstruct);
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
 THRIFT_REGISTER_GENERATOR(java, "Java",
 "    beans:           Members will be private, and setter methods will return void.\n"
 "    private-members: Members will be private, but setter methods will return 'this' like usual.\n"
diff --git a/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java b/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java
index d3b1636..3b1d886 100755
--- a/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java
+++ b/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java
@@ -36,7 +36,7 @@
  * fields, nested structures, short strings and collections, and low-value i32
  * and i64 fields you have, the more benefit you'll see.
  */
-public final class TCompactProtocol extends TProtocol {
+public class TCompactProtocol extends TProtocol {
 
   private final static TStruct ANONYMOUS_STRUCT = new TStruct("");
   private final static TField TSTOP = new TField("", TType.STOP, (short)0);
diff --git a/lib/java/src/org/apache/thrift/protocol/TProtocol.java b/lib/java/src/org/apache/thrift/protocol/TProtocol.java
index 16fac64..0e96368 100644
--- a/lib/java/src/org/apache/thrift/protocol/TProtocol.java
+++ b/lib/java/src/org/apache/thrift/protocol/TProtocol.java
@@ -22,6 +22,8 @@
 import java.nio.ByteBuffer;
 
 import org.apache.thrift.TException;
+import org.apache.thrift.scheme.IScheme;
+import org.apache.thrift.scheme.StandardScheme;
 import org.apache.thrift.transport.TTransport;
 
 /**
@@ -150,4 +152,11 @@
    * be implemented for stateful protocols.
    */
   public void reset() {}
+  
+  /**
+   * Scheme accessor
+   */
+  public Class<? extends IScheme> getScheme() {
+    return StandardScheme.class;
+  }
 }
diff --git a/lib/java/src/org/apache/thrift/protocol/TTupleProtocol.java b/lib/java/src/org/apache/thrift/protocol/TTupleProtocol.java
new file mode 100644
index 0000000..5e9a14e
--- /dev/null
+++ b/lib/java/src/org/apache/thrift/protocol/TTupleProtocol.java
@@ -0,0 +1,97 @@
+/*
+ * 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.thrift.protocol;
+
+import java.util.BitSet;
+
+import org.apache.thrift.TException;
+import org.apache.thrift.scheme.IScheme;
+import org.apache.thrift.scheme.TupleScheme;
+import org.apache.thrift.transport.TTransport;
+
+public final class TTupleProtocol extends TCompactProtocol {
+  public static class Factory implements TProtocolFactory {
+    public Factory() {}
+
+    public TProtocol getProtocol(TTransport trans) {
+      return new TTupleProtocol(trans);
+    }
+  }
+
+  public TTupleProtocol(TTransport transport) {
+    super(transport);
+  }
+
+  @Override
+  public Class<? extends IScheme> getScheme() {
+    return TupleScheme.class;
+  }
+
+  public void writeBitSet(BitSet bs) throws TException {
+    byte[] bytes = toByteArray(bs);
+    for (byte b : bytes) {
+      writeByte(b);
+    }
+  }
+
+  public BitSet readBitSet(int i) throws TException {
+    int length = (int) Math.ceil(i/8.0);
+    byte[] bytes = new byte[length];
+    for (int j = 0; j < length; j++) {
+      bytes[j] = readByte();
+    }
+    BitSet bs = fromByteArray(bytes);
+    return bs;
+  }
+
+  /**
+   * Returns a bitset containing the values in bytes. The byte-ordering must be
+   * big-endian.
+   */
+  public static BitSet fromByteArray(byte[] bytes) {
+    BitSet bits = new BitSet();
+    for (int i = 0; i < bytes.length * 8; i++) {
+      if ((bytes[bytes.length - i / 8 - 1] & (1 << (i % 8))) > 0) {
+        bits.set(i);
+      }
+    }
+    return bits;
+  }
+
+  /**
+   * Returns a byte array of at least length 1. The most significant bit in the
+   * result is guaranteed not to be a 1 (since BitSet does not support sign
+   * extension). The byte-ordering of the result is big-endian which means the
+   * most significant bit is in element 0. The bit at index 0 of the bit set is
+   * assumed to be the least significant bit.
+   * 
+   * @param bits
+   * @return
+   */
+  public static byte[] toByteArray(BitSet bits) {
+    byte[] bytes = new byte[bits.length() / 8 + 1];
+    for (int i = 0; i < bits.length(); i++) {
+      if (bits.get(i)) {
+        bytes[bytes.length - i / 8 - 1] |= 1 << (i % 8);
+      }
+    }
+    return bytes;
+  }
+
+}
diff --git a/lib/java/src/org/apache/thrift/scheme/IScheme.java b/lib/java/src/org/apache/thrift/scheme/IScheme.java
new file mode 100644
index 0000000..aa35507
--- /dev/null
+++ b/lib/java/src/org/apache/thrift/scheme/IScheme.java
@@ -0,0 +1,29 @@
+/*
+ * 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.thrift.scheme;
+
+import org.apache.thrift.TBase;
+
+public interface IScheme<T extends TBase> {
+
+  public void read(org.apache.thrift.protocol.TProtocol iproto, T struct) throws org.apache.thrift.TException;
+
+  public void write(org.apache.thrift.protocol.TProtocol oproto, T struct) throws org.apache.thrift.TException;
+
+}
diff --git a/lib/java/src/org/apache/thrift/scheme/SchemeFactory.java b/lib/java/src/org/apache/thrift/scheme/SchemeFactory.java
new file mode 100644
index 0000000..006a668
--- /dev/null
+++ b/lib/java/src/org/apache/thrift/scheme/SchemeFactory.java
@@ -0,0 +1,25 @@
+/*
+ * 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.thrift.scheme;
+
+public interface SchemeFactory {
+
+  public <S extends IScheme> S getScheme();
+
+}
diff --git a/lib/java/src/org/apache/thrift/scheme/StandardScheme.java b/lib/java/src/org/apache/thrift/scheme/StandardScheme.java
new file mode 100644
index 0000000..ffab04d
--- /dev/null
+++ b/lib/java/src/org/apache/thrift/scheme/StandardScheme.java
@@ -0,0 +1,25 @@
+/*
+ * 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.thrift.scheme;
+
+import org.apache.thrift.TBase;
+
+public abstract class StandardScheme<T extends TBase> implements IScheme<T> {
+
+}
diff --git a/lib/java/src/org/apache/thrift/scheme/TupleScheme.java b/lib/java/src/org/apache/thrift/scheme/TupleScheme.java
new file mode 100644
index 0000000..365242b
--- /dev/null
+++ b/lib/java/src/org/apache/thrift/scheme/TupleScheme.java
@@ -0,0 +1,25 @@
+/*
+ * 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.thrift.scheme;
+
+import org.apache.thrift.TBase;
+
+public abstract class TupleScheme<T extends TBase> implements IScheme<T> {
+
+}
diff --git a/lib/java/test/org/apache/thrift/Fixtures.java b/lib/java/test/org/apache/thrift/Fixtures.java
index d759bb0..b591a95 100644
--- a/lib/java/test/org/apache/thrift/Fixtures.java
+++ b/lib/java/test/org/apache/thrift/Fixtures.java
@@ -37,7 +37,7 @@
   public static final Nesting nesting;
   public static final HolyMoley holyMoley;
   public static final CompactProtoTestStruct compactProtoTestStruct;
-  
+
   private static final byte[] kUnicodeBytes = {
     (byte)0xd3, (byte)0x80, (byte)0xe2, (byte)0x85, (byte)0xae, (byte)0xce,
     (byte)0x9d, (byte)0x20, (byte)0xd0, (byte)0x9d, (byte)0xce, (byte)0xbf,
@@ -52,79 +52,79 @@
   static {
     try {
       oneOfEach = new OneOfEach();
-      oneOfEach.im_true = true;
-      oneOfEach.im_false = false;
-      oneOfEach.a_bite = (byte) 0xd6;
-      oneOfEach.integer16 = 27000;
-      oneOfEach.integer32 = 1 << 24;
-      oneOfEach.integer64 = (long) 6000 * 1000 * 1000;
-      oneOfEach.double_precision = Math.PI;
-      oneOfEach.some_characters = "JSON THIS! \"\1";
-      oneOfEach.zomg_unicode = new String(kUnicodeBytes, "UTF-8");
-      oneOfEach.base64 = ByteBuffer.wrap("base64".getBytes());
+      oneOfEach.setIm_true(true);
+      oneOfEach.setIm_false(false);
+      oneOfEach.setA_bite((byte) 0xd6);
+      oneOfEach.setInteger16((short)27000);
+      oneOfEach.setInteger32(1 << 24);
+      oneOfEach.setInteger64((long) 6000 * 1000 * 1000);
+      oneOfEach.setDouble_precision(Math.PI);
+      oneOfEach.setSome_characters("JSON THIS! \"\1");
+      oneOfEach.setZomg_unicode(new String(kUnicodeBytes, "UTF-8"));
+      oneOfEach.setBase64(ByteBuffer.wrap("base64".getBytes()));
       // byte, i16, and i64 lists are populated by default constructor
 
       Bonk bonk = new Bonk();
-      bonk.type = 31337;
-      bonk.message = "I am a bonk... xor!";
+      bonk.setType(31337);
+      bonk.setMessage("I am a bonk... xor!");
       nesting = new Nesting(bonk, oneOfEach);
 
       holyMoley = new HolyMoley();
-      holyMoley.big = new ArrayList<OneOfEach>();
-      holyMoley.big.add(new OneOfEach(oneOfEach));
-      holyMoley.big.add(nesting.my_ooe);
-      holyMoley.big.get(0).a_bite = (byte) 0x22;
-      holyMoley.big.get(1).a_bite = (byte) 0x23;
+      ArrayList big = new ArrayList<OneOfEach>();
+      big.add(new OneOfEach(oneOfEach));
+      big.add(nesting.my_ooe);
+      holyMoley.setBig(big);
+      holyMoley.getBig().get(0).setA_bite((byte) 0x22);
+      holyMoley.getBig().get(0).setA_bite((byte) 0x23);
 
-      holyMoley.contain = new HashSet<List<String>>();
+      holyMoley.setContain(new HashSet<List<String>>());
       ArrayList<String> stage1 = new ArrayList<String>(2);
       stage1.add("and a one");
       stage1.add("and a two");
-      holyMoley.contain.add(stage1);
+      holyMoley.getContain().add(stage1);
       stage1 = new ArrayList<String>(3);
       stage1.add("then a one, two");
       stage1.add("three!");
       stage1.add("FOUR!!");
-      holyMoley.contain.add(stage1);
+      holyMoley.getContain().add(stage1);
       stage1 = new ArrayList<String>(0);
-      holyMoley.contain.add(stage1);
+      holyMoley.getContain().add(stage1);
 
       ArrayList<Bonk> stage2 = new ArrayList<Bonk>();
-      holyMoley.bonks = new HashMap<String, List<Bonk>>();
+      holyMoley.setBonks(new HashMap<String, List<Bonk>>());
       // one empty
-      holyMoley.bonks.put("zero", stage2);
-      
+      holyMoley.getBonks().put("zero", stage2);
+
       // one with two
       stage2 = new ArrayList<Bonk>();
       Bonk b = new Bonk();
-      b.type = 1;
-      b.message = "Wait.";
+      b.setType(1);
+      b.setMessage("Wait.");
       stage2.add(b);
       b = new Bonk();
-      b.type = 2;
-      b.message = "What?";
+      b.setType(2);
+      b.setMessage("What?");
       stage2.add(b);      
-      holyMoley.bonks.put("two", stage2);
-      
+      holyMoley.getBonks().put("two", stage2);
+
       // one with three
       stage2 = new ArrayList<Bonk>();
       b = new Bonk();
-      b.type = 3;
-      b.message = "quoth";
+      b.setType(3);
+      b.setMessage("quoth");
       b = new Bonk();
-      b.type = 4;
-      b.message = "the raven";
+      b.setType(4);
+      b.setMessage("the raven");
       b = new Bonk();
-      b.type = 5;
-      b.message = "nevermore";
-      holyMoley.bonks.put("three", stage2);
+      b.setType(5);
+      b.setMessage("nevermore");
+      holyMoley.getBonks().put("three", stage2);
 
       // superhuge compact proto test struct
       compactProtoTestStruct = new CompactProtoTestStruct(thrift.test.Constants.COMPACT_TEST);
-      compactProtoTestStruct.a_binary = ByteBuffer.wrap(new byte[]{0,1,2,3,4,5,6,7,8});
+      compactProtoTestStruct.setA_binary(ByteBuffer.wrap(new byte[]{0,1,2,3,4,5,6,7,8}));
     } catch (Exception e) {
       throw new RuntimeException(e);
     }
   }
-  
 }
diff --git a/lib/java/test/org/apache/thrift/protocol/TestTTupleProtocol.java b/lib/java/test/org/apache/thrift/protocol/TestTTupleProtocol.java
new file mode 100644
index 0000000..948df9f
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/protocol/TestTTupleProtocol.java
@@ -0,0 +1,24 @@
+package org.apache.thrift.protocol;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.thrift.TException;
+import org.apache.thrift.transport.TMemoryBuffer;
+import org.apache.thrift.transport.TMemoryInputTransport;
+
+import thrift.test.Complex;
+import thrift.test.Simple;
+
+public class TestTTupleProtocol extends ProtocolTestBase {
+
+  @Override
+  protected boolean canBeUsedNaked() {
+    return false;
+  }
+
+  @Override
+  protected TProtocolFactory getFactory() {
+    return new TTupleProtocol.Factory();
+  }
+}