home *** CD-ROM | disk | FTP | other *** search
/ Delphi 5 for Professionals / 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.  
  490. function TXMLBroker.ApplyXMLUpdates(const Delta: string; out ErrorCount: Integer): string;
  491. var
  492.   XMLDelta: OleVariant;
  493.   XMLErrors: OleVariant;
  494. begin
  495.  
  496.  
  497.  
  498.   XMLDelta := StringToVariantArray('<?xml version="1.0" standalone="yes"?>' + Delta);
  499.  
  500.  
  501.  
  502.   if Delta = '' then
  503.     ErrorCount := 0
  504.   else
  505.     XMLErrors := AS_ApplyUpdates(XMLDelta, MaxErrors, ErrorCount);
  506.   if ErrorCount > 0 then
  507.   begin
  508.  
  509.  
  510.  
  511.     Result := VariantArrayToString(XMLErrors)
  512.   end
  513.   else
  514.     Result := '';
  515. end;
  516.  
  517. function TXMLBroker.AS_ApplyUpdates(Delta: OleVariant; MaxErrors: Integer;
  518.   out ErrorCount: Integer): OleVariant;
  519. var
  520.   OwnerData: OleVariant;
  521. begin
  522.   Result := AppServer.AS_ApplyUpdates(ProviderName, Delta, MaxErrors, ErrorCount, OwnerData);
  523. end;
  524.  
  525. function TXMLBroker.GetConnected: Boolean;
  526. begin
  527.   Result := HasAppServer;
  528. end;
  529.  
  530. procedure TXMLBroker.SetConnected(Value: Boolean);
  531. begin
  532.   if HasAppServer <> Value then
  533.     if Value then
  534.       GetAppServer
  535.     else
  536.     begin
  537.       AppServer := nil;
  538.       if Assigned(RemoteServer) then
  539.         RemoteServer.Connected := False;
  540.     end;
  541. end;
  542.  
  543. function TXMLBroker.DispatchEnabled: Boolean;
  544. begin
  545.   Result := FWebDispatch.Enabled;
  546. end;
  547.  
  548. function TXMLBroker.DispatchMask: TMask;
  549. begin
  550.   Result := FWebDispatch.Mask;
  551.  
  552. end;
  553.  
  554. function TXMLBroker.DispatchMethodType: TMethodType;
  555. begin
  556.   Result := FWebDispatch.MethodType;
  557. end;
  558.  
  559. function TXMLBroker.DispatchRequest(Sender: TObject;
  560.   Request: TWebRequest; Response: TWebResponse): Boolean;
  561. begin
  562.   Result := False;
  563.   if Assigned(FBeforeDispatch) then
  564.     FBeforeDispatch(Self, Request, Response, Result);
  565.   if not Result then
  566.     Result := RequestUpdate(Sender, Request, Response);
  567.   if Assigned(FAfterDispatch) then
  568.     FAfterDispatch(Self, Request, Response, Result);
  569. end;
  570.  
  571. function TXMLBroker.RequestUpdate(Sender: TObject; Request: TWebRequest; Response: TWebResponse): Boolean;
  572. var
  573.   Delta: string;
  574.   ErrorCount: Integer;
  575.   XMLErrors: string;
  576. begin
  577.   Result := False;
  578.   if Assigned(FRequestUpdate) then
  579.     FRequestUpdate(Sender, Request, Response, Result);
  580.   if not Result then
  581.   begin
  582.     Delta := GetDelta(Request);
  583.     if Delta <> '' then
  584.       XMLErrors := ApplyXMLUpdates(Delta, ErrorCount)
  585.     else
  586.       ErrorCount := 0;
  587.     if ErrorCount > 0 then
  588.       Result := GetErrorResponse(ErrorCount, XMLErrors, Request, Response)
  589.     else
  590.       Result := GetResponse(Request, Response);
  591.   end;
  592. end;
  593.  
  594. function TXMLBroker.GetErrors: string;
  595. begin
  596.   Result := FErrors;
  597. end;
  598.  
  599. function TXMLBroker.GetErrorCount: integer;
  600. begin
  601.   Result := FErrorCount;
  602. end;
  603.  
  604. function TXMLBroker.GetErrorResponse(ErrorCount: Integer; XMLErrors: string;
  605.   Request: TWebRequest; Response: TWebResponse): Boolean;
  606. begin
  607.   Result := False;
  608.   FErrors := XMLErrors;
  609.   FErrorCount := ErrorCount;
  610.   try
  611.     if Assigned(FGetErrorResponse) then
  612.       FGetErrorResponse(Self, ErrorCount, XMLErrors, Request, Response, Result);
  613.     if (not Result) and Assigned(FReconcileProducer) then
  614.     begin
  615.       Response.Content := FReconcileProducer.Content;
  616.       Result := True;
  617.     end;
  618.   finally
  619.     FErrors := '';
  620.     FErrorCount := 0;
  621.   end;
  622.   if not Result then
  623.     raise Exception.CreateResFmt(@sApplyUpdatesError, [ErrorCount]);
  624. end;
  625.  
  626. function TXMLBroker.GetResponse(
  627.   Request: TWebRequest; Response: TWebResponse): Boolean;
  628. var
  629.   Producer: TComponent;
  630.   Redirect: string;
  631. begin
  632.   Result := False;
  633.   if Assigned(FGetResponse) then
  634.     FGetResponse(Self, Request, Response, Result);
  635.   if not Result then
  636.   begin
  637.     Redirect := GetRedirect(Request);
  638.     if Redirect <> '' then
  639.     begin
  640.       Response.SendRedirect(Redirect);
  641.       Result := True;
  642.     end;
  643.   end;
  644.   if not Result then
  645.   begin
  646.     Producer := Owner.FindComponent(GetProducerName(Request));
  647.     if Assigned(Producer) and (Producer is TCustomContentProducer) then
  648.     begin
  649.       Response.Content := TCustomContentProducer(Producer).Content;
  650.       Result := True;
  651.     end;
  652.   end;
  653. end;
  654.  
  655. function TXMLBroker.GetProducerName(Request: TWebRequest): string;
  656. begin
  657.   Result := Request.ContentFields.Values[SProducer];
  658. end;
  659.  
  660. function TXMLBroker.GetRedirect(Request: TWebRequest): string;
  661. begin
  662.   Result := Request.ContentFields.Values[SRedirect];
  663. end;
  664.  
  665. function TXMLBroker.GetDelta(Request: TWebRequest): string;
  666. begin
  667.   Result := Request.ContentFields.Values[SPostDelta];
  668. end;
  669.  
  670. function TXMLBroker.DispatchSubItems: IInterfaceList;
  671. begin
  672.   Result := nil;
  673. end;
  674.  
  675. procedure TXMLBroker.SetWebDispatch(const Value: TWebDispatch);
  676. begin
  677.   FWebDispatch.Assign(Value);
  678. end;
  679.  
  680. function TXMLBroker.HTMLSubmitFormName: string;
  681. begin
  682.   Result := Format('Submit_%s', [Name]);
  683. end;
  684.  
  685. function TXMLBroker.SubmitFormVarName: string;
  686. begin
  687.   Result := HTMLSubmitFormName;
  688. end;
  689.  
  690. procedure TXMLBroker.AS_FetchParams;
  691. var
  692.   OwnerData: OleVariant;
  693. begin
  694.   UnpackParams(AppServer.AS_GetParams(ProviderName, OwnerData), Params);
  695. end;
  696.  
  697. procedure TXMLBroker.FetchParams;
  698. begin
  699.   AS_FetchParams;
  700. end;
  701.  
  702. function TXMLBroker.RowSetVarName(Path: TStrings): string;
  703. var
  704.   I: Integer;
  705. begin
  706.   Result := Name;
  707.   if Assigned(Path) then
  708.     for I := Path.Count - 1 downto 0 do
  709.       Result := Format('%s_%s', [Result, Path[I]]);
  710.   Result := Format(ScriptRowSetVarName, [Result]);
  711. end;
  712.  
  713. function TXMLBroker.MasterRowSetVarName(Path: TStrings): string;
  714. var
  715.   I: Integer;
  716. begin
  717.   Result := Name;
  718.   if Assigned(Path) and (Path.Count > 1) then
  719.     for I := Path.Count - 2 downto 0 do
  720.       Result := Format('%s_%s', [Result, Path[I]]);
  721.   Result := Format(ScriptRowSetVarName, [Result]);
  722. end;
  723.  
  724. procedure TXMLBroker.AddNotify(ANotify: TObject);
  725. begin
  726.   FNotify.Add(ANotify);
  727. end;
  728.  
  729. procedure TXMLBroker.RemoveNotify(ANotify: TObject);
  730. begin
  731.   FNotify.Remove(ANotify);
  732. end;
  733.  
  734. function TXMLBroker.GetNotify(Index: Integer): TObject;
  735. begin
  736.   Result := FNotify[Index];
  737. end;
  738.  
  739. function TXMLBroker.GetNotifyCount: Integer;
  740. begin
  741.   Result := FNotify.Count;
  742. end;
  743.  
  744. procedure TXMLBroker.SendConnectEvent(Connecting: Boolean);
  745. var
  746.   I: Integer;
  747.   ConnectionChange: INotifyConnectionChange;
  748. begin
  749.   for I := 0 to NotifyCount - 1 do
  750.     if Notify[I].GetInterface(INotifyConnectionChange, ConnectionChange) then
  751.       ConnectionChange.ConnectionChange(Self, Connecting);
  752. end;
  753.  
  754. procedure TXMLBroker.SetReconcileProducer(
  755.   const Value: TCustomContentProducer);
  756. begin
  757.   if FReconcileProducer <> Value then
  758.   begin
  759.     FReconcileProducer := Value;
  760.     if Value <> nil then Value.FreeNotification(Self);
  761.   end;
  762. end;
  763.  
  764. procedure TXMLBroker.Notification(AComponent: TComponent;
  765.   Operation: TOperation);
  766. begin
  767.   inherited;
  768.   if (Operation = opRemove) then
  769.   begin
  770.     if AComponent = FReconcileProducer then
  771.       FReconcileProducer := nil
  772.     else if AComponent = FRemoteServer then
  773.       FRemoteServer := nil;
  774.   end;
  775. end;
  776.  
  777. { TXMLParams }
  778.  
  779. procedure TXMLParams.AssignStrings(Value: TStrings);
  780. var
  781.   ParamName: string;
  782.   Param: TParam;
  783.   I: Integer;
  784. begin
  785.   for I := 0 to Value.Count - 1 do
  786.   begin
  787.     ParamName := Value.Names[I];
  788.     Param := FindParam(ParamName);
  789.     if Assigned(Param) then
  790.       Param.Value := Value.Values[ParamName];
  791.   end;
  792. end;
  793.  
  794. procedure TXMLParams.AssignTo(Dest: TPersistent);
  795. begin
  796.   if Dest is TXMLParams then TXMLParams(Dest).Assign(Self)
  797.   else inherited AssignTo(Dest);
  798. end;
  799.  
  800. { TWebDispatch }
  801.  
  802. constructor TWebDispatch.Create(AComponent: TComponent);
  803. begin
  804.   inherited Create;
  805.   FEnabled := True;
  806.   FMethodType := mtPost;
  807.   FPathInfo := TWebPathInfo.Create(AComponent);
  808. end;
  809.  
  810. destructor TWebDispatch.Destroy;
  811. begin
  812.   inherited;
  813.   FPathInfo.Free;
  814. end;
  815.  
  816. procedure TWebDispatch.SetPathInfo(const Value: string);
  817. begin
  818.   FPathInfo.PathInfo := Value;
  819. end;
  820.  
  821. procedure TWebDispatch.AssignTo(Dest: TPersistent);
  822. begin
  823.   if Dest is TWebDispatch then
  824.     with TWebDispatch(Dest) do
  825.     begin
  826.       PathInfo := Self.PathInfo;
  827.       MethodType := Self.MethodType;
  828.       Enabled := Self.Enabled;
  829.     end else inherited AssignTo(Dest);
  830. end;
  831.  
  832. function TWebDispatch.GetPathInfo: string;
  833. begin
  834.   Result := FPathInfo.PathInfo;
  835. end;
  836.  
  837. function TWebDispatch.GetMask: TMask;
  838. begin
  839.   Result := FPathInfo.Mask;
  840. end;
  841.  
  842. { TWebPathInfo }
  843.  
  844. constructor TWebPathInfo.Create(AOwner: TComponent);
  845. begin
  846.   FMaskPathInfo := '';
  847.   FMask := TMask.Create(FMaskPathInfo);
  848.   FOwner := AOwner;
  849. end;
  850.  
  851. destructor TWebPathInfo.Destroy;
  852. begin
  853.   FMask.Free;
  854.   inherited;
  855. end;
  856.  
  857. function TWebPathInfo.GetMask: TMask;
  858. var
  859.   Mask: TMask;
  860.   NewValue: string;
  861. begin
  862.   if PathInfo <> FMaskPathInfo then
  863.   begin
  864.     FMaskPathInfo := PathInfo;
  865.     if FMaskPathInfo <> '' then NewValue := DosPathToUnixPath(FMaskPathInfo);
  866.     if (NewValue <> '') and (NewValue[1] <> '/') then Insert('/', NewValue, 1);
  867.     Mask := TMask.Create(NewValue);
  868.     try
  869.       FPathInfo := NewValue;
  870.       FMask.Free;
  871.       FMask := nil;
  872.     except
  873.       Mask.Free;
  874.       raise;
  875.     end;
  876.     FMask := Mask;
  877.   end;
  878.   Result := FMask;
  879. end;
  880.  
  881. function TWebPathInfo.GetPathInfo: string;
  882. begin
  883.   Result := FPathInfo;
  884.   if Result = '' then
  885.     if Assigned(FOwner) then
  886.       Result := FOwner.Name;
  887. end;
  888.  
  889. procedure TWebPathInfo.SetPathInfo(const Value: string);
  890. begin
  891.   if Assigned(FOwner) and (Value = FOwner.Name) then
  892.     FPathInfo := ''
  893.   else
  894.     FPathInfo := Value;
  895. end;
  896.  
  897. end.
  898.