# Patch to support Thrift as a data interchange format in the same
# manner as Ice supports Google Protocol Buffers.
#
# Patch by: J Robert Ray jrray{_at_}imageworks{_dot_}com

diff -ru Ice-3.4.2.orig/cpp/src/Slice/JavaUtil.cpp Ice-3.4.2/cpp/src/Slice/JavaUtil.cpp
--- Ice-3.4.2.orig/cpp/src/Slice/JavaUtil.cpp	2011-06-15 12:43:59.000000000 -0700
+++ Ice-3.4.2/cpp/src/Slice/JavaUtil.cpp	2013-01-31 10:50:46.000000000 -0800
@@ -553,6 +553,11 @@
                 {
                     return string("Ice.Holder<") + meta.substr(prefix.size()) + " >";
                 }
+                prefix = "java:thrift:";
+                if(seq->findMetaData(prefix, meta))
+                {
+                    return string("Ice.Holder<") + meta.substr(prefix.size()) + " >";
+                }
             }
 
             //
@@ -591,6 +596,11 @@
                 {
                     return meta.substr(prefix.size());
                 }
+                prefix = "java:thrift:";
+                if(seq->findMetaData(prefix, meta))
+                {
+                    return meta.substr(prefix.size());
+                }
             }
 
             string instanceType, formalType;
@@ -1088,6 +1098,7 @@
     {
         string meta;
         static const string protobuf = "java:protobuf:";
+        static const string thrift = "java:thrift:";
         static const string serializable = "java:serializable:";
         if(seq->findMetaData(serializable, meta))
         {
@@ -1128,6 +1139,44 @@
             }
             return;
         }
+        else if(seq->findMetaData(thrift, meta))
+        {
+            if(marshal)
+            {
+                out << nl << "try";
+                out << sb;
+                out << nl << "org.apache.thrift.TSerializer serializer = "
+                          << "new org.apache.thrift.TSerializer("
+                          << "new org.apache.thrift.protocol.TBinaryProtocol.Factory());";
+                out << nl << stream << ".writeByteSeq(serializer.serialize(" << v << "));";
+                out << eb;
+                out << nl << "catch(org.apache.thrift.TException __ex)";
+                out << sb;
+                out << nl << "Ice.MarshalException __mex = new Ice.MarshalException();";
+                out << nl << "__mex.initCause(__ex);";
+                out << nl << "throw __mex;";
+                out << eb;
+            }
+            else
+            {
+                string type = typeToString(seq, TypeModeIn, package);
+                out << nl << "try";
+                out << sb;
+                out << nl << "org.apache.thrift.TDeserializer deserializer = "
+                          << "new org.apache.thrift.TDeserializer("
+                          << "new org.apache.thrift.protocol.TBinaryProtocol.Factory());";
+                out << nl << v << " = new " << type << "();";
+                out << nl << "deserializer.deserialize(" << v << ", " << stream << ".readByteSeq());";
+                out << eb;
+                out << nl << "catch(org.apache.thrift.TException __ex)";
+                out << sb;
+                out << nl << "Ice.MarshalException __mex = new Ice.MarshalException();";
+                out << nl << "__mex.initCause(__ex);";
+                out << nl << "throw __mex;";
+                out << eb;
+            }
+            return;
+        }
     }
 
     bool customType = false;
@@ -1956,6 +2005,7 @@
     {
         string meta;
         static const string protobuf = "java:protobuf:";
+        static const string thrift = "java:thrift:";
         static const string serializable = "java:serializable:";
         if(seq->findMetaData(serializable, meta))
         {
@@ -1996,6 +2046,44 @@
             }
             return;
         }
+        else if(seq->findMetaData(thrift, meta))
+        {
+            if(marshal)
+            {
+                out << nl << "try";
+                out << sb;
+                out << nl << "org.apache.thrift.TSerializer serializer = "
+                          << "new org.apache.thrift.TSerializer("
+                          << "new org.apache.thrift.protocol.TBinaryProtocol.Factory());";
+                out << nl << stream << ".writeByteSeq(serializer.serialize(" << v << "));";
+                out << eb;
+                out << nl << "catch(org.apache.thrift.TException __ex)";
+                out << sb;
+                out << nl << "Ice.MarshalException __mex = new Ice.MarshalException();";
+                out << nl << "__mex.initCause(__ex);";
+                out << nl << "throw __mex;";
+                out << eb;
+            }
+            else
+            {
+                string type = meta.substr(thrift.size());
+                out << nl << "try";
+                out << sb;
+                out << nl << "org.apache.thrift.TDeserializer deserializer = "
+                          << "new org.apache.thrift.TDeserializer("
+                          << "new org.apache.thrift.protocol.TBinaryProtocol.Factory());";
+                out << nl << v << " = new " << type << "();";
+                out << nl << "deserializer.deserialize(" << v << ", " << stream << ".readByteSeq());";
+                out << eb;
+                out << nl << "catch(org.apache.thrift.TException __ex)";
+                out << sb;
+                out << nl << "Ice.MarshalException __mex = new Ice.MarshalException();";
+                out << nl << "__mex.initCause(__ex);";
+                out << nl << "throw __mex;";
+                out << eb;
+            }
+            return;
+        }
     }
 
     //
@@ -2436,7 +2524,9 @@
             {
                 return true;
             }
-            else if(str.find("java:protobuf:") == 0 || str.find("java:serializable:") == 0)
+            else if(str.find("java:protobuf:") == 0 ||
+                    str.find("java:thrift:") == 0 ||
+                    str.find("java:serializable:") == 0)
             {
                 SequencePtr seq = SequencePtr::dynamicCast(cont);
                 if(seq)
@@ -2731,6 +2821,7 @@
 Slice::JavaGenerator::MetaDataVisitor::visitSequence(const SequencePtr& p)
 {
     static const string protobuf = "java:protobuf:";
+    static const string thrift = "java:thrift:";
     static const string serializable = "java:serializable:";
     StringList metaData = getMetaData(p);
     const string file =  p->file();
@@ -2740,7 +2831,9 @@
         string s = *q++;
         if(_history.count(s) == 0) // Don't complain about the same metadata more than once.
         {
-            if(s.find(protobuf) == 0 || s.find(serializable) == 0)
+            if(s.find(protobuf) == 0 ||
+               s.find(thrift) == 0 ||
+               s.find(serializable) == 0)
             {
                 //
                 // Remove from list so validateType does not try to handle as well.
@@ -2829,6 +2922,11 @@
                     result.push_back(s);
                     continue;
                 }
+                else if(s.substr(prefix.size(), pos - prefix.size()) == "thrift")
+                {
+                    result.push_back(s);
+                    continue;
+                }
 
                 emitWarning(cont->file(), cont->line(), "ignoring invalid metadata `" + s + "'");
             }
@@ -2865,7 +2963,9 @@
             }
             emitWarning(file, line, "invalid metadata for " + str);
         }
-        else if(i->find("java:protobuf:") == 0 || i->find("java:serializable:") == 0)
+        else if(i->find("java:protobuf:") == 0 ||
+                i->find("java:thrift:") == 0 ||
+                i->find("java:serializable:") == 0)
         {
             //
             // Only valid in sequence defintion which is checked in visitSequence
diff -ru Ice-3.4.2.orig/cpp/src/slice2java/Gen.cpp Ice-3.4.2/cpp/src/slice2java/Gen.cpp
--- Ice-3.4.2.orig/cpp/src/slice2java/Gen.cpp	2011-06-15 12:43:59.000000000 -0700
+++ Ice-3.4.2/cpp/src/slice2java/Gen.cpp	2013-01-31 10:50:46.000000000 -0800
@@ -3692,6 +3692,12 @@
             return; // No holders for protobuf types.
 
         }
+        prefix = "java:thrift:";
+        if(p->findMetaData(prefix, meta))
+        {
+            return; // No holders for thrift types.
+
+        }
     }
 
     writeHolder(p);
