THRIFT-3794 Split Delphi application, protocol and transport exception subtypes into separate exceptions
Client: Delphi
Patch: Kyle Johnson
diff --git a/compiler/cpp/src/generate/t_delphi_generator.cc b/compiler/cpp/src/generate/t_delphi_generator.cc
index 513bc07..5578501 100644
--- a/compiler/cpp/src/generate/t_delphi_generator.cc
+++ b/compiler/cpp/src/generate/t_delphi_generator.cc
@@ -2131,8 +2131,7 @@
if (!(*f_iter)->get_returntype()->is_void()) {
indent_impl(s_service_impl)
- << "raise "
- "TApplicationException.Create(TApplicationException.TExceptionType.MissingResult, '"
+ << "raise TApplicationExceptionMissingResult.Create('"
<< (*f_iter)->get_name() << " failed: unknown result');" << endl;
}
@@ -2255,9 +2254,8 @@
indent_impl(s_service_impl) << "TProtocolUtil.Skip(iprot, TType.Struct);" << endl;
indent_impl(s_service_impl) << "iprot.ReadMessageEnd();" << endl;
indent_impl(s_service_impl) << "x := "
- "TApplicationException.Create(TApplicationException."
- "TExceptionType.UnknownMethod, 'Invalid method name: ''' + "
- "msg.Name + '''');" << endl;
+ "TApplicationExceptionUnknownMethod.Create("
+ "'Invalid method name: ''' + msg.Name + '''');" << endl;
indent_impl(s_service_impl)
<< "msg := Thrift.Protocol.TMessageImpl.Create(msg.Name, TMessageType.Exception, msg.SeqID);"
<< endl;
@@ -2444,8 +2442,7 @@
indent_impl(s_service_impl) << "if events <> nil then events.UnhandledError(E);" << endl;
}
if (!tfunction->is_oneway()) {
- indent_impl(s_service_impl) << "appx := TApplicationException.Create( "
- "TApplicationException.TExceptionType.InternalError, E.Message);"
+ indent_impl(s_service_impl) << "appx := TApplicationExceptionInternalError.Create(E.Message);"
<< endl;
indent_impl(s_service_impl) << "try" << endl;
indent_up_impl();
@@ -3593,7 +3590,7 @@
if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
indent_impl(code_block) << "if not _req_isset_" << prop_name(*f_iter, is_exception) << endl;
indent_impl(code_block)
- << "then raise TProtocolException.Create( TProtocolException.INVALID_DATA, "
+ << "then raise TProtocolExceptionInvalidData.Create("
<< "'required field " << prop_name(*f_iter, is_exception) << " not set');"
<< endl;
}
@@ -3714,7 +3711,7 @@
if (is_required && null_allowed) {
null_allowed = false;
indent_impl(code_block) << "if (" << fieldname << " = nil)" << endl;
- indent_impl(code_block) << "then raise TProtocolException.Create( TProtocolException.INVALID_DATA, "
+ indent_impl(code_block) << "then raise TProtocolExceptionInvalidData.Create("
<< "'required field " << fieldname << " not set');"
<< endl;
}
diff --git a/lib/delphi/src/Thrift.Processor.Multiplex.pas b/lib/delphi/src/Thrift.Processor.Multiplex.pas
index f6d9446..756daa1 100644
--- a/lib/delphi/src/Thrift.Processor.Multiplex.pas
+++ b/lib/delphi/src/Thrift.Processor.Multiplex.pas
@@ -78,7 +78,7 @@
FServiceProcessorMap : TDictionary<String, IProcessor>;
procedure Error( const oprot : IProtocol; const msg : IMessage;
- extype : TApplicationException.TExceptionType; const etxt : string);
+ extype : TApplicationExceptionSpecializedClass; const etxt : string);
public
constructor Create;
@@ -142,12 +142,12 @@
procedure TMultiplexedProcessorImpl.Error( const oprot : IProtocol; const msg : IMessage;
- extype : TApplicationException.TExceptionType;
+ extype : TApplicationExceptionSpecializedClass;
const etxt : string);
var appex : TApplicationException;
newMsg : IMessage;
begin
- appex := TApplicationException.Create( extype, etxt);
+ appex := extype.Create(etxt);
try
newMsg := TMessageImpl.Create( msg.Name, TMessageType.Exception, msg.SeqID);
@@ -178,7 +178,7 @@
msg := iprot.readMessageBegin();
if not (msg.Type_ in [TMessageType.Call, TMessageType.Oneway]) then begin
Error( oprot, msg,
- TApplicationException.TExceptionType.InvalidMessageType,
+ TApplicationExceptionInvalidMessageType,
ERROR_INVALID_MSGTYPE);
Exit( FALSE);
end;
@@ -187,7 +187,7 @@
idx := Pos( TMultiplexedProtocol.SEPARATOR, msg.Name);
if idx < 1 then begin
Error( oprot, msg,
- TApplicationException.TExceptionType.InvalidProtocol,
+ TApplicationExceptionInvalidProtocol,
Format(ERROR_INCOMPATIBLE_PROT,[msg.Name]));
Exit( FALSE);
end;
@@ -197,7 +197,7 @@
if not FServiceProcessorMap.TryGetValue( sService, processor)
then begin
Error( oprot, msg,
- TApplicationException.TExceptionType.InternalError,
+ TApplicationExceptionInternalError,
Format(ERROR_UNKNOWN_SERVICE,[sService]));
Exit( FALSE);
end;
diff --git a/lib/delphi/src/Thrift.Protocol.Compact.pas b/lib/delphi/src/Thrift.Protocol.Compact.pas
index 0355c4e..e9944d6 100644
--- a/lib/delphi/src/Thrift.Protocol.Compact.pas
+++ b/lib/delphi/src/Thrift.Protocol.Compact.pas
@@ -651,14 +651,14 @@
protocolId := Byte( ReadByte);
if (protocolId <> PROTOCOL_ID)
- then raise TProtocolException.Create( 'Expected protocol id ' + IntToHex(PROTOCOL_ID,2)
- + ' but got ' + IntToHex(protocolId,2));
+ then raise TProtocolExceptionBadVersion.Create( 'Expected protocol id ' + IntToHex(PROTOCOL_ID,2)
+ + ' but got ' + IntToHex(protocolId,2));
versionAndType := Byte( ReadByte);
version := Byte( versionAndType and VERSION_MASK);
if (version <> VERSION)
- then raise TProtocolException.Create( 'Expected version ' +IntToStr(VERSION)
- + ' but got ' + IntToStr(version));
+ then raise TProtocolExceptionBadVersion.Create( 'Expected version ' +IntToStr(VERSION)
+ + ' but got ' + IntToStr(version));
type_ := Byte( (versionAndType shr TYPE_SHIFT_AMOUNT) and TYPE_BITS);
seqid := Integer( ReadVarint32);
@@ -960,7 +960,7 @@
tct := Types( type_ and $0F);
if tct in [Low(Types)..High(Types)]
then result := tcompactTypeToType[tct]
- else raise TProtocolException.Create('don''t know what type: '+IntToStr(Ord(tct)));
+ else raise TProtocolExceptionInvalidData.Create('don''t know what type: '+IntToStr(Ord(tct)));
end;
@@ -969,7 +969,7 @@
begin
if ttype in VALID_TTYPES
then result := Byte( ttypeToCompactType[ttype])
- else raise TProtocolException.Create('don''t know what type: '+IntToStr(Ord(ttype)));
+ else raise TProtocolExceptionInvalidData.Create('don''t know what type: '+IntToStr(Ord(ttype)));
end;
diff --git a/lib/delphi/src/Thrift.Protocol.JSON.pas b/lib/delphi/src/Thrift.Protocol.JSON.pas
index 896dfcc..71ee7ae 100644
--- a/lib/delphi/src/Thrift.Protocol.JSON.pas
+++ b/lib/delphi/src/Thrift.Protocol.JSON.pas
@@ -310,7 +310,7 @@
TType.Set_: result := NAME_SET;
TType.List: result := NAME_LIST;
else
- raise TProtocolException.Create( TProtocolException.NOT_IMPLEMENTED, 'Unrecognized type ('+IntToStr(Ord(typeID))+')');
+ raise TProtocolExceptionNotImplemented.Create('Unrecognized type ('+IntToStr(Ord(typeID))+')');
end;
end;
@@ -328,7 +328,7 @@
else if name = NAME_MAP then result := TType.Map
else if name = NAME_LIST then result := TType.List
else if name = NAME_SET then result := TType.Set_
- else raise TProtocolException.Create( TProtocolException.NOT_IMPLEMENTED, 'Unrecognized type ('+name+')');
+ else raise TProtocolExceptionNotImplemented.Create('Unrecognized type ('+name+')');
end;
@@ -506,7 +506,7 @@
begin
ch := FReader.Read;
if (ch <> b)
- then raise TProtocolException.Create( TProtocolException.INVALID_DATA, 'Unexpected character ('+Char(ch)+')');
+ then raise TProtocolExceptionInvalidData.Create('Unexpected character ('+Char(ch)+')');
end;
@@ -516,7 +516,7 @@
i := StrToIntDef( '$0'+Char(ch), -1);
if (0 <= i) and (i < $10)
then result := i
- else raise TProtocolException.Create( TProtocolException.INVALID_DATA, 'Expected hex character ('+Char(ch)+')');
+ else raise TProtocolExceptionInvalidData.Create('Expected hex character ('+Char(ch)+')');
end;
@@ -853,7 +853,7 @@
then begin
off := Pos( Char(ch), ESCAPE_CHARS);
if off < 1
- then raise TProtocolException.Create( TProtocolException.INVALID_DATA, 'Expected control char');
+ then raise TProtocolExceptionInvalidData.Create('Expected control char');
ch := Byte( ESCAPE_CHAR_VALS[off]);
buffer.Write( ch, 1);
Continue;
@@ -870,12 +870,12 @@
// we need to make UTF8 bytes from it, to be decoded later
if CharUtils.IsHighSurrogate(char(wch)) then begin
if highSurogate <> #0
- then raise TProtocolException.Create( TProtocolException.INVALID_DATA, 'Expected low surrogate char');
+ then raise TProtocolExceptionInvalidData.Create('Expected low surrogate char');
highSurogate := char(wch);
end
else if CharUtils.IsLowSurrogate(char(wch)) then begin
if highSurogate = #0
- then TProtocolException.Create( TProtocolException.INVALID_DATA, 'Expected high surrogate char');
+ then TProtocolExceptionInvalidData.Create('Expected high surrogate char');
surrogatePairs[0] := highSurogate;
surrogatePairs[1] := char(wch);
tmp := TEncoding.UTF8.GetBytes(surrogatePairs);
@@ -889,7 +889,7 @@
end;
if highSurogate <> #0
- then raise TProtocolException.Create( TProtocolException.INVALID_DATA, 'Expected low surrogate char');
+ then raise TProtocolExceptionInvalidData.Create('Expected low surrogate char');
SetLength( result, buffer.Size);
if buffer.Size > 0 then Move( buffer.Memory^, result[0], Length(result));
@@ -943,8 +943,7 @@
result := StrToInt64(str);
except
on e:Exception do begin
- raise TProtocolException.Create( TProtocolException.INVALID_DATA,
- 'Bad data encounted in numeric data ('+str+') ('+e.Message+')');
+ raise TProtocolExceptionInvalidData.Create('Bad data encounted in numeric data ('+str+') ('+e.Message+')');
end;
end;
end;
@@ -966,7 +965,7 @@
and not Math.IsInfinite(dub)
then begin
// Throw exception -- we should not be in a string in Self case
- raise TProtocolException.Create( TProtocolException.INVALID_DATA, 'Numeric data unexpectedly quoted');
+ raise TProtocolExceptionInvalidData.Create('Numeric data unexpectedly quoted');
end;
result := dub;
Exit;
@@ -981,8 +980,7 @@
result := StrToFloat( str, INVARIANT_CULTURE);
except
on e:Exception
- do raise TProtocolException.Create( TProtocolException.INVALID_DATA,
- 'Bad data encounted in numeric data ('+str+') ('+e.Message+')');
+ do raise TProtocolExceptionInvalidData.Create('Bad data encounted in numeric data ('+str+') ('+e.Message+')');
end;
end;
@@ -1061,7 +1059,7 @@
ReadJSONArrayStart;
if ReadJSONInteger <> VERSION
- then raise TProtocolException.Create( TProtocolException.BAD_VERSION, 'Message contained bad version.');
+ then raise TProtocolExceptionBadVersion.Create('Message contained bad version.');
result.Name := SysUtils.TEncoding.UTF8.GetString( ReadJSONString( FALSE));
result.Type_ := TMessageType( ReadJSONInteger);
diff --git a/lib/delphi/src/Thrift.Protocol.pas b/lib/delphi/src/Thrift.Protocol.pas
index 01b11a8..7ff2eae 100644
--- a/lib/delphi/src/Thrift.Protocol.pas
+++ b/lib/delphi/src/Thrift.Protocol.pas
@@ -86,21 +86,37 @@
TProtocolException = class( Exception )
public
const // TODO(jensg): change into enum
- UNKNOWN : Integer = 0;
- INVALID_DATA : Integer = 1;
- NEGATIVE_SIZE : Integer = 2;
- SIZE_LIMIT : Integer = 3;
- BAD_VERSION : Integer = 4;
- NOT_IMPLEMENTED : Integer = 5;
- DEPTH_LIMIT : Integer = 6;
+ UNKNOWN = 0;
+ INVALID_DATA = 1;
+ NEGATIVE_SIZE = 2;
+ SIZE_LIMIT = 3;
+ BAD_VERSION = 4;
+ NOT_IMPLEMENTED = 5;
+ DEPTH_LIMIT = 6;
protected
- FType : Integer;
+ constructor HiddenCreate(const Msg: string);
public
- constructor Create; overload;
- constructor Create( type_: Integer ); overload;
- constructor Create( type_: Integer; const msg: string); overload;
+ // purposefully hide inherited constructor
+ class function Create(const Msg: string): TProtocolException; overload; deprecated 'Use specialized TProtocolException types (or regenerate from IDL)';
+ class function Create: TProtocolException; overload; deprecated 'Use specialized TProtocolException types (or regenerate from IDL)';
+ class function Create( type_: Integer): TProtocolException; overload; deprecated 'Use specialized TProtocolException types (or regenerate from IDL)';
+ class function Create( type_: Integer; const msg: string): TProtocolException; overload; deprecated 'Use specialized TProtocolException types (or regenerate from IDL)';
end;
+ // Needed to remove deprecation warning
+ TProtocolExceptionSpecialized = class abstract (TProtocolException)
+ public
+ constructor Create(const Msg: string);
+ end;
+
+ TProtocolExceptionUnknown = class (TProtocolExceptionSpecialized);
+ TProtocolExceptionInvalidData = class (TProtocolExceptionSpecialized);
+ TProtocolExceptionNegativeSize = class (TProtocolExceptionSpecialized);
+ TProtocolExceptionSizeLimit = class (TProtocolExceptionSpecialized);
+ TProtocolExceptionBadVersion = class (TProtocolExceptionSpecialized);
+ TProtocolExceptionNotImplemented = class (TProtocolExceptionSpecialized);
+ TProtocolExceptionDepthLimit = class (TProtocolExceptionSpecialized);
+
IMap = interface
['{30531D97-7E06-4233-B800-C3F53CCD23E7}']
function GetKeyType: TType;
@@ -695,7 +711,7 @@
begin
if FRecursionDepth < FRecursionLimit
then Inc(FRecursionDepth)
- else raise TProtocolException.Create( TProtocolException.DEPTH_LIMIT, 'Depth limit exceeded');
+ else raise TProtocolExceptionDepthLimit.Create('Depth limit exceeded');
end;
procedure TProtocolImpl.DecrementRecursionDepth;
@@ -1143,7 +1159,7 @@
version := size and Integer( VERSION_MASK);
if ( version <> Integer( VERSION_1)) then
begin
- raise TProtocolException.Create(TProtocolException.BAD_VERSION, 'Bad version in ReadMessageBegin: ' + IntToStr(version) );
+ raise TProtocolExceptionBadVersion.Create('Bad version in ReadMessageBegin: ' + IntToStr(version) );
end;
message.Type_ := TMessageType( size and $000000ff);
message.Name := ReadString;
@@ -1152,7 +1168,7 @@
begin
if FStrictRead then
begin
- raise TProtocolException.Create( TProtocolException.BAD_VERSION, 'Missing version in readMessageBegin, old client?' );
+ raise TProtocolExceptionBadVersion.Create('Missing version in readMessageBegin, old client?' );
end;
message.Name := ReadStringBody( size );
message.Type_ := TMessageType( ReadByte );
@@ -1358,22 +1374,47 @@
{ TProtocolException }
-constructor TProtocolException.Create;
+constructor TProtocolException.HiddenCreate(const Msg: string);
begin
- inherited Create('');
- FType := UNKNOWN;
+ inherited Create(Msg);
end;
-constructor TProtocolException.Create(type_: Integer);
+class function TProtocolException.Create(const Msg: string): TProtocolException;
begin
- inherited Create('');
- FType := type_;
+ Result := TProtocolExceptionUnknown.Create(Msg);
end;
-constructor TProtocolException.Create(type_: Integer; const msg: string);
+class function TProtocolException.Create: TProtocolException;
begin
- inherited Create( msg );
- FType := type_;
+ Result := TProtocolExceptionUnknown.Create('');
+end;
+
+class function TProtocolException.Create(type_: Integer): TProtocolException;
+begin
+{$WARN SYMBOL_DEPRECATED OFF}
+ Result := Create(type_, '');
+{$WARN SYMBOL_DEPRECATED DEFAULT}
+end;
+
+class function TProtocolException.Create(type_: Integer; const msg: string): TProtocolException;
+begin
+ case type_ of
+ INVALID_DATA: Result := TProtocolExceptionInvalidData.Create(msg);
+ NEGATIVE_SIZE: Result := TProtocolExceptionNegativeSize.Create(msg);
+ SIZE_LIMIT: Result := TProtocolExceptionSizeLimit.Create(msg);
+ BAD_VERSION: Result := TProtocolExceptionBadVersion.Create(msg);
+ NOT_IMPLEMENTED: Result := TProtocolExceptionNotImplemented.Create(msg);
+ DEPTH_LIMIT: Result := TProtocolExceptionDepthLimit.Create(msg);
+ else
+ Result := TProtocolExceptionUnknown.Create(msg);
+ end;
+end;
+
+{ TProtocolExceptionSpecialized }
+
+constructor TProtocolExceptionSpecialized.Create(const Msg: string);
+begin
+ inherited HiddenCreate(Msg);
end;
{ TThriftStringBuilder }
diff --git a/lib/delphi/src/Thrift.Server.pas b/lib/delphi/src/Thrift.Server.pas
index 6521444..13c5762 100644
--- a/lib/delphi/src/Thrift.Server.pas
+++ b/lib/delphi/src/Thrift.Server.pas
@@ -350,7 +350,7 @@
if client = nil then begin
if FStop
then Abort // silent exception
- else raise TTransportException.Create( 'ServerTransport.Accept() may not return NULL' );
+ else raise TTransportExceptionUnknown.Create('ServerTransport.Accept() may not return NULL');
end;
FLogDelegate( 'Client Connected!');
diff --git a/lib/delphi/src/Thrift.Transport.Pipes.pas b/lib/delphi/src/Thrift.Transport.Pipes.pas
index fc82bf1..d4f99ab 100644
--- a/lib/delphi/src/Thrift.Transport.Pipes.pas
+++ b/lib/delphi/src/Thrift.Transport.Pipes.pas
@@ -262,8 +262,7 @@
if not DuplicateHandle( GetCurrentProcess, hSource,
GetCurrentProcess, @result,
0, FALSE, DUPLICATE_SAME_ACCESS)
- then raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'DuplicateHandle: '+SysErrorMessage(GetLastError));
+ then raise TTransportExceptionNotOpen.Create('DuplicateHandle: '+SysErrorMessage(GetLastError));
end;
@@ -331,12 +330,10 @@
var cbWritten : DWORD;
begin
if not IsOpen
- then raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'Called write on non-open pipe');
+ then raise TTransportExceptionNotOpen.Create('Called write on non-open pipe');
if not WriteFile( FPipe, buffer[offset], count, cbWritten, nil)
- then raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'Write to pipe failed');
+ then raise TTransportExceptionNotOpen.Create('Write to pipe failed');
end;
@@ -347,8 +344,7 @@
const INTERVAL = 10; // ms
begin
if not IsOpen
- then raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'Called read on non-open pipe');
+ then raise TTransportExceptionNotOpen.Create('Called read on non-open pipe');
// MSDN: Handle can be a handle to a named pipe instance,
// or it can be a handle to the read end of an anonymous pipe,
@@ -373,8 +369,7 @@
Dec( retries);
if retries > 0
then Sleep( INTERVAL)
- else raise TTransportException.Create( TTransportException.TExceptionType.TimedOut,
- 'Pipe read timed out');
+ else raise TTransportExceptionTimedOut.Create('Pipe read timed out');
end;
end;
@@ -391,8 +386,7 @@
overlapped : IOverlappedHelper;
begin
if not IsOpen
- then raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'Called write on non-open pipe');
+ then raise TTransportExceptionNotOpen.Create('Called write on non-open pipe');
overlapped := TOverlappedHelperImpl.Create;
@@ -404,18 +398,15 @@
dwWait := overlapped.WaitFor(FTimeout);
if (dwWait = WAIT_TIMEOUT)
- then raise TTransportException.Create( TTransportException.TExceptionType.TimedOut,
- 'Pipe write timed out');
+ then raise TTransportExceptionTimedOut.Create('Pipe write timed out');
if (dwWait <> WAIT_OBJECT_0)
or not GetOverlappedResult( FPipe, overlapped.Overlapped, cbWritten, TRUE)
- then raise TTransportException.Create( TTransportException.TExceptionType.Unknown,
- 'Pipe write error');
+ then raise TTransportExceptionUnknown.Create('Pipe write error');
end;
else
- raise TTransportException.Create( TTransportException.TExceptionType.Unknown,
- SysErrorMessage(dwError));
+ raise TTransportExceptionUnknown.Create(SysErrorMessage(dwError));
end;
end;
@@ -429,8 +420,7 @@
overlapped : IOverlappedHelper;
begin
if not IsOpen
- then raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'Called read on non-open pipe');
+ then raise TTransportExceptionNotOpen.Create('Called read on non-open pipe');
overlapped := TOverlappedHelperImpl.Create;
@@ -443,18 +433,15 @@
dwWait := overlapped.WaitFor(FTimeout);
if (dwWait = WAIT_TIMEOUT)
- then raise TTransportException.Create( TTransportException.TExceptionType.TimedOut,
- 'Pipe read timed out');
+ then raise TTransportExceptionTimedOut.Create('Pipe read timed out');
if (dwWait <> WAIT_OBJECT_0)
or not GetOverlappedResult( FPipe, overlapped.Overlapped, cbRead, TRUE)
- then raise TTransportException.Create( TTransportException.TExceptionType.Unknown,
- 'Pipe read error');
+ then raise TTransportExceptionUnknown.Create('Pipe read error');
end;
else
- raise TTransportException.Create( TTransportException.TExceptionType.Unknown,
- SysErrorMessage(dwError));
+ raise TTransportExceptionUnknown.Create(SysErrorMessage(dwError));
end;
end;
@@ -517,14 +504,12 @@
while not WaitNamedPipe( PChar(FPipeName), INTERVAL) do begin
dwErr := GetLastError;
if dwErr <> ERROR_FILE_NOT_FOUND
- then raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'Unable to open pipe, '+SysErrorMessage(dwErr));
+ then raise TTransportExceptionNotOpen.Create('Unable to open pipe, '+SysErrorMessage(dwErr));
if timeout <> INFINITE then begin
if (retries > 0)
then Dec(retries)
- else raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'Unable to open pipe, timed out');
+ else raise TTransportExceptionNotOpen.Create('Unable to open pipe, timed out');
end;
Sleep(INTERVAL)
@@ -540,8 +525,7 @@
0); // no template file
if hPipe = INVALID_HANDLE_VALUE
- then raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'Unable to open pipe, '+SysErrorMessage(GetLastError));
+ then raise TTransportExceptionNotOpen.Create('Unable to open pipe, '+SysErrorMessage(GetLastError));
// everything fine
FPipe := hPipe;
@@ -725,8 +709,7 @@
// pass the handles on to the client before the serve (acceptImpl)
// blocking call.
if not CreateAnonPipe
- then raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- ClassName+'.Create() failed');
+ then raise TTransportExceptionNotOpen.Create(ClassName+'.Create() failed');
end;
@@ -740,8 +723,7 @@
// This 0-byte read serves merely as a blocking call.
if not ReadFile( FReadHandle, buf, 0, br, nil)
and (GetLastError() <> ERROR_MORE_DATA)
- then raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'TServerPipe unable to initiate pipe communication');
+ then raise TTransportExceptionNotOpen.Create('TServerPipe unable to initiate pipe communication');
// create the transport impl
result := TAnonymousPipeTransportImpl.Create( FReadHandle, FWriteHandle, FALSE, FTimeOut);
@@ -798,16 +780,14 @@
sa.bInheritHandle := TRUE; //allow passing handle to child
if not CreatePipe( hCAR, hPipeW, @sa, FBufSize) then begin //create stdin pipe
- raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'TServerPipe CreatePipe (anon) failed, '+SysErrorMessage(GetLastError));
+ raise TTransportExceptionNotOpen.Create('TServerPipe CreatePipe (anon) failed, '+SysErrorMessage(GetLastError));
Exit;
end;
if not CreatePipe( hPipe, hCAW, @sa, FBufSize) then begin //create stdout pipe
CloseHandle( hCAR);
CloseHandle( hPipeW);
- raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'TServerPipe CreatePipe (anon) failed, '+SysErrorMessage(GetLastError));
+ raise TTransportExceptionNotOpen.Create('TServerPipe CreatePipe (anon) failed, '+SysErrorMessage(GetLastError));
Exit;
end;
@@ -888,8 +868,7 @@
else
InternalClose;
- raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'Client connection failed');
+ raise TTransportExceptionNotOpen.Create('Client connection failed');
end;
end;
@@ -1001,8 +980,7 @@
if( result <> INVALID_HANDLE_VALUE)
then InterlockedExchangePointer( Pointer(FHandle), Pointer(result))
- else raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'CreateNamedPipe() failed ' + IntToStr(GetLastError));
+ else raise TTransportExceptionNotOpen.Create('CreateNamedPipe() failed ' + IntToStr(GetLastError));
finally
if sd <> nil then LocalFree( Cardinal( sd));
diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas
index a46fe5c..080cb8c 100644
--- a/lib/delphi/src/Thrift.Transport.pas
+++ b/lib/delphi/src/Thrift.Transport.pas
@@ -84,14 +84,30 @@
Interrupted
);
private
- FType : TExceptionType;
+ function GetType: TExceptionType;
+ protected
+ constructor HiddenCreate(const Msg: string);
public
- constructor Create( AType: TExceptionType); overload;
- constructor Create( const msg: string); overload;
- constructor Create( AType: TExceptionType; const msg: string); overload;
- property Type_: TExceptionType read FType;
+ class function Create( AType: TExceptionType): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)';
+ class function Create( const msg: string): TTransportException; reintroduce; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)';
+ class function Create( AType: TExceptionType; const msg: string): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)';
+ property Type_: TExceptionType read GetType;
end;
+ // Needed to remove deprecation warning
+ TTransportExceptionSpecialized = class abstract (TTransportException)
+ public
+ constructor Create(const Msg: string);
+ end;
+
+ TTransportExceptionUnknown = class (TTransportExceptionSpecialized);
+ TTransportExceptionNotOpen = class (TTransportExceptionSpecialized);
+ TTransportExceptionAlreadyOpen = class (TTransportExceptionSpecialized);
+ TTransportExceptionTimedOut = class (TTransportExceptionSpecialized);
+ TTransportExceptionEndOfFile = class (TTransportExceptionSpecialized);
+ TTransportExceptionBadArgs = class (TTransportExceptionSpecialized);
+ TTransportExceptionInterrupted = class (TTransportExceptionSpecialized);
+
IHTTPClient = interface( ITransport )
['{0F5DB8AB-710D-4338-AAC9-46B5734C5057}']
procedure SetConnectionTimeout(const Value: Integer);
@@ -349,10 +365,10 @@
function GetTransport( const ATrans: ITransport): ITransport; override;
end;
- {$IFDEF HAVE_CLASS_CTOR}
+ {$IFDEF HAVE_CLASS_CTOR}
class constructor Create;
{$ENDIF}
-
+
constructor Create; overload;
constructor Create( const ATrans: ITransport); overload;
destructor Destroy; override;
@@ -397,8 +413,8 @@
while got < len do begin
ret := Read( buf, off + got, len - got);
if ret > 0
- then Inc( got, ret)
- else raise TTransportException.Create( 'Cannot read, Remote side has closed' );
+ then Inc( got, ret)
+ else raise TTransportExceptionNotOpen.Create( 'Cannot read, Remote side has closed' );
end;
Result := got;
end;
@@ -488,15 +504,14 @@
function THTTPClientImpl.Read( var buf: TBytes; off, len: Integer): Integer;
begin
if FInputStream = nil then begin
- raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'No request has been sent');
+ raise TTransportExceptionNotOpen.Create('No request has been sent');
end;
try
Result := FInputStream.Read( buf, off, len )
except
on E: Exception
- do raise TTransportException.Create( TTransportException.TExceptionType.Unknown, E.Message);
+ do raise TTransportExceptionUnknown.Create(E.Message);
end;
end;
@@ -542,22 +557,55 @@
{ TTransportException }
-constructor TTransportException.Create(AType: TExceptionType);
+function TTransportException.GetType: TExceptionType;
+begin
+ if Self is TTransportExceptionNotOpen then Result := TExceptionType.NotOpen
+ else if Self is TTransportExceptionAlreadyOpen then Result := TExceptionType.AlreadyOpen
+ else if Self is TTransportExceptionTimedOut then Result := TExceptionType.TimedOut
+ else if Self is TTransportExceptionEndOfFile then Result := TExceptionType.EndOfFile
+ else if Self is TTransportExceptionBadArgs then Result := TExceptionType.BadArgs
+ else if Self is TTransportExceptionInterrupted then Result := TExceptionType.Interrupted
+ else Result := TExceptionType.Unknown;
+end;
+
+constructor TTransportException.HiddenCreate(const Msg: string);
+begin
+ inherited Create(Msg);
+end;
+
+class function TTransportException.Create(AType: TExceptionType): TTransportException;
begin
//no inherited;
- Create( AType, '' )
+{$WARN SYMBOL_DEPRECATED OFF}
+ Result := Create(AType, '')
+{$WARN SYMBOL_DEPRECATED DEFAULT}
end;
-constructor TTransportException.Create(AType: TExceptionType;
- const msg: string);
+class function TTransportException.Create(AType: TExceptionType;
+ const msg: string): TTransportException;
begin
- inherited Create(msg);
- FType := AType;
+ case AType of
+ TExceptionType.NotOpen: Result := TTransportExceptionNotOpen.Create(msg);
+ TExceptionType.AlreadyOpen: Result := TTransportExceptionAlreadyOpen.Create(msg);
+ TExceptionType.TimedOut: Result := TTransportExceptionTimedOut.Create(msg);
+ TExceptionType.EndOfFile: Result := TTransportExceptionEndOfFile.Create(msg);
+ TExceptionType.BadArgs: Result := TTransportExceptionBadArgs.Create(msg);
+ TExceptionType.Interrupted: Result := TTransportExceptionInterrupted.Create(msg);
+ else
+ Result := TTransportExceptionUnknown.Create(msg);
+ end;
end;
-constructor TTransportException.Create(const msg: string);
+class function TTransportException.Create(const msg: string): TTransportException;
begin
- inherited Create(msg);
+ Result := TTransportExceptionUnknown.Create(Msg);
+end;
+
+{ TTransportExceptionSpecialized }
+
+constructor TTransportExceptionSpecialized.Create(const Msg: string);
+begin
+ inherited HiddenCreate(Msg);
end;
{ TTransportFactoryImpl }
@@ -629,8 +677,7 @@
trans : IStreamTransport;
begin
if FServer = nil then begin
- raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'No underlying server socket.');
+ raise TTransportExceptionNotOpen.Create('No underlying server socket.');
end;
{$IFDEF OLD_SOCKETS}
@@ -662,7 +709,7 @@
except
on E: Exception do begin
client.Free;
- raise TTransportException.Create( E.ToString );
+ raise TTransportExceptionUnknown.Create(E.ToString);
end;
end;
{$ELSE}
@@ -694,7 +741,7 @@
FServer.Active := True;
except
on E: Exception
- do raise TTransportException.Create('Could not accept on listening socket: ' + E.Message);
+ do raise TTransportExceptionUnknown.Create('Could not accept on listening socket: ' + E.Message);
end;
{$ELSE}
FServer.Listen;
@@ -710,7 +757,7 @@
FServer.Active := False;
except
on E: Exception
- do raise TTransportException.Create('Error on closing socket : ' + E.Message);
+ do raise TTransportExceptionUnknown.Create('Error on closing socket : ' + E.Message);
end;
{$ELSE}
FServer.Close;
@@ -800,18 +847,15 @@
procedure TSocketImpl.Open;
begin
if IsOpen then begin
- raise TTransportException.Create( TTransportException.TExceptionType.AlreadyOpen,
- 'Socket already connected');
+ raise TTransportExceptionAlreadyOpen.Create('Socket already connected');
end;
if FHost = '' then begin
- raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'Cannot open null host');
+ raise TTransportExceptionNotOpen.Create('Cannot open null host');
end;
if Port <= 0 then begin
- raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'Cannot open without port');
+ raise TTransportExceptionNotOpen.Create('Cannot open without port');
end;
if FClient = nil
@@ -973,8 +1017,7 @@
procedure TStreamTransportImpl.Flush;
begin
if FOutputStream = nil then begin
- raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'Cannot flush null outputstream' );
+ raise TTransportExceptionNotOpen.Create('Cannot flush null outputstream' );
end;
FOutputStream.Flush;
@@ -1003,8 +1046,7 @@
function TStreamTransportImpl.Read(var buf: TBytes; off, len: Integer): Integer;
begin
if FInputStream = nil then begin
- raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'Cannot read from null inputstream' );
+ raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' );
end;
Result := FInputStream.Read( buf, off, len );
@@ -1013,8 +1055,7 @@
procedure TStreamTransportImpl.Write(const buf: TBytes; off, len: Integer);
begin
if FOutputStream = nil then begin
- raise TTransportException.Create( TTransportException.TExceptionType.NotOpen,
- 'Cannot write to null outputstream' );
+ raise TTransportExceptionNotOpen.Create('Cannot write to null outputstream' );
end;
FOutputStream.Write( buf, off, len );
@@ -1145,8 +1186,7 @@
data_len := len - FHeaderSize;
if (data_len < 0) then begin
- raise TTransportException.Create( TTransportException.TExceptionType.Unknown,
- 'TFramedTransport.Flush: data_len < 0' );
+ raise TTransportExceptionUnknown.Create('TFramedTransport.Flush: data_len < 0' );
end;
InitWriteBuffer;
@@ -1434,8 +1474,7 @@
if (FTimeout = 0)
then Exit
else begin
- raise TTransportException.Create( TTransportException.TExceptionType.TimedOut,
- SysErrorMessage(Cardinal(wsaError)));
+ raise TTransportExceptionTimedOut.Create(SysErrorMessage(Cardinal(wsaError)));
end;
end;
@@ -1482,7 +1521,7 @@
inherited;
if not FTcpClient.Active
- then raise TTransportException.Create( TTransportException.TExceptionType.NotOpen);
+ then raise TTransportExceptionNotOpen.Create('not open');
// The select function returns the total number of socket handles that are ready
// and contained in the fd_set structures, zero if the time limit expired,
@@ -1490,14 +1529,13 @@
// WSAGetLastError can be used to retrieve a specific error code.
retval := Self.Select( nil, @bCanWrite, @bError, FTimeOut, wsaError);
if retval = SOCKET_ERROR
- then raise TTransportException.Create( TTransportException.TExceptionType.Unknown,
- SysErrorMessage(Cardinal(wsaError)));
+ then raise TTransportExceptionUnknown.Create(SysErrorMessage(Cardinal(wsaError)));
if (retval = 0)
- then raise TTransportException.Create( TTransportException.TExceptionType.TimedOut);
+ then raise TTransportExceptionTimedOut.Create('timed out');
if bError or not bCanWrite
- then raise TTransportException.Create( TTransportException.TExceptionType.Unknown);
+ then raise TTransportExceptionUnknown.Create('unknown error');
FTcpClient.SendBuf( Pointer(@buffer[offset])^, count);
end;
diff --git a/lib/delphi/src/Thrift.pas b/lib/delphi/src/Thrift.pas
index 65f23ab..e969ebf 100644
--- a/lib/delphi/src/Thrift.pas
+++ b/lib/delphi/src/Thrift.pas
@@ -28,6 +28,8 @@
Version = '1.0.0-dev';
type
+ TApplicationExceptionSpecializedClass = class of TApplicationExceptionSpecialized;
+
TApplicationException = class( SysUtils.Exception )
public
type
@@ -47,16 +49,40 @@
);
{$SCOPEDENUMS OFF}
private
- FType : TExceptionType;
+ function GetType: TExceptionType;
+ protected
+ constructor HiddenCreate(const Msg: string);
public
- constructor Create; overload;
- constructor Create( AType: TExceptionType); overload;
- constructor Create( AType: TExceptionType; const msg: string); overload;
+ // purposefully hide inherited constructor
+ class function Create(const Msg: string): TApplicationException; overload; deprecated 'Use specialized TApplicationException types (or regenerate from IDL)';
+ class function Create: TApplicationException; overload; deprecated 'Use specialized TApplicationException types (or regenerate from IDL)';
+ class function Create( AType: TExceptionType): TApplicationException; overload; deprecated 'Use specialized TApplicationException types (or regenerate from IDL)';
+ class function Create( AType: TExceptionType; const msg: string): TApplicationException; overload; deprecated 'Use specialized TApplicationException types (or regenerate from IDL)';
+
+ class function GetSpecializedExceptionType(AType: TExceptionType): TApplicationExceptionSpecializedClass;
class function Read( const iprot: IProtocol): TApplicationException;
procedure Write( const oprot: IProtocol );
end;
+ // Needed to remove deprecation warning
+ TApplicationExceptionSpecialized = class abstract (TApplicationException)
+ public
+ constructor Create(const Msg: string);
+ end;
+
+ TApplicationExceptionUnknown = class (TApplicationExceptionSpecialized);
+ TApplicationExceptionUnknownMethod = class (TApplicationExceptionSpecialized);
+ TApplicationExceptionInvalidMessageType = class (TApplicationExceptionSpecialized);
+ TApplicationExceptionWrongMethodName = class (TApplicationExceptionSpecialized);
+ TApplicationExceptionBadSequenceID = class (TApplicationExceptionSpecialized);
+ TApplicationExceptionMissingResult = class (TApplicationExceptionSpecialized);
+ TApplicationExceptionInternalError = class (TApplicationExceptionSpecialized);
+ TApplicationExceptionProtocolError = class (TApplicationExceptionSpecialized);
+ TApplicationExceptionInvalidTransform = class (TApplicationExceptionSpecialized);
+ TApplicationExceptionInvalidProtocol = class (TApplicationExceptionSpecialized);
+ TApplicationExceptionUnsupportedClientType = class (TApplicationExceptionSpecialized);
+
// base class for IDL-generated exceptions
TException = class( SysUtils.Exception)
public
@@ -84,22 +110,64 @@
{ TApplicationException }
-constructor TApplicationException.Create;
+function TApplicationException.GetType: TExceptionType;
begin
- inherited Create( '' );
+ if Self is TApplicationExceptionUnknownMethod then Result := TExceptionType.UnknownMethod
+ else if Self is TApplicationExceptionInvalidMessageType then Result := TExceptionType.InvalidMessageType
+ else if Self is TApplicationExceptionWrongMethodName then Result := TExceptionType.WrongMethodName
+ else if Self is TApplicationExceptionBadSequenceID then Result := TExceptionType.BadSequenceID
+ else if Self is TApplicationExceptionMissingResult then Result := TExceptionType.MissingResult
+ else if Self is TApplicationExceptionInternalError then Result := TExceptionType.InternalError
+ else if Self is TApplicationExceptionProtocolError then Result := TExceptionType.ProtocolError
+ else if Self is TApplicationExceptionInvalidTransform then Result := TExceptionType.InvalidTransform
+ else if Self is TApplicationExceptionInvalidProtocol then Result := TExceptionType.InvalidProtocol
+ else if Self is TApplicationExceptionUnsupportedClientType then Result := TExceptionType.UnsupportedClientType
+ else Result := TExceptionType.Unknown;
end;
-constructor TApplicationException.Create(AType: TExceptionType;
- const msg: string);
+constructor TApplicationException.HiddenCreate(const Msg: string);
begin
- inherited Create( msg );
- FType := AType;
+ inherited Create(Msg);
end;
-constructor TApplicationException.Create(AType: TExceptionType);
+class function TApplicationException.Create(const Msg: string): TApplicationException;
begin
- inherited Create('');
- FType := AType;
+ Result := TApplicationExceptionUnknown.Create(Msg);
+end;
+
+class function TApplicationException.Create: TApplicationException;
+begin
+ Result := TApplicationExceptionUnknown.Create('');
+end;
+
+class function TApplicationException.Create( AType: TExceptionType): TApplicationException;
+begin
+{$WARN SYMBOL_DEPRECATED OFF}
+ Result := Create(AType, '');
+{$WARN SYMBOL_DEPRECATED DEFAULT}
+end;
+
+class function TApplicationException.Create( AType: TExceptionType; const msg: string): TApplicationException;
+begin
+ Result := GetSpecializedExceptionType(AType).Create(msg);
+end;
+
+class function TApplicationException.GetSpecializedExceptionType(AType: TExceptionType): TApplicationExceptionSpecializedClass;
+begin
+ case AType of
+ TExceptionType.UnknownMethod: Result := TApplicationExceptionUnknownMethod;
+ TExceptionType.InvalidMessageType: Result := TApplicationExceptionInvalidMessageType;
+ TExceptionType.WrongMethodName: Result := TApplicationExceptionWrongMethodName;
+ TExceptionType.BadSequenceID: Result := TApplicationExceptionBadSequenceID;
+ TExceptionType.MissingResult: Result := TApplicationExceptionMissingResult;
+ TExceptionType.InternalError: Result := TApplicationExceptionInternalError;
+ TExceptionType.ProtocolError: Result := TApplicationExceptionProtocolError;
+ TExceptionType.InvalidTransform: Result := TApplicationExceptionInvalidTransform;
+ TExceptionType.InvalidProtocol: Result := TApplicationExceptionInvalidProtocol;
+ TExceptionType.UnsupportedClientType: Result := TApplicationExceptionUnsupportedClientType;
+ else
+ Result := TApplicationExceptionUnknown;
+ end;
end;
class function TApplicationException.Read( const iprot: IProtocol): TApplicationException;
@@ -147,7 +215,7 @@
iprot.ReadFieldEnd;
end;
iprot.ReadStructEnd;
- Result := TApplicationException.Create( typ, msg );
+ Result := GetSpecializedExceptionType(typ).Create(msg);
end;
procedure TApplicationException.Write( const oprot: IProtocol);
@@ -174,10 +242,17 @@
field.Type_ := TType.I32;
field.Id := 2;
oprot.WriteFieldBegin(field);
- oprot.WriteI32(Integer(FType));
+ oprot.WriteI32(Integer(GetType));
oprot.WriteFieldEnd();
oprot.WriteFieldStop();
oprot.WriteStructEnd();
end;
+{ TApplicationExceptionSpecialized }
+
+constructor TApplicationExceptionSpecialized.Create(const Msg: string);
+begin
+ inherited HiddenCreate(Msg);
+end;
+
end.
diff --git a/lib/delphi/test/client.dpr b/lib/delphi/test/client.dpr
index 88f0fd4..f2e5250 100644
--- a/lib/delphi/test/client.dpr
+++ b/lib/delphi/test/client.dpr
@@ -33,6 +33,7 @@
Thrift.Protocol in '..\src\Thrift.Protocol.pas',
Thrift.Protocol.JSON in '..\src\Thrift.Protocol.JSON.pas',
Thrift.Protocol.Compact in '..\src\Thrift.Protocol.Compact.pas',
+ Thrift.Protocol.Multiplex in '..\src\Thrift.Protocol.Multiplex.pas',
Thrift.Collections in '..\src\Thrift.Collections.pas',
Thrift.Server in '..\src\Thrift.Server.pas',
Thrift.Stream in '..\src\Thrift.Stream.pas',
diff --git a/lib/delphi/test/server.dpr b/lib/delphi/test/server.dpr
index 9739f5f..d87a331 100644
--- a/lib/delphi/test/server.dpr
+++ b/lib/delphi/test/server.dpr
@@ -33,6 +33,8 @@
Thrift.Protocol in '..\src\Thrift.Protocol.pas',
Thrift.Protocol.JSON in '..\src\Thrift.Protocol.JSON.pas',
Thrift.Protocol.Compact in '..\src\Thrift.Protocol.Compact.pas',
+ Thrift.Protocol.Multiplex in '..\src\Thrift.Protocol.Multiplex.pas',
+ Thrift.Processor.Multiplex in '..\src\Thrift.Processor.Multiplex.pas',
Thrift.Collections in '..\src\Thrift.Collections.pas',
Thrift.Server in '..\src\Thrift.Server.pas',
Thrift.Console in '..\src\Thrift.Console.pas',