diff --git a/wst/trunk/base_service_intf.pas b/wst/trunk/base_service_intf.pas index e867ae5cb..2dffbced9 100644 --- a/wst/trunk/base_service_intf.pas +++ b/wst/trunk/base_service_intf.pas @@ -63,6 +63,7 @@ const type EServiceException = class(Exception) end; + EServiceExtensionException = class(Exception) end; ETransportExecption = class(EServiceException) end; EBaseRemoteException = class(EServiceException) diff --git a/wst/trunk/client_utils.pas b/wst/trunk/client_utils.pas new file mode 100644 index 000000000..e82b0c907 --- /dev/null +++ b/wst/trunk/client_utils.pas @@ -0,0 +1,182 @@ +{ + This file is part of the Web Service Toolkit + Copyright (c) 2010 by Inoussa OUEDRAOGO + + This file is provide under modified LGPL licence + ( the files COPYING.modifiedLGPL and COPYING.LGPL). + + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +} +{$INCLUDE wst_global.inc} +unit client_utils; + +interface +uses + Classes, SysUtils, + service_intf, imp_utils, base_service_intf, wst_types, filter_intf; + +Type + +{$M+} + TBaseTransport = class(TSimpleFactoryItem,ITransport) + Private + FPropMngr : IPropertyManager; + FFilter : IDataFilter; + protected + function HasFilter() : Boolean; + function GetFilter() : IDataFilter; + function GetFilterString: string; + procedure SetFilterString(const Value: string); + procedure FilterInput(ASource, ADest : TStream); + procedure FilterOutput(ASource, ADest : TStream); + public + constructor Create();override; + destructor Destroy();override; + function GetPropertyManager():IPropertyManager; + procedure SendAndReceive(ARequest,AResponse:TStream); virtual; abstract; + published + property FilterString : string read GetFilterString write SetFilterString; + End; +{$M+} + + +implementation +uses + wst_consts; + +{ TBaseTransport } + +constructor TBaseTransport.Create(); +begin + inherited; + FPropMngr := TPublishedPropertyManager.Create(Self); +end; + +destructor TBaseTransport.Destroy(); +begin + FPropMngr := Nil; + inherited; +end; + +procedure TBaseTransport.FilterInput(ASource, ADest: TStream); +var + locInBuffer, locBuffer : TByteDynArray; + locOldPos : Int64; +begin + if ASource.InheritsFrom(TMemoryStream) then begin + locBuffer := FFilter.ExecuteInput(TMemoryStream(ASource).Memory^,ASource.Size); + end else begin + SetLength(locInBuffer,ASource.Size); + locOldPos := ASource.Position; + ASource.Position := 0; + try + ASource.Read(locInBuffer[0],Length(locInBuffer)); + finally + ASource.Position := locOldPos; + end; + locBuffer := FFilter.ExecuteInput(locInBuffer[0],Length(locInBuffer)); + end; + ADest.Size := Length(locBuffer); + ADest.Position := 0; + ADest.Write(locBuffer[0],Length(locBuffer)); + ADest.Position := 0; +end; + +procedure TBaseTransport.FilterOutput(ASource, ADest: TStream); +var + locInBuffer, locBuffer : TByteDynArray; + locOldPos : Int64; +begin + if ASource.InheritsFrom(TMemoryStream) then begin + locBuffer := FFilter.ExecuteOutput(TMemoryStream(ASource).Memory^,ASource.Size); + end else begin + SetLength(locInBuffer,ASource.Size); + locOldPos := ASource.Position; + ASource.Position := 0; + try + ASource.Read(locInBuffer[0],Length(locInBuffer)); + finally + ASource.Position := locOldPos; + end; + locBuffer := FFilter.ExecuteOutput(locInBuffer[0],Length(locInBuffer)); + end; + ADest.Size := Length(locBuffer); + ADest.Position := 0; + ADest.Write(locBuffer[0],Length(locBuffer)); + ADest.Position := 0; +end; + +function TBaseTransport.GetFilter() : IDataFilter; +begin + Result := FFilter; +end; + +function TBaseTransport.GetFilterString: string; +var + locPM : IPropertyManager; + ls : TStringList; + locRes, s : string; + i : Integer; +begin + locRes := ''; + if ( FFilter <> nil ) then begin + locRes := FFilter.GetName(); + locPM := FFilter.GetPropertyManager(); + ls := TStringList.Create(); + try + if ( locPM.GetPropertyNames(ls) > 0 ) then begin + for i := 0 to Pred(ls.Count) do begin + s := ls[i]; + locRes := Format('%s,%s>%s',[locRes,s,locPM.GetProperty(s)]); + end; + end; + finally + ls.Free(); + end; + end; + Result := locRes; +end; + +function TBaseTransport.GetPropertyManager: IPropertyManager; +begin + Result := FPropMngr; +end; + +function TBaseTransport.HasFilter() : Boolean; +begin + Result := (FFilter <> nil); +end; + +procedure TBaseTransport.SetFilterString(const Value: string); +var + locBuffer, locName, locValue : string; + locPM : IPropertyManager; + locFilterManager : IDataFilterRegistry; + locFilter : IDataFilter; +begin + locBuffer := Value; + if IsStrEmpty(locBuffer) then begin + FFilter := nil; + Exit; + end; + + //The filter name + locName := Trim(GetToken(locBuffer,',')); + locFilterManager := GetDataFilterRegistry(); + if not locFilterManager.Find(locName,locFilter) then + raise ETransportExecption.CreateFmt(SERR_DataFilterNotFound,[locName]); + locPM := locFilter.GetPropertyManager(); + while True do begin + locName := GetToken(locBuffer,'>'); + if IsStrEmpty(locName) then + Break; + locValue := GetToken(locBuffer,','); + locPM.SetProperty(locName,locValue); + end; + FFilter := locFilter; +end; + +end. \ No newline at end of file diff --git a/wst/trunk/filter_intf.pas b/wst/trunk/filter_intf.pas new file mode 100644 index 000000000..a4a591acd --- /dev/null +++ b/wst/trunk/filter_intf.pas @@ -0,0 +1,89 @@ +{ + This file is part of the Web Service Toolkit + Copyright (c) 2010 by Inoussa OUEDRAOGO + + This file is provide under modified LGPL licence + ( the files COPYING.modifiedLGPL and COPYING.LGPL). + + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +} + +{$INCLUDE wst_global.inc} + +unit filter_intf; + +interface +uses + SysUtils, + wst_types, base_service_intf; + +type + + EFilterException = class(Exception) end; + + IDataFilter = interface + ['{9D9886A4-37B6-4D62-BD3B-603A8EF00A13}'] + function GetPropertyManager() : IPropertyManager; + function GetName() : string; + function ExecuteInput(const AData; const ASize : Integer) : TByteDynArray; + function ExecuteOutput(const AData; const ASize : Integer) : TByteDynArray; + end; + + IDataFilterRegistry = interface + ['{06489785-4447-4844-965B-9A50A417B20D}'] + function Find( + const AName : string; + out ARes : IDataFilter + ):Boolean; + procedure Register( + const AName : string; + AFactory : IItemFactory + ); + end; + + function GetDataFilterRegistry():IDataFilterRegistry; + +implementation + +type + { TDataFilterRegistry } + TDataFilterRegistry = class(TBaseFactoryRegistry,IInterface,IDataFilterRegistry) + protected + function Find( + const AName : string; + out ARes : IDataFilter + ):Boolean; + end; + + +var + DataFilterRegistryInst : IDataFilterRegistry = nil; +function GetDataFilterRegistry():IDataFilterRegistry; +begin + if not Assigned(DataFilterRegistryInst) then + DataFilterRegistryInst := TDataFilterRegistry.Create() as IDataFilterRegistry;// Lock!!! + Result := DataFilterRegistryInst; +end; + +{ TDataFilterRegistry } + +function TDataFilterRegistry.Find( + const AName : string; + out ARes : IDataFilter +): Boolean; +var + fct : IItemFactory; +begin + fct := FindFactory(AName); + if Assigned(fct) then begin + ARes := fct.CreateInstance() as IDataFilter; + Result := True; + end else begin + Result := False; + end; +end; + +end. diff --git a/wst/trunk/indy_http_protocol.pas b/wst/trunk/indy_http_protocol.pas index 0e36b7215..b0958ce47 100644 --- a/wst/trunk/indy_http_protocol.pas +++ b/wst/trunk/indy_http_protocol.pas @@ -13,26 +13,24 @@ {$INCLUDE wst_global.inc} unit indy_http_protocol; -//{$DEFINE WST_DBG} +{.$DEFINE WST_DBG} interface uses Classes, SysUtils, - service_intf, imp_utils, base_service_intf, wst_types, - IdHTTP; + service_intf, imp_utils, base_service_intf, wst_types, filter_intf, + client_utils, IdHTTP; Const sTRANSPORT_NAME = 'HTTP'; Type -{$M+} { THTTPTransport } - THTTPTransport = class(TSimpleFactoryItem,ITransport) + THTTPTransport = class(TBaseTransport,ITransport) Private FFormat : string; - FPropMngr : IPropertyManager; FConnection : TidHttp; FSoapAction: string; FContentType: string; @@ -49,12 +47,11 @@ Type procedure SetProxyPort(const AValue: Integer); procedure SetProxyServer(const AValue: string); procedure SetProxyUsername(const AValue: string); - Public + public constructor Create();override; destructor Destroy();override; - function GetPropertyManager():IPropertyManager; - procedure SendAndReceive(ARequest,AResponse:TStream); - Published + procedure SendAndReceive(ARequest,AResponse:TStream); override; + published property ContentType : string Read FContentType Write FContentType; property Address : string Read GetAddress Write SetAddress; property ProxyServer : string Read GetProxyServer Write SetProxyServer; @@ -65,7 +62,6 @@ Type property Format : string read FFormat write FFormat; property ProtocolVersion : string read GetProtocolVersion write SetProtocolVersion; End; -{$M+} procedure INDY_RegisterHTTP_Transport(); @@ -164,25 +160,20 @@ end; constructor THTTPTransport.Create(); begin - FPropMngr := TPublishedPropertyManager.Create(Self); + inherited; FConnection := TidHttp.Create(Nil); end; destructor THTTPTransport.Destroy(); begin FreeAndNil(FConnection); - FPropMngr := Nil; inherited Destroy(); end; -function THTTPTransport.GetPropertyManager(): IPropertyManager; -begin - Result := FPropMngr; -end; - procedure THTTPTransport.SendAndReceive(ARequest, AResponse: TStream); -{$IFDEF WST_DBG} var + locTempStream, locTempRes : TMemoryStream; +{$IFDEF WST_DBG} s : TBinaryString; i : Int64; {$ENDIF WST_DBG} @@ -199,13 +190,35 @@ begin {$IFDEF WST_DBG} TMemoryStream(ARequest).SaveToFile('request.log'); {$ENDIF WST_DBG} - FConnection.Post(Address,ARequest, AResponse); + if not HasFilter() then begin + FConnection.Post(Address,ARequest, AResponse); + end else begin + locTempRes := nil; + locTempStream := TMemoryStream.Create(); + try + FilterInput(ARequest,locTempStream); +{$IFDEF WST_DBG} + TMemoryStream(locTempStream).SaveToFile('request.log.wire'); +{$ENDIF WST_DBG} + locTempRes := TMemoryStream.Create(); + FConnection.Post(Address,locTempStream,locTempRes); {$IFDEF WST_DBG} - i := AResponse.Size; - SetLength(s,i); - Move(TMemoryStream(AResponse).Memory^,s[1],i); - WriteLn('--------------------------------------------'); - WriteLn(s); + TMemoryStream(locTempRes).SaveToFile('response.log.wire'); + {$ENDIF WST_DBG} + FilterOutput(locTempRes,AResponse); + finally + locTempRes.Free(); + locTempStream.Free(); + end; + end; + {$IFDEF WST_DBG} + if IsConsole then begin + i := AResponse.Size; + SetLength(s,i); + Move(TMemoryStream(AResponse).Memory^,s[1],i); + WriteLn('--------------------------------------------'); + WriteLn(s); + end; TMemoryStream(AResponse).SaveToFile('response.log'); {$ENDIF WST_DBG} end; @@ -215,4 +228,5 @@ begin GetTransportRegistry().Register(sTRANSPORT_NAME,TSimpleItemFactory.Create(THTTPTransport) as IItemFactory); end; + end. diff --git a/wst/trunk/indy_tcp_protocol.pas b/wst/trunk/indy_tcp_protocol.pas index efaa4a050..acd877faf 100644 --- a/wst/trunk/indy_tcp_protocol.pas +++ b/wst/trunk/indy_tcp_protocol.pas @@ -17,10 +17,10 @@ interface uses Classes, SysUtils, - service_intf, imp_utils, base_service_intf, + service_intf, imp_utils, base_service_intf, client_utils, IdTCPClient; -//{$DEFINE WST_DBG} +{.$DEFINE WST_DBG} Const sTRANSPORT_NAME = 'TCP'; @@ -29,13 +29,11 @@ Type ETCPException = class(EServiceException) End; - -{$M+} + { TTCPTransport } - TTCPTransport = class(TSimpleFactoryItem,ITransport) + TTCPTransport = class(TBaseTransport,ITransport) Private FFormat : string; - FPropMngr : IPropertyManager; FConnection : TIdTCPClient; FContentType : string; FTarget: string; @@ -47,8 +45,7 @@ Type public constructor Create();override; destructor Destroy();override; - function GetPropertyManager():IPropertyManager; - procedure SendAndReceive(ARequest,AResponse:TStream); + procedure SendAndReceive(ARequest,AResponse:TStream); override; Published property Target : string Read FTarget Write FTarget; property ContentType : string Read FContentType Write FContentType; @@ -57,7 +54,6 @@ Type property DefaultTimeOut : Integer read FDefaultTimeOut write FDefaultTimeOut; property Format : string read FFormat write FFormat; End; -{$M+} procedure INDY_RegisterTCP_Transport(); @@ -91,7 +87,7 @@ end; constructor TTCPTransport.Create(); begin - FPropMngr := TPublishedPropertyManager.Create(Self); + inherited; FConnection := TIdTCPClient.Create(nil); //FConnection.ReadTimeout:=; FDefaultTimeOut := 90000; @@ -100,22 +96,21 @@ end; destructor TTCPTransport.Destroy(); begin FreeAndNil(FConnection); - FPropMngr := Nil; inherited Destroy(); end; -function TTCPTransport.GetPropertyManager(): IPropertyManager; -begin - Result := FPropMngr; -end; - procedure TTCPTransport.SendAndReceive(ARequest, AResponse: TStream); var wrtr : IDataStore; buffStream : TMemoryStream; binBuff : TByteDynArray; bufferLen : LongInt; + locTempStream : TMemoryStream; begin +{$IFDEF WST_DBG} + TMemoryStream(ARequest).SaveToFile('request.log'); +{$ENDIF WST_DBG} + locTempStream := nil; buffStream := TMemoryStream.Create(); try wrtr := CreateBinaryWriter(buffStream); @@ -123,9 +118,21 @@ begin wrtr.WriteAnsiStr(Target); wrtr.WriteAnsiStr(ContentType); wrtr.WriteAnsiStr(Self.Format); - SetLength(binBuff,ARequest.Size); - ARequest.Position := 0; - ARequest.Read(binBuff[0],Length(binBuff)); + if not HasFilter() then begin + SetLength(binBuff,ARequest.Size); + ARequest.Position := 0; + ARequest.Read(binBuff[0],Length(binBuff)); + end else begin + locTempStream := TMemoryStream.Create(); + FilterInput(ARequest,locTempStream); +{$IFDEF WST_DBG} + TMemoryStream(locTempStream).SaveToFile('request.log.wire'); +{$ENDIF WST_DBG} + SetLength(binBuff,locTempStream.Size); + locTempStream.Position := 0; + locTempStream.Read(binBuff[0],Length(binBuff)); + locTempStream.Size := 0; + end; wrtr.WriteBinary(binBuff); buffStream.Position := 0; wrtr.WriteInt32S(buffStream.Size-4); @@ -137,16 +144,30 @@ begin bufferLen := 0; bufferLen := FConnection.IOHandler.ReadLongInt(False); bufferLen := Reverse_32(bufferLen); - AResponse.Size := bufferLen; - if ( bufferLen > 0 ) then begin - AResponse.Position := 0; - FConnection.IOHandler.ReadStream(AResponse,bufferLen,False); + if not HasFilter() then begin + AResponse.Size := bufferLen; + if ( bufferLen > 0 ) then begin + AResponse.Position := 0; + FConnection.IOHandler.ReadStream(AResponse,bufferLen,False); + end; + end else begin + locTempStream.Size := bufferLen; + if ( bufferLen > 0 ) then begin + locTempStream.Position := 0; + FConnection.IOHandler.ReadStream(locTempStream,bufferLen,False); + {$IFDEF WST_DBG} + TMemoryStream(locTempStream).SaveToFile('response.log.wire'); + {$ENDIF WST_DBG} + FilterOutput(locTempStream,AResponse); + locTempStream.Size := 0; + end; end; AResponse.Position := 0; {$IFDEF WST_DBG} TMemoryStream(AResponse).SaveToFile('response.log'); {$ENDIF WST_DBG} finally + locTempStream.Free(); buffStream.Free(); end; end; diff --git a/wst/trunk/indy_tcp_server.pas b/wst/trunk/indy_tcp_server.pas index b53e55508..1cbc1b1c8 100644 --- a/wst/trunk/indy_tcp_server.pas +++ b/wst/trunk/indy_tcp_server.pas @@ -92,7 +92,7 @@ procedure TwstIndyTcpListener.Handle_OnExecute( var strBuff : TIdBytes; bufferLen : LongInt; - i, j, c : PtrInt; + i, c : PtrInt; begin Result := 0; bufferLen := 0; diff --git a/wst/trunk/logger_extension.pas b/wst/trunk/logger_extension.pas index 0c012eb1e..09af75b9b 100644 --- a/wst/trunk/logger_extension.pas +++ b/wst/trunk/logger_extension.pas @@ -23,6 +23,8 @@ type { TLoggerServiceExtension } TLoggerServiceExtension = class(TSimpleFactoryItem,IServiceExtension) + private + FPropertyManager : IPropertyManager; protected procedure TraceMessage(const AMsg : string);virtual; protected @@ -36,8 +38,9 @@ type - IFormatterResponse on "msAfterDeserialize", "msBeforeSerialize" } ); + function GetPropertyManager():IPropertyManager; end; - + implementation uses TypInfo; @@ -93,7 +96,14 @@ begin TraceMessage(Format('%sTimeStamp : %s; %s',[sLineBreak,DateTimeToStr(Now()),s])); end; +function TLoggerServiceExtension.GetPropertyManager: IPropertyManager; +begin + if ( FPropertyManager = nil ) then + FPropertyManager := TStoredPropertyManager.Create(); + Result := FPropertyManager; +end; + initialization GetServiceExtensionRegistry().Register('TLoggerServiceExtension',TSimpleItemFactory.Create(TLoggerServiceExtension) as IItemFactory); - + end. diff --git a/wst/trunk/server_filter_extension.pas b/wst/trunk/server_filter_extension.pas new file mode 100644 index 000000000..dc7a66009 --- /dev/null +++ b/wst/trunk/server_filter_extension.pas @@ -0,0 +1,232 @@ +{ + This file is part of the Web Service Toolkit + Copyright (c) 2010 by Inoussa OUEDRAOGO + + This file is provide under modified LGPL licence + ( the files COPYING.modifiedLGPL and COPYING.LGPL). + + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +} +{$INCLUDE wst_global.inc} +unit server_filter_extension; + +{.$DEFINE WST_DBG} + +interface + +uses + SysUtils, Classes, + wst_types, base_service_intf, server_service_intf, filter_intf; + +type + + { TFilterExtension } +{$TYPEINFO ON} + TFilterExtension = class(TSimpleFactoryItem,IServiceExtension) + private + FPropertyManager : IPropertyManager; + FFilter : IDataFilter; + function GetFilterString: string; + procedure SetFilterString(const Value: string); + private + procedure FilterInput(ASource, ADest : TStream); + procedure FilterOutput(ASource, ADest : TStream); + protected + procedure ProcessMessage( + const AMessageStage : TMessageStage; + ACallContext : ICallContext; + AMsgData : IInterface + { The "AMsgData" parameter actual type depends on the message state + on correspond to : + - IRequestBuffer on "msBeforeDeserialize" and "msAfterSerialize" + - IFormatterResponse on "msAfterDeserialize", "msBeforeSerialize" + } + ); + function GetPropertyManager():IPropertyManager; + public + constructor Create(); override; + published + property FilterString : string read GetFilterString write SetFilterString; + end; +{$TYPEINFO OFF} + +implementation +uses + TypInfo, imp_utils, wst_consts; + +{ TFilterExtension } + +procedure TFilterExtension.ProcessMessage( + const AMessageStage: TMessageStage; + ACallContext: ICallContext; + AMsgData: IInterface +); +var + rb : IRequestBuffer; + strm : TStream; + locStream : TMemoryStream; +begin + case AMessageStage of + msBeforeDeserialize : + begin + rb := AMsgData as IRequestBuffer; + strm := rb.GetContent(); +{$IFDEF WST_DBG} + TMemoryStream(strm).SaveToFile('req.log.wire'); +{$ENDIF WST_DBG} + locStream := TMemoryStream.Create(); + try + FilterOutput(strm,locStream); +{$IFDEF WST_DBG} + locStream.SaveToFile('req.log'); +{$ENDIF WST_DBG} + strm.Size := locStream.Size; + strm.Position := 0; + strm.CopyFrom(locStream,0); + finally + locStream.Free(); + end; + strm.Position := 0; + end; + msAfterSerialize : + begin + rb := AMsgData as IRequestBuffer; + strm := rb.GetResponse(); + locStream := TMemoryStream.Create(); + try + FilterInput(strm,locStream); + strm.Size := locStream.Size; + strm.Position := 0; + strm.CopyFrom(locStream,0); + finally + locStream.Free(); + end; + strm.Position := 0; + end; + end; +end; + +procedure TFilterExtension.FilterInput(ASource, ADest: TStream); +var + locInBuffer, locBuffer : TByteDynArray; + locOldPos : Int64; +begin + if ASource.InheritsFrom(TMemoryStream) then begin + locBuffer := FFilter.ExecuteInput(TMemoryStream(ASource).Memory^,ASource.Size); + end else begin + SetLength(locInBuffer,ASource.Size); + locOldPos := ASource.Position; + ASource.Position := 0; + try + ASource.Read(locInBuffer[0],Length(locInBuffer)); + finally + ASource.Position := locOldPos; + end; + locBuffer := FFilter.ExecuteInput(locInBuffer[0],Length(locInBuffer)); + end; + ADest.Size := Length(locBuffer); + ADest.Position := 0; + ADest.Write(locBuffer[0],Length(locBuffer)); + ADest.Position := 0; +end; + +procedure TFilterExtension.FilterOutput(ASource, ADest: TStream); +var + locInBuffer, locBuffer : TByteDynArray; + locOldPos : Int64; +begin + if ASource.InheritsFrom(TMemoryStream) then begin + locBuffer := FFilter.ExecuteOutput(TMemoryStream(ASource).Memory^,ASource.Size); + end else begin + SetLength(locInBuffer,ASource.Size); + locOldPos := ASource.Position; + ASource.Position := 0; + try + ASource.Read(locInBuffer[0],Length(locInBuffer)); + finally + ASource.Position := locOldPos; + end; + locBuffer := FFilter.ExecuteOutput(locInBuffer[0],Length(locInBuffer)); + end; + ADest.Size := Length(locBuffer); + ADest.Position := 0; + ADest.Write(locBuffer[0],Length(locBuffer)); + ADest.Position := 0; +end; + +constructor TFilterExtension.Create; +begin + inherited; + FPropertyManager := TPublishedPropertyManager.Create(Self) as IPropertyManager; +end; + +function TFilterExtension.GetPropertyManager: IPropertyManager; +begin + Result := FPropertyManager; +end; + +function TFilterExtension.GetFilterString: string; +var + locPM : IPropertyManager; + ls : TStringList; + locRes, s : string; + i : Integer; +begin + locRes := ''; + if ( FFilter <> nil ) then begin + locRes := FFilter.GetName(); + locPM := FFilter.GetPropertyManager(); + ls := TStringList.Create(); + try + if ( locPM.GetPropertyNames(ls) > 0 ) then begin + for i := 0 to Pred(ls.Count) do begin + s := ls[i]; + locRes := SysUtils.Format('%s,%s>%s',[locRes,s,locPM.GetProperty(s)]); + end; + end; + finally + ls.Free(); + end; + end; + Result := locRes; +end; + +procedure TFilterExtension.SetFilterString(const Value: string); +var + locBuffer, locName, locValue : string; + locPM : IPropertyManager; + locFilterManager : IDataFilterRegistry; + locFilter : IDataFilter; +begin + locBuffer := Value; + if IsStrEmpty(locBuffer) then begin + FFilter := nil; + Exit; + end; + + //The filter name + locName := Trim(GetToken(locBuffer,',')); + locFilterManager := GetDataFilterRegistry(); + if not locFilterManager.Find(locName,locFilter) then + raise EServiceExtensionException.CreateFmt(SERR_DataFilterNotFound,[locName]); + locPM := locFilter.GetPropertyManager(); + while True do begin + locName := GetToken(locBuffer,'>'); + if IsStrEmpty(locName) then + Break; + locValue := GetToken(locBuffer,','); + locPM.SetProperty(locName,locValue); + end; + FFilter := locFilter; +end; + +initialization + GetServiceExtensionRegistry().Register( + 'TFilterExtension', + TSimpleItemFactory.Create(TFilterExtension) as IItemFactory + ); + +end. diff --git a/wst/trunk/server_service_intf.pas b/wst/trunk/server_service_intf.pas index 4b4e1d8d0..90b2c9fd5 100644 --- a/wst/trunk/server_service_intf.pas +++ b/wst/trunk/server_service_intf.pas @@ -22,7 +22,8 @@ uses const sREMOTE_IP = 'RemoteIP'; sREMOTE_PORT = 'RemotePort'; - + sSERVICES_EXTENSIONS = 'extensions'; + type IRequestBuffer = interface; @@ -73,6 +74,7 @@ type - IFormatterResponse on "msAfterDeserialize", "msBeforeSerialize" } ); + function GetPropertyManager():IPropertyManager; end; IServiceExtensionRegistry = Interface @@ -99,10 +101,14 @@ type ['{23A745BC-5F63-404D-BF53-55A6E64DE5BE}'] procedure RegisterExtension( const AExtensionList : array of string - ); + ); overload; function GetExtension( out AExtensionList : string ) : Boolean; + procedure RegisterExtension( + const AExtension : string; + const AInitString : string + ); overload; end; IServiceImplementationRegistry = Interface @@ -198,10 +204,14 @@ type procedure ReleaseInstance(const AInstance : IInterface);override; procedure RegisterExtension( const AExtensionList : array of string - ); + ); overload; function GetExtension( out AExtensionList : string ) : Boolean; + procedure RegisterExtension( + const AExtension : string; + const AInitString : string + ); overload; end; @@ -539,14 +549,16 @@ procedure TBaseServiceBinder.DoProcessMessage( AMsgData : IInterface ); var - s : string; + s, extInitString : string; ls : TStringList; i : Integer; exreg : IServiceExtensionRegistry; se : IServiceExtension; + pm : IPropertyManager; begin exreg := GetServiceExtensionRegistry(); if FImplementationFactory.GetExtension(s) then begin + pm := FImplementationFactory.GetPropertyManager(sSERVICES_EXTENSIONS,True); ls := TStringList.Create(); try ls.QuoteChar := #0; @@ -555,8 +567,12 @@ begin for i := 0 to Pred(ls.Count) do begin s := ls[i]; se := exreg.Find(s); - if Assigned(se) then + if Assigned(se) then begin + extInitString := pm.GetProperty(s); + if ( Length(extInitString) > 0 ) then + se.GetPropertyManager().SetProperties(extInitString); se.ProcessMessage(AMessageStage,ACallContext,AMsgData); + end; end; finally ls.Free(); @@ -700,7 +716,8 @@ end; { TImplementationFactory } -const sSERVICES_EXTENSIONS = 'extensions';sLIST = 'list'; +const + sLIST = 'list'; procedure TImplementationFactory.ReleaseInstance(const AInstance : IInterface); var @@ -720,25 +737,54 @@ procedure TImplementationFactory.RegisterExtension( const AExtensionList : array of string ); var - pmngr : IPropertyManager; i : Integer; - strBuffer, s : string; begin if ( Length(AExtensionList) > 0 ) then begin - pmngr := GetPropertyManager(sSERVICES_EXTENSIONS,True); - strBuffer := ''; - for i := Low(AExtensionList) to High(AExtensionList) do begin - s := Trim(AExtensionList[i]); - if ( Length(s) > 0 ) then - strBuffer := strBuffer + ';' + s; + for i := Low(AExtensionList) to High(AExtensionList) do + RegisterExtension(AExtensionList[i],''); + end; +end; + +procedure TImplementationFactory.RegisterExtension( + const AExtension : string; + const AInitString : string +); + + function IsIn(const AList, AItem : string) : Boolean; + var + ls : TStringList; + begin + ls := TStringList.Create(); + try + ls.QuoteChar := #0; + ls.Delimiter := PROP_LIST_DELIMITER; + ls.DelimitedText := AList; + Result := ( ls.IndexOf(AItem) >= 0 ); + finally + ls.Free(); end; - if ( Length(strBuffer) > 0 ) then begin - s:= Trim(pmngr.GetProperty(sLIST)); + end; + +var + pmngr : IPropertyManager; + strBuffer, s : string; + wasExistent : Boolean; +begin + strBuffer := Trim(AExtension); + if ( Length(strBuffer) > 0 ) then begin + pmngr := GetPropertyManager(sSERVICES_EXTENSIONS,True); + s := Trim(pmngr.GetProperty(sLIST)); + wasExistent := IsIn(s,strBuffer); + if ( Length(s) = 0 ) or ( not wasExistent ) then begin if ( Length(s) = 0 ) then - Delete(strBuffer,1,1); - s := s + strBuffer; + s := strBuffer + else + s := Format('%s;%s',[s,strBuffer]); pmngr.SetProperty(sLIST,s); end; + s := Trim(AInitString); + if wasExistent or ( Length(s) > 0 ) then + pmngr.SetProperty(strBuffer,s); end; end; diff --git a/wst/trunk/synapse_http_protocol.pas b/wst/trunk/synapse_http_protocol.pas index c960f8772..04273a2ec 100644 --- a/wst/trunk/synapse_http_protocol.pas +++ b/wst/trunk/synapse_http_protocol.pas @@ -13,7 +13,7 @@ {$INCLUDE wst_global.inc} unit synapse_http_protocol; -//{$DEFINE WST_DBG} +{$DEFINE WST_DBG} interface diff --git a/wst/trunk/wst_consts.pas b/wst/trunk/wst_consts.pas index 0cbbc8883..32dd9e02b 100644 --- a/wst/trunk/wst_consts.pas +++ b/wst/trunk/wst_consts.pas @@ -19,9 +19,10 @@ interface const sWST_SIGNATURE = 'WST_METADATA_0.6'; -resourcestring - SERR_CannotMakeInternalSymbolName ='Unable to make an internal symbol Name from "%s".'; +resourcestring + SERR_CannotMakeInternalSymbolName ='Unable to make an internal symbol Name from "%s".'; SERR_CannotResolveNamespace = 'Unable to resolve this namespace : "%s".'; + SERR_DataFilterNotFound = 'Data Filter not found : "%s".'; SERR_DuplicateBindingName = 'Duplicated binding : "%s".'; SERR_ExpectingRemotableObjectClass = 'Expecting remotable object class but found "%s".'; SERR_FailedTransportRequest = '%s Request to %s failed.';