+Delphi : QWord = UInt64 for CompilerVersion > 16.0

+THeaderBlockProxy :
  This class is used as a wrapper to allow a TBaseRemotable instance to be sent and received as a header block
+ICallContext.AddHeader() : 
  Overload to support classes that do not inherit from THeaderBlock
+TTypeRegistryItem.AddExternalSynonym(), TTypeRegistryItem.IsExternalSynonym()
  Usefull when a xsd defines a complex type and a "element" which type is the complex one.
+TTypeRegistry.FindByDeclaredName():
  Add an option to include the external synonyms in the search

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@744 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
inoussa
2009-03-18 15:53:10 +00:00
parent 3affd43c12
commit d2abf9846b
7 changed files with 666 additions and 36 deletions

View File

@ -123,7 +123,12 @@ type
function AddHeader(
const AHeader : THeaderBlock;
const AKeepOwnership : Boolean
):Integer;
):Integer;overload;
function AddHeader(
const AHeader : TBaseRemotable;
const AKeepOwnership : Boolean;
const AName : string = ''
):Integer;overload;
function GetHeaderCount(const ADirections : THeaderDirections):Integer;
function GetHeader(const AIndex : Integer) : THeaderBlock;
procedure ClearHeaders(const ADirection : THeaderDirection);
@ -228,7 +233,12 @@ type
function AddHeader(
const AHeader : THeaderBlock;
const AKeepOwnership : Boolean
):Integer;
):Integer;overload;
function AddHeader(
const AHeader : TBaseRemotable;
const AKeepOwnership : Boolean;
const AName : string = ''
):Integer;overload;
function GetHeaderCount(const ADirections : THeaderDirections):Integer;
function GetHeader(const AIndex : Integer) : THeaderBlock;
procedure ClearHeaders(const ADirection : THeaderDirection);
@ -758,12 +768,18 @@ type
private
FDirection: THeaderDirection;
FmustUnderstand: Integer;
FName: string;
FUnderstood: Boolean;
private
function HasmustUnderstand: boolean;
procedure SetmustUnderstand(const AValue: Integer);
protected
function GetName: string; virtual;
procedure SetName(const AValue: string); virtual;
public
property Direction : THeaderDirection read FDirection write FDirection;
property Understood : Boolean read FUnderstood write FUnderstood;
property Name : string read GetName write SetName;
published
property mustUnderstand : Integer read FmustUnderstand write SetmustUnderstand stored HasmustUnderstand;
end;
@ -791,6 +807,39 @@ type
property Value : string read FValue write FValue;
end;
{ THeaderBlockProxy
This class is used as a wrapper to allow a TBaseRemotable instance to be
sent and received as a header block.
}
THeaderBlockProxy = class(THeaderBlock)
private
FActualObject: TBaseRemotable;
FOwnObject: Boolean;
FNameSet : Boolean;
private
procedure SetActualObject(const AValue: TBaseRemotable);
protected
function GetName : string; override;
procedure SetName(const AValue: string); override;
public
destructor Destroy(); override;
class procedure Save(
AObject : TBaseRemotable;
AStore : IFormatterBase;
const AName : string;
const ATypeInfo : PTypeInfo
);override;
class procedure Load(
var AObject : TObject;
AStore : IFormatterBase;
var AName : string;
const ATypeInfo : PTypeInfo
);override;
property ActualObject : TBaseRemotable read FActualObject write SetActualObject;
property OwnObject : Boolean read FOwnObject write FOwnObject;
end;
{ TObjectCollectionRemotable
An implementation for array handling. The array items are "owned" by
this class instance, so one has not to free them.
@ -1434,7 +1483,8 @@ type
FNameSpace: string;
FDeclaredName : string;
FOptions: TTypeRegistryItemOptions;
FSynonymTable : TStrings;
FPascalSynonyms : TStrings;
FExternalSynonyms : TStrings;
FExternalNames : TStrings;
FInternalNames : TStrings;
private
@ -1448,7 +1498,9 @@ type
);virtual;
destructor Destroy();override;
function AddPascalSynonym(const ASynonym : string):TTypeRegistryItem;
function AddExternalSynonym(const ASynonym : string):TTypeRegistryItem;
function IsSynonym(const APascalTypeName : string):Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
function IsExternalSynonym(const AExternalName : string):Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
procedure RegisterExternalPropertyName(const APropName, AExtPropName : string);
function GetExternalPropertyName(const APropName : string) : string;{$IFDEF USE_INLINE}inline;{$ENDIF}
@ -1464,6 +1516,9 @@ type
property Options : TTypeRegistryItemOptions read FOptions write FOptions;
end;
TTypeRegistrySearchOption = ( trsoIncludeExternalSynonyms );
TTypeRegistrySearchOptions = set of TTypeRegistrySearchOption;
{ TTypeRegistry }
TTypeRegistry = class
@ -1491,7 +1546,11 @@ type
):TTypeRegistryItem;
function Find(ATypeInfo : PTypeInfo; Const AExact : Boolean):TTypeRegistryItem;overload;
function Find(const APascalTypeName : string):TTypeRegistryItem;overload;
function FindByDeclaredName(const ATypeName,ANameSpace : string):TTypeRegistryItem;
function FindByDeclaredName(
const ATypeName,
ANameSpace : string;
const AOptions : TTypeRegistrySearchOptions = []
) : TTypeRegistryItem;
Property Count : Integer Read GetCount;
Property Item[Index:Integer] : TTypeRegistryItem Read GetItemByIndex;default;
Property ItemByTypeInfo[Index:PTypeInfo] : TTypeRegistryItem Read GetItemByTypeInfo;
@ -1543,6 +1602,10 @@ const
const AField : shortstring;
const AVisibility : Boolean
);
function GetExternalName(
const ATypeInfo : PTypeInfo;
const ARegistry : TTypeRegistry = nil
) : string;
function IsStoredPropClass(AClass : TClass;PropInfo : PPropInfo) : TPropStoreType;
@ -1629,6 +1692,8 @@ begin
ri.Options := ri.Options + [trioNonVisibleToMetadataService];
ri := r.Register(sSOAP_ENV,TypeInfo(TSimpleContentHeaderBlock));
ri.Options := ri.Options + [trioNonVisibleToMetadataService];
ri := r.Register(sSOAP_ENV,TypeInfo(THeaderBlockProxy));
ri.Options := ri.Options + [trioNonVisibleToMetadataService];
r.Register(sWST_BASE_NS,TypeInfo(TArrayOfStringRemotable),'TArrayOfStringRemotable').AddPascalSynonym('TArrayOfStringRemotable');
@ -1683,6 +1748,25 @@ begin
r.Register(sXSD_NS,TypeInfo(TBase16StringExtRemotable),'hexBinary').AddPascalSynonym('TBase16StringExtRemotable');
end;
function GetExternalName(
const ATypeInfo : PTypeInfo;
const ARegistry : TTypeRegistry
) : string;
var
locReg : TTypeRegistry;
locRegItem : TTypeRegistryItem;
begin
if ( ARegistry = nil ) then
locReg := GetTypeRegistry()
else
locReg := ARegistry;
locRegItem := locReg.Find(ATypeInfo,False);
if ( locRegItem <> nil ) then
Result := locRegItem.DeclaredName
else
Result := ATypeInfo^.Name;
end;
procedure SetFieldSerializationVisibility(
const ATypeInfo : PTypeInfo; // must be tkRecord
const AField : shortstring;
@ -2766,6 +2850,35 @@ begin
AddObjectToFree(AHeader);
end;
function TSimpleCallContext.AddHeader(
const AHeader : TBaseRemotable;
const AKeepOwnership : Boolean;
const AName : string = ''
) : Integer;
var
locProxy : THeaderBlockProxy;
begin
if ( AHeader <> nil ) then begin
if AHeader.InheritsFrom(THeaderBlock) then begin
if not IsStrEmpty(AName) then
THeaderBlock(AHeader).Name := AName;
Result := AddHeader(THeaderBlock(AHeader),AKeepOwnership);
end else begin
locProxy := THeaderBlockProxy.Create();
locProxy.ActualObject := AHeader;
locProxy.OwnObject := AKeepOwnership;
if not IsStrEmpty(AName) then
locProxy.Name := AName;
Result := AddHeader(locProxy,True);
end;
end else begin
locProxy := THeaderBlockProxy.Create();
if not IsStrEmpty(AName) then
locProxy.Name := AName;
Result := AddHeader(locProxy,True);
end;
end;
function TSimpleCallContext.GetHeaderCount(const ADirections : THeaderDirections):Integer;
var
i : Integer;
@ -2885,7 +2998,8 @@ begin
FreeObjects();
FInternalNames.Free();
FExternalNames.Free();
FSynonymTable.Free();
FPascalSynonyms.Free();
FExternalSynonyms.Free();
inherited Destroy();
end;
@ -2894,19 +3008,39 @@ begin
Result := Self;
if AnsiSameText(ASynonym,DataType^.Name) then
Exit;
if not Assigned(FSynonymTable) then begin
FSynonymTable := TStringList.Create();
FSynonymTable.Add(FDataType^.Name);
if not Assigned(FPascalSynonyms) then begin
FPascalSynonyms := TStringList.Create();
FPascalSynonyms.Add(FDataType^.Name);
end;
if ( FSynonymTable.IndexOf(ASynonym) = -1 ) then
FSynonymTable.Add(AnsiLowerCase(ASynonym));
if ( FPascalSynonyms.IndexOf(ASynonym) = -1 ) then
FPascalSynonyms.Add(AnsiLowerCase(ASynonym));
end;
function TTypeRegistryItem.AddExternalSynonym(const ASynonym: string): TTypeRegistryItem;
begin
Result := Self;
if AnsiSameText(ASynonym,DataType^.Name) then
Exit;
if not Assigned(FExternalSynonyms) then begin
FExternalSynonyms := TStringList.Create();
FExternalSynonyms.Add(Self.DeclaredName);
end;
if ( FExternalSynonyms.IndexOf(ASynonym) = -1 ) then
FExternalSynonyms.Add(AnsiLowerCase(ASynonym));
end;
function TTypeRegistryItem.IsSynonym(const APascalTypeName: string): Boolean;
begin
Result := AnsiSameText(APascalTypeName,DataType^.Name);
if ( not Result ) and Assigned(FSynonymTable) then
Result := ( FSynonymTable.IndexOf(APascalTypeName) >= 0 ) ;
if ( not Result ) and Assigned(FPascalSynonyms) then
Result := ( FPascalSynonyms.IndexOf(APascalTypeName) >= 0 ) ;
end;
function TTypeRegistryItem.IsExternalSynonym(const AExternalName: string): Boolean;
begin
Result := AnsiSameText(AExternalName,Self.DeclaredName);
if ( not Result ) and Assigned(FExternalSynonyms) then
Result := ( FExternalSynonyms.IndexOf(AExternalName) >= 0 ) ;
end;
procedure TTypeRegistryItem.RegisterExternalPropertyName(const APropName,AExtPropName: string);
@ -3119,18 +3253,33 @@ end;
function TTypeRegistry.FindByDeclaredName(
const ATypeName,
ANameSpace : string
ANameSpace : string;
const AOptions : TTypeRegistrySearchOptions
): TTypeRegistryItem;
var
i, c : Integer;
begin
{ The external synonym is not tested in the first loop so that the declared
names are _first_ search for.
}
c := Count;
for i := 0 to Pred(c) do begin
Result := Item[i];
if AnsiSameText(ANameSpace,Result.NameSpace) and
AnsiSameText(ATypeName,Result.DeclaredName)
then
Exit;
if ( c > 0 ) then begin
for i := 0 to Pred(c) do begin
Result := Item[i];
if AnsiSameText(ANameSpace,Result.NameSpace) and
AnsiSameText(ATypeName,Result.DeclaredName)
then
Exit;
end;
if ( trsoIncludeExternalSynonyms in AOptions ) then begin
for i := 0 to Pred(c) do begin
Result := Item[i];
if AnsiSameText(ANameSpace,Result.NameSpace) and
Result.IsExternalSynonym(ATypeName)
then
Exit;
end;
end;
end;
Result := nil;
end;
@ -4429,6 +4578,13 @@ begin
Result := ( FmustUnderstand <> 0 );
end;
function THeaderBlock.GetName : string;
begin
if IsStrEmpty(FName) then
FName := GetExternalName(PTypeInfo(Self.ClassInfo));
Result := FName;
end;
procedure THeaderBlock.SetmustUnderstand(const AValue: Integer);
begin
if ( AValue <> 0 ) then
@ -4437,6 +4593,11 @@ begin
FmustUnderstand := 0;
end;
procedure THeaderBlock.SetName(const AValue: string);
begin
FName := AValue;
end;
{ TSimpleContentHeaderBlock }
class procedure TSimpleContentHeaderBlock.Save(
@ -4498,6 +4659,91 @@ begin
end;
end;
{ THeaderBlockProxy }
procedure THeaderBlockProxy.SetActualObject(const AValue: TBaseRemotable);
var
locObj : TObject;
begin
if ( FActualObject <> AValue ) then begin
if OwnObject and ( FActualObject <> nil ) then begin
locObj := FActualObject;
FActualObject := nil;
locObj.Free();
end;
FActualObject := AValue;
end;
end;
function THeaderBlockProxy.GetName : string;
begin
if FNameSet then
Result := inherited GetName()
else if ( ActualObject <> nil ) then
Result := GetExternalName(PTypeInfo(ActualObject.ClassInfo))
else
Result := Self.ClassName();
end;
procedure THeaderBlockProxy.SetName(const AValue: string);
begin
inherited SetName(AValue);
FNameSet := not IsStrEmpty(AValue);
end;
destructor THeaderBlockProxy.Destroy();
begin
if OwnObject then
ActualObject.Free();
inherited Destroy();
end;
class procedure THeaderBlockProxy.Save(
AObject : TBaseRemotable;
AStore : IFormatterBase;
const AName : string;
const ATypeInfo : PTypeInfo
);
var
locObj : THeaderBlockProxy;
begin
if ( AObject <> nil ) and AObject.InheritsFrom(THeaderBlockProxy) then begin
locObj := THeaderBlockProxy(AObject);
if ( locObj.ActualObject <> nil ) then
locObj.ActualObject.Save(
locObj.ActualObject,
AStore,
AName,
PTypeInfo(locObj.ActualObject.ClassInfo)
);
end;
end;
class procedure THeaderBlockProxy.Load(
var AObject : TObject;
AStore : IFormatterBase;
var AName : string;
const ATypeInfo : PTypeInfo
);
var
locObj : THeaderBlockProxy;
locActualObj : TObject;
begin
if ( AObject <> nil ) and AObject.InheritsFrom(THeaderBlockProxy) then begin
locObj := THeaderBlockProxy(AObject);
if ( locObj.ActualObject <> nil ) then
locActualObj := locObj.ActualObject;
locObj.ActualObject.Load(
locActualObj,
AStore,
AName,
PTypeInfo(locObj.ActualObject.ClassInfo)
);
if ( locObj.ActualObject <> locActualObj ) then
locObj.ActualObject := TBaseRemotable(locActualObj);
end;
end;
{ TStoredPropertyManager }
procedure TStoredPropertyManager.Error(Const AMsg: string);

View File

@ -441,6 +441,7 @@ type
resourcestring
SERR_NodeNotFoundByID = 'Node not found with this ID in the document : %s.';
SERR_ExpectingRemotableObjectClass = 'Expecting remotable object class but found %s.';
implementation
Uses {$IFDEF WST_DELPHI}XMLDoc,XMLIntf,{$ELSE}XMLWrite, XMLRead,wst_fpc_xml,{$ENDIF}
@ -1540,16 +1541,22 @@ function TSOAPBaseFormatter.ReadHeaders(ACallContext: ICallContext): Integer;
s := sXML_NS + ':' + nsSN;
if not FindAttributeByNameInNode(s,ANode,nsLN) then
nsLN := FindAttributeByNameInScope(s);
Result := GetTypeRegistry().FindByDeclaredName(Copy(ndName,Succ(j),MaxInt),nsLN);
Result := GetTypeRegistry().FindByDeclaredName(
Copy(ndName,Succ(j),MaxInt),
nsLN,
[trsoIncludeExternalSynonyms]
);
end;
var
i : Integer;
nd : TDOMElement;
typItm : TTypeRegistryItem;
tmpObj : THeaderBlock;
tmpHeader : THeaderBlock;
locName : string;
chdLst : TDOMNodeList;
typData : PTypeData;
tmpObj : TBaseRemotable;
begin
SetStyleAndEncoding(Document,Literal);
try
@ -1562,12 +1569,29 @@ begin
typItm := ExtractTypeInfo(nd);
if Assigned(typItm) then begin
if ( typItm.DataType^.Kind = tkClass ) then begin
tmpObj := nil;
tmpHeader := nil;
locName := nd.NodeName;
Get(typItm.DataType,locName,tmpObj);
if Assigned(tmpObj) then begin
tmpObj.Direction := hdIn;
ACallContext.AddHeader(tmpObj,True);
typData := GetTypeData(typItm.DataType);
if typData^.ClassType.InheritsFrom(THeaderBlock) then begin
Get(typItm.DataType,locName,tmpHeader);
if Assigned(tmpHeader) then begin
tmpHeader.Direction := hdIn;
ACallContext.AddHeader(tmpHeader,True);
tmpHeader.Name := ExtractNameFromQualifiedName(locName);
end;
end else if typData^.ClassType.InheritsFrom(TBaseRemotable) then begin
tmpObj := nil;
Get(typItm.DataType,locName,tmpObj);
if Assigned(tmpObj) then begin
tmpHeader := THeaderBlockProxy.Create();
THeaderBlockProxy(tmpHeader).ActualObject := tmpObj;
THeaderBlockProxy(tmpHeader).OwnObject := True;
tmpHeader.Direction := hdIn;
ACallContext.AddHeader(tmpHeader,True);
tmpHeader.Name := ExtractNameFromQualifiedName(locName);
end;
end else begin
Error(SERR_ExpectingRemotableObjectClass,[typItm.DataType^.Name]);
end;
end;
end;
@ -1596,7 +1620,8 @@ begin
h := ACallContext.GetHeader(i);
if ( h.Direction = hdOut ) then begin
ptyp := PTypeInfo(h.ClassInfo);
Put(GetTypeRegistry().ItemByTypeInfo[ptyp].DeclaredName,ptyp,h);
//Put(GetTypeRegistry().ItemByTypeInfo[ptyp].DeclaredName,ptyp,h);
Put(h.Name,ptyp,h);
end;
end;
finally

View File

@ -46,6 +46,7 @@ Type
function IsStrEmpty(Const AStr:ShortString):Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}overload;
function GetToken(var ABuffer : string; const ADelimiter : string): string;
function ExtractOptionName(const ACompleteName : string):string;
function ExtractNameFromQualifiedName(const AQualifiedName : string; const ASeparator : Char = ':') : string;
function TranslateDotToDecimalSeperator(const Value: string) : string;
function wst_FormatFloat(
const ATypeInfo : PTypeInfo;
@ -101,6 +102,16 @@ begin
Result := Trim(Result);
end;
function ExtractNameFromQualifiedName(const AQualifiedName : string; const ASeparator : Char) : string;
var
sepPos : Integer;
begin
sepPos := Pos(ASeparator,AQualifiedName);
if ( sepPos <= 0 ) then
sepPos := 0;
Result := Copy(AQualifiedName,(sepPos + 1),Length(AQualifiedName));
end;
function TranslateDotToDecimalSeperator(const Value: string) : string;
var
i : PtrInt;

View File

@ -19,10 +19,7 @@ interface
uses
Classes, SysUtils, TypInfo, Contnrs,
base_service_intf;
{$INCLUDE wst.inc}
{$INCLUDE wst_delphi.inc}
base_service_intf, wst_types;
Const
sTARGET = 'target';
@ -99,7 +96,12 @@ Type
function AddHeader(
const AHeader : THeaderBlock;
const AKeepOwnership : Boolean
):Integer;
):Integer;overload;
function AddHeader(
const AHeader : TBaseRemotable;
const AKeepOwnership : Boolean;
const AName : string = ''
):Integer;overload;
function GetHeaderCount(const ADirections : THeaderDirections):Integer;
function GetHeader(const AIndex : Integer) : THeaderBlock;
// ---- END >> ICallContext implementation ----
@ -267,6 +269,15 @@ begin
Result := FCallContext.AddHeader(AHeader,AKeepOwnership);
end;
function TBaseProxy.AddHeader(
const AHeader : TBaseRemotable;
const AKeepOwnership : Boolean;
const AName : string = ''
): Integer;
begin
Result := FCallContext.AddHeader(AHeader,AKeepOwnership,AName);
end;
function TBaseProxy.GetHeaderCount(const ADirections : THeaderDirections):Integer;
begin
Result := FCallContext.GetHeaderCount(ADirections);

View File

@ -33,6 +33,28 @@ type
TSOAPTestEnum = ( steOne, steTwo, steThree, steFour );
{ TLoginInfos }
TLoginInfos = class(TBaseComplexRemotable)
private
FPassword: string;
FUserName: string;
published
property UserName : string read FUserName write FUserName;
property Password : string read FPassword write FPassword;
end;
{ THeaderProxyTestObject }
THeaderProxyTestObject = class(TBaseComplexRemotable)
private
FDestructionCount: PInteger;
procedure SetDestructionCount(const AValue: PInteger);
public
destructor Destroy(); override;
property DestructionCount : PInteger read FDestructionCount write SetDestructionCount;
end;
{ NBHeader }
NBHeader = class(THeaderBlock)
@ -130,9 +152,15 @@ type
TTest_SoapFormatterHeader = class(TTestCase)
published
procedure write_header_simple_content_1();
procedure write_header_simple_content_1_b();
procedure write_header_simple_content_2();
procedure read_header_simple_content_1();
procedure read_header_simple_content_2();
procedure write_header_proxy_header_block();
procedure write_header_proxy_header_block_name();
procedure read_header_proxy_header_block();
procedure read_header_proxy_header_block_name();
end;
THRefTestSession = class(TBaseComplexRemotable)
@ -151,6 +179,15 @@ type
procedure test_soap_href_id();
end;
{ TTest_THeaderBlockProxy }
TTest_THeaderBlockProxy = class(TTestCase)
published
procedure ActualObject;
procedure OwnObject_Destroy;
procedure OwnObject_SetActualObject;
end;
implementation
uses
object_serializer, server_service_soap, test_suite_utils, soap_formatter;
@ -489,6 +526,39 @@ begin
end;
end;
procedure TTest_SoapFormatterHeader.write_header_simple_content_1_b();
var
ser : IFormatterClient;
cc : ICallContext;
hdr : TSampleSimpleContentHeaderBlock_A;
locStream : TMemoryStream;
locDoc, locExistDoc : TXMLDocument;
begin
cc := TSimpleCallContext.Create();
hdr := TSampleSimpleContentHeaderBlock_A.Create();
cc.AddHeader(TBaseRemotable(hdr),True);
hdr.Direction := hdOut;
hdr.Value := 'sample header simple content value';
ser := soap_formatter.TSOAPFormatter.Create();
ser.BeginCall('test_proc','TestService',cc);
ser.EndScope();
locDoc := nil;
locExistDoc := nil;
locStream := TMemoryStream.Create();
try
ser.SaveToStream(locStream);
//locStream.SaveToFile(wstExpandLocalFileName('write_header_simple_content_1.xml'));
locStream.Position := 0;
ReadXMLFile(locDoc,locStream);
ReadXMLFile(locExistDoc,wstExpandLocalFileName(TestFilesPath + 'write_header_simple_content_1.xml'));
Check(CompareNodes(locExistDoc.DocumentElement,locDoc.DocumentElement),'generated document differs from the existent one.');
finally
ReleaseDomNode(locDoc);
ReleaseDomNode(locExistDoc);
locStream.Free();
end;
end;
procedure TTest_SoapFormatterHeader.write_header_simple_content_2();
var
ser : IFormatterClient;
@ -623,6 +693,175 @@ begin
end;
end;
procedure TTest_SoapFormatterHeader.write_header_proxy_header_block();
var
ser : IFormatterClient;
cc : ICallContext;
locLoginInfo : TLoginInfos;
locStream : TMemoryStream;
locDoc, locExistDoc : TXMLDocument;
begin
cc := TSimpleCallContext.Create();
locLoginInfo := TLoginInfos.Create();
locLoginInfo.UserName := 'Inoussa-wst';
locLoginInfo.Password := 'sample password';
cc.AddHeader(locLoginInfo,True);
ser := soap_formatter.TSOAPFormatter.Create();
ser.BeginCall('test_proc','TestService',cc);
ser.EndScope();
locDoc := nil;
locExistDoc := nil;
locStream := TMemoryStream.Create();
try
ser.SaveToStream(locStream);
locStream.SaveToFile(wstExpandLocalFileName('write_header_proxy_header_block.xml'));
locStream.Position := 0;
ReadXMLFile(locDoc,locStream);
ReadXMLFile(locExistDoc,wstExpandLocalFileName(TestFilesPath + 'write_header_proxy_header_block.xml'));
Check(CompareNodes(locExistDoc.DocumentElement,locDoc.DocumentElement),'generated document differs from the existent one.');
finally
ReleaseDomNode(locDoc);
ReleaseDomNode(locExistDoc);
locStream.Free();
end;
end;
procedure TTest_SoapFormatterHeader.write_header_proxy_header_block_name();
var
ser : IFormatterClient;
cc : ICallContext;
locLoginInfo : TLoginInfos;
locStream : TMemoryStream;
locDoc, locExistDoc : TXMLDocument;
begin
cc := TSimpleCallContext.Create();
locLoginInfo := TLoginInfos.Create();
locLoginInfo.UserName := 'Inoussa-wst';
locLoginInfo.Password := 'sample password';
cc.AddHeader(locLoginInfo,True,'NamedLoginInfos');
ser := soap_formatter.TSOAPFormatter.Create();
ser.BeginCall('test_proc','TestService',cc);
ser.EndScope();
locDoc := nil;
locExistDoc := nil;
locStream := TMemoryStream.Create();
try
ser.SaveToStream(locStream);
locStream.SaveToFile(wstExpandLocalFileName('write_header_proxy_header_block_name.xml'));
locStream.Position := 0;
ReadXMLFile(locDoc,locStream);
ReadXMLFile(locExistDoc,wstExpandLocalFileName(TestFilesPath + 'write_header_proxy_header_block_name.xml'));
Check(CompareNodes(locExistDoc.DocumentElement,locDoc.DocumentElement),'generated document differs from the existent one.');
finally
ReleaseDomNode(locDoc);
ReleaseDomNode(locExistDoc);
locStream.Free();
end;
end;
procedure TTest_SoapFormatterHeader.read_header_proxy_header_block();
const
XML_SOURCE =
'<?xml version="1.0"?>' + sLineBreak +
'<SOAP-ENV:Envelope ' + sLineBreak +
' xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' + sLineBreak +
' xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" ' + sLineBreak +
' xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" ' + sLineBreak +
' xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">' + sLineBreak +
' <SOAP-ENV:Header xmlns:ns1="soap.test.namespace">' + sLineBreak +
' <ns1:LoginInfos >' + sLineBreak +
' <ns1:UserName>Inoussa-wst</ns1:UserName>' + sLineBreak +
' <ns1:Password>sample password</ns1:Password>' + sLineBreak +
' </ns1:LoginInfos>' + sLineBreak +
' </SOAP-ENV:Header>' + sLineBreak +
' <SOAP-ENV:Body>' + sLineBreak +
' <ns2:test_proc xmlns:ns2="TestService"/>' + sLineBreak +
' </SOAP-ENV:Body>' + sLineBreak +
'</SOAP-ENV:Envelope>';
var
f : IFormatterClient;
strm : TMemoryStream;
strBuffer : ansistring;
cctx : ICallContext;
hdr : THeaderBlockProxy;
actualHeader : TLoginInfos;
begin
f := soap_formatter.TSOAPFormatter.Create() as IFormatterClient;
strm := TMemoryStream.Create();
try
strBuffer := XML_SOURCE;
strm.Write(strBuffer[1],Length(strBuffer));
strm.Position := 0;
f.LoadFromStream(strm);
cctx := TSimpleCallContext.Create() as ICallContext;
f.BeginCallRead(cctx);
CheckEquals(0,cctx.GetHeaderCount([hdOut]),'Ouput header count');
CheckEquals(1,cctx.GetHeaderCount([hdIn]),'Input header count');
CheckIs(cctx.GetHeader(0),THeaderBlockProxy);
hdr := THeaderBlockProxy(cctx.GetHeader(0));
CheckIs(hdr.ActualObject,TLoginInfos);
actualHeader := TLoginInfos(hdr.ActualObject);
//CheckEquals(1,hdr.mustUnderstand,'mustUnderstand');
CheckEquals('LoginInfos',hdr.Name,'Name');
CheckEquals('Inoussa-wst',actualHeader.UserName,'UserName');
CheckEquals('sample password',actualHeader.Password,'Password');
f.EndScopeRead();
finally
FreeAndNil(strm);
end;
end;
procedure TTest_SoapFormatterHeader.read_header_proxy_header_block_name();
const
XML_SOURCE =
'<?xml version="1.0"?>' + sLineBreak +
'<SOAP-ENV:Envelope ' + sLineBreak +
' xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' + sLineBreak +
' xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" ' + sLineBreak +
' xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" ' + sLineBreak +
' xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">' + sLineBreak +
' <SOAP-ENV:Header xmlns:ns1="soap.test.namespace">' + sLineBreak +
' <ns1:NamedLoginInfos >' + sLineBreak +
' <ns1:UserName>Inoussa-wst</ns1:UserName>' + sLineBreak +
' <ns1:Password>sample password</ns1:Password>' + sLineBreak +
' </ns1:NamedLoginInfos>' + sLineBreak +
' </SOAP-ENV:Header>' + sLineBreak +
' <SOAP-ENV:Body>' + sLineBreak +
' <ns2:test_proc xmlns:ns2="TestService"/>' + sLineBreak +
' </SOAP-ENV:Body>' + sLineBreak +
'</SOAP-ENV:Envelope>';
var
f : IFormatterClient;
strm : TMemoryStream;
strBuffer : ansistring;
cctx : ICallContext;
hdr : THeaderBlockProxy;
actualHeader : TLoginInfos;
begin
f := soap_formatter.TSOAPFormatter.Create() as IFormatterClient;
strm := TMemoryStream.Create();
try
strBuffer := XML_SOURCE;
strm.Write(strBuffer[1],Length(strBuffer));
strm.Position := 0;
f.LoadFromStream(strm);
cctx := TSimpleCallContext.Create() as ICallContext;
f.BeginCallRead(cctx);
CheckEquals(0,cctx.GetHeaderCount([hdOut]),'Ouput header count');
CheckEquals(1,cctx.GetHeaderCount([hdIn]),'Input header count');
CheckIs(cctx.GetHeader(0),THeaderBlockProxy);
hdr := THeaderBlockProxy(cctx.GetHeader(0));
CheckIs(hdr.ActualObject,TLoginInfos);
actualHeader := TLoginInfos(hdr.ActualObject);
CheckEquals('NamedLoginInfos',hdr.Name,'Name');
CheckEquals('Inoussa-wst',actualHeader.UserName,'UserName');
CheckEquals('sample password',actualHeader.Password,'Password');
f.EndScopeRead();
finally
FreeAndNil(strm);
end;
end;
{ TTest_SoapFormatterClient }
procedure TTest_SoapFormatterClient.test_soap_href_id();
@ -674,6 +913,92 @@ begin
end;
end;
{ THeaderProxyTestObject }
procedure THeaderProxyTestObject.SetDestructionCount(const AValue: PInteger);
begin
if ( FDestructionCount = AValue ) then
Exit;
FDestructionCount := AValue;
end;
destructor THeaderProxyTestObject.Destroy();
begin
if ( FDestructionCount <> nil ) then
Inc(FDestructionCount^);
inherited Destroy();
end;
{ TTest_THeaderBlockProxy }
procedure TTest_THeaderBlockProxy.ActualObject;
var
locObj : THeaderBlockProxy;
ao1, ao2 : THeaderProxyTestObject;
begin
ao1 := nil;
ao2 := nil;
locObj := THeaderBlockProxy.Create();
try
CheckNull(locObj.ActualObject);
CheckEquals(False, locObj.OwnObject);
ao1 := THeaderProxyTestObject.Create();
ao2 := THeaderProxyTestObject.Create();
locObj.ActualObject := ao1;
CheckSame(ao1, locObj.ActualObject);
locObj.ActualObject := ao2;
CheckSame(ao2,locObj.ActualObject);
locObj.ActualObject := nil;
CheckNull(locObj.ActualObject);
finally
locObj.Free();
ao1.Free();
ao2.Free();
end;
end;
procedure TTest_THeaderBlockProxy.OwnObject_Destroy;
var
locObj : THeaderBlockProxy;
ao1 : THeaderProxyTestObject;
locDestructionCount : Integer;
begin
locDestructionCount := 0;
ao1 := nil;
locObj := THeaderBlockProxy.Create();
ao1 := THeaderProxyTestObject.Create();
locObj.ActualObject := ao1;
locObj.OwnObject := True;
ao1.DestructionCount := @locDestructionCount;
locObj.Free();
CheckEquals(1,locDestructionCount);
end;
procedure TTest_THeaderBlockProxy.OwnObject_SetActualObject;
var
locObj : THeaderBlockProxy;
ao1, ao2 : THeaderProxyTestObject;
locDestructionCount : Integer;
begin
locDestructionCount := 0;
ao1 := nil;
locObj := THeaderBlockProxy.Create();
ao1 := THeaderProxyTestObject.Create();
ao1.DestructionCount := @locDestructionCount;
ao2 := THeaderProxyTestObject.Create();
ao2.DestructionCount := @locDestructionCount;
locObj.OwnObject := True;
locObj.ActualObject := ao1;
locObj.ActualObject := ao2;
CheckEquals(1,locDestructionCount);
locObj.ActualObject := ao2;
CheckEquals(1,locDestructionCount,'Setting the same value should not free the object.');
locObj.Free();
CheckEquals(2,locDestructionCount);
end;
initialization
GetTypeRegistry().Register(TSampleSimpleContentHeaderBlock_A.GetNameSpace(),TypeInfo(TSampleSimpleContentHeaderBlock_A));
@ -686,10 +1011,14 @@ initialization
GetTypeRegistry().Register(TNameSpaceC_Class.GetNameSpace(),TypeInfo(TNameSpaceC_Class));
GetTypeRegistry().Register(ns_soap_test,TypeInfo(TSOAPTestEnum));
GetTypeRegistry().Register('urn:WS_PlotjetIntfU',TypeInfo(THRefTestSession),'TSession');
GetTypeRegistry().Register(ns_soap_test,TypeInfo(TLoginInfos),'LoginInfos').AddExternalSynonym('NamedLoginInfos');
GetTypeRegistry().Register(ns_soap_test,TypeInfo(THeaderProxyTestObject));
RegisterTest('Serializer',TTest_SoapFormatterServerNameSpace.Suite);
RegisterTest('Serializer',TTest_SoapFormatterHeader.Suite);
RegisterTest('Serializer',TTest_SoapFormatterClient.Suite);
RegisterTest('Support',TTest_THeaderBlockProxy.Suite);
end.

View File

@ -1,6 +1,14 @@
{$IFNDEF FPC}
{$IFDEF DELPHI}
type
{$IFDEF CompilerVersion}
{$IF ( CompilerVersion > 16.0 )}
QWord = UInt64;
{$IFEND}
{$ENDIF CompilerVersion}
{$IF Not Declared(QWord) }
QWord = type Int64;
{$IFEND
}
DWORD = LongWord;
PtrInt = Integer;
PByteArray = ^ByteArray;
@ -8,4 +16,4 @@
PtrUInt = Cardinal;
SizeInt = Longint;
UnicodeChar = WideChar;
{$ENDIF}
{$ENDIF DELPHI}