THRIFT-3743 Java JSON protocol left in incorrect state when an exception is thrown during read or write operations

This closes #952
diff --git a/lib/java/src/org/apache/thrift/protocol/TJSONProtocol.java b/lib/java/src/org/apache/thrift/protocol/TJSONProtocol.java
index 12341ab..fd54fdf 100644
--- a/lib/java/src/org/apache/thrift/protocol/TJSONProtocol.java
+++ b/lib/java/src/org/apache/thrift/protocol/TJSONProtocol.java
@@ -308,6 +308,13 @@
     context_ = contextStack_.pop();
   }
 
+  // Reset the context stack to its initial state
+  private void resetContext() {
+    while (!contextStack_.isEmpty()) {
+      popContext();
+    }
+  }
+
   /**
    * Constructor
    */
@@ -503,6 +510,7 @@
 
   @Override
   public void writeMessageBegin(TMessage message) throws TException {
+    resetContext(); // THRIFT-3743
     writeJSONArrayStart();
     writeJSONInteger(VERSION);
     try {
@@ -854,6 +862,7 @@
 
   @Override
   public TMessage readMessageBegin() throws TException {
+    resetContext(); // THRIFT-3743
     readJSONArrayStart();
     if (readJSONInteger() != VERSION) {
       throw new TProtocolException(TProtocolException.BAD_VERSION,
diff --git a/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java b/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java
index ffa139a..b24e421 100644
--- a/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java
+++ b/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java
@@ -143,6 +143,15 @@
   }
 
   /**
+   * Reset the write context stack to its initial state.
+   */
+  protected void resetWriteContext() {
+    while (!writeContextStack_.isEmpty()) {
+      popWriteContext();
+    }
+  }
+
+  /**
    * Used to make sure that we are not encountering a map whose keys are containers
    */
   protected void assertContextIsNotMapKey(String invalidKeyType) throws CollectionMapKeyException {
@@ -159,6 +168,7 @@
   }
 
   public void writeMessageBegin(TMessage message) throws TException {
+    resetWriteContext(); // THRIFT-3743
     trans_.write(LBRACKET);
     pushWriteContext(new ListContext());
     writeString(message.name);