THRIFT-1962 Multiplex processor should send any TApplicationException back to client

Patch: Jens Geyer
diff --git a/lib/delphi/src/Thrift.Processor.Multiplex.pas b/lib/delphi/src/Thrift.Processor.Multiplex.pas
index b771d43..8d6d8b0 100644
--- a/lib/delphi/src/Thrift.Processor.Multiplex.pas
+++ b/lib/delphi/src/Thrift.Processor.Multiplex.pas
@@ -77,6 +77,9 @@
   private
     FServiceProcessorMap : TDictionary<String, IProcessor>;
 
+    procedure Error( const oprot : IProtocol; const msg : IMessage;
+                     extype : TApplicationException.TExceptionType; const etxt : string);
+
   public
     constructor Create;
     destructor Destroy;  override;
@@ -138,6 +141,27 @@
 end;
 
 
+procedure TMultiplexedProcessorImpl.Error( const oprot : IProtocol; const msg : IMessage;
+                                           extype : TApplicationException.TExceptionType;
+                                           const etxt : string);
+var appex  : TApplicationException;
+    newMsg : IMessage;
+begin
+  appex := TApplicationException.Create( extype, etxt);
+  try
+    newMsg := TMessageImpl.Create( msg.Name, TMessageType.Exception, msg.SeqID);
+

+    oprot.WriteMessageBegin(newMsg);
+    appex.Write(oprot);
+    oprot.WriteMessageEnd();
+    oprot.Transport.Flush();
+
+  finally
+    appex.Free;

+  end;
+end;
+
+
 function TMultiplexedProcessorImpl.Process(const iprot, oprot : IProtocol) : Boolean;
 var msg, newMsg : IMessage;
     idx         : Integer;
@@ -152,21 +176,31 @@
   // Use the actual underlying protocol (e.g. TBinaryProtocol) to read the message header.
   // This pulls the message "off the wire", which we'll deal with at the end of this method.
   msg := iprot.readMessageBegin();
-  if not (msg.Type_ in [TMessageType.Call, TMessageType.Oneway])
-  then raise TApplicationException.Create( TApplicationException.TExceptionType.InvalidMessageType,
-                                           ERROR_INVALID_MSGTYPE);
-
+  if not (msg.Type_ in [TMessageType.Call, TMessageType.Oneway]) then begin
+    Error( oprot, msg,
+           TApplicationException.TExceptionType.InvalidMessageType,
+           ERROR_INVALID_MSGTYPE);
+    Exit( FALSE);

+  end;

+

   // Extract the service name
   idx := Pos( TMultiplexedProtocol.SEPARATOR, msg.Name);
-  if idx < 1
-  then raise TApplicationException.Create( TApplicationException.TExceptionType.InvalidProtocol,
-                                           Format(ERROR_INCOMPATIBLE_PROT,[msg.Name]));
+  if idx < 1 then begin
+    Error( oprot, msg,
+           TApplicationException.TExceptionType.InvalidProtocol,
+           Format(ERROR_INCOMPATIBLE_PROT,[msg.Name]));
+    Exit( FALSE);
+  end;

 
   // Create a new TMessage, something that can be consumed by any TProtocol
   sService := Copy( msg.Name, 1, idx-1);
   if not FServiceProcessorMap.TryGetValue( sService, processor)
-  then raise TApplicationException.Create( TApplicationException.TExceptionType.InternalError,
-                                           Format(ERROR_UNKNOWN_SERVICE,[sService]));
+  then begin
+    Error( oprot, msg,
+           TApplicationException.TExceptionType.InternalError,
+           Format(ERROR_UNKNOWN_SERVICE,[sService]));
+    Exit( FALSE);
+  end;

 
   // Create a new TMessage, removing the service name
   Inc( idx, Length(TMultiplexedProtocol.SEPARATOR));