Logo Search packages:      
Sourcecode: zeroc-ice-java version File versions  Download package

ServiceManagerI.java

// **********************************************************************
//
// Copyright (c) 2003-2006 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.
//
// **********************************************************************

package IceBox;

//
// NOTE: the class isn't final on purpose to allow users to eventually
// extend it.
//
public class ServiceManagerI extends _ServiceManagerDisp
{
    public
    ServiceManagerI(Ice.Application server, String[] args)
    {
      _server = server;
      _logger = _server.communicator().getLogger();
      _argv = args;
    }

    public java.util.Map
    getSliceChecksums(Ice.Current current)
    {
      return SliceChecksums.checksums;
    }

    public void
    shutdown(Ice.Current current)
    {
      _server.communicator().shutdown();
    }

    public int
    run()
    {
      try
      {
          //
          // Create an object adapter. Services probably should NOT share
          // this object adapter, as the endpoint(s) for this object adapter
          // will most likely need to be firewalled for security reasons.
          //
          Ice.ObjectAdapter adapter = _server.communicator().createObjectAdapter("IceBox.ServiceManager");

          Ice.Properties properties = _server.communicator().getProperties();
            Ice.Identity managerIdentity = new Ice.Identity();
            String identity = properties.getProperty("IceBox.ServiceManager.Identity");
            if(identity.length() != 0)
            {
                managerIdentity = _server.communicator().stringToIdentity(identity);
            }
            else
            {
                managerIdentity.category = properties.getPropertyWithDefault("IceBox.InstanceName", "IceBox"); 
                managerIdentity.name = "ServiceManager";
            }
          adapter.add(this, managerIdentity);

          //
          // Parse the IceBox.LoadOrder property.
          //
          String order = properties.getProperty("IceBox.LoadOrder");
          String[] loadOrder = null;
          if(order.length() > 0)
          {
            loadOrder = order.trim().split("[,\t ]+");
          }

          //
          // Load and start the services defined in the property set
          // with the prefix "IceBox.Service.". These properties should
          // have the following format:
          //
          // IceBox.Service.Foo=Package.Foo [args]
          //
          // We load the services specified in IceBox.LoadOrder first,
          // then load any remaining services.
          //
          final String prefix = "IceBox.Service.";
          java.util.Map services = properties.getPropertiesForPrefix(prefix);
          if(loadOrder != null)
          {
            for(int i = 0; i < loadOrder.length; ++i)
            {
                if(loadOrder[i].length() > 0)
                {
                  String key = prefix + loadOrder[i];
                  String value = (String)services.get(key);
                  if(value == null)
                  {
                      FailureException ex = new FailureException();
                      ex.reason = "ServiceManager: no service definition for `" + loadOrder[i] + "'";
                      throw ex;
                  }
                  load(loadOrder[i], value);
                  services.remove(key);
                }
            }
          }
          java.util.Iterator p = services.entrySet().iterator();
          while(p.hasNext())
          {
            java.util.Map.Entry entry = (java.util.Map.Entry)p.next();
            String name = ((String)entry.getKey()).substring(prefix.length());
            String value = (String)entry.getValue();
            load(name, value);
          }

          //
          // We may want to notify external scripts that the services
          // have started. This is done by defining the property:
          //
          // IceBox.PrintServicesReady=bundleName
          //
          // Where bundleName is whatever you choose to call this set of
          // services. It will be echoed back as "bundleName ready".
          //
          // This must be done after start() has been invoked on the
          // services.
          //
          String bundleName = properties.getProperty("IceBox.PrintServicesReady");
          if(bundleName.length() > 0)
          {
            System.out.println(bundleName + " ready");
          }

          //
          // Don't move after the adapter activation. This allows
          // applications to wait for the service manager to be
          // reachable before sending a signal to shutdown the
          // IceBox.
          //
          _server.shutdownOnInterrupt();

          //
          // Start request dispatching after we've started the services.
          //
          try
          {
            adapter.activate();
          }
          catch(Ice.ObjectAdapterDeactivatedException ex)
          {
            //
            // Expected if the communicator has been shutdown.
            //
          }

          _server.communicator().waitForShutdown();
          _server.defaultInterrupt();

          //
          // Invoke stop() on the services.
          //
          stopAll();
      }
      catch(FailureException ex)
      {
          java.io.StringWriter sw = new java.io.StringWriter();
          java.io.PrintWriter pw = new java.io.PrintWriter(sw);
          pw.println(ex.reason);
          ex.printStackTrace(pw);
          pw.flush();
          _logger.error(sw.toString());
          stopAll();
          return 1;
      }
      catch(Ice.LocalException ex)
      {
          java.io.StringWriter sw = new java.io.StringWriter();
          java.io.PrintWriter pw = new java.io.PrintWriter(sw);
          ex.printStackTrace(pw);
          pw.flush();
          _logger.error("ServiceManager: " + ex + "\n" + sw.toString());
          stopAll();
          return 1;
      }
      catch(java.lang.Exception ex)
      {
          java.io.StringWriter sw = new java.io.StringWriter();
          java.io.PrintWriter pw = new java.io.PrintWriter(sw);
          ex.printStackTrace(pw);
          pw.flush();
          _logger.error("ServiceManager: unknown exception\n" + sw.toString());
          stopAll();
          return 1;
      }

      return 0;
    }

    private void
    load(String name, String value)
        throws FailureException
    {
      //
      // Separate the entry point from the arguments.
      //
      String className;
      String[] args;
      int pos = IceUtil.StringUtil.findFirstOf(value, " \t\n");
      if(pos == -1)
      {
          className = value;
          args = new String[0];
      }
      else
      {
          className = value.substring(0, pos);
          try
          {
            args = IceUtil.Options.split(value.substring(pos));
          }
          catch(IceUtil.Options.BadQuote ex)
          {
            FailureException e = new FailureException();
            e.reason = "ServiceManager: invalid arguments for service `" + name + "':\n" + ex.toString();
            throw e;
          }
      }

      start(name, className, args);
    }

    private void
    start(String service, String className, String[] args)
        throws FailureException
    {
      //
      // Create the service property set from the service arguments
      // and the server arguments. The service property set will be
      // used to create a new communicator, or will be added to the
      // shared communicator, depending on the value of the
      // IceBox.UseSharedCommunicator property.
      //
      java.util.ArrayList l = new java.util.ArrayList();
      for(int j = 0; j < args.length; j++)
      {
          l.add(args[j]);
      }
      for(int j = 0; j < _argv.length; j++)
      {
          if(_argv[j].startsWith("--" + service + "."))
          {
            l.add(_argv[j]);
          }
      }

      String[] serviceArgs = new String[l.size()];
      l.toArray(serviceArgs);

      //
      // Instantiate the class.
      //
      ServiceInfo info = new ServiceInfo();
      try
      {
          Class c = Class.forName(className);
          java.lang.Object obj = c.newInstance();
          try
          {
            info.service = (Service)obj;
          }
          catch(ClassCastException ex)
          {
            FailureException e = new FailureException();
            e.reason = "ServiceManager: class " + className + " does not implement IceBox.Service";
            throw e;
          }
      }
      catch(ClassNotFoundException ex)
      {
          FailureException e = new FailureException();
          e.reason = "ServiceManager: class " + className + " not found";
          e.initCause(ex);
          throw e;
      }
      catch(IllegalAccessException ex)
      {
          FailureException e = new FailureException();
          e.reason = "ServiceManager: unable to access default constructor in class " + className;
          e.initCause(ex);
          throw e;
      }
      catch(InstantiationException ex)
      {
          FailureException e = new FailureException();
          e.reason = "ServiceManager: unable to instantiate class " + className;
          e.initCause(ex);
          throw e;
      }

      //
      // Invoke Service::start().
      //
      try
      {
          //
          // If Ice.UseSharedCommunicator.<name> is defined, create a
          // communicator for the service. The communicator inherits
          // from the shared communicator properties. If it's not
          // defined, add the service properties to the shared
          // commnunicator property set.
          //
          Ice.Properties properties = _server.communicator().getProperties();
          if(properties.getPropertyAsInt("IceBox.UseSharedCommunicator." + service) > 0)
          {
            Ice.Properties fileProperties = Ice.Util.createProperties(serviceArgs);
            properties.parseCommandLineOptions("", fileProperties.getCommandLineOptions());

            serviceArgs = properties.parseIceCommandLineOptions(serviceArgs);
            serviceArgs = properties.parseCommandLineOptions(service, serviceArgs);
          }
          else
          {
            Ice.Properties serviceProperties = properties._clone();

            //
            // Initialize the Ice.ProgramName property with the name of this service.
            //
            String name = serviceProperties.getProperty("Ice.ProgramName");
            if(!name.equals(service))
            {
                name = name.length() == 0 ? service : name + "-" + service;
            }

            //
            // Load property file eventually specified with
            // --Ice.Config and add the properties from the file to
            // the service properties.
            //
            Ice.Properties fileProperties = Ice.Util.createProperties(serviceArgs);
            serviceProperties.parseCommandLineOptions("", fileProperties.getCommandLineOptions());

            serviceProperties.setProperty("Ice.ProgramName", name);

            //
            // Parse Ice and <service>.* command line options.
            //
            serviceArgs = serviceProperties.parseIceCommandLineOptions(serviceArgs);
            serviceArgs = serviceProperties.parseCommandLineOptions(service, serviceArgs);

            //
            // Remaining command line options are passed to the
            // communicator with argc/argv. This is necessary for Ice
            // plugin properties (e.g.: IceSSL).
            //
            Ice.InitializationData initData = new Ice.InitializationData();
            initData.properties = serviceProperties;
            info.communicator = Ice.Util.initialize(serviceArgs, initData);
          }
      
          Ice.Communicator communicator = info.communicator != null ? info.communicator : _server.communicator();

          try
          {
            info.service.start(service, communicator, serviceArgs);
          }
          catch(Throwable ex)
          {
            if(info.communicator != null)
            {
                try
                {
                  info.communicator.shutdown();
                  info.communicator.waitForShutdown();
                }
                catch(Ice.CommunicatorDestroyedException e)
                {
                  //
                  // Ignore, the service might have already destroyed
                  // the communicator for its own reasons.
                  //
                }
                catch(java.lang.Exception e)
                {
                  java.io.StringWriter sw = new java.io.StringWriter();
                  java.io.PrintWriter pw = new java.io.PrintWriter(sw);
                  e.printStackTrace(pw);
                  pw.flush();
                  _logger.warning("ServiceManager: exception in shutting down communicator for service "
                              + service + "\n" + sw.toString());
                }
                
                try
                {
                  info.communicator.destroy();
                }
                catch(java.lang.Exception e)
                {
                  java.io.StringWriter sw = new java.io.StringWriter();
                  java.io.PrintWriter pw = new java.io.PrintWriter(sw);
                  e.printStackTrace(pw);
                  pw.flush();
                  _logger.warning("ServiceManager: exception in destroying communciator for service"
                              + service + "\n" + sw.toString());
                }
            }
            throw ex;
          }

          _services.put(service, info);
      }
      catch(FailureException ex)
      {
          throw ex;
      }
      catch(Throwable ex)
      {
          FailureException e = new FailureException();
          e.reason = "ServiceManager: exception while starting service " + service + ": " + ex;
          e.initCause(ex);
          throw e;
      }
    }

    private void
    stopAll()
    {
      //
      // First, for each service, we call stop on the service and flush its database environment to 
      // the disk.
      //
      java.util.Iterator p = _services.entrySet().iterator();
      while(p.hasNext())
      {
          java.util.Map.Entry entry = (java.util.Map.Entry)p.next();
          String name = (String)entry.getKey();
          ServiceInfo info = (ServiceInfo)entry.getValue();
          try
          {
            info.service.stop();
          }
          catch(java.lang.Exception e)
          {
            java.io.StringWriter sw = new java.io.StringWriter();
            java.io.PrintWriter pw = new java.io.PrintWriter(sw);
            e.printStackTrace(pw);
            pw.flush();
            _logger.warning("ServiceManager: exception in stop for service " + name + "\n" + sw.toString());
          }

          if(info.communicator != null)
          {
            try
            {
                info.communicator.shutdown();
                info.communicator.waitForShutdown();
            }
            catch(Ice.CommunicatorDestroyedException e)
            {
                //
                // Ignore, the service might have already destroyed
                // the communicator for its own reasons.
                //
            }
            catch(java.lang.Exception e)
            {
                java.io.StringWriter sw = new java.io.StringWriter();
                java.io.PrintWriter pw = new java.io.PrintWriter(sw);
                e.printStackTrace(pw);
                pw.flush();
                _logger.warning("ServiceManager: exception in stop for service " + name + "\n" + sw.toString());
            }
          
            try
            {
                info.communicator.destroy();
            }
            catch(java.lang.Exception e)
            {
                java.io.StringWriter sw = new java.io.StringWriter();
                java.io.PrintWriter pw = new java.io.PrintWriter(sw);
                e.printStackTrace(pw);
                pw.flush();
                _logger.warning("ServiceManager: exception in stop for service " + name + "\n" + sw.toString());
            }
          }
      }

      _services.clear();
    }

    class ServiceInfo
    {
        public Service service;
      public Ice.Communicator communicator = null;
    }

    private Ice.Application _server;
    private Ice.Logger _logger;
    private String[] _argv; // Filtered server argument vector
    private java.util.HashMap _services = new java.util.HashMap();
}

Generated by  Doxygen 1.6.0   Back to index