context: // **********************************************************************
  //
  // Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
  //
  // This copy of Ice is licensed to you under the terms described in the
  // ICE_LICENSE file included in this distribution.
  //
  // **********************************************************************
  
  using System;
  using System.Diagnostics;
  using System.Collections.Generic;
  using System.Threading;
  
  namespace Glacier2
  {
  
  /// <summary>
  /// Utility base class that makes it easy to to correctly initialize and finalize
  /// the Ice run time, as well as handle signals. Unless the application specifies
  /// a logger, Application installs a per-process logger that logs to the standard
  /// error output.
  ///
  /// Applications must create a derived class that implements the {@link #run} method.
  /// 
  /// A program can contain only one instance of this class.
  /// </summary>
  public abstract class Application : Ice.Application
  {
      /// <summary>
      /// This exception is raised if the session should be restarted.
      /// </summary>
      public class RestartSessionException : System.Exception
      {
      }
  
      /// <summary>
      /// Initializes an instance that calls Communicator.shutdown if
      /// a signal is received.
      /// </summary>
      public
      Application()
      {
      }
  
      /// <summary>
      /// Initializes an instance that handles signals according to the signal
      /// policy.
      /// </summary>
      /// <param name="signalPolicy">@param signalPolicy Determines how to 
      /// respond to signals.</param>
      public
      Application(Ice.SignalPolicy signalPolicy) : base(signalPolicy)
      {
      }
  
      /// <summary>
      /// Called once the communicator has been initialized and the Glacier2 session
      /// has been established. A derived class must implement <code>runWithSession</code>,
      /// which is the application's starting method.
      /// </summary>
      /// <param name="args"> The argument vector for the application. Application
      /// scans the argument vector passed to <code>main</code> for options that are
      /// specific to the Ice run time and removes them; therefore, the vector passed
      /// to <code>runWithSession</code> is free from Ice-related options and contains
      /// only options and arguments that are application-specific.</param>
      ///
      /// <returns> The runWithSession method should return zero for successful
      /// termination, and non-zero otherwise. Application.main returns the
      /// value returned by runWithSession.</returns>
      ///
      public abstract int
      runWithSession(string[] args);
  
      /// <summary>
      /// Run should not be overridden for Glacier2.Application. Instead
      /// runWithSession should be used.
      /// </summary>
      public override int
      run(string[] args)
      {
          //
          // This shouldn't be called.
          //
          Debug.Assert(false);
          return 0;
      }
  
      /// <summary>
      /// Called to restart the application's Glacier2 session. This
      /// method never returns.
      /// </summary>
      /// <returns>throws RestartSessionException This exception is 
      /// always thrown.</returns>
      ///
      public void
      restart()
      {
          throw new RestartSessionException();
      }
  
      /// <summary>
      /// Creates a new Glacier2 session. A call to createSession always
      /// precedes a call to runWithSession. If Ice.LocalException is thrown 
      /// from this method, the application is terminated.
      /// </summary>
      /// <returns> The Glacier2 session.</returns>
      public abstract Glacier2.SessionPrx
      createSession();
  
      /// <summary>
      /// Called when the base class detects that the session has been destroyed.
      /// A subclass can override this method to take action after the loss of
      /// connectivity with the Glacier2 router.
      /// </summary>
      public virtual void
      sessionDestroyed()
      {
      }
  
      /// <summary>
      /// Returns the Glacier2 router proxy.
      /// </summary>
      /// <returns>The router proxy.</returns>
      public static Glacier2.RouterPrx
      router()
      {
          return _router;
      }
  
      /// <summary>
      /// Returns the Glacier2 session proxy.
      /// </summary>
      /// <returns>The session proxy.</returns>
      public static Glacier2.SessionPrx
      session()
      {
          return _session;
      }
  
      /// <summary>
      /// Returns the category to be used in the identities of all of the client's
      /// callback objects. Clients must use this category for the router to
      /// forward callback requests to the intended client.
      /// Throws SessionNotExistException if no session exists.
      /// </summary>
      /// <returns>The category.</returns>
      public string
      categoryForClient()
      {
          if(_router == null)
          {
              throw new SessionNotExistException();
          }
          return _category;
      }
  
      /// <summary>
      /// Create a new Ice identity for callback objects with the given
      /// identity name field.
      /// </summary>
      /// <returns>The identity.</returns>
      public Ice.Identity
      createCallbackIdentity(string name)
      {
          return new Ice.Identity(name, categoryForClient());
      }
  
      /// <summary>
      /// Adds a servant to the callback object adapter's Active Servant Map with a UUID.
      /// </summary>
      /// <param name="servant">The servant to add.</param>
      /// <returns>The proxy for the servant.</returns>
      public Ice.ObjectPrx
      addWithUUID(Ice.Object servant)
      {
          return objectAdapter().add(servant, createCallbackIdentity(Guid.NewGuid().ToString()));
      }
  
      /// <summary>
      /// Returns an object adapter for callback objects, creating it if necessary.
      /// </summary>
      /// <returns>The object adapter.</returns>
      public Ice.ObjectAdapter
      objectAdapter()
      {
          if(_router == null)
          {
              throw new SessionNotExistException();
          }
  
          mutex__.Lock();
          try
          {
              if(_adapter == null)
              {
                  _adapter = communicator().createObjectAdapterWithRouter("", _router);
                  _adapter.activate();
              }
          }
          finally
          {
              mutex__.Unlock();
          }
          return _adapter;
      }
  
      private class SessionPingThread
      {
          public SessionPingThread(Application app, Glacier2.RouterPrx router, long period)
          {
              _app = app;
              _router = router;
              _period = period;
              _done = false;
          }
  
          private class AMI_Router_refreshSessionI : Glacier2.AMI_Router_refreshSession
          {
              public AMI_Router_refreshSessionI(Application app, SessionPingThread ping)
              {
                  _app = app;
                  _ping = ping;
              }
  
              public override void
              ice_response()
              {
              }
  
              public override void
              ice_exception(Ice.Exception ex)
              {
                  //
                  // Here the session has gone. The thread
                  // terminates, and we notify the
                  // application that the session has been
                  // destroyed.
                  //
                  _ping.done();
                  _app.sessionDestroyed();
              }
              
              private SessionPingThread _ping;
              private Application _app;
          }
  
          public void
          run()
          {
              _m.Lock();
              try
              {
                  while(!_done)
                  {
                      try
                      {
                          _router.refreshSession_async(new AMI_Router_refreshSessionI(_app, this));
                      }
                      catch(Ice.CommunicatorDestroyedException)
                      {
                          //
                          // AMI requests can raise CommunicatorDestroyedException directly.
                          //
                          break;
                      }
  
                      if(!_done)
                      {
                          _m.TimedWait((int)_period);
                      }
                  }
              }
              finally
              {
                  _m.Unlock();
              }
          }
  
          public void
          done()
          {
              _m.Lock();
              try
              {
                  if(!_done)
                  {
                      _done = true;
                      _m.NotifyAll();
                  }
              }
              finally
              {
                  _m.Unlock();
              }
          }
  
          private Application _app;
          private Glacier2.RouterPrx _router;
          private long _period;
          private bool _done = false;
          private readonly IceUtilInternal.Monitor _m = new IceUtilInternal.Monitor();
      }
  
      protected override int
  
gt:     doMain(string[] originArgs, Ice.InitializationData initData)