THRIFT-2157 generated code would cause ClassCastException
Client: Java
Patch: Marc Breslow <marc.breslow@devfactory.com>

This closes #822
diff --git a/lib/java/src/org/apache/thrift/TApplicationException.java b/lib/java/src/org/apache/thrift/TApplicationException.java
index b54a5ce..4d693d9 100644
--- a/lib/java/src/org/apache/thrift/TApplicationException.java
+++ b/lib/java/src/org/apache/thrift/TApplicationException.java
@@ -29,7 +29,7 @@
  * Application level exception
  *
  */
-public class TApplicationException extends TException {
+public class TApplicationException extends TException implements TSerializable {
 
   private static final TStruct TAPPLICATION_EXCEPTION_STRUCT = new TStruct("TApplicationException");
   private static final TField MESSAGE_FIELD = new TField("message", TType.STRING, (short)1);
@@ -50,6 +50,7 @@
   public static final int UNSUPPORTED_CLIENT_TYPE = 10;
 
   protected int type_ = UNKNOWN;
+  private String message_ = null;
 
   public TApplicationException() {
     super();
@@ -73,7 +74,18 @@
     return type_;
   }
 
-  public static TApplicationException read(TProtocol iprot) throws TException {
+  @Override
+  public String getMessage() {
+    if (message_ == null) {
+      return super.getMessage();
+    }
+    else {
+      return message_;
+    }
+  }
+
+  public void read(TProtocol iprot) throws TException
+  {
     TField field;
     iprot.readStructBegin();
 
@@ -86,32 +98,43 @@
         break;
       }
       switch (field.id) {
-      case 1:
-        if (field.type == TType.STRING) {
-          message = iprot.readString();
-        } else {
+        case 1:
+          if (field.type == TType.STRING) {
+            message = iprot.readString();
+          } else {
+            TProtocolUtil.skip(iprot, field.type);
+          }
+          break;
+        case 2:
+          if (field.type == TType.I32) {
+            type = iprot.readI32();
+          } else {
+            TProtocolUtil.skip(iprot, field.type);
+          }
+          break;
+        default:
           TProtocolUtil.skip(iprot, field.type);
-        }
-        break;
-      case 2:
-        if (field.type == TType.I32) {
-          type = iprot.readI32();
-        } else {
-          TProtocolUtil.skip(iprot, field.type);
-        }
-        break;
-      default:
-        TProtocolUtil.skip(iprot, field.type);
-        break;
+          break;
       }
       iprot.readFieldEnd();
     }
     iprot.readStructEnd();
-
-    return new TApplicationException(type, message);
+    type_ = type;
+    message_ = message;
   }
 
-  public void write(TProtocol oprot) throws TException {
+  /**
+   * Convenience factory method for constructing a TApplicationException given a TProtocol input
+   */
+  public static TApplicationException readFrom(TProtocol iprot) throws TException
+  {
+    TApplicationException result = new TApplicationException();
+    result.read(iprot);
+    return result;
+  }
+
+  public void write(TProtocol oprot) throws TException
+  {
     oprot.writeStructBegin(TAPPLICATION_EXCEPTION_STRUCT);
     if (getMessage() != null) {
       oprot.writeFieldBegin(MESSAGE_FIELD);
diff --git a/lib/java/src/org/apache/thrift/TBase.java b/lib/java/src/org/apache/thrift/TBase.java
index ef70e5b..e1489d5 100644
--- a/lib/java/src/org/apache/thrift/TBase.java
+++ b/lib/java/src/org/apache/thrift/TBase.java
@@ -27,21 +27,7 @@
  * Generic base interface for generated Thrift objects.
  *
  */
-public interface TBase<T extends TBase<T,F>, F extends TFieldIdEnum> extends Comparable<T>,  Serializable {
-
-  /**
-   * Reads the TObject from the given input protocol.
-   *
-   * @param iprot Input protocol
-   */
-  public void read(TProtocol iprot) throws TException;
-
-  /**
-   * Writes the objects out to the protocol
-   *
-   * @param oprot Output protocol
-   */
-  public void write(TProtocol oprot) throws TException;
+public interface TBase<T extends TBase<T,F>, F extends TFieldIdEnum> extends Comparable<T>,  TSerializable, Serializable {
 
   /**
    * Get the F instance that corresponds to fieldId.
@@ -56,7 +42,7 @@
   public boolean isSet(F field);
 
   /**
-   * Get a field's value by field variable. Primitive types will be wrapped in 
+   * Get a field's value by field variable. Primitive types will be wrapped in
    * the appropriate "boxed" types.
    *
    * @param field
diff --git a/lib/java/src/org/apache/thrift/TSerializable.java b/lib/java/src/org/apache/thrift/TSerializable.java
new file mode 100644
index 0000000..80002c7
--- /dev/null
+++ b/lib/java/src/org/apache/thrift/TSerializable.java
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+import org.apache.thrift.protocol.TProtocol;
+
+/**
+ * Generic base interface for generated Thrift objects.
+ *
+ */
+public interface TSerializable {
+
+  /**
+   * Reads the TObject from the given input protocol.
+   *
+   * @param iprot Input protocol
+   */
+  public void read(TProtocol iprot) throws TException;
+
+  /**
+   * Writes the objects out to the protocol
+   *
+   * @param oprot Output protocol
+   */
+  public void write(TProtocol oprot) throws TException;
+
+}
diff --git a/lib/java/src/org/apache/thrift/TServiceClient.java b/lib/java/src/org/apache/thrift/TServiceClient.java
index 259a507..31153ec 100644
--- a/lib/java/src/org/apache/thrift/TServiceClient.java
+++ b/lib/java/src/org/apache/thrift/TServiceClient.java
@@ -76,7 +76,8 @@
   protected void receiveBase(TBase<?,?> result, String methodName) throws TException {
     TMessage msg = iprot_.readMessageBegin();
     if (msg.type == TMessageType.EXCEPTION) {
-      TApplicationException x = TApplicationException.read(iprot_);
+      TApplicationException x = new TApplicationException();
+      x.read(iprot_);
       iprot_.readMessageEnd();
       throw x;
     }