1 /*----------------------------------------------------------------------------
  2 Name:      XmlBlasterAccess.cs
  3 Project:   xmlBlaster.org
  4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
  5 Comment:   Provides abstraction to xmlBlaster access from C#
  6 Author:    "Marcel Ruff" <xmlBlaster@marcelruff.info>
  7 Date:      07/2006
  8 See:       http://www.xmlblaster.org/xmlBlaster/doc/requirements/interface.html
  9 -----------------------------------------------------------------------------*/
 10 using System;
 11 using System.Text;
 12 using System.Collections;
 13 using System.Runtime.InteropServices;
 14 using org.xmlBlaster.util;
 15 
 16 namespace org.xmlBlaster.client
 17 {
 18    /// Calling unmanagegd code: xmlBlasterClientC.dll

 19    public class XmlBlasterAccess : I_XmlBlasterAccess, I_ConnectionStateListener, I_ProgressCallback, I_LoggingCallback
 20    {
 21       private I_XmlBlasterAccess delegateXb;
 22 
 23       private Hashtable properties;
 24 
 25       private long pingIntervalMillis = 10000;
 26 
 27       private long pollIntervalMillis = 5000;
 28 
 29       private I_ConnectionStateListener connectionStateListener;
 30 
 31       private XbPinger xbPinger;
 32 
 33       private XbPoller xbPoller;
 34 
 35       private I_LoggingCallback loggingCallback;
 36 
 37       private I_ProgressCallback progressCallback;
 38 
 39       private I_Callback callback;
 40 
 41       private volatile string connectQosStr;
 42 
 43       private volatile ConnectReturnQos connectReturnQos;
 44 
 45       private volatile bool connectCalled = false;
 46 
 47       private volatile bool initializeCalled = false;
 48 
 49       private volatile bool disconnectCalled = false;
 50 
 51       private volatile bool isDead = false;
 52 
 53       private volatile bool pollOnInitialConnectFail = false;
 54 
 55       private volatile ConnectionStateEnum currentState = ConnectionStateEnum.UNDEF;
 56 
 57       private I_GprsManager gprsManager;
 58 
 59       public XmlBlasterAccess()
 60       {
 61          this.delegateXb = CreateNative();
 62       }
 63 
 64       private I_XmlBlasterAccess CreateNative()
 65       {
 66          I_XmlBlasterAccess native = XmlBlasterAccessFactory.CreateInstance("org.xmlBlaster.client.PInvokeCE");
 67          native.RegisterConnectionListener(this);
 68          native.AddLoggingListener(this);
 69          native.AddCallbackProgressListener(this);
 70          native.Initialize(this.properties);
 71          return native;
 72       }
 73 
 74       public void Initialize(string[] argv)
 75       {
 76          this.delegateXb.Initialize(argv);
 77       }
 78 
 79       public void Initialize(Hashtable properties)
 80       {
 81          this.initializeCalled = true;
 82          if (properties == null) properties = new Hashtable();
 83          this.properties = properties;
 84          if (this.properties.Contains("I_GprsManager"))
 85          {
 86             this.gprsManager = (I_GprsManager)this.properties["I_GprsManager"];
 87             this.properties.Remove("I_GprsManager"); // we later expect strings only

 88          }
 89          this.pingIntervalMillis = Stuff.Get(properties, "dispatch/connection/pingInterval", this.pingIntervalMillis);
 90          this.pollIntervalMillis = Stuff.Get(properties, "dispatch/connection/delay", this.pollIntervalMillis);
 91          this.pollOnInitialConnectFail = Stuff.Get(properties, "dispatch/connection/pollOnInitialConnectFail", this.pollOnInitialConnectFail);
 92          //int retries = (int)Stuff.Get(properties, "dispatch/connection/retries", -1);

 93          this.xbPinger = new XbPinger(this, this.pingIntervalMillis, this);
 94          this.xbPoller = new XbPoller(this, this.pollIntervalMillis, this);
 95          this.delegateXb.Initialize(this.properties);
 96       }
 97 
 98       public void RegisterConnectionListener(I_ConnectionStateListener connectionStateListener)
 99       {
100          this.connectionStateListener = connectionStateListener;
101          this.delegateXb.RegisterConnectionListener(this);
102       }
103 
104       public void CheckValid()
105       {
106          if (!this.initializeCalled)
107             throw new XmlBlasterException("user.illegalargument", "Please initialize XmlBlasterAccess first");
108          if (this.disconnectCalled)
109             throw new XmlBlasterException("user.illegalargument", "XmlBlasterAccess is shutdown");
110          if (this.isDead)
111             throw new XmlBlasterException("user.illegalargument", "XmlBlasterAccess is connection is DEAD");
112       }
113 
114       public bool IsValid()
115       {
116          try
117          {
118             this.CheckValid();
119             return true;
120          }
121          catch (Exception)
122          {
123             return false;
124          }
125       }
126 
127       public ConnectReturnQos Connect(string qos, I_Callback listener)
128       {
129          try
130          {
131             this.CheckValid();
132             this.connectQosStr = qos;
133             this.callback = listener;
134             this.connectCalled = true; // before connect()

135             this.disconnectCalled = false;
136             this.connectReturnQos = this.delegateXb.Connect(qos, listener);
137             this.xbPoller.Stop();
138             this.xbPinger.Start();
139             return this.connectReturnQos;
140          }
141          catch (Exception e)
142          {
143             if (this.pollOnInitialConnectFail)
144             {
145                StartPolling();
146                return null;
147             }
148             else
149             {
150                throw e;
151             }
152          }
153       }
154 
155       public bool Disconnect(string qos)
156       {
157          this.CheckValid();
158          this.disconnectCalled = true;
159          bool ret = this.delegateXb.Disconnect(qos);
160          Shutdown();
161          return ret;
162       }
163 
164       public void LeaveServer()
165       {
166          this.CheckValid();
167          this.disconnectCalled = true;
168          this.delegateXb.LeaveServer();
169          Shutdown();
170       }
171 
172       private void Shutdown()
173       {
174          this.isDead = true;
175          ConnectionStateEnum oldState = this.currentState;
176          StopPinging();
177          StopPolling();
178          this.currentState = ConnectionStateEnum.DEAD;
179          callStateListener(oldState, ConnectionStateEnum.DEAD);
180       }
181 
182       public PublishReturnQos Publish(MsgUnit msgUnit)
183       {
184          this.CheckValid();
185          return this.delegateXb.Publish(msgUnit);
186       }
187 
188       public PublishReturnQos Publish(string key, string content, string qos)
189       {
190          this.CheckValid();
191          return this.delegateXb.Publish(key, content, qos);
192       }
193 
194       public void PublishOneway(MsgUnit[] msgUnitArr)
195       {
196          this.CheckValid();
197          this.delegateXb.PublishOneway(msgUnitArr);
198       }
199 
200       public SubscribeReturnQos Subscribe(string key, string qos)
201       {
202          this.CheckValid();
203          return this.delegateXb.Subscribe(key, qos);
204       }
205 
206       public UnSubscribeReturnQos[] UnSubscribe(string key, string qos)
207       {
208          this.CheckValid();
209          return this.delegateXb.UnSubscribe(key, qos);
210       }
211 
212       public EraseReturnQos[] Erase(string key, string qos)
213       {
214          this.CheckValid();
215          return this.delegateXb.Erase(key, qos);
216       }
217 
218       public MsgUnitGet[] Get(string key, string qos)
219       {
220          this.CheckValid();
221          return this.delegateXb.Get(key, qos);
222       }
223 
224       public string Ping(string qos)
225       {
226          this.CheckValid();
227          return this.delegateXb.Ping(qos);
228       }
229 
230       public bool IsConnected()
231       {
232          if (!this.IsValid()) return false;
233          return this.delegateXb.IsConnected();
234       }
235 
236       public string GetVersion()
237       {
238          return this.delegateXb.GetVersion();
239       }
240 
241       public string GetUsage()
242       {
243          return this.delegateXb.GetUsage();
244       }
245 
246       public void OnLogging(XmlBlasterLogLevel logLevel, string location, string message)
247       {
248          I_LoggingCallback l = this.loggingCallback;
249          if (l != null)
250             l.OnLogging(logLevel, location, message);
251          else
252             Console.WriteLine(logLevel + " " + location + " " + message);
253       }
254 
255       public void AddLoggingListener(I_LoggingCallback listener)
256       {
257          this.loggingCallback = listener;
258          this.delegateXb.AddLoggingListener(this);
259       }
260 
261       public void RemoveLoggingListener(I_LoggingCallback listener)
262       {
263          this.loggingCallback = null; // listener;

264          this.delegateXb.RemoveLoggingListener(listener);
265       }
266 
267       public void AddCallbackProgressListener(I_ProgressCallback listener)
268       {
269          this.progressCallback = listener;
270          this.delegateXb.AddCallbackProgressListener(this);
271       }
272 
273       public void RemoveCallbackProgressListener(I_ProgressCallback listener)
274       {
275          this.progressCallback = null; // listener;

276          this.delegateXb.RemoveCallbackProgressListener(listener);
277       }
278 
279       public string GetEmeiId()
280       {
281          return this.delegateXb.GetEmeiId();
282       }
283 
284       public string GetDeviceUniqueId()
285       {
286          return this.delegateXb.GetDeviceUniqueId();
287       }
288 
289       public void OnData(bool read, int currBytesRead, int nbytes)
290       {
291          I_ProgressCallback l = this.progressCallback;
292          if (l != null)
293          {
294             l.OnData(read, currBytesRead, nbytes);
295          }
296       }
297 
298       public void reachedAlive(ConnectionStateEnum oldStateBeneath, I_XmlBlasterAccess connection)
299       {
300          ConnectionStateEnum oldState = this.currentState;
301          this.currentState = ConnectionStateEnum.ALIVE;
302          I_ConnectionStateListener l = this.connectionStateListener;
303          if (l != null)
304          {
305             try
306             {
307                l.reachedAlive(oldState, connection);
308             }
309             catch (Exception e)
310             {
311                OnLogging(XmlBlasterLogLevel.WARN, "reachedAlive", "User code failed: " + e.ToString());
312             }
313          }
314          StopPolling();
315          StartPinging();
316       }
317 
318       public void reachedPolling(ConnectionStateEnum oldStateBeneath, I_XmlBlasterAccess connection)
319       {
320          ConnectionStateEnum oldState = this.currentState;
321          this.currentState = ConnectionStateEnum.POLLING;
322          I_ConnectionStateListener l = this.connectionStateListener;
323          if (l != null)
324          {
325             try
326             {
327                l.reachedPolling(oldState, connection);
328             }
329             catch (Exception e)
330             {
331                OnLogging(XmlBlasterLogLevel.WARN, "reachedPolling", "User code failed: " + e.ToString());
332             }
333          }
334          StopPinging();
335          StartPolling();
336       }
337 
338       public void reachedDead(ConnectionStateEnum oldStateBeneath, I_XmlBlasterAccess connection)
339       {
340          ConnectionStateEnum oldState = this.currentState;
341          if (this.xbPoller.IsConfiguredToWork()) // We know better than the layer below

342          {
343             this.currentState = ConnectionStateEnum.POLLING;
344             callStateListener(oldState, this.currentState);
345             StopPinging();
346             StartPolling();
347             return;
348          }
349          this.currentState = ConnectionStateEnum.DEAD;
350          callStateListener(oldState, this.currentState);
351          StopPinging();
352          StopPolling();
353       }
354 
355       private bool StartPolling()
356       {
357          if (!this.IsValid()) return false;
358          //if (this.disconnectCalled) return false;

359          if (this.pollIntervalMillis < 1L) return false;
360          bool started = this.xbPoller.Start();
361          if (started)
362          {
363             ConnectionStateEnum oldState = this.currentState;
364             this.currentState = ConnectionStateEnum.POLLING;
365             callStateListener(oldState, this.currentState);
366          }
367          return started;
368       }
369 
370       private void StopPolling()
371       {
372          this.xbPoller.Stop();
373       }
374 
375 
376       private bool StartPinging()
377       {
378          this.CheckValid();
379          //if (this.connectReturnQos == null) return false;

380          //if (this.disconnectCalled) return false;

381          if (this.pingIntervalMillis < 1L) return false;
382          bool started = this.xbPinger.Start();
383          if (started)
384          {
385             ConnectionStateEnum oldState = this.currentState;
386             this.currentState = ConnectionStateEnum.ALIVE;
387             callStateListener(oldState, this.currentState);
388          }
389          return started;
390       }
391 
392       private void callStateListener(ConnectionStateEnum oldState, ConnectionStateEnum newState)
393       {
394          if (oldState == newState)
395          {
396             OnLogging(XmlBlasterLogLevel.WARN, "XmlBlasterAccess", "Same states in transition: " + newState);
397             return;
398          }
399          
400          I_ConnectionStateListener l = this.connectionStateListener;
401          if (l != null)
402          {
403             try
404             {
405                if (newState == ConnectionStateEnum.ALIVE)
406                   l.reachedAlive(oldState, this);
407                else if (newState == ConnectionStateEnum.POLLING)
408                   l.reachedPolling(oldState, this);
409                else if (newState == ConnectionStateEnum.DEAD)
410                   l.reachedDead(oldState, this);
411             }
412             catch (Exception e)
413             {
414                OnLogging(XmlBlasterLogLevel.WARN, ""+newState, "User code failed: " + e.ToString());
415             }
416          }
417       }
418 
419       private bool StopPinging()
420       {
421          return this.xbPinger.Stop();
422       }
423 
424       public void OnReconnectTry()
425       {
426          if (!this.connectCalled || this.disconnectCalled)
427          {
428             StopPolling();
429             return;
430          }
431 
432          I_XmlBlasterAccess old = this.delegateXb;
433          if (old != null) {
434             this.delegateXb = null;
435             old.LeaveServer();
436          }
437 
438          if (this.gprsManager != null)
439             this.gprsManager.Connect(false);
440 
441          this.delegateXb = CreateNative();
442 
443          ConnectReturnQos qr = Connect(this.connectQosStr, this.callback);
444          if (qr == null)
445             throw new XmlBlasterException("communication.noConnection", "we are polling for the server");
446 
447          StopPolling();
448          StartPinging();
449          //OnLogging(XmlBlasterLogLevel.WARN, "XmlBlasterAccess", "No connection to server: " + e.ToString());

450       }
451 
452       public void OnPingFailed(Exception ex)
453       {
454          if (this.disconnectCalled)
455          {
456             StopPinging();
457             return;
458          }
459          OnSocketDisconnected(ex);
460       }
461 
462       // socket EOF

463       public void OnSocketDisconnected(Exception ex)
464       {
465          StopPinging();
466          StartPolling();
467       }
468    }
469 }


syntax highlighted by Code2HTML, v. 0.9.1