IceBox::ServiceManagerI::ServiceManagerI(CommunicatorPtr communicator, int& argc, char* argv[]) :
    _communicator(communicator),
    _adminEnabled(false),
    _pendingStatusChanges(false),
    _traceServiceObserver(0)
{
#ifndef ICE_CPP11_MAPPING
    const_cast<CallbackPtr&>(_observerCompletedCB) = newCallback(this, &ServiceManagerI::observerCompleted);
#endif
    _logger = _communicator->getLogger();

    PropertiesPtr props = _communicator->getProperties();
    _traceServiceObserver = props->getPropertyAsInt("IceBox.Trace.ServiceObserver");

    if(props->getProperty("Ice.Admin.Enabled") == "")
    {
        _adminEnabled = props->getProperty("Ice.Admin.Endpoints") != "";
    }
    else
    {
        _adminEnabled = props->getPropertyAsInt("Ice.Admin.Enabled") > 0;
    }

    if(_adminEnabled)
    {
        StringSeq facetSeq = props->getPropertyAsList("Ice.Admin.Facets");
        if(!facetSeq.empty())
        {
            _adminFacetFilter.insert(facetSeq.begin(), facetSeq.end());
        }
    }

    for(int i = 1; i < argc; i++)
    {
        _argv.push_back(argv[i]);
    }
}
Esempio n. 2
0
bool
IceBox::ServiceManagerI::start()
{
    try
    {
        ServiceManagerPtr obj = this;
        PropertiesPtr properties = _communicator->getProperties();

        //
        // 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.
        //
        ObjectAdapterPtr adapter;
        if(properties->getProperty("IceBox.ServiceManager.Endpoints") != "")
        {
            adapter = _communicator->createObjectAdapter("IceBox.ServiceManager");

            Identity identity;
            identity.category = properties->getPropertyWithDefault("IceBox.InstanceName", "IceBox");
            identity.name = "ServiceManager";
            adapter->add(obj, identity);
        }

        //
        // Parse the property set with the prefix "IceBox.Service.". These
        // properties should have the following format:
        //
        // IceBox.Service.Foo=entry_point [args]
        //
        // We parse the service properties specified in IceBox.LoadOrder 
        // first, then the ones from remaining services.
        //
        const string prefix = "IceBox.Service.";
        PropertyDict services = properties->getPropertiesForPrefix(prefix);
        PropertyDict::iterator p;
        StringSeq loadOrder = properties->getPropertyAsList("IceBox.LoadOrder");
        vector<StartServiceInfo> servicesInfo;
        for(StringSeq::const_iterator q = loadOrder.begin(); q != loadOrder.end(); ++q)
        {
            p = services.find(prefix + *q);
            if(p == services.end())
            {
                FailureException ex(__FILE__, __LINE__);
                ex.reason = "ServiceManager: no service definition for `" + *q + "'";
                throw ex;
            }
            servicesInfo.push_back(StartServiceInfo(*q, p->second, _argv));
            services.erase(p);
        }
        for(p = services.begin(); p != services.end(); ++p)
        {
            servicesInfo.push_back(StartServiceInfo(p->first.substr(prefix.size()), p->second, _argv));
        }
        
        //
        // Check if some services are using the shared communicator in which
        // case we create the shared communicator now with a property set which
        // is the union of all the service properties (services which are using
        // the shared communicator).
        //
        PropertyDict sharedCommunicatorServices = properties->getPropertiesForPrefix("IceBox.UseSharedCommunicator.");
        if(!sharedCommunicatorServices.empty())
        {
            InitializationData initData;
            initData.properties = createServiceProperties("SharedCommunicator");
            for(vector<StartServiceInfo>::iterator q = servicesInfo.begin(); q != servicesInfo.end(); ++q)
            {
                if(properties->getPropertyAsInt("IceBox.UseSharedCommunicator." + q->name) <= 0)
                {
                    continue;
                }

                //
                // Load the service properties using the shared communicator properties as
                // the default properties.
                //
                PropertiesPtr svcProperties = createProperties(q->args, initData.properties);

                //
                // Erase properties from the shared communicator which don't exist in the
                // service properties (which include the shared communicator properties
                // overriden by the service properties).
                //
                PropertyDict allProps = initData.properties->getPropertiesForPrefix("");
                for(PropertyDict::iterator p = allProps.begin(); p != allProps.end(); ++p)
                {
                    if(svcProperties->getProperty(p->first) == "")
                    {
                        initData.properties->setProperty(p->first, "");
                    }
                }

                //
                // Add the service properties to the shared communicator properties.
                //
                PropertyDict props = svcProperties->getPropertiesForPrefix("");
                for(PropertyDict::const_iterator r = props.begin(); r != props.end(); ++r)
                {
                    initData.properties->setProperty(r->first, r->second);
                }
            
                //
                // Parse <service>.* command line options (the Ice command line options 
                // were parsed by the createProperties above)
                //
                q->args = initData.properties->parseCommandLineOptions(q->name, q->args);                
            }
            _sharedCommunicator = initialize(initData);
        }

        //
        // Start the services.
        //
        for(vector<StartServiceInfo>::const_iterator r = servicesInfo.begin(); r != servicesInfo.end(); ++r)
        {
            start(r->name, r->entryPoint, r->args);
        }

        //
        // 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.empty())
        {
            cout << bundleName << " ready" << endl;
        }

        //
        // Register "this" as a facet to the Admin object, and then create
        // Admin object
        //
        try
        {
            _communicator->addAdminFacet(this, "IceBox.ServiceManager");

            //
            // Add a Properties facet for each service
            // 
            for(vector<ServiceInfo>::iterator r = _services.begin(); r != _services.end(); ++r)
            {
                const ServiceInfo& info = *r;
                CommunicatorPtr communicator = info.communicator != 0 ? info.communicator : _sharedCommunicator;
                _communicator->addAdminFacet(new PropertiesAdminI(communicator->getProperties()),
                                             "IceBox.Service." + info.name + ".Properties");
            }
          
            _communicator->getAdmin();
        }
        catch(const ObjectAdapterDeactivatedException&)
        {
            //
            // Expected if the communicator has been shutdown.
            //
        }

        if(adapter)
        {
            try
            {
                adapter->activate();
            }
            catch(const ObjectAdapterDeactivatedException&)
            {
                //
                // Expected if the communicator has been shutdown.
                //
            }
        }
    }
    catch(const FailureException& ex)
    {
        Error out(_logger);
        out << ex.reason;
        stopAll();
        return false;
    }
    catch(const Exception& ex)
    {
        Error out(_logger);
        out << "ServiceManager: " << ex;
        stopAll();
        return false;
    }

    return true;
}
Esempio n. 3
0
void
Ice::PluginManagerI::loadPlugins(int& argc, const char* argv[])
{
    assert(_communicator);

    StringSeq cmdArgs = argsToStringSeq(argc, argv);

    const string prefix = "Ice.Plugin.";
    PropertiesPtr properties = _communicator->getProperties();
    PropertyDict plugins = properties->getPropertiesForPrefix(prefix);

    //
    // First, load static plugin factories which were setup to load on
    // communicator initialization. If a matching plugin property is
    // set, we load the plugin with the plugin specification. The
    // entryPoint will be ignored but the rest of the plugin
    // specification might be used.
    //
    if(loadOnInitialization)
    {
        for(vector<string>::const_iterator p = loadOnInitialization->begin(); p != loadOnInitialization->end(); ++p)
        {
            string property = prefix + *p;
            PropertyDict::iterator r = plugins.find(property + ".cpp");
            if(r == plugins.end())
            {
                r = plugins.find(property);
            }
            else
            {
                plugins.erase(property);
            }

            if(r != plugins.end())
            {
                loadPlugin(*p, r->second, cmdArgs);
                plugins.erase(r);
            }
            else
            {
                loadPlugin(*p, "", cmdArgs);
            }
        }
    }

    //
    // Next, load and initialize the plug-ins defined in the property
    // set with the prefix "Ice.Plugin.". These properties should have
    // the following format:
    //
    // Ice.Plugin.name[.<language>]=entry_point [args]
    //
    // If the Ice.PluginLoadOrder property is defined, load the
    // specified plug-ins in the specified order, then load any
    // remaining plug-ins.
    //
    StringSeq loadOrder = properties->getPropertyAsList("Ice.PluginLoadOrder");
    for(StringSeq::const_iterator p = loadOrder.begin(); p != loadOrder.end(); ++p)
    {
        string name = *p;

        if(findPlugin(name))
        {
            PluginInitializationException ex(__FILE__, __LINE__);
            ex.reason = "plug-in `" + name + "' already loaded";
            throw ex;
        }

        string property = prefix + name;
        PropertyDict::iterator r = plugins.find(property + ".cpp");
        if(r == plugins.end())
        {
            r = plugins.find(property);
        }
        else
        {
            plugins.erase(property);
        }

        if(r != plugins.end())
        {
            loadPlugin(name, r->second, cmdArgs);
            plugins.erase(r);
        }
        else
        {
            PluginInitializationException ex(__FILE__, __LINE__);
            ex.reason = "plug-in `" + name + "' not defined";
            throw ex;
        }
    }

    //
    // Load any remaining plug-ins that weren't specified in PluginLoadOrder.
    //

    while(!plugins.empty())
    {
        PropertyDict::iterator p = plugins.begin();

        string name = p->first.substr(prefix.size());

        size_t dotPos = name.find_last_of('.');
        if(dotPos != string::npos)
        {
            string suffix = name.substr(dotPos + 1);
            if(suffix == "java" || suffix == "clr")
            {
                //
                // Ignored
                //
                plugins.erase(p);
            }
            else if(suffix == "cpp")
            {
                name = name.substr(0, dotPos);
                loadPlugin(name, p->second, cmdArgs);
                plugins.erase(p);

                plugins.erase(prefix + name);
            }
            else
            {
                //
                // Name is just a regular name that happens to contain a dot
                //
                dotPos = string::npos;
            }
        }

        if(dotPos == string::npos)
        {
            //
            // Is there a .cpp entry?
            //
            PropertyDict::iterator q = plugins.find(prefix + name + ".cpp");
            if(q != plugins.end())
            {
                plugins.erase(p);
                p = q;
            }

            loadPlugin(name, p->second, cmdArgs);
            plugins.erase(p);
        }
    }

    stringSeqToArgs(cmdArgs, argc, argv);
}