Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1620 lines
47 KiB

  1. using System;
  2. using System.Collections;
  3. using System.Data;
  4. using System.IO;
  5. using System.Net;
  6. using System.Security.Cryptography.X509Certificates;
  7. using System.Text;
  8. using System.Web.Services;
  9. using System.Web.Services.Description;
  10. using System.Web.Services.Protocols;
  11. using System.Xml;
  12. using System.Xml.Schema;
  13. using System.Xml.Serialization;
  14. using System.Data.SqlClient;
  15. using UDDI;
  16. using UDDI.API;
  17. using UDDI.Diagnostics;
  18. namespace UDDI.Replication
  19. {
  20. /// ********************************************************************
  21. /// class ReplicationHelper
  22. /// --------------------------------------------------------------------
  23. /// <summary>
  24. /// </summary>
  25. /// ********************************************************************
  26. ///
  27. public class ReplicationHelper
  28. {
  29. private static OperatorNode LocalOperator = null;
  30. private static X509Certificate LocalCertificate = null;
  31. private static OperatorNodeCollection RemoteOperators = null;
  32. private static ChangeRecordVectorCollection ChangesAlreadySeen = null;
  33. private static ReplicationSoapClient SoapClient = null;
  34. private static Hashtable NodeChangeRecordCounts = null;
  35. private static Hashtable SessionChangeRecordCounts = null;
  36. /// ****************************************************************
  37. /// private Initialize [static]
  38. /// ----------------------------------------------------------------
  39. /// <summary>
  40. /// Initializes replication variables.
  41. /// </summary>
  42. /// ****************************************************************
  43. ///
  44. private static void Initialize()
  45. {
  46. Debug.Enter();
  47. Debug.VerifySetting( "OperatorKey" );
  48. //
  49. // Get information about the local operator node.
  50. //
  51. LocalOperator = new OperatorNode( Config.GetString( "OperatorKey" ) );
  52. LocalOperator.Get();
  53. //
  54. // Get the local certificate.
  55. //
  56. LocalCertificate = new X509Certificate( LocalOperator.Certificate );
  57. //
  58. // Get the list of operator nodes to which we can send
  59. // get_changeRecords messages. Remove ourself from the
  60. // list!
  61. //
  62. RemoteOperators = new OperatorNodeCollection();
  63. RemoteOperators.Get();
  64. RemoteOperators.Remove( LocalOperator.OperatorNodeID );
  65. //
  66. // Get a ChangesAlreadySeen list for each operator node (not
  67. // just the ones we are replicating with).
  68. //
  69. GetHighWaterMarks();
  70. //
  71. // Initialize our soap client.
  72. //
  73. string proxy = Config.GetString( "Proxy", null );
  74. SoapClient = new ReplicationSoapClient();
  75. SoapClient.ClientCertificates.Add( LocalCertificate );
  76. if( !Utility.StringEmpty( proxy ) )
  77. SoapClient.Proxy = new WebProxy( proxy, true );
  78. //
  79. // Setup the context for a replication session.
  80. //
  81. Context.ApiVersionMajor = 2;
  82. Context.ContextType = ContextType.Replication;
  83. Context.LogChangeRecords = false;
  84. //
  85. // Setup logging.
  86. //
  87. SessionChangeRecordCounts = new Hashtable();
  88. foreach( int payloadType in Enum.GetValues( typeof( ChangeRecordPayloadType ) ) )
  89. {
  90. SessionChangeRecordCounts[ payloadType ] = 0;
  91. }
  92. Debug.Leave();
  93. }
  94. private static void GetHighWaterMarks()
  95. {
  96. try
  97. {
  98. GetHighWaterMarks getHighWaterMarks = new GetHighWaterMarks();
  99. HighWaterMarkDetail detail = getHighWaterMarks.Get();
  100. ChangesAlreadySeen = detail.HighWaterMarks;
  101. }
  102. catch( Exception e )
  103. {
  104. #if never
  105. Debug.OperatorMessage(
  106. SeverityType.Error,
  107. CategoryType.Replication,
  108. OperatorMessageType.CannotRetrieveHighWaterMarks,
  109. "Could not retrive high water marks for operator nodes.\r\n\r\nDetail:\r\n" + e.ToString() );
  110. #endif
  111. Debug.OperatorMessage(
  112. SeverityType.Error,
  113. CategoryType.Replication,
  114. OperatorMessageType.CannotRetrieveHighWaterMarks,
  115. new UDDIText( "UDDI_ERROR_REPLICATION_HIGHWATER_MARKS", e.ToString() ).GetText() );
  116. throw new UDDIException( ErrorType.E_fatalError, "UDDI_ERROR_REPLICATION_HIGHWATER_MARKS", e );
  117. }
  118. }
  119. /// ****************************************************************
  120. /// public Replicate [static]
  121. /// ----------------------------------------------------------------
  122. /// <summary>
  123. /// </summary>
  124. /// ****************************************************************
  125. ///
  126. public static void Replicate()
  127. {
  128. //
  129. // Initialize the replication session.
  130. //
  131. Initialize();
  132. //
  133. // Verify that we do in fact have operators to replicate
  134. // with.
  135. //
  136. if( RemoteOperators.Count < 1 )
  137. {
  138. #if never
  139. Debug.OperatorMessage(
  140. SeverityType.Info,
  141. CategoryType.Replication,
  142. OperatorMessageType.NoReplicationOperators,
  143. "There are no operators to replicate with. Please check the replication configuration." );
  144. #endif
  145. Debug.OperatorMessage(
  146. SeverityType.Info,
  147. CategoryType.Replication,
  148. OperatorMessageType.NoReplicationOperators,
  149. new UDDIText( "UDDI_ERROR_REPLICATION_NO_OPERATORS" ).GetText() );
  150. return;
  151. }
  152. //
  153. // TODO: Get the node id of the last operator we replicated
  154. // with.
  155. //
  156. //
  157. // TODO: Re-order the operator node list so that we replicate
  158. // in a round-robin fashion.
  159. //
  160. //
  161. // Create the start replication session log entry.
  162. //
  163. LogSessionStart();
  164. //
  165. // Replicate with each operator node.
  166. //
  167. foreach( OperatorNode remoteNode in RemoteOperators )
  168. {
  169. ReplicationResult result = null;
  170. //
  171. // Log the node replication start.
  172. //
  173. LogOperatorStart( remoteNode );
  174. //
  175. // Get the branch list for the node. The branch list is
  176. // the remote node itself, plus any alternatives that we
  177. // may try if we have trouble communicating with the first
  178. // node. For now, we don't support alternate nodes, so
  179. // the remote node is the only node we add to this list.
  180. //
  181. OperatorNodeCollection branchNodes = new OperatorNodeCollection();
  182. branchNodes.Add( remoteNode );
  183. foreach( OperatorNode branchNode in branchNodes )
  184. {
  185. //
  186. // Get the last replication status for this node.
  187. //
  188. result = ReplicateWithNode( branchNode );
  189. if( ReplicationStatus.Success == result.ReplicationStatus )
  190. break;
  191. //
  192. // Determine what we should do based on this attempts result
  193. // and the result of the last replication cycle with this
  194. // node. TODO: if it is a communication error, we'll need
  195. // to try alternate edges. This is reserved until alternate
  196. // edges are actually used.
  197. //
  198. }
  199. //
  200. // Log the node replication end.
  201. //
  202. LogOperatorEnd( remoteNode, result );
  203. }
  204. //
  205. // Create the end replication session log entry.
  206. //
  207. LogSessionEnd();
  208. Debug.Leave();
  209. }
  210. /// ****************************************************************
  211. /// public ReplicateWithNode [static]
  212. /// ----------------------------------------------------------------
  213. /// <summary>
  214. /// </summary>
  215. /// ****************************************************************
  216. ///
  217. public static ReplicationResult ReplicateWithNode( string operatorNodeID )
  218. {
  219. OperatorNode remoteNode = null;
  220. //
  221. // Initialize the replication session.
  222. //
  223. Initialize();
  224. //
  225. // Replicate with the specified node.
  226. //
  227. try
  228. {
  229. remoteNode = new OperatorNode( operatorNodeID );
  230. remoteNode.Get();
  231. }
  232. catch( Exception e )
  233. {
  234. #if never
  235. string message = String.Format(
  236. "Could not get details for operator {{{0}}}.\r\n\r\nDetails:\r\n{1}",
  237. operatorNodeID,
  238. e.ToString() );
  239. Debug.OperatorMessage(
  240. SeverityType.Error,
  241. CategoryType.Replication,
  242. OperatorMessageType.UnknownOperator,
  243. message );
  244. throw new Exception( message, e );
  245. #endif
  246. UDDIText uddiText = new UDDIText( "UDDI_ERROR_REPLICATION_OPERATOR_DETAILS", operatorNodeID, e.ToString() );
  247. Debug.OperatorMessage(
  248. SeverityType.Error,
  249. CategoryType.Replication,
  250. OperatorMessageType.UnknownOperator,
  251. uddiText.GetText() );
  252. throw new UDDIException( ErrorType.E_fatalError, uddiText.GetText() );
  253. }
  254. //
  255. // Log the node replication start.
  256. //
  257. LogOperatorStart( remoteNode );
  258. //
  259. // Replicate
  260. //
  261. ReplicationResult result = ReplicateWithNode( remoteNode );
  262. //
  263. // Log the node replication end.
  264. //
  265. LogOperatorEnd( remoteNode, result );
  266. return result;
  267. }
  268. /// ****************************************************************
  269. /// private ReplicateWithNode [static]
  270. /// ----------------------------------------------------------------
  271. /// <summary>
  272. /// </summary>
  273. /// ****************************************************************
  274. ///
  275. private static ReplicationResult ReplicateWithNode( OperatorNode remoteNode )
  276. {
  277. //
  278. // Retrieve the change records from the remote node and process
  279. // them.
  280. //
  281. ChangeRecordCollection changeRecords = null;
  282. //
  283. // Keep track of the number of times we call GetChangeRecords on each operator. We
  284. // don't want to be in a situation where we call them infinitely if they keep updating
  285. // their data.
  286. //
  287. int maxIterations = Config.GetInt( "Replication.MaxGetChangeIterations", 100 );
  288. int iterations = 0;
  289. //
  290. // Keep getting change records until there are no more; we need to do this because some
  291. // operators will limit the number of change records that they send back.
  292. //
  293. do
  294. {
  295. try
  296. {
  297. changeRecords = GetChangeRecords( remoteNode );
  298. }
  299. catch( Exception e )
  300. {
  301. return ReplicationResult.LogCommunicationError( remoteNode, e, ChangesAlreadySeen );
  302. }
  303. foreach( ChangeRecord changeRecord in changeRecords )
  304. {
  305. //
  306. // Make sure we haven't seen this change record before.
  307. //
  308. if( ChangesAlreadySeen.IsProcessed( changeRecord.ChangeID ) )
  309. {
  310. Debug.Write(
  311. SeverityType.Info,
  312. CategoryType.Replication,
  313. String.Format(
  314. "Change already seen.\r\nSkipping record {0}:{1} retrieved from node {2}",
  315. changeRecord.ChangeID.NodeID,
  316. changeRecord.ChangeID.OriginatingUSN,
  317. remoteNode.OperatorNodeID ) );
  318. continue;
  319. }
  320. //
  321. // Make sure we aren't trying to replicate one of our own
  322. // change records.
  323. //
  324. if( 0 == String.Compare( changeRecord.ChangeID.NodeID, LocalOperator.OperatorNodeID, true ) )
  325. {
  326. Debug.Write(
  327. SeverityType.Info,
  328. CategoryType.Replication,
  329. String.Format(
  330. "Skipping replication of local change record.\r\nSkipping record {0}:{1} retrieved from node {2}",
  331. changeRecord.ChangeID.NodeID,
  332. changeRecord.ChangeID.OriginatingUSN,
  333. remoteNode.OperatorNodeID ) );
  334. continue;
  335. }
  336. //
  337. // Begin a transaction.
  338. //
  339. ConnectionManager.BeginTransaction();
  340. try
  341. {
  342. //
  343. // Set user context information and process the
  344. // change record.
  345. //
  346. Context.User.ID = changeRecord.ChangeID.NodeID;
  347. Context.TimeStamp = DateTime.Now;
  348. //
  349. // Validate the change record, then process it. There is a very good
  350. // reason for doing this validation on a change record by change record
  351. // basis: if there is one error in the incoming change record stream,
  352. // we would reject the entire stream, not just the errant change record.
  353. //
  354. SchemaCollection.Validate( changeRecord );
  355. try
  356. {
  357. changeRecord.Process();
  358. }
  359. catch( Exception innerException )
  360. {
  361. //
  362. // Exceptions that are related to IN 60 are ignored.
  363. //
  364. if( Context.ExceptionSource == ExceptionSource.PublisherAssertion ||
  365. Context.ExceptionSource == ExceptionSource.BrokenServiceProjection )
  366. {
  367. //
  368. // Log the error
  369. //
  370. ReplicationResult.LogInvalidKeyWarning( remoteNode, changeRecord, innerException );
  371. }
  372. else
  373. {
  374. //
  375. // Otherwise, throw the exception for real.
  376. //
  377. throw innerException;
  378. }
  379. }
  380. //
  381. // Commit the transaction.
  382. //
  383. ConnectionManager.Commit();
  384. //
  385. // Update our changeAlreadySeen vector for the
  386. // originating node.
  387. //
  388. ChangesAlreadySeen.MarkAsProcessed( changeRecord.ChangeID );
  389. //
  390. // Update log counts.
  391. //
  392. LogCounts( changeRecord );
  393. }
  394. catch( Exception e )
  395. {
  396. ConnectionManager.Abort();
  397. return ReplicationResult.LogValidationError( remoteNode, changeRecord, e, ChangesAlreadySeen );
  398. }
  399. }
  400. //
  401. // Refresh our highwater mark vector. We do this instead of calling gethighwatermarks on the
  402. // operator because hitting our DB is faster then making the SOAP call across HTTP.
  403. //
  404. GetHighWaterMarks();
  405. iterations++;
  406. }while( 0 != changeRecords.Count && iterations < maxIterations );
  407. //
  408. // Log success!
  409. //
  410. return ReplicationResult.LogSuccess( remoteNode, null );
  411. }
  412. /// ****************************************************************
  413. /// private GetChangeRecords [static]
  414. /// ----------------------------------------------------------------
  415. /// <summary>
  416. /// </summary>
  417. /// ****************************************************************
  418. ///
  419. private static ChangeRecordCollection GetChangeRecords( OperatorNode remoteNode )
  420. {
  421. GetChangeRecords getChangeRecords = new GetChangeRecords();
  422. getChangeRecords.RequestingNode = LocalOperator.OperatorNodeID;
  423. getChangeRecords.ChangesAlreadySeen = ChangesAlreadySeen;
  424. SoapClient.Url = remoteNode.SoapReplicationURL;
  425. ChangeRecordDetail detail = SoapClient.GetChangeRecords( getChangeRecords );
  426. return detail.ChangeRecords;
  427. }
  428. /// ****************************************************************
  429. /// private LogSessionStart [static]
  430. /// ----------------------------------------------------------------
  431. /// <summary>
  432. /// </summary>
  433. /// ****************************************************************
  434. ///
  435. private static void LogSessionStart()
  436. {
  437. StringWriter log = new StringWriter();
  438. try
  439. {
  440. // log.WriteLine( "Replication cycle started." );
  441. log.WriteLine( new UDDIText( "UDDI_MSG_REPLICATION_START" ).GetText() );
  442. log.WriteLine();
  443. // log.WriteLine( "REPLICATION NODES:" );
  444. log.WriteLine( new UDDIText( "UDDI_MSG_REPLICATION_NODES" ).GetText() );
  445. foreach( OperatorNode operatorNode in RemoteOperators )
  446. {
  447. log.Write( " " );
  448. log.WriteLine( operatorNode.Name );
  449. log.Write( " {" );
  450. log.Write( operatorNode.OperatorNodeID );
  451. log.WriteLine( "}" );
  452. log.Write( " " );
  453. log.WriteLine( operatorNode.SoapReplicationURL );
  454. log.WriteLine();
  455. }
  456. // log.WriteLine( "CURRENT HIGHWATER MARKS:" );
  457. log.WriteLine( new UDDIText( "UDDI_MSG_REPLICATION_CURRENT_HIGHWATER_MARKS" ).GetText() );
  458. foreach( ChangeRecordVector vector in ChangesAlreadySeen )
  459. {
  460. log.Write( " {" );
  461. log.Write( vector.NodeID );
  462. log.Write( "} : " );
  463. log.WriteLine( vector.OriginatingUSN );
  464. }
  465. Debug.OperatorMessage(
  466. SeverityType.Info,
  467. CategoryType.Replication,
  468. OperatorMessageType.StartingReplicationSession,
  469. log.ToString() );
  470. }
  471. finally
  472. {
  473. log.Close();
  474. }
  475. }
  476. /// ****************************************************************
  477. /// private LogOperatorStart [static]
  478. /// ----------------------------------------------------------------
  479. /// <summary>
  480. /// </summary>
  481. /// ****************************************************************
  482. ///
  483. private static void LogOperatorStart( OperatorNode remoteNode )
  484. {
  485. NodeChangeRecordCounts = new Hashtable();
  486. foreach( int payloadType in Enum.GetValues( typeof( ChangeRecordPayloadType ) ) )
  487. {
  488. NodeChangeRecordCounts[ payloadType ] = 0;
  489. }
  490. StringWriter log = new StringWriter();
  491. try
  492. {
  493. // log.WriteLine( "Starting replication with node.\r\n" );
  494. log.WriteLine( new UDDIText( "UDDI_MSG_REPLICATION_NODE_START" ).GetText() );
  495. // log.WriteLine( "REPLICATION NODE:" );
  496. log.WriteLine( new UDDIText( "UDDI_MSG_REPLICATION_NODE" ).GetText() );
  497. log.Write( " " );
  498. log.WriteLine( remoteNode.Name );
  499. log.Write( " {" );
  500. log.Write( remoteNode.OperatorNodeID );
  501. log.WriteLine( "}" );
  502. log.Write( " " );
  503. log.WriteLine( remoteNode.SoapReplicationURL );
  504. log.WriteLine();
  505. // log.WriteLine( "CURRENT HIGHWATER MARKS:" );
  506. log.WriteLine( new UDDIText( "UDDI_MSG_REPLICATION_CURRENT_HIGHWATER_MARKS" ).GetText() );
  507. foreach( ChangeRecordVector vector in ChangesAlreadySeen )
  508. {
  509. log.Write( " {" );
  510. log.Write( vector.NodeID );
  511. log.Write( "} : " );
  512. log.WriteLine( vector.OriginatingUSN );
  513. }
  514. Debug.OperatorMessage(
  515. SeverityType.Info,
  516. CategoryType.Replication,
  517. OperatorMessageType.StartingReplicationWithNode,
  518. log.ToString() );
  519. }
  520. finally
  521. {
  522. log.Close();
  523. }
  524. }
  525. /// ****************************************************************
  526. /// private LogOperatorEnd [static]
  527. /// ----------------------------------------------------------------
  528. /// <summary>
  529. /// </summary>
  530. /// ****************************************************************
  531. ///
  532. private static void LogOperatorEnd( OperatorNode remoteNode, ReplicationResult result )
  533. {
  534. StringWriter log = new StringWriter();
  535. try
  536. {
  537. if( ReplicationStatus.Success == result.ReplicationStatus )
  538. {
  539. // log.WriteLine( "Replication with node complete." );
  540. log.WriteLine( new UDDIText( "UDDI_MSG_REPLICATION_COMPLETE" ).GetText() );
  541. }
  542. else
  543. {
  544. // log.Write( "Replication with node interrupted\r\n ERROR: " );
  545. log.Write( new UDDIText( "UDDI_MSG_REPLICATION_INTERRUPTED" ).GetText() );
  546. log.WriteLine( result.ReplicationStatus.ToString() );
  547. }
  548. log.WriteLine();
  549. // log.WriteLine( "REPLICATION NODE:" );
  550. log.WriteLine( new UDDIText( "UDDI_MSG_REPLICATION_NODE" ).GetText() );
  551. log.Write( " " );
  552. log.WriteLine( remoteNode.Name );
  553. log.Write( " {" );
  554. log.Write( remoteNode.OperatorNodeID );
  555. log.WriteLine( "}" );
  556. log.Write( " " );
  557. log.WriteLine( remoteNode.SoapReplicationURL );
  558. log.WriteLine();
  559. // log.WriteLine( "CHANGE RECORDS PROCESSED:" );
  560. log.WriteLine( new UDDIText( "UDDI_MSG_REPLICATION_CHANGE_RECORDS_PROCESSED" ).GetText() );
  561. foreach( int payloadType in Enum.GetValues( typeof( ChangeRecordPayloadType ) ) )
  562. {
  563. string name = Enum.GetName( typeof( ChangeRecordPayloadType ), payloadType ) + ":";
  564. log.Write( " " );
  565. log.Write( name.PadRight( 30 ) );
  566. log.Write( "\t" );
  567. log.WriteLine( NodeChangeRecordCounts[ payloadType ] );
  568. }
  569. log.WriteLine();
  570. //log.WriteLine( "NEW HIGHWATER MARKS:" );
  571. log.WriteLine( new UDDIText( "UDDI_MSG_REPLICATION_NEW_HIGHWATER_MARKS" ).GetText() );
  572. foreach( ChangeRecordVector vector in ChangesAlreadySeen )
  573. {
  574. log.Write( " {" );
  575. log.Write( vector.NodeID );
  576. log.Write( "} : " );
  577. log.WriteLine( vector.OriginatingUSN );
  578. }
  579. SeverityType severity = SeverityType.Info;
  580. if( ReplicationStatus.Success != result.ReplicationStatus )
  581. severity = SeverityType.Error;
  582. string message = log.ToString();
  583. //
  584. // Log results
  585. //
  586. Debug.OperatorMessage(
  587. severity,
  588. CategoryType.Replication,
  589. OperatorMessageType.EndingReplicationWithNode,
  590. message );
  591. //
  592. // Only send mail on success; if there was a failure, mail will be sent at the point of failure.
  593. //
  594. if( ReplicationStatus.Success == result.ReplicationStatus )
  595. {
  596. Debug.OperatorMail(
  597. SeverityType.None,
  598. CategoryType.Replication,
  599. OperatorMessageType.EndingReplicationWithNode,
  600. message );
  601. }
  602. }
  603. finally
  604. {
  605. log.Close();
  606. }
  607. //
  608. // Add the operator node counts to the totals.
  609. //
  610. foreach( int payloadType in Enum.GetValues( typeof( ChangeRecordPayloadType ) ) )
  611. {
  612. SessionChangeRecordCounts[ payloadType ] = (int)SessionChangeRecordCounts[ payloadType ] + (int)NodeChangeRecordCounts[ payloadType ];
  613. }
  614. }
  615. /// ****************************************************************
  616. /// private LogSessionEnd [static]
  617. /// ----------------------------------------------------------------
  618. /// <summary>
  619. /// </summary>
  620. /// ****************************************************************
  621. ///
  622. private static void LogSessionEnd()
  623. {
  624. StringWriter log = new StringWriter();
  625. try
  626. {
  627. // log.WriteLine( "Replication cycle complete." );
  628. log.WriteLine( new UDDIText( "UDDI_MSG_REPLICATION_END" ).GetText() );
  629. log.WriteLine();
  630. //log.WriteLine( "CHANGE RECORDS PROCESSED:" );
  631. log.WriteLine( new UDDIText( "UDDI_MSG_REPLICATION_CHANGERECORDS_PROCESSED" ).GetText() );
  632. foreach( int payloadType in Enum.GetValues( typeof( ChangeRecordPayloadType ) ) )
  633. {
  634. string name = Enum.GetName( typeof( ChangeRecordPayloadType ), payloadType ) + ":";
  635. log.Write( " " );
  636. log.Write( name.PadRight( 30 ) );
  637. log.Write( "\t" );
  638. log.WriteLine( SessionChangeRecordCounts[ payloadType ] );
  639. }
  640. log.WriteLine();
  641. // log.WriteLine( "NEW HIGHWATER MARKS:" );
  642. log.WriteLine( new UDDIText( "UDDI_MSG_REPLICATION_NEW_HIGHWATER_MARKS" ).GetText() );
  643. foreach( ChangeRecordVector vector in ChangesAlreadySeen )
  644. {
  645. log.Write( " {" );
  646. log.Write( vector.NodeID );
  647. log.Write( "} : " );
  648. log.WriteLine( vector.OriginatingUSN );
  649. }
  650. Debug.OperatorMessage(
  651. SeverityType.Info,
  652. CategoryType.Replication,
  653. OperatorMessageType.EndingReplicationWithNode,
  654. log.ToString() );
  655. }
  656. finally
  657. {
  658. log.Close();
  659. }
  660. }
  661. /// ****************************************************************
  662. /// private LogCounts [static]
  663. /// ----------------------------------------------------------------
  664. /// <summary>
  665. /// </summary>
  666. /// ****************************************************************
  667. ///
  668. private static void LogCounts( ChangeRecord changeRecord )
  669. {
  670. int payloadType = (int)changeRecord.Payload.ChangeRecordPayloadType;
  671. NodeChangeRecordCounts[ payloadType ] = (int)NodeChangeRecordCounts[ payloadType ] + 1;
  672. }
  673. }
  674. /// ********************************************************************
  675. /// class ReplicationResult
  676. /// --------------------------------------------------------------------
  677. /// <summary>
  678. /// </summary>
  679. /// ********************************************************************
  680. ///
  681. public class ReplicationResult
  682. {
  683. public UDDI.Replication.ReplicationStatus ReplicationStatus;
  684. public string OperatorNodeID;
  685. public string Description;
  686. public string LastNodeID;
  687. public long LastUSN;
  688. public long LastChange;
  689. /// ****************************************************************
  690. /// public GetLast
  691. /// ----------------------------------------------------------------
  692. /// <summary>
  693. /// </summary>
  694. /// ****************************************************************
  695. ///
  696. public void GetLast( string operatorNodeID, bool inboundStatus )
  697. {
  698. Debug.Enter();
  699. SqlStoredProcedureAccessor sp = new SqlStoredProcedureAccessor();
  700. sp.ProcedureName = "net_operatorLogLast_get";
  701. sp.Parameters.Add( "@operatorKey", SqlDbType.UniqueIdentifier );
  702. sp.Parameters.Add( "@inboundStatus", SqlDbType.Bit );
  703. sp.Parameters.Add( "@replStatusID", SqlDbType.TinyInt, ParameterDirection.Output );
  704. sp.Parameters.Add( "@description", SqlDbType.NVarChar, UDDI.Constants.Lengths.Description, ParameterDirection.Output );
  705. sp.Parameters.Add( "@lastOperatorKey", SqlDbType.UniqueIdentifier, ParameterDirection.Output );
  706. sp.Parameters.Add( "@lastUSN", SqlDbType.BigInt, ParameterDirection.Output );
  707. sp.Parameters.Add( "@lastChange", SqlDbType.BigInt, ParameterDirection.Output );
  708. sp.Parameters.SetGuidFromString( "@operatorKey", operatorNodeID );
  709. sp.Parameters.SetBool( "@inboundStatus", inboundStatus );
  710. sp.ExecuteNonQuery();
  711. this.OperatorNodeID = operatorNodeID;
  712. this.ReplicationStatus = (ReplicationStatus)sp.Parameters.GetShort( "@replStatusID" );
  713. this.Description = sp.Parameters.GetString( "@description" );
  714. this.LastNodeID = sp.Parameters.GetGuidString( "@lastOperatorKey" );
  715. this.LastUSN = sp.Parameters.GetLong( "@lastUSN" );
  716. this.LastChange = sp.Parameters.GetLong( "@lastChange" );
  717. Debug.Leave();
  718. }
  719. /// ****************************************************************
  720. /// public Save
  721. /// ----------------------------------------------------------------
  722. /// <summary>
  723. /// </summary>
  724. /// ****************************************************************
  725. ///
  726. public void Save()
  727. {
  728. Debug.Enter();
  729. try
  730. {
  731. SqlStoredProcedureAccessor sp = new SqlStoredProcedureAccessor();
  732. sp.ProcedureName = "net_operatorLog_save";
  733. sp.Parameters.Add( "@operatorKey", SqlDbType.UniqueIdentifier );
  734. sp.Parameters.Add( "@replStatusID", SqlDbType.TinyInt );
  735. sp.Parameters.Add( "@description", SqlDbType.NVarChar, UDDI.Constants.Lengths.Description );
  736. sp.Parameters.Add( "@lastOperatorKey", SqlDbType.UniqueIdentifier );
  737. sp.Parameters.Add( "@lastUSN", SqlDbType.BigInt );
  738. sp.Parameters.Add( "@lastChange", SqlDbType.BigInt );
  739. sp.Parameters.SetGuidFromString( "@operatorKey", OperatorNodeID );
  740. sp.Parameters.SetShort( "@replStatusID", (short)ReplicationStatus );
  741. sp.Parameters.SetString( "@description", Description );
  742. sp.Parameters.SetGuidFromString( "@lastOperatorKey", LastNodeID );
  743. sp.Parameters.SetLong( "@lastUSN", LastUSN );
  744. sp.Parameters.SetLong( "@lastChange", LastChange );
  745. sp.ExecuteNonQuery();
  746. }
  747. catch
  748. {
  749. #if never
  750. Debug.OperatorMessage(
  751. SeverityType.Error,
  752. CategoryType.Replication,
  753. OperatorMessageType.ValidationError,
  754. String.Format(
  755. "Could not store last replication result.\r\n\r\n" +
  756. "REPLICATION NODE:\r\n" +
  757. " {{{0}}}\r\n\r\n" +
  758. "CHANGE RECORD:\r\n" +
  759. " {{{1}}} : {2}",
  760. OperatorNodeID,
  761. LastNodeID,
  762. LastUSN ) );
  763. #endif
  764. Debug.OperatorMessage(
  765. SeverityType.Error,
  766. CategoryType.Replication,
  767. OperatorMessageType.ValidationError,
  768. new UDDIText( "UDDI_ERROR_REPLICATION_COULD_NOT_STORE_RESULT", OperatorNodeID, LastNodeID, LastUSN ).GetText() );
  769. }
  770. Debug.Leave();
  771. }
  772. /// ****************************************************************
  773. /// public LogSuccess [static]
  774. /// ----------------------------------------------------------------
  775. /// <summary>
  776. /// </summary>
  777. /// ****************************************************************
  778. ///
  779. public static ReplicationResult LogSuccess( OperatorNode remoteNode, string description )
  780. {
  781. ReplicationResult result = new ReplicationResult();
  782. result.ReplicationStatus = ReplicationStatus.Success;
  783. result.Description = description;
  784. result.OperatorNodeID = remoteNode.OperatorNodeID;
  785. result.LastNodeID = null;
  786. result.LastUSN = 0;
  787. result.LastChange = DateTime.UtcNow.Ticks;
  788. result.Save();
  789. return result;
  790. }
  791. /// ****************************************************************
  792. /// public LogCommunicationError [static]
  793. /// ----------------------------------------------------------------
  794. /// <summary>
  795. /// </summary>
  796. /// ****************************************************************
  797. ///
  798. public static ReplicationResult LogCommunicationError( OperatorNode remoteNode, Exception e, ChangeRecordVectorCollection changesAlreadySeen )
  799. {
  800. ReplicationResult result = new ReplicationResult();
  801. result.ReplicationStatus = ReplicationStatus.CommunicationError;
  802. result.Description = e.ToString();
  803. result.OperatorNodeID = remoteNode.OperatorNodeID;
  804. result.LastNodeID = null;
  805. result.LastUSN = 0;
  806. result.LastChange = DateTime.UtcNow.Ticks;
  807. result.Save();
  808. string response = e.ToString();
  809. if( e is WebException )
  810. {
  811. WebException we = (WebException)e;
  812. if( null != we.Response )
  813. {
  814. StreamReader reader = null;
  815. try
  816. {
  817. reader = new StreamReader( we.Response.GetResponseStream() );
  818. response += "\r\nRESPONSE:\r\n\r\n";
  819. response += reader.ReadToEnd();
  820. }
  821. catch
  822. {
  823. }
  824. finally
  825. {
  826. if( null != reader )
  827. reader.Close();
  828. }
  829. }
  830. }
  831. else if( e is SoapException )
  832. {
  833. SoapException se = (SoapException)e;
  834. if( null != se.Detail )
  835. {
  836. response += "\r\nSOAP FAULT DETAILS:\r\n\r\n";
  837. response += se.Detail.OuterXml;
  838. }
  839. }
  840. //
  841. // Also send the highwater marks.
  842. //
  843. StringWriter highWaterMarks = new StringWriter();
  844. foreach( ChangeRecordVector vector in changesAlreadySeen )
  845. {
  846. highWaterMarks.Write( " {" );
  847. highWaterMarks.Write( vector.NodeID );
  848. highWaterMarks.Write( "} : " );
  849. highWaterMarks.WriteLine( vector.OriginatingUSN );
  850. }
  851. #if never
  852. //
  853. // Communications Error
  854. //
  855. string message = String.Format(
  856. "Error communicating with operator.\r\n\r\n" +
  857. "REPLICATION NODE:\r\n" +
  858. " {0}\r\n" +
  859. " {{{1}}}\r\n" +
  860. " {2}\r\n\r\n" +
  861. "DETAILS:\r\n\r\n{3}\r\n\r\nCURRENT HIGHWATER MARKS:\r\n\r\n{4}",
  862. remoteNode.Name,
  863. remoteNode.OperatorNodeID,
  864. remoteNode.SoapReplicationURL,
  865. response,
  866. highWaterMarks.ToString() );
  867. #endif
  868. //
  869. // Communications Error
  870. //
  871. UDDIText message = new UDDIText( "UDDI_ERROR_REPLICATION_OPERATOR_COMMUNICATION_ERROR",
  872. remoteNode.Name,
  873. remoteNode.OperatorNodeID,
  874. remoteNode.SoapReplicationURL,
  875. response,
  876. highWaterMarks.ToString() );
  877. Debug.OperatorMessage(
  878. SeverityType.Error,
  879. CategoryType.Replication,
  880. OperatorMessageType.ErrorCommunicatingWithNode,
  881. message.GetText() );
  882. Debug.OperatorMail(
  883. SeverityType.Error,
  884. CategoryType.Replication,
  885. OperatorMessageType.ErrorCommunicatingWithNode,
  886. message.GetText() );
  887. return result;
  888. }
  889. /// ****************************************************************
  890. /// public LogValidationError [static]
  891. /// ----------------------------------------------------------------
  892. /// <summary>
  893. /// </summary>
  894. /// ****************************************************************
  895. ///
  896. public static ReplicationResult LogValidationError( OperatorNode remoteNode, ChangeRecord changeRecord, Exception e, ChangeRecordVectorCollection changesAlreadySeen )
  897. {
  898. ReplicationResult result = new ReplicationResult();
  899. result.ReplicationStatus = ReplicationStatus.ValidationError;
  900. result.Description = e.ToString();
  901. result.OperatorNodeID = remoteNode.OperatorNodeID;
  902. result.LastNodeID = changeRecord.ChangeID.NodeID;
  903. result.LastUSN = changeRecord.ChangeID.OriginatingUSN;
  904. result.LastChange = DateTime.UtcNow.Ticks;
  905. result.Save();
  906. //
  907. // Also send the highwater marks.
  908. //
  909. StringWriter highWaterMarks = new StringWriter();
  910. foreach( ChangeRecordVector vector in changesAlreadySeen )
  911. {
  912. highWaterMarks.Write( " {" );
  913. highWaterMarks.Write( vector.NodeID );
  914. highWaterMarks.Write( "} : " );
  915. highWaterMarks.WriteLine( vector.OriginatingUSN );
  916. }
  917. #if never
  918. string message = String.Format(
  919. "Could not process entity from remote operator.\r\n\r\n" +
  920. "REPLICATION NODE:\r\n" +
  921. " {0}\r\n" +
  922. " {{{1}}}\r\n" +
  923. " {2}\r\n\r\n" +
  924. "DETAILS:\r\n\r\n" +
  925. "{3}\r\n\r\n" +
  926. "CHANGE RECORD:\r\n" +
  927. " {{{4}}} : {5}\r\n\r\n" +
  928. "{6}\r\n\r\nCURRENT HIGHWATER MARKS:\r\n\r\n{7}",
  929. remoteNode.Name,
  930. remoteNode.OperatorNodeID,
  931. remoteNode.SoapReplicationURL,
  932. e.ToString(),
  933. changeRecord.ChangeID.NodeID,
  934. changeRecord.ChangeID.OriginatingUSN,
  935. changeRecord.ToString(),
  936. highWaterMarks.ToString() );
  937. #endif
  938. UDDIText message = new UDDIText( "UDDI_ERROR_REPLICATION_COULD_NOT_PROCESS_ENTITY",
  939. remoteNode.Name,
  940. remoteNode.OperatorNodeID,
  941. remoteNode.SoapReplicationURL,
  942. e.ToString(),
  943. changeRecord.ChangeID.NodeID,
  944. changeRecord.ChangeID.OriginatingUSN,
  945. changeRecord.ToString(),
  946. highWaterMarks.ToString() );
  947. Debug.OperatorMessage(
  948. SeverityType.Error,
  949. CategoryType.Replication,
  950. OperatorMessageType.ValidationError,
  951. message.GetText() );
  952. Debug.OperatorMail(
  953. SeverityType.Error,
  954. CategoryType.Replication,
  955. OperatorMessageType.ValidationError,
  956. message.GetText() );
  957. return result;
  958. }
  959. public static void LogInvalidKeyWarning( OperatorNode remoteNode, ChangeRecord changeRecord, Exception e )
  960. {
  961. ReplicationResult result = new ReplicationResult();
  962. result.ReplicationStatus = ReplicationStatus.CommunicationError;
  963. result.Description = e.ToString();
  964. result.OperatorNodeID = remoteNode.OperatorNodeID;
  965. result.LastNodeID = changeRecord.ChangeID.NodeID;
  966. result.LastUSN = changeRecord.ChangeID.OriginatingUSN;
  967. result.LastChange = DateTime.UtcNow.Ticks;
  968. result.Save();
  969. #if never
  970. string message = String.Format(
  971. "Invalid key from remote operator.\r\n\r\n" +
  972. "REPLICATION NODE:\r\n" +
  973. " {0}\r\n" +
  974. " {{{1}}}\r\n" +
  975. " {2}\r\n\r\n" +
  976. "DETAILS:\r\n\r\n" +
  977. "{3}\r\n\r\n" +
  978. "CHANGE RECORD:\r\n" +
  979. " {{{4}}} : {5}\r\n\r\n" +
  980. "{6}",
  981. remoteNode.Name,
  982. remoteNode.OperatorNodeID,
  983. remoteNode.SoapReplicationURL,
  984. e.ToString(),
  985. changeRecord.ChangeID.NodeID,
  986. changeRecord.ChangeID.OriginatingUSN,
  987. changeRecord.ToString() );
  988. #endif
  989. UDDIText message = new UDDIText( "UDDI_ERROR_REPLICATION_INVALID_KEY",
  990. remoteNode.Name,
  991. remoteNode.OperatorNodeID,
  992. remoteNode.SoapReplicationURL,
  993. e.ToString(),
  994. changeRecord.ChangeID.NodeID,
  995. changeRecord.ChangeID.OriginatingUSN,
  996. changeRecord.ToString() );
  997. Debug.OperatorMessage(
  998. SeverityType.Warning,
  999. CategoryType.Replication,
  1000. OperatorMessageType.InvalidKey,
  1001. message.GetText() );
  1002. //
  1003. // TODO for now don't send mail on a warning.
  1004. //
  1005. #if never
  1006. Debug.OperatorMail(
  1007. SeverityType.Error,
  1008. CategoryType.Replication,
  1009. OperatorMessageType.ValidationError,
  1010. message );
  1011. #endif
  1012. }
  1013. }
  1014. /// ********************************************************************
  1015. /// class ReplicationSoapClient
  1016. /// --------------------------------------------------------------------
  1017. /// <summary>
  1018. /// </summary>
  1019. /// ********************************************************************
  1020. ///
  1021. [ WebServiceBinding( Name="ExternalMessagesSoap", Namespace=UDDI.Replication.Constants.Namespace ) ]
  1022. internal sealed class ReplicationSoapClient : SoapHttpClientProtocol
  1023. {
  1024. /// ****************************************************************
  1025. /// public GetChangeRecords
  1026. /// ----------------------------------------------------------------
  1027. /// <summary>
  1028. /// </summary>
  1029. /// ****************************************************************
  1030. ///
  1031. [ System.Diagnostics.DebuggerStepThrough ]
  1032. [ SoapDocumentMethod( "", Use=SoapBindingUse.Literal, ParameterStyle=SoapParameterStyle.Bare ) ]
  1033. [ return: XmlElement( "changeRecords", Namespace=UDDI.Replication.Constants.Namespace, IsNullable=false ) ]
  1034. public ChangeRecordDetail GetChangeRecords( GetChangeRecords get_changeRecords )
  1035. {
  1036. object[] results = Invoke( "GetChangeRecords", new object[] { get_changeRecords } );
  1037. return (ChangeRecordDetail)results[ 0 ];
  1038. }
  1039. protected override WebRequest GetWebRequest( Uri uri )
  1040. {
  1041. WebRequest innerWebRequest = base.GetWebRequest( uri );
  1042. UDDIWebRequest webRequest = new UDDIWebRequest( innerWebRequest );
  1043. return webRequest;
  1044. }
  1045. }
  1046. /// <summary>
  1047. /// UDDIWebResponse allows us to return our own Stream object.
  1048. /// </summary>
  1049. internal class UDDIWebResponse : WebResponse
  1050. {
  1051. WebResponse innerWebResponse;
  1052. UDDIResponseStream uddiResponseStream;
  1053. /// <summary>
  1054. /// Constructor
  1055. /// </summary>
  1056. /// <param name="innerWebResponse">This object should come from the WebResponse created by HttpSoapClientProtocol.</param>
  1057. public UDDIWebResponse( WebResponse innerWebResponse )
  1058. {
  1059. this.innerWebResponse = innerWebResponse;
  1060. }
  1061. /// <summary>
  1062. /// Return our response stream (UDDIResponseStream) instead of the Stream associated with our inner response.
  1063. /// </summary>
  1064. /// <returns></returns>
  1065. public override Stream GetResponseStream()
  1066. {
  1067. if( null == uddiResponseStream )
  1068. {
  1069. uddiResponseStream = new UDDIResponseStream( innerWebResponse.GetResponseStream() );
  1070. }
  1071. return uddiResponseStream;
  1072. }
  1073. /// <summary>
  1074. /// Delegates to the inner web response.
  1075. /// </summary>
  1076. public override void Close()
  1077. {
  1078. innerWebResponse.Close();
  1079. }
  1080. /// <summary>
  1081. /// Delegates to the inner web response.
  1082. /// </summary>
  1083. public override long ContentLength
  1084. {
  1085. get { return innerWebResponse.ContentLength; }
  1086. set { innerWebResponse.ContentLength = value; }
  1087. }
  1088. /// <summary>
  1089. /// Delegates to the inner web response.
  1090. /// </summary>
  1091. public override string ContentType
  1092. {
  1093. get { return innerWebResponse.ContentType; }
  1094. set { innerWebResponse.ContentType = value; }
  1095. }
  1096. /// <summary>
  1097. /// Delegates to the inner web response.
  1098. /// </summary>
  1099. public override Uri ResponseUri
  1100. {
  1101. get { return innerWebResponse.ResponseUri; }
  1102. }
  1103. /// <summary>
  1104. /// Delegates to the inner web response.
  1105. /// </summary>
  1106. public override WebHeaderCollection Headers
  1107. {
  1108. get { return innerWebResponse.Headers; }
  1109. }
  1110. }
  1111. /// <summary>
  1112. /// UDDIResponseStream allows us to manipulate the XML sent back from the web service.
  1113. /// </summary>
  1114. internal class UDDIResponseStream : MemoryStream
  1115. {
  1116. //
  1117. // TODO: at some point it may be necessary to pass in the current version as a parameter if the transforms become
  1118. // more complicated.
  1119. //
  1120. /// <summary>
  1121. /// Constructor. We read all the XML sent from the server, do our version manipulation, then write the new XML
  1122. /// into our inner responseStream object.
  1123. /// </summary>
  1124. /// <param name="responseStream">This object should be the responseStream from a WebResponse object.</param>
  1125. public UDDIResponseStream( Stream responseStream )
  1126. {
  1127. try
  1128. {
  1129. //
  1130. // Get the XML the server sent to us.
  1131. //
  1132. StreamReader reader = new StreamReader( responseStream );
  1133. string responseXml = reader.ReadToEnd();
  1134. reader.Close();
  1135. //
  1136. // Write this transformed XML into ourselves.
  1137. //
  1138. StreamUtility.WriteStringToStream( this, responseXml );
  1139. //
  1140. // Rewind ourselves
  1141. //
  1142. this.Position = 0;
  1143. //
  1144. // Validate the incoming XML. We have to read the data from the stream first because it is not seekable
  1145. //
  1146. try
  1147. {
  1148. SchemaCollection.Validate( this );
  1149. }
  1150. catch( XmlSchemaException schemaException )
  1151. {
  1152. string message = schemaException.ToString() + "\r\n\r\nResponse XML:\r\n\r\n" + responseXml;
  1153. Debug.OperatorMessage( SeverityType.Error, CategoryType.Replication, OperatorMessageType.ValidationError, message );
  1154. throw schemaException;
  1155. }
  1156. }
  1157. finally
  1158. {
  1159. //
  1160. // Rewind ourselves
  1161. //
  1162. this.Position = 0;
  1163. }
  1164. }
  1165. }
  1166. /// <summary>
  1167. /// UDDIWebRequest allows us to return our own request and response objects.
  1168. /// </summary>
  1169. /// <summary>
  1170. /// UDDIWebRequest allows us to return our own request and response objects.
  1171. /// </summary>
  1172. internal class UDDIWebRequest : WebRequest
  1173. {
  1174. WebRequest innerWebRequest;
  1175. UDDIRequestStream uddiRequestStream;
  1176. UDDIWebResponse uddiWebResponse;
  1177. /// <summary>
  1178. /// Constructor
  1179. /// </summary>
  1180. /// <param name="uri">Uri to the web service we are calling</param>
  1181. /// <param name="uddiVersion">UDDI version to use for requests</param>
  1182. public UDDIWebRequest( WebRequest innerWebRequest )
  1183. {
  1184. this.innerWebRequest = innerWebRequest;
  1185. }
  1186. /// <summary>
  1187. /// Return a UDDIRequestStream object instead of the default one.
  1188. /// </summary>
  1189. /// <returns>UDDIRequestStream object</returns>
  1190. public override Stream GetRequestStream()
  1191. {
  1192. if( null == uddiRequestStream )
  1193. {
  1194. uddiRequestStream = new UDDIRequestStream( innerWebRequest.GetRequestStream() );
  1195. }
  1196. return uddiRequestStream;
  1197. }
  1198. /// <summary>
  1199. /// Return a UDDIWebRequest object instead of the default one.
  1200. /// </summary>
  1201. /// <returns>UDDIWebResponse object</returns>
  1202. public override WebResponse GetResponse()
  1203. {
  1204. if( null == uddiWebResponse )
  1205. {
  1206. uddiWebResponse = new UDDIWebResponse( innerWebRequest.GetResponse() );
  1207. }
  1208. return uddiWebResponse;
  1209. }
  1210. /// <summary>
  1211. /// Delegates to our inner WebRequest
  1212. /// </summary>
  1213. public override string Method
  1214. {
  1215. get { return innerWebRequest.Method; }
  1216. set { innerWebRequest.Method = value; }
  1217. }
  1218. /// <summary>
  1219. /// Delegates to our inner WebRequest
  1220. /// </summary>
  1221. public override Uri RequestUri
  1222. {
  1223. get { return innerWebRequest.RequestUri; }
  1224. }
  1225. /// <summary>
  1226. /// Delegates to our inner WebRequest
  1227. /// </summary>
  1228. public override string ConnectionGroupName
  1229. {
  1230. get { return innerWebRequest.ConnectionGroupName; }
  1231. set { innerWebRequest.ConnectionGroupName = value; }
  1232. }
  1233. /// <summary>
  1234. /// Delegates to our inner WebRequest
  1235. /// </summary>
  1236. public override WebHeaderCollection Headers
  1237. {
  1238. get { return innerWebRequest.Headers; }
  1239. set { innerWebRequest.Headers = value; }
  1240. }
  1241. /// <summary>
  1242. /// Delegates to our inner WebRequest
  1243. /// </summary>
  1244. public override long ContentLength
  1245. {
  1246. get { return innerWebRequest.ContentLength; }
  1247. set { innerWebRequest.ContentLength = value; }
  1248. }
  1249. /// <summary>
  1250. /// Delegates to our inner WebRequest
  1251. /// </summary>
  1252. public override string ContentType
  1253. {
  1254. get { return innerWebRequest.ContentType; }
  1255. set { innerWebRequest.ContentType = value; }
  1256. }
  1257. /// <summary>
  1258. /// Delegates to our inner WebRequest
  1259. /// </summary>
  1260. public override ICredentials Credentials
  1261. {
  1262. get { return innerWebRequest.Credentials; }
  1263. set { innerWebRequest.Credentials = value; }
  1264. }
  1265. /// <summary>
  1266. /// Delegates to our inner WebRequest
  1267. /// </summary>
  1268. public override IWebProxy Proxy
  1269. {
  1270. get { return innerWebRequest.Proxy; }
  1271. set { innerWebRequest.Proxy = value; }
  1272. }
  1273. /// <summary>
  1274. /// Delegates to our inner WebRequest
  1275. /// </summary>
  1276. public override bool PreAuthenticate
  1277. {
  1278. get { return innerWebRequest.PreAuthenticate; }
  1279. set { innerWebRequest.PreAuthenticate = value; }
  1280. }
  1281. /// <summary>
  1282. /// Delegates to our inner WebRequest
  1283. /// </summary>
  1284. public override int Timeout
  1285. {
  1286. get { return innerWebRequest.Timeout; }
  1287. set { innerWebRequest.Timeout = value; }
  1288. }
  1289. /// <summary>
  1290. /// Delegates to our inner WebRequest
  1291. /// </summary>
  1292. public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state)
  1293. {
  1294. return innerWebRequest.BeginGetResponse( callback, state );
  1295. }
  1296. /// <summary>
  1297. /// Delegates to our inner WebRequest
  1298. /// </summary>
  1299. public override WebResponse EndGetResponse(IAsyncResult asyncResult)
  1300. {
  1301. return innerWebRequest.EndGetResponse( asyncResult );
  1302. }
  1303. /// <summary>
  1304. /// Delegates to our inner WebRequest
  1305. /// </summary>
  1306. public override IAsyncResult BeginGetRequestStream(AsyncCallback callback, Object state)
  1307. {
  1308. return innerWebRequest.BeginGetRequestStream( callback, state );
  1309. }
  1310. /// <summary>
  1311. /// Delegates to our inner WebRequest
  1312. /// </summary>
  1313. public override Stream EndGetRequestStream(IAsyncResult asyncResult)
  1314. {
  1315. return innerWebRequest.EndGetRequestStream( asyncResult );
  1316. }
  1317. /// <summary>
  1318. /// Delegates to our inner WebRequest
  1319. /// </summary>
  1320. public override void Abort()
  1321. {
  1322. innerWebRequest.Abort();
  1323. }
  1324. }
  1325. /// <summary>
  1326. /// UDDIRequestStream allows us to manipulate the XML before we send it to the client. This class will accept all data that
  1327. /// is written to it from the ASP.NET web service framework. When the framework closes the stream (ie. wants to send the data), we
  1328. /// will manipulate this XML so that it has the right UDDI version, then send it out using our innerStream object.
  1329. /// </summary>
  1330. internal class UDDIRequestStream : MemoryStream
  1331. {
  1332. Stream innerStream;
  1333. /// <summary>
  1334. /// Constructor
  1335. /// </summary>
  1336. /// <param name="innerStream">Should be from a WebRequest object.</param>
  1337. /// <param name="uddiVersion">The UDD version we should use to send to the server</param>
  1338. public UDDIRequestStream( Stream innerStream )
  1339. {
  1340. this.innerStream = innerStream;
  1341. }
  1342. /// <summary>
  1343. /// Before we actually close the request stream, we want to manipulate the XML.
  1344. /// </summary>
  1345. public override void Close()
  1346. {
  1347. try
  1348. {
  1349. //
  1350. // Rewind ourselves.
  1351. //
  1352. this.Position = 0;
  1353. //
  1354. // Read the XML that was written; this is the XML request that will be sent to the UDDI server.
  1355. //
  1356. StreamReader reader = new StreamReader( this );
  1357. string requestXml = reader.ReadToEnd();
  1358. //
  1359. // Rewind ourselves.
  1360. //
  1361. this.Position = 0;
  1362. #if DEBUG
  1363. try
  1364. {
  1365. //
  1366. // Validate the XML that we are about to send.
  1367. //
  1368. SchemaCollection.Validate( this );
  1369. }
  1370. catch( XmlSchemaException schemaException )
  1371. {
  1372. string message = schemaException.ToString() + "\r\n\r\nRequest XML:\r\n\r\n" + requestXml;
  1373. Debug.OperatorMessage( SeverityType.Error, CategoryType.Replication, OperatorMessageType.ValidationError, message );
  1374. throw schemaException;
  1375. }
  1376. #endif
  1377. //
  1378. // Write the transformed data to the 'real' stream.
  1379. //
  1380. StreamUtility.WriteStringToStream( innerStream, requestXml );
  1381. }
  1382. finally
  1383. {
  1384. //
  1385. // Make sure we clean up properly.
  1386. //
  1387. innerStream.Close();
  1388. base.Close();
  1389. }
  1390. }
  1391. }
  1392. /// <summary>
  1393. /// Simple utility class to help us write string data to Stream objects.
  1394. /// </summary>
  1395. internal sealed class StreamUtility
  1396. {
  1397. public static void WriteStringToStream( Stream stream, string stringToWrite )
  1398. {
  1399. StreamWriter writer = new StreamWriter( stream );
  1400. writer.Write( stringToWrite );
  1401. writer.Flush();
  1402. }
  1403. }
  1404. }