1 using System;
   2 using System.Text ;
   3 //using System.Diagnostics ;

   4 using System.Xml ;
   5 using System.Collections ;
   6 using System.Collections.Specialized ; // for ListDictionary

   7 using System.Net ; // for WebException

   8 using System.Runtime.Remoting ;
   9 using System.Runtime.Remoting.Channels ;
  10 using System.Runtime.Remoting.Channels.Http ;
  11 
  12 using SimpleLogLib ;
  13 using CookComputing.XmlRpc ;
  14 
  15 namespace XmlBlasterLib
  16 {
  17    /// <summary>

  18    /// Implémentation du client XmlBlaster

  19    /// </summary>

  20    public class XmlBlasterClient
  21    {
  22       IXmlBlasterClient xmlBlasterClientProxy ;
  23       XmlRpcClientProtocol xmlBlasterClientProtocol ;
  24 
  25       // TODO: Ajouter un identifiant de thread ou autre

  26       SimpleLog logger = SimpleLogLib.SimpleLogManager.GetLog("XmlBlasterClient", LogLevel.Debug );
  27 
  28       /// <summary>

  29       /// A utiliser par les qos

  30       /// </summary>

  31       internal static SimpleLog loggerQos = SimpleLogLib.SimpleLogManager.GetLog("XmlBlasterQos", LogLevel.Debug );
  32 
  33       //string uniqueId ;

  34       string sessionId ;
  35       public string SessionId
  36       {
  37          get { return this.sessionId ; }
  38       }
  39 
  40 
  41       Uri callbackServerUri ;
  42       public string Url
  43       {
  44          get { return xmlBlasterClientProtocol.Url ; }
  45          set { xmlBlasterClientProtocol.Url = value ; }
  46       }
  47 
  48       HttpChannel httpChannel ;
  49 
  50       public XmlBlasterClient()
  51       {
  52          //

  53          // Client

  54          //

  55 
  56          xmlBlasterClientProxy = (IXmlBlasterClient) XmlRpcProxyGen.Create(typeof(IXmlBlasterClient)) ;
  57          xmlBlasterClientProtocol = (XmlRpcClientProtocol) xmlBlasterClientProxy ;
  58 
  59          //

  60          // Callback Server

  61          //

  62 
  63          // On peut le faire depuis un fichier

  64          //RemotingConfiguration.Configure("xmlrpc.exe.config"); 

  65 
  66          // Ou bien à la mano

  67          try 
  68          {
  69             //int port = FindFreeHttpPort( 9090 ) ;

  70             //logger.Debug( "FindFreeHttpPort() found port "+port );

  71             // port = 0 pour que le système assigne automatiquement un port non-utilisé.

  72             int port = 0 ;
  73 
  74             ListDictionary channelProperties = new ListDictionary();
  75             channelProperties.Add( "port", port );
  76 
  77             httpChannel = new HttpChannel(
  78                channelProperties,
  79                new CookComputing.XmlRpc.XmlRpcClientFormatterSinkProvider(),
  80                new CookComputing.XmlRpc.XmlRpcServerFormatterSinkProvider(null,null)
  81                //new SoapClientFormatterSinkProvider(),

  82                //new SoapServerFormatterSinkProvider()

  83                );
  84          }
  85          catch( Exception ex )
  86          {
  87             // Listener config failed : Une seule utilisation de chaque adresse de socket (protocole/adresse réseau/port) est habituellement autorisée

  88             XmlBlasterException.HandleException( new Exception("XmlBlaster callback server, Listener config failed.", ex ) );
  89          }
  90 
  91          try
  92          {
  93             ChannelServices.RegisterChannel( httpChannel );
  94          }
  95          catch( System.Runtime.Remoting.RemotingException )
  96          {
  97             // Pas grave: The channel has already been registered.

  98          }
  99          catch( Exception ex )
 100          {
 101             XmlBlasterException.HandleException( new Exception("XmlBlasterCallback server, failed to RegisterChannel.", ex ) );
 102          }
 103 
 104          RemotingConfiguration.RegisterWellKnownServiceType( 
 105             typeof(XmlBlasterCallback), 
 106             "XmlBlasterCallback",
 107             WellKnownObjectMode.Singleton
 108             );
 109 
 110 
 111          // Comme on a pas indiqué de port, celui-ci a été assigné automatiquement.

 112          // Il nous faut donc retrouver l'url afin de pouvoir la transmettre dans le Qos de connexion.

 113 
 114          string[] urls = httpChannel.GetUrlsForUri("XmlBlasterCallback");
 115          foreach (string url in urls)
 116             logger.Debug("XmlBlasterCallback url: {0}", url);
 117          //url: http://192.168.0.151:4808/XmlBlasterCallback

 118          if( urls.Length != 1 )
 119          {
 120             XmlBlasterException.HandleException( new Exception("XmlBlasterCallback server, failed to retreive url." ) );
 121          }
 122          this.callbackServerUri = new Uri( urls[ 0 ] );
 123 
 124       }
 125 
 126 
 127       public void Connect( string url, string username, string password )
 128       {
 129          logger.Debug( "XmlBlaster.Connect()" );
 130          logger.Debug( "XmlBlaster.Connect() url:["+url+"]" );
 131 
 132          // reset

 133          this.sessionId = null ;
 134 
 135          this.Url = url ; // Set xml-rpc server url

 136 
 137          try
 138          {
 139             // try connect (login)

 140             // to construct authentification data

 141             QosConnect qos = new QosConnect( username,password,this.callbackServerUri.ToString() );
 142 
 143             XmlBlasterCallback.pingInterval = qos.PingInterval ;
 144 
 145             string result = xmlBlasterClientProxy.Connect( qos.ToString() );
 146 
 147             QosConnectResult qosConnectResult = new QosConnectResult( result );
 148 
 149             this.sessionId = qosConnectResult.SessionId ;
 150 
 151             // TODO: sessionId should be secret !

 152             // do something better ;o)

 153             //Random rnd = new Random( );

 154             //this.uniqueId = rnd.NextDouble().ToString() ;

 155          }
 156          catch( Exception ex )
 157          {
 158             // reset

 159             this.sessionId = null ;
 160 
 161             XmlBlasterException.HandleException(ex);
 162          }
 163       }
 164 
 165       public void Disconnect()
 166       {
 167          string me="Disconnect()";
 168          logger.Debug(me);
 169 
 170          // construct authentification data

 171          string qos = @"
 172             <qos>
 173                <deleteSubjectQueue>true</deleteSubjectQueue>
 174                <clearSessions>true</clearSessions>
 175             </qos>";
 176 
 177          try
 178          {
 179             xmlBlasterClientProxy.Disconnect( this.sessionId, qos );
 180          }
 181          catch( Exception ex )
 182          {
 183             //XmlBlasterException.HandleException(ex);

 184             logger.Error( "{0} Failed. Ex: {1}.", me, ex.Message );
 185          }
 186       }
 187 
 188 
 189       /// <summary>

 190       /// Make a subscribtion to messages that match the query.

 191       /// </summary>

 192       /// <param name="query">the query to subscribe to</param>

 193       /// <param name="xpath">is it an xpath query</param>

 194       /// <returns>the Subscribtion ID or null if failed</returns>

 195       public string Subscribe( string query, bool xpath )
 196       {
 197          string me="Subscribe()";
 198          logger.Debug(me);
 199 
 200          string key ;
 201          if( xpath )
 202          {
 203             key = "<key oid='' queryType='XPATH'>"+query+"</key>";
 204          }
 205          else
 206          {
 207             key = "<key oid=\""+query+"\" />\n" ;
 208          }
 209 
 210          StringBuilder qos = new StringBuilder();
 211          qos.Append("<qos>");
 212          //qos.Append("<initialUpdate>false</initialUpdate>");

 213          qos.Append("<local>false</local>");
 214          qos.Append("</qos>");
 215 
 216          return this.Subscribe( key, qos.ToString() );
 217       }
 218 
 219       public string Subscribe( string key, string qos )
 220       {
 221          string me="Subscribe()";
 222          logger.Debug(me);
 223 
 224          /* key exemples:
 225           *  exact :
 226           * <key oid='MyMessage' />
 227           * xpath :
 228           * <key oid='' queryType='XPATH'> /xmlBlaster/key[starts-with(@oid,'radar.')] </key>
 229           */
 230          try
 231          {
 232             string result = xmlBlasterClientProxy.Subscribe( this.sessionId, key, qos.ToString() );
 233 
 234             XmlBlasterLib.QosSubscribeResult qsr = new QosSubscribeResult( result );
 235 
 236             return qsr.SubscribeId ;
 237          }
 238          catch( Exception ex )
 239          {
 240             XmlBlasterException.HandleException(ex);
 241             return null ;
 242          }
 243       }
 244 
 245 
 246       public bool Unsubscribe( string subscribtionId )
 247       {
 248          string me="Unsubscribe()";
 249          logger.Debug( me );
 250 
 251          try
 252          {
 253             string key = "<key oid=\""+subscribtionId+"\" />\n" ;
 254             QosUnsubscribe qos = new QosUnsubscribe();
 255 
 256             string[] results = xmlBlasterClientProxy.Unsubscribe( this.sessionId, key, qos.ToString() );
 257 
 258             logger.Debug( "{0} results count={1}", me, results.Length );
 259             foreach( string s in results )
 260             {
 261                XmlBlasterLib.QosUnsubscribeResult qur = new QosUnsubscribeResult( s );
 262                logger.Debug( qur.ToString() );
 263             }
 264          }
 265          catch( Exception ex )
 266          {
 267             XmlBlasterException.HandleException(ex);
 268             return false ;
 269          }
 270 
 271          return true ;
 272       }
 273 
 274 
 275       public bool Publish( string topic, string xmlContent )
 276       {
 277          string me="Publish()";
 278          logger.Debug(me);
 279 
 280          string key = "<key oid=\""+topic+"\" contentMime=\"text/xml\" >\n" ;
 281          //key += "<sender>"+uniqueId+"</sender>\n" ;

 282          key += "</key>" ;
 283 
 284          string qos = "<qos />" ;
 285 
 286          return this.Publish( key, qos, xmlContent );
 287       }
 288 
 289       public bool Publish( string key, string qos, string xmlContent )
 290       {
 291          string me="Publish";
 292          logger.Debug(me);
 293          try
 294          {
 295             string result = xmlBlasterClientProxy.Publish( this.sessionId, key, xmlContent, qos );
 296 
 297             // TODO: Publish Qos Result

 298             return true ;
 299          }
 300          catch( Exception ex )
 301          {
 302             XmlBlasterException.HandleException(ex);
 303          }
 304          return false ;
 305       }
 306 
 307 
 308       public MessageUnit[] Get( string query, bool xpath )
 309       {
 310          string me="Get()";
 311          logger.Debug(me);
 312 
 313          string key ;
 314          if( xpath )
 315          {
 316             // exemple: <key oid='' queryType='XPATH'> /xmlBlaster/key[starts-with(@oid,'radar.')] </key>

 317             key = "<key oid='' queryType='XPATH'>"+query+"</key>";
 318          }
 319          else
 320          {
 321             key = "<key oid=\""+query+"\" />\n" ;
 322          }
 323          string qos = "<qos><content>true</content></qos>";
 324 
 325          return this.Get( key, qos );
 326       }
 327 
 328       public MessageUnit[] Get( string key, string qos )
 329       {
 330          string me="Get()";
 331          logger.Debug(me);
 332          MessageUnit[] msgs = null ;
 333          try
 334          {
 335             object[][] results = xmlBlasterClientProxy.Get( this.sessionId, key, qos );
 336 
 337             int nbrMsgs = results.Length ;
 338             logger.Debug("{0} nbrMsgs= {1}", me, nbrMsgs);
 339             msgs = new MessageUnit[nbrMsgs];
 340             for( int i=0; i<nbrMsgs; i++ )
 341             {
 342                try
 343                {
 344                   msgs[i] = new MessageUnit( (string) results[i][0], (byte[]) results[i][1], (string) results[i][2] );
 345                }
 346                catch(Exception ex)
 347                {
 348                   XmlBlasterException.HandleException( new Exception( me+" received a malformed message. Ex: "+ex.Message, ex ) );
 349                }
 350             }
 351 
 352          }
 353          catch( Exception ex )
 354          {
 355             XmlBlasterException.HandleException(ex);
 356          }
 357          return msgs ;
 358       }
 359 
 360 
 361       public bool Erase( string query, bool xpath )
 362       {
 363          string me="Erase()";
 364          logger.Debug(me);
 365 
 366          string key ;
 367          if( xpath )
 368          {
 369             // exemple: <key oid='' queryType='XPATH'> /xmlBlaster/key[starts-with(@oid,'radar.')] </key>

 370             key = "<key oid='' queryType='XPATH'>"+query+"</key>";
 371          }
 372          else
 373          {
 374             key = "<key oid=\""+query+"\" />\n" ;
 375          }
 376 
 377          string qos = "<qos />" ;
 378 
 379          return this.Erase( key, qos );
 380       }
 381 
 382       public bool Erase( string key, string qos )
 383       {
 384          string me="Erase()";
 385          logger.Debug(me);
 386          try
 387          {
 388             string[] results = xmlBlasterClientProxy.Erase( this.sessionId, key, qos );
 389 
 390             if( logger.IsDebug )
 391             {
 392                logger.Debug( "{0} Results:", me);
 393                foreach( string s in results )
 394                {
 395                   logger.Debug( "\tEraseQosResult: {0}", s);
 396                }
 397             }
 398 
 399             // TODO: Erase Qos Result

 400             return true ;
 401          }
 402          catch( Exception ex )
 403          {
 404             XmlBlasterException.HandleException(ex);
 405          }
 406          return false ;
 407       }
 408 
 409       /// <summary>

 410       /// L'interface IXmlBlasterClient représente les accès au serveur XmlBlaster

 411       /// via XmlRpc (CookComputing.XmlRpc).

 412       /// @see XmlBlasterClient.xmlBlasterClientProxy

 413       /// </summary>

 414       internal interface IXmlBlasterClient
 415       {
 416          [XmlRpcMethod("authenticate.connect")]
 417          string Connect( string connectQos );
 418 
 419          [XmlRpcMethod("authenticate.disconnect")]
 420          void Disconnect( string sessiondId, string qos );
 421 
 422          [XmlRpcMethod("xmlBlaster.publish")]
 423          string Publish( string sessiondId, string key, string xmlMessage, string qos );
 424 
 425          [XmlRpcMethod("xmlBlaster.subscribe")]
 426          string Subscribe( string sessiondId, string key, string qos );
 427 
 428          [XmlRpcMethod("xmlBlaster.unSubscribe")]
 429          string[] Unsubscribe( string sessiondId, string key, string qos );
 430 
 431          [XmlRpcMethod("xmlBlaster.get")]
 432          object[][] Get( string sessiondId, string key, string qos );
 433 
 434          [XmlRpcMethod("xmlBlaster.erase")]
 435          string[] Erase( string sessiondId, string key, string qos );
 436 
 437       }
 438 
 439    }
 440 
 441    /// <summary>

 442    /// La class XmlBlasterCallback représente les méthodes que nous exposons à l'extérieur via XmlRpc.

 443    /// C'est le serveur XmlBlaster qui appellera ces méthodes.

 444    /// Nous lui avons fourni notre adresse d'écoute au moment du Connect().

 445    /// </summary>

 446    public class XmlBlasterCallback : MarshalByRefObject 
 447    {
 448       // TODO: Ajouter un identifiant de thread ou autre

 449       static SimpleLog logger = SimpleLogLib.SimpleLogManager.GetLog("XmlBlasterCallback", LogLevel.Debug );
 450 
 451       //public delegate void MessageArrivedDelegate( string key, string xmlMessage, string sender, string subscribtionId );

 452       public delegate void MessageArrivedDelegate( XmlBlasterLib.MessageUnit msgUnit );
 453       public static /*event*/ MessageArrivedDelegate messageArrived ;
 454 
 455       //public delegate void PingArrivedDelegate();

 456       //public static PingArrivedDelegate pingArrived ;

 457 
 458       internal static int pingLastTime = 0 ;
 459       internal static int pingInterval = 0 ;
 460 
 461       public enum XmlBlasterServerHealthStatus
 462       {
 463          VERYGOOD, GOOD, BAD, VERY_BAD, DEAD
 464       }
 465 
 466       public static XmlBlasterServerHealthStatus XmlBlasterServerHealth
 467       {
 468          get
 469          {
 470             if( pingLastTime == 0 )
 471             {
 472                return XmlBlasterServerHealthStatus.DEAD ;
 473             }
 474             int lap = Environment.TickCount - pingLastTime ;
 475             if( lap <= pingInterval/2 )
 476             {
 477                return XmlBlasterServerHealthStatus.VERYGOOD ;
 478             }
 479             else if( lap <= pingInterval )
 480             {
 481                return XmlBlasterServerHealthStatus.GOOD ;
 482             }
 483             else if( lap <= (pingInterval+pingInterval/2) )
 484             {
 485                return XmlBlasterServerHealthStatus.BAD ;
 486             }
 487             else if( lap <= (pingInterval*2) )
 488             {
 489                return XmlBlasterServerHealthStatus.VERY_BAD ;
 490             }
 491             return XmlBlasterServerHealthStatus.DEAD ;
 492          }
 493       }
 494 
 495 
 496       [XmlRpcMethod("ping")] 
 497       public string Ping( string msg ) 
 498       {
 499          // XML-RPC message :

 500          // [12-Nov-2005 11:18:15] string(144) "<?xml version="1.0" encoding="ISO-8859-1"?><methodCall><methodName>ping</methodName><params><param><value></value></param></params></methodCall>"

 501 
 502          logger.Debug( "Ping()" );
 503 
 504          //logger.Debug( "\t msg: ", msg );

 505 
 506          // refresh last server heartbeat

 507          pingLastTime = Environment.TickCount ;
 508 
 509          //if( XmlBlasterCallback.pingArrived != null )

 510          //{

 511          // //XmlBlasterCallback.pingArrived();

 512          // // Asynchronously invoke the method.

 513          // IAsyncResult ar = XmlBlasterCallback.pingArrived.BeginInvoke( null, null );

 514          //}

 515 
 516          return "<qos><state>OK</state></qos>" ;
 517       }
 518 
 519 
 520       [XmlRpcMethod("update")] 
 521       public string Update( string cbSessionId, string key, System.Byte[] content, string qos ) 
 522       {
 523          string me="Update()";
 524          logger.Debug(me);
 525 
 526          // refresh last server heartbeat

 527          pingLastTime = Environment.TickCount ;
 528 
 529          // Note (from requirements/interface.update.html)

 530          //

 531          // Be prepared to receive all sorts of messages on update,

 532          // like normal messages or internal xmlBlaster messages or administrative command messages.

 533          //

 534 
 535          /*
 536             XmlBlasterCallback.Update() cbSessionId: 
 537                unknown
 538             XmlBlasterCallback.Update() key: 
 539                <key oid='__sys__UserList'>
 540                   <__sys__internal/>
 541                </key>
 542             XmlBlasterCallback.Update() qos: 
 543                <qos>
 544                   <sender>/node/xmlBlaster_127_0_0_1_3412/client/__RequestBroker_internal[xmlBlaster_127_0_0_1_3412]/1</sender>
 545                   <subscribe id='__subId:xmlBlaster_127_0_0_1_3412-XPATH1132587264334000000'/>
 546                   <expiration lifeTime='-1'/>
 547                   <rcvTimestamp nanos='1132587264254000001'/>
 548                   <queue index='0' size='3'/>
 549                   <forceUpdate/>
 550                   <isPublish/>
 551                </qos>
 552             */
 553 
 554          /*
 555          logger.Debug( "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" );
 556          logger.Debug( "{0} cbSessionId: {1}", me, cbSessionId ); // SecretSessionId, so should be 'Unknow'.
 557          logger.Debug( "{0} key:\n{1}", me, key );
 558          logger.Debug( "{0} qos:\n{1}", me, qos );
 559          logger.Debug( "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" );
 560          */
 561 
 562 
 563          if( XmlBlasterCallback.messageArrived != null )
 564          {
 565             //string xml = Encoding.Default.GetString( msg );

 566             //XmlBlasterCallback.messageArrived( key, xml, qosUpdate.Sender, qosUpdate.SubscribeId );

 567             MessageUnit msg ;
 568             try
 569             {
 570                msg = new MessageUnit( key, content, qos );
 571 
 572                try
 573                {
 574                   //XmlBlasterCallback.messageArrived( msg );

 575 
 576                   //logger.Debug( "{0} InvocationList: {1}", me, XmlBlasterCallback.messageArrived.GetInvocationList().Length );

 577                   // Asynchronously invoke the method.

 578                   IAsyncResult ar = XmlBlasterCallback.messageArrived.BeginInvoke( msg, null, null );
 579                   //XmlBlasterCallback.messageArrived.EndInvoke(ar);

 580                }
 581                catch( Exception ex )
 582                {
 583                   logger.Error( "{0} Failed to fire messageArrived. Ex: {1}", me, ex.Message );
 584                }
 585             }
 586             catch( Exception ex )
 587             {
 588                logger.Error( "{0} Received a malformed message. Ex: {1}", me, ex.Message );
 589             }
 590          }
 591 
 592          return "<qos><state>OK</state></qos>";
 593       }
 594    }
 595 
 596 
 597    /// <summary>

 598    /// Transforme toutes les exceptions catchée dans le client XmlBlaster

 599    /// en exception du type XmlBlasterException afin de clarifier les erreurs.

 600    /// Le code utilisateur de XmlBlasterClient ne verra que des exceptions de ce type.

 601    /// </summary>

 602    public class XmlBlasterException : Exception
 603    {
 604       const string exceptionMessage = "XmlBlaster operation has failed.";
 605 
 606       internal XmlBlasterException()
 607          : base( exceptionMessage )
 608       {
 609       }
 610 
 611       internal XmlBlasterException( string auxMessage )
 612          : base( String.Format( "{0} - {1}", exceptionMessage, auxMessage ) )
 613       {
 614       }
 615 
 616       internal XmlBlasterException( string auxMessage, Exception inner )
 617          : base( String.Format( "{0} - {1}", exceptionMessage, auxMessage ), inner )
 618       {
 619       }
 620 
 621       internal XmlBlasterException( Exception inner )
 622          : base( String.Format( "{0} - {1}", exceptionMessage, inner.Message ), inner )
 623       {
 624       }
 625 
 626       protected static SimpleLog logger = SimpleLogLib.SimpleLogManager.GetLog("XmlBlasterException");
 627 
 628       /// <summary>

 629       /// Pour transformer toutes les exceptions en XmlBlasterException

 630       /// </summary>

 631       /// <param name="ex"></param>

 632       internal static void HandleException( Exception ex )
 633       {
 634          logger.Error( "HandleException() {0}", ex.Message );
 635          logger.Error( "HandleException() {0}", ex.StackTrace );
 636 
 637          //string msgBoxTitle = "Error" ;

 638          try
 639          {
 640             throw ex;
 641          }
 642          catch(XmlRpcFaultException fex)
 643          {
 644             //MessageBox.Show("Fault Response: " + fex.FaultCode + " " 

 645             // + fex.FaultString, msgBoxTitle,

 646             // MessageBoxButtons.OK, MessageBoxIcon.Error);

 647             throw new XmlBlasterException( fex.FaultString, fex ) ;
 648          }
 649          catch(WebException webEx)
 650          {
 651             //MessageBox.Show("WebException: " + webEx.Message, msgBoxTitle,

 652             // MessageBoxButtons.OK, MessageBoxIcon.Error);

 653             if (webEx.Response != null)
 654                webEx.Response.Close();
 655             throw new XmlBlasterException( webEx ) ;
 656          }
 657          catch(XmlRpcServerException xmlRpcEx)
 658          {
 659             //MessageBox.Show("XmlRpcServerException: " + xmlRpcEx.Message, 

 660             // msgBoxTitle,

 661             // MessageBoxButtons.OK, MessageBoxIcon.Error);

 662             throw new XmlBlasterException( xmlRpcEx ) ;
 663          }
 664          catch(Exception defEx)
 665          {
 666             //MessageBox.Show("Exception: " + defEx.Message, msgBoxTitle,

 667             // MessageBoxButtons.OK, MessageBoxIcon.Error);

 668             throw new XmlBlasterException( defEx ) ;
 669          }
 670       }
 671 
 672    }
 673 
 674 
 675    public class MessageUnit
 676    {
 677       static SimpleLog logger = SimpleLogLib.SimpleLogManager.GetLog("XmlBlaster.MessageUnit", LogLevel.Debug );
 678 
 679       //string xml = Encoding.Default.GetString( msg );

 680 
 681       public MessageUnit( string key, byte[] content, string qos )
 682       {
 683          string me="MessageUnit()";
 684          logger.Debug("{0} message key: {1}", me, key );
 685 
 686          //this.key = new MessageKey( key );

 687          this.keyStr = key ;
 688          this.contentBytes = content ;
 689          this.qos = new QosMessageUnit( qos );
 690       }
 691 
 692 
 693       QosMessageUnit qos ;
 694       public QosMessageUnit Qos
 695       {
 696          get
 697          {
 698             return this.qos ;
 699          }
 700       }
 701 
 702 
 703       byte[] contentBytes ;
 704       string contentStr ;
 705       public string ContentStr
 706       {
 707          get
 708          {
 709             if( this.contentStr == null )
 710             {
 711                this.contentStr = Encoding.Default.GetString( this.contentBytes );
 712             }
 713             return this.contentStr ;
 714          }
 715       }
 716       public byte[] ContentBytes
 717       {
 718          get
 719          {
 720             return this.contentBytes ;
 721          }
 722       }
 723 
 724 
 725       string keyStr ;
 726       XmlDocument keyXmlDoc ;
 727       public string KeyStr
 728       {
 729          get
 730          {
 731             return this.keyStr ;
 732          }
 733       }
 734       public string KeyOid
 735       {
 736          get 
 737          {
 738             //return this.key.Oid ;

 739             if( this.keyStr != null )
 740             {
 741                try
 742                {
 743                   if( this.keyXmlDoc == null )
 744                   {
 745                      this.keyXmlDoc = new XmlDocument();
 746                      this.keyXmlDoc.LoadXml( this.keyStr );
 747                   }
 748                   //XmlNode node = this.keyXmlDoc.DocumentElement.SelectSingleNode("key");

 749                   //return (string) node.Attributes[ "oid" ].Value ;

 750                   return this.keyXmlDoc.DocumentElement.Attributes[ "oid" ].Value ;
 751                }
 752                catch(Exception ex )
 753                {
 754                   logger.Error( "MessageUnit.KeyOid() Failed. Ex: "+ex.Message );
 755                }
 756                return null ;
 757             }
 758             return null ;
 759          }
 760       }
 761 
 762       public string KeyQuery
 763       {
 764          get
 765          {
 766             if( this.keyStr != null )
 767             {
 768                try
 769                {
 770                   if( this.keyXmlDoc == null )
 771                   {
 772                      this.keyXmlDoc = new XmlDocument();
 773                      this.keyXmlDoc.LoadXml( this.keyStr );
 774                   }
 775                   return this.keyXmlDoc.DocumentElement.InnerText.ToString();
 776                }
 777                catch(Exception ex )
 778                {
 779                   logger.Error( "MessageUnit.KeyOid() Failed. Ex: "+ex.Message );
 780                }
 781                return null ;
 782             }
 783             return null ;
 784          }
 785       }
 786 
 787    }
 788 
 789    #region Les Qos (QosConnect, QosUpdate, ...

 790 
 791    public class QosConnect
 792    {
 793       const int DEFAULT_PINGINTERVAL = 5000 ;
 794 
 795       static SimpleLog logger = XmlBlasterClient.loggerQos ;
 796 
 797 
 798       public string securityService_type = "htpasswd" ;
 799       public string securityService_version = "1.0" ;
 800       public string username ;
 801       public string password ;
 802       public string callbackUri = null ;
 803 
 804       Hashtable options ;
 805 
 806       public int PingInterval 
 807       {
 808          get
 809          {
 810             try{ return Convert.ToInt32( this.options["pingInterval"] ); }catch{}
 811             return 0 ;
 812          }
 813       }
 814 
 815       internal QosConnect()
 816       {
 817          // Setting default options

 818          options = new Hashtable();
 819          options.Add( "pingInterval", DEFAULT_PINGINTERVAL );
 820       }
 821       public QosConnect( string username, string password )
 822          : this()
 823       {
 824          this.username = username ;
 825          this.password = password ;
 826          this.callbackUri = null ;
 827       }
 828       public QosConnect( string username, string password, string callbackUri )
 829          : this()
 830       {
 831          this.username = username ;
 832          this.password = password ;
 833          this.callbackUri = callbackUri ;
 834       }
 835 
 836       public QosConnect( string username, string password, string callbackUri, Hashtable options )
 837          : this()
 838       {
 839          this.username = username ;
 840          this.password = password ;
 841          this.callbackUri = callbackUri ;
 842 
 843          // Options Merge: user overload or add options

 844          try
 845          {
 846             foreach( object key in options )
 847             {
 848                if( this.options.ContainsKey( key ) )
 849                {
 850                   this.options[ key ] = options[ key ];
 851                }
 852                else
 853                {
 854                   this.options.Add( key, options[ key ] );
 855                }
 856             }
 857          }
 858          catch( Exception ex )
 859          {
 860             logger.Warn("Failed to understand options. Ex: "+ex.Message );
 861          }
 862       }
 863 
 864       public override string ToString()
 865       {
 866          string me="ToString()";
 867 
 868          StringBuilder sb = new StringBuilder( 255 );
 869 
 870          sb.Append( "<qos>\n" );
 871 
 872          sb.Append( " <securityService type=\""+this.securityService_type + "\" version=\""+this.securityService_version+"\">\n" );
 873          sb.Append( "  <user>"+ this.username +"</user>\n" );
 874          sb.Append( "  <passwd>"+ this.password +"</passwd>\n" );
 875          sb.Append( " </securityService>\n" );
 876 
 877          if( callbackUri != null )
 878          {
 879             sb.Append( "<callback type=\"XMLRPC\" retries=\"2\" delay=\"2000\" pingInterval=\""+this.options["pingInterval"].ToString()+"\" >" );
 880             //sb.Append( "http://192.168.0.151:9090/RPC2" );

 881             //sb.Append( "http://127.0.0.1:9090/RPC2" );

 882 
 883             //sb.Append( "http://127.0.0.1:8090/EssaisDivers/xmlBLaster.essais/demo.php/callback.php" );

 884             //sb.Append( "http://127.0.0.1:9090/XmlBlasterCallback" );

 885             sb.Append( this.callbackUri );
 886 
 887             sb.Append( "</callback>\n" );
 888          }
 889 
 890          // Subscribe Qos ?

 891          //sb.Append( "<local>false</local>\n" );

 892 
 893          sb.Append( "</qos>\n" );
 894 
 895          string s = sb.ToString() ;
 896          logger.Debug("{0} XML:\n{1}", me, s );
 897          return s ;
 898       }
 899 
 900    }
 901 
 902    public class QosConnectResult
 903    {
 904       static SimpleLog logger = XmlBlasterClient.loggerQos ;
 905 
 906       /*
 907       <qos>
 908          <securityService type="htpasswd" version="1.0">
 909             <user>guest</user>
 910             <passwd>guest</passwd>
 911          </securityService>
 912          <instanceId>/xmlBlaster/node/xmlBlaster_192_168_0_151_3412/instanceId/1131719045135</instanceId>
 913          <session name='/node/xmlBlaster_192_168_0_151_3412/client/guest/-4'
 914             timeout='86400000' maxSessions='10' clearSessions='false' reconnectSameClientOnly='false'
 915             sessionId='sessionId:192.168.0.151-null-1131720478106-2108614840-5'
 916          />
 917          <queue relating='connection' maxEntries='10000000' maxEntriesCache='1000'>
 918             <address type='IOR' dispatchPlugin='undef'>
 919             </address>
 920          </queue>
 921          <queue relating='subject'/>
 922          <queue relating='callback' maxEntries='1000' maxEntriesCache='1000'/>
 923       </qos>
 924        */
 925       protected XmlDocument xmlDoc ;
 926       public QosConnectResult( string xml )
 927       {
 928          logger.Debug("Create with XML:\n{0}", xml );
 929 
 930          this.xmlDoc = new XmlDocument();
 931          xmlDoc.LoadXml( xml );
 932       }
 933 
 934       public string SessionId
 935       {
 936          get 
 937          {
 938             string s = null ;
 939             try
 940             {
 941                XmlNode root = xmlDoc.DocumentElement ;
 942                XmlNode node ;
 943                //node = root.SelectSingleNode("descendant::book[author/last-name='Austen']");

 944                node = root.SelectSingleNode("session");
 945                s = node.Attributes[ "sessionId" ].Value ;
 946             }
 947             catch( Exception ex )
 948             {
 949                logger.Error("Failed to retreive SessionId. Ex: {0}", ex.Message );
 950             }
 951             logger.Debug("sessionId : {0}", s );
 952             return s ;
 953          }
 954       }
 955    }
 956 
 957    public class QosSubscribeResult : XmlDocument
 958    {
 959       static SimpleLog logger = XmlBlasterClient.loggerQos ;
 960 
 961       /*
 962          <qos>
 963          <subscribe id='__subId:xmlBlaster_127_0_0_1_3412-XPATH1132586655128000000'/>
 964          <isSubscribe/>
 965          </qos>
 966       */
 967       protected string subscribeId ;
 968       public QosSubscribeResult( string xml )
 969       {
 970          logger.Debug("Create with XML:\n{0}", xml );
 971 
 972          this.LoadXml( xml );
 973       }
 974       public string SubscribeId
 975       {
 976          get 
 977          {
 978             if( subscribeId == null )
 979             {
 980                XmlNode root = this.DocumentElement ;
 981                XmlNode node = root.SelectSingleNode("subscribe");
 982                this.subscribeId = node.Attributes[ "id" ].Value ;
 983             }
 984             logger.Debug("QosSubscribeResult.SubscribeId : "+this.subscribeId);
 985             return this.subscribeId ;
 986          }
 987       }
 988    }
 989 
 990    public class QosUnsubscribe : XmlDocument
 991    {
 992       static SimpleLog logger = XmlBlasterClient.loggerQos ;
 993 
 994       public QosUnsubscribe()
 995       {
 996          string xml = "<qos/>";
 997          logger.Debug("Create with XML:\n{0}", xml );
 998          this.LoadXml( xml );
 999       }
1000       public override string ToString()
1001       {
1002          return base.OuterXml ;
1003       }
1004    }
1005 
1006    public class QosUnsubscribeResult : XmlDocument
1007    {
1008       static SimpleLog logger = XmlBlasterClient.loggerQos ;
1009 
1010       public QosUnsubscribeResult( string xml )
1011       {
1012          logger.Debug("Create with XML:\n{0}", xml );
1013          this.LoadXml( xml );
1014       }
1015       public override string ToString()
1016       {
1017          return base.OuterXml ;
1018       }
1019    }
1020 
1021    public class QosUpdate : XmlDocument
1022    {
1023       static SimpleLog logger = XmlBlasterClient.loggerQos ;
1024       /*
1025       XmlBlasterCallback.Update() cbSessionId: 
1026          unknown
1027       XmlBlasterCallback.Update() key: 
1028          <key oid='__sys__UserList'>
1029             <__sys__internal/>
1030          </key>
1031       XmlBlasterCallback.Update() qos: 
1032          <qos>
1033             <sender>/node/xmlBlaster_127_0_0_1_3412/client/__RequestBroker_internal[xmlBlaster_127_0_0_1_3412]/1</sender>
1034             <subscribe id='__subId:xmlBlaster_127_0_0_1_3412-XPATH1132587264334000000'/>
1035             <expiration lifeTime='-1'/>
1036             <rcvTimestamp nanos='1132587264254000001'/>
1037             <queue index='0' size='3'/>
1038             <forceUpdate/>
1039             <isPublish/>
1040          </qos>
1041       */
1042       protected string sender ;
1043       protected string subscribeId ;
1044 
1045       public QosUpdate( string xml )
1046       {
1047          logger.Debug("Create with XML:\n{0}", xml );
1048          this.LoadXml( xml );
1049       }
1050 
1051       public string SubscribeId
1052       {
1053          get 
1054          {
1055             if( subscribeId == null )
1056             {
1057                XmlNode node = this.DocumentElement.SelectSingleNode("subscribe");
1058                this.subscribeId = node.Attributes[ "id" ].Value ;
1059             }
1060             logger.Debug("QosUpdate.SubscribeId: {0}", this.subscribeId );
1061             return this.subscribeId ;
1062          }
1063       }
1064       public string Sender
1065       {
1066          get 
1067          {
1068             if( sender == null )
1069             {
1070                XmlNode node = this.DocumentElement.SelectSingleNode("sender");
1071                this.sender = node.InnerText ;
1072             }
1073             logger.Debug("QosUpdate.Sender: {0} ", this.sender );
1074             return sender ;
1075          }
1076       }
1077    }
1078    public class QosErase
1079    {
1080       static SimpleLog logger = XmlBlasterClient.loggerQos ;
1081 
1082       bool forceDestroy = false ;
1083       public bool ForceDestroy
1084       {
1085          get
1086          {
1087             return this.forceDestroy ;
1088          }
1089          set 
1090          {
1091             this.forceDestroy = value ;
1092          }
1093       }
1094       int numEntries = -1 ;
1095       public int NumEntries 
1096       {
1097          get
1098          {
1099             return this.numEntries ;
1100          }
1101          set
1102          {
1103             this.numEntries = value ;
1104          }
1105       }
1106       public QosErase()
1107       {
1108       }
1109       public override string ToString()
1110       {
1111          StringBuilder sb = new StringBuilder( 256 );
1112          sb.Append( "<qos>\n" );
1113          sb.Append( "<erase forceDestroy=\""+(forceDestroy?"true":"false")+"\" >" );
1114          sb.Append( "<history numEntries=\""+numEntries.ToString()+"\" />" );
1115          sb.Append( "</erase>" );
1116          sb.Append( "</qos>" );
1117 
1118          if( logger.IsDebug )
1119          {
1120             logger.Debug("QosErase.ToString() XML:\n{0}", sb.ToString() );
1121          }
1122          return sb.ToString() ;
1123       }
1124    }
1125 
1126    public class QosMessageUnit : XmlDocument
1127    {
1128       static SimpleLog logger = XmlBlasterClient.loggerQos ;
1129 
1130       /*
1131       XmlBlasterCallback.Update() cbSessionId: 
1132          unknown
1133       XmlBlasterCallback.Update() key: 
1134          <key oid='__sys__UserList'>
1135             <__sys__internal/>
1136          </key>
1137       XmlBlasterCallback.Update() qos: 
1138          <qos>
1139             <sender>/node/xmlBlaster_127_0_0_1_3412/client/__RequestBroker_internal[xmlBlaster_127_0_0_1_3412]/1</sender>
1140             <subscribe id='__subId:xmlBlaster_127_0_0_1_3412-XPATH1132587264334000000'/>
1141             <expiration lifeTime='-1'/>
1142             <rcvTimestamp nanos='1132587264254000001'/>
1143             <queue index='0' size='3'/>
1144             <forceUpdate/>
1145             <isPublish/>
1146          </qos>
1147       */
1148 
1149       protected string sender ;
1150       protected string subscribeId ;
1151       public QosMessageUnit( string xml )
1152       {
1153          string me="QosMessageUnit.QosMessageUnit()";
1154          logger.Debug("{0} XML:\n{1}", me, xml );
1155 
1156          this.LoadXml( xml );
1157       }
1158 
1159       public string SubscribeId
1160       {
1161          get 
1162          {
1163             if( subscribeId == null )
1164             {
1165                XmlNode node = this.DocumentElement.SelectSingleNode("subscribe");
1166                this.subscribeId = node.Attributes[ "id" ].Value ;
1167             }
1168             logger.Debug("QosMessageUnit.SubscribeId: {0}", this.subscribeId );
1169             return this.subscribeId ;
1170          }
1171       }
1172       public string Sender
1173       {
1174          get 
1175          {
1176             if( sender == null )
1177             {
1178                XmlNode node = this.DocumentElement.SelectSingleNode("sender");
1179                this.sender = node.InnerText ;
1180             }
1181             logger.Debug("QosMessageUnit.Sender: {0} ", this.sender );
1182             return sender ;
1183          }
1184       }
1185    }
1186 
1187 
1188    #endregion

1189 
1190 }


syntax highlighted by Code2HTML, v. 0.9.1