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); }
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; }
void PropertiesAdminI::setProperties_async(const AMD_PropertiesAdmin_setPropertiesPtr& cb, const PropertyDict& props, const Current&) { Lock sync(*this); PropertyDict old = _properties->getPropertiesForPrefix(""); PropertyDict::const_iterator p; const int traceLevel = _properties->getPropertyAsInt("Ice.Trace.Admin.Properties"); // // Compute the difference between the new property set and the existing property set: // // 1) Any properties in the new set that were not defined in the existing set. // // 2) Any properties that appear in both sets but with different values. // // 3) Any properties not present in the new set but present in the existing set. // In other words, the property has been removed. // PropertyDict added, changed, removed; for(p = props.begin(); p != props.end(); ++p) { PropertyDict::iterator q = old.find(p->first); if(q == old.end()) { if(!p->second.empty()) { // // This property is new. // added.insert(*p); } } else { if(p->second != q->second) { if(p->second.empty()) { // // This property was removed. // removed.insert(*p); } else { // // This property has changed. // changed.insert(*p); } } } } if(traceLevel > 0 && (!added.empty() || !changed.empty() || !removed.empty())) { Trace out(_logger, traceCategory); out << "Summary of property changes"; if(!added.empty()) { out << "\nNew properties:"; for(p = added.begin(); p != added.end(); ++p) { out << "\n " << p->first; if(traceLevel > 1) { out << " = " << p->second; } } } if(!changed.empty()) { out << "\nChanged properties:"; for(p = changed.begin(); p != changed.end(); ++p) { out << "\n " << p->first; if(traceLevel > 1) { out << " = " << p->second << " (old value = " << _properties->getProperty(p->first) << ")"; } } } if(!removed.empty()) { out << "\nRemoved properties:"; for(p = removed.begin(); p != removed.end(); ++p) { out << "\n " << p->first; } } } // // Update the property set. // for(p = added.begin(); p != added.end(); ++p) { _properties->setProperty(p->first, p->second); } for(p = changed.begin(); p != changed.end(); ++p) { _properties->setProperty(p->first, p->second); } for(p = removed.begin(); p != removed.end(); ++p) { _properties->setProperty(p->first, ""); } // // Send the response now so that we do not block the client during // the call to the update callback. // cb->ice_response(); // // Copy the callbacks to allow callbacks to update the callbacks. // vector<PropertiesAdminUpdateCallbackPtr> callbacks = _updateCallbacks; if(!callbacks.empty()) { PropertyDict changes = added; changes.insert(changed.begin(), changed.end()); changes.insert(removed.begin(), removed.end()); for(vector<PropertiesAdminUpdateCallbackPtr>::const_iterator p = callbacks.begin(); p != callbacks.end(); ++p) { try { (*p)->updated(changes); } catch(...) { // Ignore. } } } }