merge changes for 0.6 rc2

git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1065464 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/CHANGES b/CHANGES
index 0609ca2..1f92670 100644
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,7 @@
 THRIFT-1003   C glib               Polishing c_glib code (Anatol Pomozov)
 THRIFT-582    C glib               C implementation of Thrift (Anatol Pomozov)
 THRIFT-992    C#                   Naming convention in C# constructor is not consistent with other fields causes compile errors (Roger Meier)
+THRIFT-904    C#		   Disable nagle and linger
 THRIFT-977    C++                  Hex Conversion Bug in C++ TJSONProtocol (Aravind Narayanan)
 THRIFT-922    C++                  Templatized [de]serialization code for C++ (David Reiss)
 THRIFT-923    C++                  Event-driven client and server support for C++ (David Reiss)
@@ -48,10 +49,14 @@
 THRIFT-949    Java                 Modify the TEnum interface so it defines a method similar to findByValue (Mathias Herberts)
 THRIFT-960    Java                 add TestServer, TestNonblockingServer and TestClient again (Roger Meier)
 THRIFT-969    Java                 Java Tutorial broken, move CalculatorHandler to a separate file (Roger Meier)
+THRIFT-1051   Java		   Fix compiler issue for java 1.5
 THRIFT-807    JavaScript           JavaScript: Initialization of Base Types with 0 instead of null (Roger Meier)
 THRIFT-913    JavaScript           Test Case for Url encoded strings + simple enhancement to lib/js/test/RunTestServer.sh (Roger Meier)
 THRIFT-961    JavaScript
-THRIFT-1033   JavaScript           Node.js support
+THRIFT-1033   JavaScript           Node.js support (Wade Simmons)
+THRIFT-1042   JavaScript           Node.js Fix TApplicationException.read Patch (Wade Simmons)
+THRIFT-1043   JavaScript	   Node.js Fix how the length of a map is calculated
+THRIFT-1044   JavaScript	   Fix JavaScript inheritance Patch (Wade Simmons)
 THRIFT-71     Misc                 Debian packaging for thrift (Roger Meier)
 THRIFT-1020   OCaml                OCaml compiler generates invalid OCaml (Richard Low)
 THRIFT-347    PHP                  PHP TSocket Timeout Issues (Tyler Hobbs)
diff --git a/compiler/cpp/src/generate/t_js_generator.cc b/compiler/cpp/src/generate/t_js_generator.cc
index 4aa6811..a654fc9 100644
--- a/compiler/cpp/src/generate/t_js_generator.cc
+++ b/compiler/cpp/src/generate/t_js_generator.cc
@@ -157,6 +157,7 @@
    */
 
   std::string js_includes();
+  std::string render_includes();
   std::string declare_field(t_field* tfield, bool init=false, bool obj=false);
   std::string function_signature(t_function* tfunction, std::string prefix="", bool include_callback=false);
   std::string argument_list(t_struct* tstruct);
@@ -191,11 +192,15 @@
       return pieces;
   }
 
-  std::string js_type_namespace(t_program* p) {
+  std::string js_type_namespace(t_type* ttype) {
+    t_program* program = ttype->get_program();
     if (gen_node_) {
+      if (program != NULL && program != program_) {
+        return program->get_name() + "_ttypes.";
+      }
       return "ttypes.";
     }
-    return js_namespace(p);
+    return js_namespace(program);
   }
 
   std::string js_export_namespace(t_program* p) {
@@ -287,6 +292,26 @@
 }
 
 /**
+ * Renders all the imports necessary for including another Thrift program
+ */
+string t_js_generator::render_includes() {
+  if (gen_node_) {
+    const vector<t_program*>& includes = program_->get_includes();
+    string result = "";
+    for (size_t i = 0; i < includes.size(); ++i) {
+      result += "var " + includes[i]->get_name() + "_ttypes = require('./" + includes[i]->get_name() + "_types')\n";
+    }
+    if (includes.size() > 0) {
+      result += "\n";
+    }
+    return result;
+  }
+  string inc;
+
+  return inc;
+}
+
+/**
  * Close up (or down) some filez.
  */
 void t_js_generator::close_generator() {
@@ -311,7 +336,7 @@
  * @param tenum The enumeration
  */
 void t_js_generator::generate_enum(t_enum* tenum) {
-  f_types_ << js_type_namespace(tenum->get_program())<<tenum->get_name()<<" = { "<<endl;
+  f_types_ << js_type_namespace(tenum)<<tenum->get_name()<<" = { "<<endl;
 
   vector<t_enum_value*> constants = tenum->get_constants();
   vector<t_enum_value*>::iterator c_iter;
@@ -334,7 +359,7 @@
   string name = tconst->get_name();
   t_const_value* value = tconst->get_value();
 
-  f_types_ << js_type_namespace(program_)  << name << " = ";
+  f_types_ << js_type_namespace(type)  << name << " = ";
   f_types_ << render_const_value(type, value) << endl;
 }
 
@@ -376,7 +401,7 @@
   } else if (type->is_enum()) {
     out << value->get_integer();
   } else if (type->is_struct() || type->is_xception()) {
-    out << "new " << js_type_namespace(type->get_program()) << type->get_name() << "({" << endl;
+    out << "new " << js_type_namespace(type) << type->get_name() << "({" << endl;
     indent_up();
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
@@ -541,19 +566,12 @@
   out << "}\n";
 
   if (is_exception) {
-      if (gen_node_) {
-          out << "require('util').inherits(" <<
-              js_namespace(tstruct->get_program()) <<
-              tstruct->get_name() << ", Thrift.TException)" << endl;
-      } else {
-          out << "for (var property in Thrift.TException)"<<endl<<
-              js_namespace(tstruct->get_program())<<tstruct->get_name()<<"[property] = Thrift.TException[property]"<<endl;
-      }
-  }
-
-  if (!gen_node_) {
-      //init prototype
-      out << js_namespace(tstruct->get_program())<<tstruct->get_name() <<".prototype = {}\n";
+    out << "Thrift.inherits(" <<
+        js_namespace(tstruct->get_program()) <<
+        tstruct->get_name() << ", Thrift.TException)" << endl;
+  } else {
+    //init prototype
+    out << js_namespace(tstruct->get_program())<<tstruct->get_name() <<".prototype = {}\n";
   }
 
 
@@ -696,11 +714,23 @@
 
     f_service_ <<
       autogen_comment() <<
-      js_includes() << endl;
+      js_includes() << endl <<
+      render_includes() << endl;
 
     if (gen_node_) {
-      f_service_ <<
-        "var ttypes = require('./" + program_->get_name() + "_types.js');" << endl;
+        if (tservice->get_extends() != NULL) {
+          f_service_ <<
+            "var " << tservice->get_extends()->get_name() <<
+            " = require('./" << tservice->get_extends()->get_name() << "')" << endl <<
+            "var " << tservice->get_extends()->get_name() << "Client = " <<
+            tservice->get_extends()->get_name() << ".Client" << endl;
+
+        }
+
+        if (gen_node_) {
+          f_service_ <<
+            "var ttypes = require('./" + program_->get_name() + "_types');" << endl;
+        }
     }
 
     generate_service_helpers(tservice);
@@ -935,17 +965,15 @@
 
 
   if (tservice->get_extends() != NULL) {
-      extends = tservice->get_extends()->get_name();
-
-      f_service_ << "for (var property in "<<extends<<"Client)"<<endl<<
-          js_namespace(tservice->get_program()) << service_name_<<"Client[property] = "<<extends<<"Client[property]"<<endl;
-
+    indent(f_service_) << "Thrift.inherits(" <<
+        js_namespace(tservice->get_program()) <<
+        service_name_ << "Client, " <<
+        tservice->get_extends()->get_name() << "Client)" << endl;
+  } else {
+      //init prototype
+      indent(f_service_) <<  js_namespace(tservice->get_program())<<service_name_ << "Client.prototype = {}"<<endl;
   }
 
-  //init prototype
-  f_service_ <<  js_namespace(tservice->get_program())<<service_name_ << "Client.prototype = {}"<<endl;
-
-
   // Generate client method implementations
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::const_iterator f_iter;
@@ -1231,7 +1259,7 @@
                                                    t_struct* tstruct,
                                                    string prefix) {
     out <<
-        indent() << prefix << " = new " <<  js_type_namespace(tstruct->get_program())<<tstruct->get_name() << "()" << endl <<
+        indent() << prefix << " = new " <<  js_type_namespace(tstruct)<<tstruct->get_name() << "()" << endl <<
         indent() << prefix << ".read(input)" << endl;
 
 }
@@ -1478,7 +1506,7 @@
         "output.writeMapBegin(" <<
         type_to_enum(((t_map*)ttype)->get_key_type()) << ", " <<
         type_to_enum(((t_map*)ttype)->get_val_type()) << ", " <<
-        prefix << ".length)" << endl;
+        "Thrift.objectLength(" << prefix << "))" << endl;
   } else if (ttype->is_set()) {
     indent(out) <<
       "output.writeSetBegin(" <<
@@ -1625,7 +1653,7 @@
       result += " = null";
     } else if (type->is_struct() || type->is_xception()) {
       if (obj) {
-          result += " = new " +js_type_namespace(type->get_program()) + type->get_name() + "()";
+          result += " = new " +js_type_namespace(type) + type->get_name() + "()";
       } else {
         result += " = null";
       }
diff --git a/lib/csharp/src/Transport/TFramedTransport.cs b/lib/csharp/src/Transport/TFramedTransport.cs
index b7ad5f2..e259f5a 100644
--- a/lib/csharp/src/Transport/TFramedTransport.cs
+++ b/lib/csharp/src/Transport/TFramedTransport.cs
@@ -24,9 +24,12 @@
 	public class TFramedTransport : TTransport
 	{
 		protected TTransport transport = null;
-		protected MemoryStream writeBuffer = new MemoryStream(1024);
+		protected MemoryStream writeBuffer;
 		protected MemoryStream readBuffer = null;
 
+		private const int header_size = 4;
+		private static byte[] header_dummy = new byte[header_size]; // used as header placeholder while initilizing new write buffer
+
 		public class Factory : TTransportFactory
 		{
 			public override TTransport GetTransport(TTransport trans)
@@ -35,7 +38,12 @@
 			}
 		}
 
-		public TFramedTransport(TTransport transport)
+		public TFramedTransport()
+		{
+			InitWriteBuffer();
+		}
+
+		public TFramedTransport(TTransport transport) : this()
 		{
 			this.transport = transport;
 		}
@@ -77,8 +85,8 @@
 
 		private void ReadFrame()
 		{
-			byte[] i32rd = new byte[4];
-			transport.ReadAll(i32rd, 0, 4);
+			byte[] i32rd = new byte[header_size];
+			transport.ReadAll(i32rd, 0, header_size);
 			int size =
 				((i32rd[0] & 0xff) << 24) |
 				((i32rd[1] & 0xff) << 16) |
@@ -99,16 +107,31 @@
 		{
 			byte[] buf = writeBuffer.GetBuffer();
 			int len = (int)writeBuffer.Length;
-			writeBuffer = new MemoryStream(writeBuffer.Capacity);
+			int data_len = len - header_size;
+			if ( data_len < 0 )
+				throw new System.InvalidOperationException (); // logic error actually
 
-			byte[] i32out = new byte[4];
-			i32out[0] = (byte)(0xff & (len >> 24));
-			i32out[1] = (byte)(0xff & (len >> 16));
-			i32out[2] = (byte)(0xff & (len >> 8));
-			i32out[3] = (byte)(0xff & (len));
-			transport.Write(i32out, 0, 4);
+			InitWriteBuffer();
+
+			// Inject message header into the reserved buffer space
+			buf[0] = (byte)(0xff & (data_len >> 24));
+			buf[1] = (byte)(0xff & (data_len >> 16));
+			buf[2] = (byte)(0xff & (data_len >> 8));
+			buf[3] = (byte)(0xff & (data_len));
+
+			// Send the entire message at once
 			transport.Write(buf, 0, len);
+
 			transport.Flush();
 		}
+
+		private void InitWriteBuffer ()
+		{
+			// Create new buffer instance
+			writeBuffer = new MemoryStream(1024);
+
+			// Reserve space for message header to be put right before sending it out
+			writeBuffer.Write ( header_dummy, 0, header_size );
+		}
 	}
 }
diff --git a/lib/java/src/org/apache/thrift/async/TAsyncClientManager.java b/lib/java/src/org/apache/thrift/async/TAsyncClientManager.java
index b28c312..98f7194 100644
--- a/lib/java/src/org/apache/thrift/async/TAsyncClientManager.java
+++ b/lib/java/src/org/apache/thrift/async/TAsyncClientManager.java
@@ -183,7 +183,6 @@
 
   /** Comparator used in TreeSet */
   private static class TAsyncMethodCallTimeoutComparator implements Comparator<TAsyncMethodCall> {
-    @Override
     public int compare(TAsyncMethodCall left, TAsyncMethodCall right) {
       if (left.getTimeoutTimestamp() == right.getTimeoutTimestamp()) {
         return (int)(left.getSequenceId() - right.getSequenceId());
diff --git a/lib/js/thrift.js b/lib/js/thrift.js
index 9b92658..c06e27a 100644
--- a/lib/js/thrift.js
+++ b/lib/js/thrift.js
@@ -713,5 +713,20 @@
    
 }
 
+Thrift.objectLength = function(obj) {
+  var length = 0;
+  for (k in obj) {
+    if (obj.hasOwnProperty(k)) {
+      length++;
+    }
+  }
+  return length;
+}
 
-
+Thirft.inherits = function(constructor, superConstructor) {
+  // Prototypal Inheritance
+  // http://javascript.crockford.com/prototypal.html
+  function F() {}
+  F.prototype = superConstructor.prototype;
+  constructor.prototype = new F();
+}
diff --git a/lib/nodejs/lib/thrift/thrift.js b/lib/nodejs/lib/thrift/thrift.js
index 73f772b..53ca106 100644
--- a/lib/nodejs/lib/thrift/thrift.js
+++ b/lib/nodejs/lib/thrift/thrift.js
@@ -85,7 +85,7 @@
           case 1:
               if( ret.ftype == Type.STRING ){
                   ret = input.readString()
-                  this.message = ret.value
+                  this.message = ret
               } else {
                   ret = input.skip(ret.ftype)
               }
@@ -94,7 +94,7 @@
           case 2:
               if( ret.ftype == Type.I32 ){
                   ret = input.readI32()
-                  this.type = ret.value
+                  this.type = ret
               } else {
                   ret   = input.skip(ret.ftype)
               }
@@ -128,3 +128,11 @@
   output.writeFieldStop()
   output.writeStructEnd()
 }
+
+exports.objectLength = function(obj) {
+  return Object.keys(obj).length;
+}
+
+exports.inherits = function(constructor, superConstructor) {
+  sys.inherits(constructor, superConstructor);
+}
diff --git a/test/csharp/ThriftTest/TestClient.cs b/test/csharp/ThriftTest/TestClient.cs
index 1d7c75e..60fc995 100644
--- a/test/csharp/ThriftTest/TestClient.cs
+++ b/test/csharp/ThriftTest/TestClient.cs
@@ -39,7 +39,7 @@
 				int port = 9090;
 				string url = null;
 				int numThreads = 1;
-				bool buffered = false;
+				bool buffered = false, framed = false;
 
 				try
 				{
@@ -67,6 +67,11 @@
 							buffered = true;
 							Console.WriteLine("Using buffered sockets");
 						}
+						else if (args[i] == "-f" || args[i] == "-framed")
+						{
+							framed = true;
+							Console.WriteLine("Using framed transport");
+						}
 						else if (args[i] == "-t")
 						{
 							numThreads = Convert.ToInt32(args[++i]);
@@ -89,16 +94,13 @@
 					threads[test] = t;
 					if (url == null)
 					{
-						TSocket socket = new TSocket(host, port);
+						TTransport trans = new TSocket(host, port);
 						if (buffered)
-						{
-							TBufferedTransport buffer = new TBufferedTransport(socket);
-							t.Start(buffer);
-						}
-						else
-						{
-							t.Start(socket);
-						}
+							trans = new TBufferedTransport(trans as TStreamTransport);
+						if (framed)
+							trans = new TFramedTransport(trans);
+							
+						t.Start(trans);
 					}
 					else
 					{
@@ -428,6 +430,12 @@
 
 			Console.WriteLine("Test Oneway(1)");
 			client.testOneway(1);
+
+			Console.Write("Test Calltime()");
+			var startt = DateTime.UtcNow;
+			for ( int k=0; k<1000; ++k )
+				client.testVoid();
+			Console.WriteLine(" = " + (DateTime.UtcNow - startt).TotalSeconds.ToString() + " ms a testVoid() call" );
 		}
 	}
 }
diff --git a/test/csharp/ThriftTest/TestServer.cs b/test/csharp/ThriftTest/TestServer.cs
index e370640..894ec9c 100644
--- a/test/csharp/ThriftTest/TestServer.cs
+++ b/test/csharp/ThriftTest/TestServer.cs
@@ -301,7 +301,7 @@
 		{
 			try
 			{
-				bool useBufferedSockets = false;
+				bool useBufferedSockets = false, useFramed = false;
 				int port = 9090;
 				if (args.Length > 0)
 				{
@@ -309,7 +309,23 @@
 
 					if (args.Length > 1)
 					{
-						bool.TryParse(args[1], out useBufferedSockets);
+						if ( args[1] == "raw" )
+						{
+							// as default
+						}
+						else if ( args[1] == "buffered" )
+						{
+							useBufferedSockets = true;
+						}
+						else if ( args[1] == "framed" )
+						{
+							useFramed = true;
+						}
+						else
+						{
+							// Fall back to the older boolean syntax
+							bool.TryParse(args[1], out useBufferedSockets);
+						}
 					}
 				}
 
@@ -320,10 +336,12 @@
 				// Transport
 				TServerSocket tServerSocket = new TServerSocket(port, 0, useBufferedSockets);
 
-				TServer serverEngine;
-
 				// Simple Server
-				serverEngine = new TSimpleServer(testProcessor, tServerSocket);
+				TServer serverEngine;
+				if ( useFramed )
+					serverEngine = new TSimpleServer(testProcessor, tServerSocket, new TFramedTransport.Factory());
+				else
+					serverEngine = new TSimpleServer(testProcessor, tServerSocket);
 
 				// ThreadPool Server
 				// serverEngine = new TThreadPoolServer(testProcessor, tServerSocket);
@@ -334,7 +352,10 @@
 				testHandler.server = serverEngine;
 
 				// Run it
-				Console.WriteLine("Starting the server on port " + port + (useBufferedSockets ? " with buffered socket" : "") + "...");
+				Console.WriteLine("Starting the server on port " + port + 
+					(useBufferedSockets ? " with buffered socket" : "") + 
+					(useFramed ? " with framed transport" : "") + 
+					"...");
 				serverEngine.Serve();
 
 			}