home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Runimage / Delphi50 / Source / Internet / XMLBROKR.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1999-08-11  |  25.9 KB  |  894 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Borland Delphi Visual Component Library         }
  5. {                                                       }
  6. {       Copyright (c) 1999 Inprise Corporation          }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit XMLBrokr;
  11.  
  12. interface
  13.  
  14. uses Classes, HTTPApp, Db, DbClient, Provider,
  15.   WebComp, Masks, Midas;
  16.  
  17. type
  18.  
  19. { TXMLBroker }
  20.  
  21.   TRequestRecordsEvent = procedure (Sender: TObject; Request: TWebRequest;
  22.      out RecCount: Integer; var OwnerData: OleVariant; var Records: string) of object;
  23.   TRequestUpdateEvent = procedure (Sender: TObject; Request: TWebRequest;
  24.      Response: TWebResponse; var Handled: Boolean) of object;
  25.   TGetErrorResponseEvent = procedure (Sender: TObject; ErrorCount: Integer; XMLErrors: string; Request: TWebRequest;
  26.      Response: TWebResponse; var Handled: Boolean) of object;
  27.   TGetResponseEvent = procedure (Sender: TObject;Request: TWebRequest;
  28.      Response: TWebResponse; var Handled: Boolean) of object;
  29.  
  30.   TXMLParams = class(TParams)
  31.   protected
  32.     procedure AssignTo(Dest: TPersistent); override;
  33.   public
  34.     procedure AssignStrings(Value: TStrings);
  35.   end;
  36.  
  37.   TXMLOption = (xoQuote);
  38.   TXMLOptions = set of TXMLOption;
  39.  
  40.   TWebDispatch = class;
  41.  
  42.   TXMLBroker = class(TComponent, IWebDispatch)
  43.   private
  44.     FWebDispatch: TWebDispatch;
  45.     FAppServer: IAppServer;
  46.     FProviderName: string;
  47.     FRemoteServer: TCustomRemoteServer;
  48.     FParams: TXMLParams;
  49.     FMaxRecords: Integer;
  50.     FRequestRecords: TRequestRecordsEvent;
  51.     FBeforeDispatch: THTTPMethodEvent;
  52.     FAfterDispatch: THTTPMethodEvent;
  53.     FRequestUpdate: TRequestUpdateEvent;
  54.     FMaxErrors: Integer;
  55.     FReconcileProducer: TCustomContentProducer;
  56.     FGetResponse: TGetResponseEvent;
  57.     FGetErrorResponse: TGetErrorResponseEvent;
  58.     FErrors: string;
  59.     FErrorCount: Integer;
  60.     FNotify: TList;
  61.   protected
  62.     procedure AS_FetchParams;
  63.     function AS_GetRecords(Count: Integer; out RecsOut: Integer;
  64.       Options: Integer; const CommandText: WideString; Params: OleVariant; var OwnerData: OleVariant): OleVariant;
  65.     function AS_ApplyUpdates(Delta: OleVariant; MaxErrors: Integer;
  66.       out ErrorCount: Integer): OleVariant;
  67.     { IWebDispatch }
  68.     function DispatchEnabled: Boolean;
  69.     function DispatchMethodType: TMethodType;
  70.     function DispatchRequest(Sender: TObject; Request: TWebRequest; Response: TWebResponse): Boolean;
  71.     function DispatchMask: TMask;
  72.     function DispatchSubItems: IInterfaceList;
  73.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  74.     procedure SetWebDispatch(const Value: TWebDispatch);
  75.     function GetAppServer: IAppServer;
  76.     function GetHasAppServer: Boolean;
  77.     procedure SetAppServer(Value: IAppServer);
  78.     procedure SetProviderName(const Value: string);
  79.     procedure SetRemoteServer(Value: TCustomRemoteServer);
  80.     function GetConnected: Boolean;
  81.     procedure SetConnected(Value: Boolean);
  82.     procedure CheckInactive;
  83.     procedure SetParams(const Value: TXMLParams);
  84.     function GetErrorResponse(ErrorCount: Integer; XMLErrors: string;
  85.       Request: TWebRequest; Response: TWebResponse): Boolean;
  86.     function GetResponse(Request: TWebRequest;
  87.       Response: TWebResponse): Boolean;
  88.     function GetProducerName(Request: TWebRequest): string;
  89.     function GetRedirect(Request: TWebRequest): string;
  90.     procedure SendConnectEvent(Connecting: Boolean);
  91.     function GetNotify(Index: Integer): TObject;
  92.     function GetNotifyCount: Integer;
  93.     procedure SetReconcileProducer(const Value: TCustomContentProducer);
  94.   public
  95.     constructor Create(AOwner: TComponent); override;
  96.     destructor Destroy; override;
  97.     function GetXMLRecords(var RecsOut: Integer;
  98.       var OwnerData: OleVariant; XMLOptions: TXMLOptions): string;
  99.     function ApplyXMLUpdates(const Delta: string; out ErrorCount: Integer): string;
  100.     function GetDelta(Request: TWebRequest): string;
  101.     function GetErrors: string;
  102.     function GetErrorCount: Integer;
  103.     function HTMLSubmitFormName: string;
  104.     function SubmitFormVarName: string;
  105.     function RowSetVarName(Path: TStrings): string;
  106.     function MasterRowSetVarName(Path: TStrings): string;
  107.     property HasAppServer: Boolean read GetHasAppServer;
  108.     procedure SetProvider(Provider: TComponent);
  109.     property AppServer: IAppServer read GetAppServer write SetAppServer;
  110.     function RequestRecords(Sender: TObject; Request: TWebRequest; out RecCount: Integer;
  111.       var OwnerData: OleVariant; XMLOptions: TXMLOptions): string; virtual;
  112.     function RequestUpdate(Sender: TObject; Request: TWebRequest;
  113.       Response: TWebResponse): Boolean; virtual;
  114.     procedure FetchParams; virtual;
  115.     procedure AddNotify(ANotify: TObject);
  116.     procedure RemoveNotify(ANotify: TObject);
  117.     property Notify[Index: Integer]: TObject read GetNotify;
  118.     property NotifyCount: Integer read GetNotifyCount;
  119.   published
  120.     property Connected: Boolean read GetConnected write SetConnected stored False;
  121.     property MaxRecords: Integer read FMaxRecords write FMaxRecords default -1;
  122.     property MaxErrors: Integer read FMaxErrors write FMaxErrors default -1;
  123.     property Params: TXMLParams read FParams write SetParams;
  124.     property ProviderName: string read FProviderName write SetProviderName;
  125.     property RemoteServer: TCustomRemoteServer read FRemoteServer write SetRemoteServer;
  126.     property WebDispatch: TWebDispatch read FWebDispatch write SetWebDispatch;
  127.     property OnRequestRecords: TRequestRecordsEvent read FRequestRecords write FRequestRecords;
  128.     property OnRequestUpdate: TRequestUpdateEvent read FRequestUpdate write FRequestUpdate;
  129.     property BeforeDispatch: THTTPMethodEvent read FBeforeDispatch write FBeforeDispatch;
  130.     property AfterDispatch: THTTPMethodEvent read FAfterDispatch write FAfterDispatch;
  131.     property ReconcileProducer: TCustomContentProducer read FReconcileProducer write SetReconcileProducer;
  132.     property OnGetErrorResponse: TGetErrorResponseEvent read FGetErrorResponse write FGetErrorResponse;
  133.     property OnGetResponse: TGetResponseEvent read FGetResponse write FGetResponse;
  134.   end;
  135.  
  136.   TWebPathInfo = class;
  137.  
  138.   TWebDispatch = class(TPersistent)
  139.   private
  140.     FPathInfo: TWebPathInfo;
  141.     FMethodType: TMethodType;
  142.     FEnabled: Boolean;
  143.     function GetMask: TMask;
  144.   protected
  145.     procedure AssignTo(Dest: TPersistent); override;
  146.     procedure SetPathInfo(const Value: string);
  147.     function GetPathInfo: string;
  148.   public
  149.     constructor Create(AComponent: TComponent);
  150.     destructor Destroy; override;
  151.     property Mask: TMask read GetMask;
  152.   published
  153.     property Enabled: Boolean read FEnabled write FEnabled default True;
  154.     property MethodType: TMethodType read FMethodType write FMethodType default mtPost;
  155.     property PathInfo: string read GetPathInfo write SetPathInfo;
  156.   end;
  157.  
  158.   TWebPathInfo = class
  159.   private
  160.     FMask: TMask;
  161.     FMaskPathInfo: string;
  162.     FPathInfo: string;
  163.     FOwner: TComponent;
  164.     function GetMask: TMask;
  165.     function GetPathInfo: string;
  166.     procedure SetPathInfo(const Value: string);
  167.   public
  168.     constructor Create(AOwner: TComponent);
  169.     destructor Destroy; override;
  170.     property Mask: TMask read GetMask;
  171.     property PathInfo: string read GetPathInfo write SetPathInfo;
  172.   end;
  173.  
  174.   INotifyConnectionChange = interface
  175.   ['{0BC29A90-0EEC-11D3-AFED-00C04FB16EC3}']
  176.     procedure ConnectionChange(Sender: TComponent; Connected: Boolean);
  177.   end;
  178.  
  179. const
  180.   sProducer = 'PRODUCER';
  181.   sPostDelta = 'postdelta';
  182.   sRedirect = 'REDIRECT';
  183.  
  184. function FormatXML(const Value: string; XMLOptions: TXMLOptions): string;
  185.  
  186. implementation
  187.  
  188. uses Windows, Messages, DbConsts, MidConst, ActiveX, ComObj, WebConst, sysutils, DbWeb, Forms,
  189.   DsIntf, WbmConst;
  190.  
  191. { TLocalAppServer }
  192.  
  193. type
  194.  
  195.   TLocalAppServer = class(TInterfacedObject, IAppServer, ISupportErrorInfo)
  196.   private
  197.     FProvider: TCustomProvider;
  198.   protected
  199.     { IDispatch }
  200.     function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
  201.     function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
  202.     function GetIDsOfNames(const IID: TGUID; Names: Pointer;
  203.       NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
  204.     function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
  205.       Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
  206.     { IAppServer }
  207.     function AS_ApplyUpdates(const ProviderName: WideString; Delta: OleVariant; MaxErrors: Integer;
  208.                              out ErrorCount: Integer; var OwnerData: OleVariant): OleVariant; safecall;
  209.     function AS_GetRecords(const ProviderName: WideString; Count: Integer; out RecsOut: Integer;
  210.                            Options: Integer; const CommandText: WideString; var Params: OleVariant; 
  211.                            var OwnerData: OleVariant): OleVariant; safecall;
  212.     function AS_DataRequest(const ProviderName: WideString; Data: OleVariant): OleVariant; safecall;
  213.     function AS_GetProviderNames: OleVariant; safecall;
  214.     function AS_GetParams(const ProviderName: WideString; var OwnerData: OleVariant): OleVariant; safecall;
  215.     function AS_RowRequest(const ProviderName: WideString; Row: OleVariant; RequestType: Integer;
  216.                            var OwnerData: OleVariant): OleVariant; safecall;
  217.     procedure AS_Execute(const ProviderName: WideString; const CommandText: WideString; var Params: OleVariant;
  218.                          var OwnerData: OleVariant); safecall;
  219.     { ISupportErrorInfo }
  220.     function InterfaceSupportsErrorInfo(const iid: TIID): HResult; stdcall;
  221.   public
  222.     constructor Create(AProvider: TCustomProvider);
  223.     function SafeCallException(ExceptObject: TObject;
  224.       ExceptAddr: Pointer): HResult; override;
  225.   end;
  226.  
  227. { TLocalAppServer }
  228.  
  229. // Copied from dbclient
  230. constructor TLocalAppServer.Create(AProvider: TCustomProvider);
  231. begin
  232.   FProvider := AProvider;
  233. end;
  234.  
  235. function TLocalAppServer.GetTypeInfoCount(out Count: Integer): HResult;
  236. begin
  237.   Result := E_NOTIMPL;
  238. end;
  239.  
  240. function TLocalAppServer.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult;
  241. begin
  242.   Result := E_NOTIMPL;
  243. end;
  244.  
  245. function TLocalAppServer.GetIDsOfNames(const IID: TGUID; Names: Pointer;
  246.   NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
  247. begin
  248.   Result := E_NOTIMPL;
  249. end;
  250.  
  251. function TLocalAppServer.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
  252.   Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult;
  253. begin
  254.   Result := E_NOTIMPL;
  255. end;
  256.  
  257. function TLocalAppServer.AS_ApplyUpdates(const ProviderName: WideString;
  258.   Delta: OleVariant; MaxErrors: Integer; out ErrorCount: Integer;
  259.   var OwnerData: OleVariant): OleVariant;
  260. begin
  261.   Result := FProvider.ApplyUpdates(Delta, MaxErrors, ErrorCount, OwnerData);
  262. end;
  263.  
  264. function TLocalAppServer.AS_GetRecords(const ProviderName: WideString; Count: Integer;
  265.   out RecsOut: Integer; Options: Integer; const CommandText: WideString; var Params, OwnerData: OleVariant): OleVariant;
  266. begin
  267.   Result := FProvider.GetRecords(Count, RecsOut, Options, CommandText, Params, OwnerData);
  268. end;
  269.  
  270. function TLocalAppServer.AS_GetProviderNames: OleVariant;
  271. begin
  272.   Result := NULL;
  273. end;
  274.  
  275. function TLocalAppServer.AS_DataRequest(const ProviderName: WideString;
  276.   Data: OleVariant): OleVariant;
  277. begin
  278.   Result := FProvider.DataRequest(Data);
  279. end;
  280.  
  281. function TLocalAppServer.AS_GetParams(const ProviderName: WideString;
  282.   var OwnerData: OleVariant): OleVariant;
  283. begin
  284.   Result := FProvider.GetParams(OwnerData);
  285. end;
  286.  
  287. function TLocalAppServer.AS_RowRequest(const ProviderName: WideString;
  288.   Row: OleVariant; RequestType: Integer; var OwnerData: OleVariant): OleVariant;
  289. begin
  290.   Result := FProvider.RowRequest(Row, RequestType, OwnerData);
  291. end;
  292.  
  293. procedure TLocalAppServer.AS_Execute(const ProviderName: WideString;
  294.   const CommandText: WideString; var Params, OwnerData: OleVariant);
  295. begin
  296.   FProvider.Execute(CommandText, Params, OwnerData);
  297. end;
  298.  
  299. function TLocalAppServer.InterfaceSupportsErrorInfo(const iid: TIID): HResult;
  300. begin
  301.   if IsEqualGUID(IAppServer, iid) then
  302.     Result := S_OK else
  303.     Result := S_FALSE;
  304. end;
  305.  
  306. function TLocalAppServer.SafeCallException(ExceptObject: TObject;
  307.   ExceptAddr: Pointer): HResult;
  308. begin
  309.   Result := HandleSafeCallException(ExceptObject, ExceptAddr, IAppServer, '', '');
  310. end;
  311.  
  312. { TXMLBroker }
  313.  
  314. procedure TXMLBroker.SetRemoteServer(Value: TCustomRemoteServer);
  315. begin
  316.   if Value = FRemoteServer then Exit;
  317.   AppServer := nil;
  318.   if Assigned(Value) then
  319.   begin
  320.     CheckInactive;
  321.     Value.FreeNotification(Self);
  322.     FRemoteServer := Value;
  323.     SendConnectEvent(True);
  324.   end
  325.   else
  326.   begin
  327.     FRemoteServer := Value;
  328.     SendConnectEvent(False);
  329.   end;
  330. end;
  331.  
  332. constructor TXMLBroker.Create(AOwner: TComponent);
  333. begin
  334.   inherited Create(AOwner);
  335.   FWebDispatch := TWebDispatch.Create(Self);
  336.   FParams := TXMLParams.Create(Self);
  337.   FMaxRecords := -1;
  338.   FMaxErrors := -1;
  339.   FNotify := TList.Create;
  340. end;
  341.  
  342. destructor TXMLBroker.Destroy;
  343. begin
  344.   inherited Destroy;
  345.   FWebDispatch.Free;
  346.   SetRemoteServer(nil);
  347.   AppServer := nil;
  348.   FParams.Free;
  349.   FNotify.Free;
  350. end;
  351.  
  352. procedure TXMLBroker.CheckInactive;
  353. begin
  354.   if Connected then
  355.     if ([csUpdating, csDesigning] * ComponentState) <> [] then
  356.       Connected := False else
  357.       DatabaseError(SDataSetOpen, Self);
  358. end;
  359.  
  360. function TXMLBroker.GetAppServer: IAppServer;
  361. var
  362.   ProvComp: TComponent;
  363. begin
  364.   Result := nil;
  365.   if not HasAppServer then
  366.   begin
  367.     if ProviderName <> '' then
  368.       if Assigned(RemoteServer) then
  369.         RemoteServer.Connected := True
  370.       else
  371.       begin
  372.         if Assigned(Owner) then
  373.         begin
  374.           ProvComp := Owner.FindComponent(ProviderName);
  375.           if Assigned(ProvComp) and (ProvComp is TCustomProvider) then
  376.             FAppServer := TLocalAppServer.Create(TCustomProvider(ProvComp));
  377.         end;
  378.       end;
  379.     if not HasAppServer then
  380.       DatabaseError(SNoDataProvider, Self);
  381.   end;
  382.   if Assigned(FAppServer) then
  383.     Result := FAppServer
  384.   else if Assigned(RemoteServer) then
  385.     Result := RemoteServer.GetServer;
  386. end;
  387.  
  388. function TXMLBroker.GetHasAppServer: Boolean;
  389. begin
  390.   Result := Assigned(FAppServer) or
  391.     (Assigned(FRemoteServer) and FRemoteServer.Connected);
  392. end;
  393.  
  394. procedure TXMLBroker.SetAppServer(Value: IAppServer);
  395. begin
  396.   FAppServer := Value;
  397.   SendConnectEvent(FAppServer <> nil);
  398. end;
  399.  
  400. procedure TXMLBroker.SetProvider(Provider: TComponent);
  401. begin
  402.   if Provider is TCustomProvider then
  403.     AppServer := TLocalAppServer.Create(TCustomProvider(Provider));
  404. end;
  405.  
  406. procedure TXMLBroker.SetProviderName(const Value: string);
  407. begin
  408.   if Value = FProviderName then Exit;
  409.   if (Value <> '') then
  410.   begin
  411.     CheckInactive;
  412.     FProviderName := Value;
  413.     SendConnectEvent(True);
  414.   end
  415.   else
  416.   begin
  417.     FProviderName := Value;
  418.     SendConnectEvent(False);
  419.   end;
  420. end;
  421.  
  422. function TXMLBroker.AS_GetRecords(Count: Integer; out RecsOut: Integer;
  423.   Options: Integer; const CommandText: WideString; Params: OleVariant; var OwnerData: OleVariant): OleVariant;
  424. begin
  425.   Result := AppServer.AS_GetRecords(ProviderName, Count, RecsOut, Options, CommandText, Params, OwnerData);
  426.   UnPackParams(Params, Self.Params);
  427. end;
  428.  
  429. function FormatXML(const Value: string; XMLOptions: TXMLOptions): string;
  430. var
  431.   P: PChar;
  432. begin
  433.   Result := Value;
  434.   P := PChar(Value);
  435.   if (P[0] = '<') and (P[1] = '?') then
  436.   begin
  437.     P := StrPos(P, '?>');
  438.     if P <> nil then
  439.       Delete(Result, 1, (P - PChar(Value)) + 2);
  440.   end;
  441.   if xoQuote in XMLOptions then
  442.     Result := '''' + TrimRight(Result) + '''';
  443. end;
  444.  
  445. function TXMLBroker.GetXMLRecords(
  446.   var RecsOut: Integer; var OwnerData: OleVariant;
  447.   XMLOptions: TXMLOptions): string;
  448. var
  449.   ByteArray: OleVariant;
  450.   Options: TGetRecordOptions;
  451. begin
  452.   Options := [grMetaData, grXML, grReset];
  453.   RecsOut := 0;
  454.   ByteArray := AS_GetRecords(MaxRecords, RecsOut, Byte(Options), '', PackageParams(Params), OwnerData);
  455.   Result := FormatXML(VariantArrayToString(ByteArray),
  456.      XMLOptions);
  457. end;
  458.  
  459. function TXMLBroker.RequestRecords(Sender: TObject; Request: TWebRequest;
  460.   out RecCount: Integer; var OwnerData: OleVariant;
  461.   XMLOptions: TXMLOptions): string;
  462. begin
  463.   Result := '';
  464.   if Assigned(FRequestRecords) then
  465.     FRequestRecords(Sender, Request, RecCount, OwnerData, Result);
  466.   if Result = '' then
  467.     Result := GetXMLRecords(RecCount, OwnerData, XMLOptions);
  468. end;
  469.  
  470. procedure TXMLBroker.SetParams(const Value: TXMLParams);
  471. begin
  472.   FParams.Assign(Value);
  473. end;
  474.  
  475. //{$DEFINE DEBUG}
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489. function TXMLBroker.ApplyXMLUpdates(const Delta: string; out ErrorCount: Integer): string;
  490. var
  491.   XMLDelta: OleVariant;
  492.   XMLErrors: OleVariant;
  493. begin
  494.  
  495.  
  496.   XMLDelta := StringToVariantArray('<?xml version="1.0" standalone="yes"?>' + Delta);
  497.  
  498.  
  499.   if Delta = '' then
  500.     ErrorCount := 0
  501.   else
  502.     XMLErrors := AS_ApplyUpdates(XMLDelta, MaxErrors, ErrorCount);
  503.   if ErrorCount > 0 then
  504.   begin
  505.  
  506.  
  507.     Result := VariantArrayToString(XMLErrors)
  508.   end
  509.   else
  510.     Result := '';
  511. end;
  512.  
  513. function TXMLBroker.AS_ApplyUpdates(Delta: OleVariant; MaxErrors: Integer;
  514.   out ErrorCount: Integer): OleVariant;
  515. var
  516.   OwnerData: OleVariant;
  517. begin
  518.   Result := AppServer.AS_ApplyUpdates(ProviderName, Delta, MaxErrors, ErrorCount, OwnerData);
  519. end;
  520.  
  521. function TXMLBroker.GetConnected: Boolean;
  522. begin
  523.   Result := HasAppServer;
  524. end;
  525.  
  526. procedure TXMLBroker.SetConnected(Value: Boolean);
  527. begin
  528.   if HasAppServer <> Value then
  529.     if Value then
  530.       GetAppServer
  531.     else
  532.     begin
  533.       AppServer := nil;
  534.       if Assigned(RemoteServer) then
  535.         RemoteServer.Connected := False;
  536.     end;
  537. end;
  538.  
  539. function TXMLBroker.DispatchEnabled: Boolean;
  540. begin
  541.   Result := FWebDispatch.Enabled;
  542. end;
  543.  
  544. function TXMLBroker.DispatchMask: TMask;
  545. begin
  546.   Result := FWebDispatch.Mask;
  547.  
  548. end;
  549.  
  550. function TXMLBroker.DispatchMethodType: TMethodType;
  551. begin
  552.   Result := FWebDispatch.MethodType;
  553. end;
  554.  
  555. function TXMLBroker.DispatchRequest(Sender: TObject;
  556.   Request: TWebRequest; Response: TWebResponse): Boolean;
  557. begin
  558.   Result := False;
  559.   if Assigned(FBeforeDispatch) then
  560.     FBeforeDispatch(Self, Request, Response, Result);
  561.   if not Result then
  562.     Result := RequestUpdate(Sender, Request, Response);
  563.   if Assigned(FAfterDispatch) then
  564.     FAfterDispatch(Self, Request, Response, Result);
  565. end;
  566.  
  567. function TXMLBroker.RequestUpdate(Sender: TObject; Request: TWebRequest; Response: TWebResponse): Boolean;
  568. var
  569.   Delta: string;
  570.   ErrorCount: Integer;
  571.   XMLErrors: string;
  572. begin
  573.   Result := False;
  574.   if Assigned(FRequestUpdate) then
  575.     FRequestUpdate(Sender, Request, Response, Result);
  576.   if not Result then
  577.   begin
  578.     Delta := GetDelta(Request);
  579.     if Delta <> '' then
  580.       XMLErrors := ApplyXMLUpdates(Delta, ErrorCount)
  581.     else
  582.       ErrorCount := 0;
  583.     if ErrorCount > 0 then
  584.       Result := GetErrorResponse(ErrorCount, XMLErrors, Request, Response)
  585.     else
  586.       Result := GetResponse(Request, Response);
  587.   end;
  588. end;
  589.  
  590. function TXMLBroker.GetErrors: string;
  591. begin
  592.   Result := FErrors;
  593. end;
  594.  
  595. function TXMLBroker.GetErrorCount: integer;
  596. begin
  597.   Result := FErrorCount;
  598. end;
  599.  
  600. function TXMLBroker.GetErrorResponse(ErrorCount: Integer; XMLErrors: string;
  601.   Request: TWebRequest; Response: TWebResponse): Boolean;
  602. begin
  603.   Result := False;
  604.   FErrors := XMLErrors;
  605.   FErrorCount := ErrorCount;
  606.   try
  607.     if Assigned(FGetErrorResponse) then
  608.       FGetErrorResponse(Self, ErrorCount, XMLErrors, Request, Response, Result);
  609.     if (not Result) and Assigned(FReconcileProducer) then
  610.     begin
  611.       Response.Content := FReconcileProducer.Content;
  612.       Result := True;
  613.     end;
  614.   finally
  615.     FErrors := '';
  616.     FErrorCount := 0;
  617.   end;
  618.   if not Result then
  619.     raise Exception.CreateResFmt(@sApplyUpdatesError, [ErrorCount]);
  620. end;
  621.  
  622. function TXMLBroker.GetResponse(
  623.   Request: TWebRequest; Response: TWebResponse): Boolean;
  624. var
  625.   Producer: TComponent;
  626.   Redirect: string;
  627. begin
  628.   Result := False;
  629.   if Assigned(FGetResponse) then
  630.     FGetResponse(Self, Request, Response, Result);
  631.   if not Result then
  632.   begin
  633.     Redirect := GetRedirect(Request);
  634.     if Redirect <> '' then
  635.     begin
  636.       Response.SendRedirect(Redirect);
  637.       Result := True;
  638.     end;
  639.   end;
  640.   if not Result then
  641.   begin
  642.     Producer := Owner.FindComponent(GetProducerName(Request));
  643.     if Assigned(Producer) and (Producer is TCustomContentProducer) then
  644.     begin
  645.       Response.Content := TCustomContentProducer(Producer).Content;
  646.       Result := True;
  647.     end;
  648.   end;
  649. end;
  650.  
  651. function TXMLBroker.GetProducerName(Request: TWebRequest): string;
  652. begin
  653.   Result := Request.ContentFields.Values[SProducer];
  654. end;
  655.  
  656. function TXMLBroker.GetRedirect(Request: TWebRequest): string;
  657. begin
  658.   Result := Request.ContentFields.Values[SRedirect];
  659. end;
  660.  
  661. function TXMLBroker.GetDelta(Request: TWebRequest): string;
  662. begin
  663.   Result := Request.ContentFields.Values[SPostDelta];
  664. end;
  665.  
  666. function TXMLBroker.DispatchSubItems: IInterfaceList;
  667. begin
  668.   Result := nil;
  669. end;
  670.  
  671. procedure TXMLBroker.SetWebDispatch(const Value: TWebDispatch);
  672. begin
  673.   FWebDispatch.Assign(Value);
  674. end;
  675.  
  676. function TXMLBroker.HTMLSubmitFormName: string;
  677. begin
  678.   Result := Format('Submit_%s', [Name]);
  679. end;
  680.  
  681. function TXMLBroker.SubmitFormVarName: string;
  682. begin
  683.   Result := HTMLSubmitFormName;
  684. end;
  685.  
  686. procedure TXMLBroker.AS_FetchParams;
  687. var
  688.   OwnerData: OleVariant;
  689. begin
  690.   UnpackParams(AppServer.AS_GetParams(ProviderName, OwnerData), Params);
  691. end;
  692.  
  693. procedure TXMLBroker.FetchParams;
  694. begin
  695.   AS_FetchParams;
  696. end;
  697.  
  698. function TXMLBroker.RowSetVarName(Path: TStrings): string;
  699. var
  700.   I: Integer;
  701. begin
  702.   Result := Name;
  703.   if Assigned(Path) then
  704.     for I := Path.Count - 1 downto 0 do
  705.       Result := Format('%s_%s', [Result, Path[I]]);
  706.   Result := Format(ScriptRowSetVarName, [Result]);
  707. end;
  708.  
  709. function TXMLBroker.MasterRowSetVarName(Path: TStrings): string;
  710. var
  711.   I: Integer;
  712. begin
  713.   Result := Name;
  714.   if Assigned(Path) and (Path.Count > 1) then
  715.     for I := Path.Count - 2 downto 0 do
  716.       Result := Format('%s_%s', [Result, Path[I]]);
  717.   Result := Format(ScriptRowSetVarName, [Result]);
  718. end;
  719.  
  720. procedure TXMLBroker.AddNotify(ANotify: TObject);
  721. begin
  722.   FNotify.Add(ANotify);
  723. end;
  724.  
  725. procedure TXMLBroker.RemoveNotify(ANotify: TObject);
  726. begin
  727.   FNotify.Remove(ANotify);
  728. end;
  729.  
  730. function TXMLBroker.GetNotify(Index: Integer): TObject;
  731. begin
  732.   Result := FNotify[Index];
  733. end;
  734.  
  735. function TXMLBroker.GetNotifyCount: Integer;
  736. begin
  737.   Result := FNotify.Count;
  738. end;
  739.  
  740. procedure TXMLBroker.SendConnectEvent(Connecting: Boolean);
  741. var
  742.   I: Integer;
  743.   ConnectionChange: INotifyConnectionChange;
  744. begin
  745.   for I := 0 to NotifyCount - 1 do
  746.     if Notify[I].GetInterface(INotifyConnectionChange, ConnectionChange) then
  747.       ConnectionChange.ConnectionChange(Self, Connecting);
  748. end;
  749.  
  750. procedure TXMLBroker.SetReconcileProducer(
  751.   const Value: TCustomContentProducer);
  752. begin
  753.   if FReconcileProducer <> Value then
  754.   begin
  755.     FReconcileProducer := Value;
  756.     if Value <> nil then Value.FreeNotification(Self);
  757.   end;
  758. end;
  759.  
  760. procedure TXMLBroker.Notification(AComponent: TComponent;
  761.   Operation: TOperation);
  762. begin
  763.   inherited;
  764.   if (Operation = opRemove) then
  765.   begin
  766.     if AComponent = FReconcileProducer then
  767.       FReconcileProducer := nil
  768.     else if AComponent = FRemoteServer then
  769.       FRemoteServer := nil;
  770.   end;
  771. end;
  772.  
  773. { TXMLParams }
  774.  
  775. procedure TXMLParams.AssignStrings(Value: TStrings);
  776. var
  777.   ParamName: string;
  778.   Param: TParam;
  779.   I: Integer;
  780. begin
  781.   for I := 0 to Value.Count - 1 do
  782.   begin
  783.     ParamName := Value.Names[I];
  784.     Param := FindParam(ParamName);
  785.     if Assigned(Param) then
  786.       Param.Value := Value.Values[ParamName];
  787.   end;
  788. end;
  789.  
  790. procedure TXMLParams.AssignTo(Dest: TPersistent);
  791. begin
  792.   if Dest is TXMLParams then TXMLParams(Dest).Assign(Self)
  793.   else inherited AssignTo(Dest);
  794. end;
  795.  
  796. { TWebDispatch }
  797.  
  798. constructor TWebDispatch.Create(AComponent: TComponent);
  799. begin
  800.   inherited Create;
  801.   FEnabled := True;
  802.   FMethodType := mtPost;
  803.   FPathInfo := TWebPathInfo.Create(AComponent);
  804. end;
  805.  
  806. destructor TWebDispatch.Destroy;
  807. begin
  808.   inherited;
  809.   FPathInfo.Free;
  810. end;
  811.  
  812. procedure TWebDispatch.SetPathInfo(const Value: string);
  813. begin
  814.   FPathInfo.PathInfo := Value;
  815. end;
  816.  
  817. procedure TWebDispatch.AssignTo(Dest: TPersistent);
  818. begin
  819.   if Dest is TWebDispatch then
  820.     with TWebDispatch(Dest) do
  821.     begin
  822.       PathInfo := Self.PathInfo;
  823.       MethodType := Self.MethodType;
  824.       Enabled := Self.Enabled;
  825.     end else inherited AssignTo(Dest);
  826. end;
  827.  
  828. function TWebDispatch.GetPathInfo: string;
  829. begin
  830.   Result := FPathInfo.PathInfo;
  831. end;
  832.  
  833. function TWebDispatch.GetMask: TMask;
  834. begin
  835.   Result := FPathInfo.Mask;
  836. end;
  837.  
  838. { TWebPathInfo }
  839.  
  840. constructor TWebPathInfo.Create(AOwner: TComponent);
  841. begin
  842.   FMaskPathInfo := '';
  843.   FMask := TMask.Create(FMaskPathInfo);
  844.   FOwner := AOwner;
  845. end;
  846.  
  847. destructor TWebPathInfo.Destroy;
  848. begin
  849.   FMask.Free;
  850.   inherited;
  851. end;
  852.  
  853. function TWebPathInfo.GetMask: TMask;
  854. var
  855.   Mask: TMask;
  856.   NewValue: string;
  857. begin
  858.   if PathInfo <> FMaskPathInfo then
  859.   begin
  860.     FMaskPathInfo := PathInfo;
  861.     if FMaskPathInfo <> '' then NewValue := DosPathToUnixPath(FMaskPathInfo);
  862.     if (NewValue <> '') and (NewValue[1] <> '/') then Insert('/', NewValue, 1);
  863.     Mask := TMask.Create(NewValue);
  864.     try
  865.       FPathInfo := NewValue;
  866.       FMask.Free;
  867.       FMask := nil;
  868.     except
  869.       Mask.Free;
  870.       raise;
  871.     end;
  872.     FMask := Mask;
  873.   end;
  874.   Result := FMask;
  875. end;
  876.  
  877. function TWebPathInfo.GetPathInfo: string;
  878. begin
  879.   Result := FPathInfo;
  880.   if Result = '' then
  881.     if Assigned(FOwner) then
  882.       Result := FOwner.Name;
  883. end;
  884.  
  885. procedure TWebPathInfo.SetPathInfo(const Value: string);
  886. begin
  887.   if Assigned(FOwner) and (Value = FOwner.Name) then
  888.     FPathInfo := ''
  889.   else
  890.     FPathInfo := Value;
  891. end;
  892.  
  893. end.
  894.