OW_CIMOMEnvironment.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *  this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *  this list of conditions and the following disclaimer in the documentation
00012 *  and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Vintela, Inc. nor the names of its
00015 *  contributors may be used to endorse or promote products derived from this
00016 *  software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
00029 *******************************************************************************/
00030 
00036 #include "OW_config.h"
00037 #include "OW_CIMOMEnvironment.hpp"
00038 #include "OW_ConfigOpts.hpp"
00039 #include "OW_ConfigException.hpp"
00040 #include "OW_Format.hpp"
00041 #include "OW_FileSystem.hpp"
00042 #include "OW_SafeLibCreate.hpp"
00043 #include "OW_SelectEngine.hpp"
00044 #include "OW_CIMServer.hpp"
00045 #include "OW_CIMRepository.hpp"
00046 #include "OW_CIMInstance.hpp"
00047 #include "OW_CIMNameSpace.hpp"
00048 #include "OW_ServiceIFC.hpp"
00049 #include "OW_RequestHandlerIFC.hpp"
00050 #include "OW_IndicationServer.hpp"
00051 #include "OW_PollingManager.hpp"
00052 #include "OW_Assertion.hpp"
00053 #include "OW_AuthManager.hpp"
00054 #include "OW_LocalCIMOMHandle.hpp"
00055 #include "OW_WQLFilterRep.hpp"
00056 #include "OW_IndicationRepLayer.hpp"
00057 #include "OW_Platform.hpp"
00058 #include "OW_WQLIFC.hpp"
00059 #include "OW_SharedLibraryRepository.hpp"
00060 #include "OW_IndicationRepLayerMediator.hpp"
00061 #include "OW_OperationContext.hpp"
00062 #include "OW_Authorizer2IFC.hpp"
00063 #include "OW_ExceptionIds.hpp"
00064 #include "OW_CIMObjectPath.hpp"
00065 #include "OW_AuthorizerManager.hpp"
00066 #include "OW_AuthorizerIFC.hpp"
00067 #include "OW_Socket.hpp"
00068 #include "OW_LogAppender.hpp"
00069 #include "OW_AppenderLogger.hpp"
00070 #include "OW_CerrLogger.hpp"
00071 #include "OW_ProviderEnvironmentIFC.hpp"
00072 #include "OW_ProviderManager.hpp"
00073 
00074 #include <iostream>
00075 #include <map>
00076 #include <set>
00077 
00078 namespace OW_NAMESPACE
00079 {
00080 
00081 OW_DECLARE_EXCEPTION(CIMOMEnvironment)
00082 OW_DEFINE_EXCEPTION_WITH_ID(CIMOMEnvironment)
00083 
00084 using std::cerr;
00085 using std::endl;
00086 
00087 namespace
00088 {
00089 // the one and only
00090 CIMOMEnvironmentRef theCimomEnvironment;
00091 }
00092 
00093 CIMOMEnvironmentRef&
00094 CIMOMEnvironment::instance()
00095 {
00096    if (!theCimomEnvironment)
00097    {
00098       theCimomEnvironment = CIMOMEnvironmentRef(new CIMOMEnvironment);
00099    }
00100    return theCimomEnvironment;
00101 }
00102 
00103 String CIMOMEnvironment::COMPONENT_NAME("ow.owcimomd");
00104 
00105 namespace
00106 {
00107    class CIMOMProviderEnvironment : public ProviderEnvironmentIFC
00108    {
00109    public:
00110       CIMOMProviderEnvironment(CIMOMEnvironmentRef pCenv)
00111          : m_pCenv(pCenv)
00112          , m_context()
00113       {}
00114       virtual String getConfigItem(const String &name, const String& defRetVal="") const
00115       {
00116          return m_pCenv->getConfigItem(name, defRetVal);
00117       }
00118       virtual StringArray getMultiConfigItem(const String &itemName, 
00119          const StringArray& defRetVal, const char* tokenizeSeparator) const
00120       {
00121          return m_pCenv->getMultiConfigItem(itemName, defRetVal, tokenizeSeparator);
00122       }
00123       virtual CIMOMHandleIFCRef getCIMOMHandle() const
00124       {
00125          OW_ASSERT("Cannot call CIMOMProviderEnvironment::getCIMOMHandle()" == 0);
00126          return CIMOMHandleIFCRef();
00127       }
00128       
00129       virtual CIMOMHandleIFCRef getRepositoryCIMOMHandle() const
00130       {
00131          OW_ASSERT("Cannot call CIMOMProviderEnvironment::getRepositoryCIMOMHandle()" == 0);
00132          return CIMOMHandleIFCRef();
00133       }
00134       
00135       virtual RepositoryIFCRef getRepository() const
00136       {
00137          return m_pCenv->getRepository();
00138       }
00139       virtual LoggerRef getLogger() const
00140       {
00141          return m_pCenv->getLogger();
00142       }
00143       virtual LoggerRef getLogger(const String& componentName) const
00144       {
00145          return m_pCenv->getLogger(componentName);
00146       }
00147       virtual String getUserName() const
00148       {
00149          return Platform::getCurrentUserName();
00150       }
00151       virtual OperationContext& getOperationContext()
00152       {
00153          return m_context;
00154       }
00155       virtual ProviderEnvironmentIFCRef clone() const
00156       {
00157          return ProviderEnvironmentIFCRef(new CIMOMProviderEnvironment(m_pCenv));
00158       }
00159    private:
00160       CIMOMEnvironmentRef m_pCenv;
00161       OperationContext m_context;
00162    };
00163    ProviderEnvironmentIFCRef createProvEnvRef(const CIMOMEnvironmentRef& pcenv)
00164    {
00165       return ProviderEnvironmentIFCRef(new CIMOMProviderEnvironment(pcenv));
00166    }
00167 } // end anonymous namespace
00169 // We don't initialize everything here, since startServices() and shutdown() manage the lifecycle.
00170 // We start off with a dumb logger and an empty config map.
00171 CIMOMEnvironment::CIMOMEnvironment()
00172    : m_Logger(new CerrLogger)
00173    , m_configItems(new ConfigMap)
00174    , m_indicationsDisabled(true)
00175    , m_indicationRepLayerDisabled(false)
00176    , m_state(E_STATE_INVALID)
00177    , m_indicationRepLayerMediatorRef(new IndicationRepLayerMediator)
00178 {
00179 }
00181 CIMOMEnvironment::~CIMOMEnvironment()
00182 {
00183    try
00184    {
00185       try
00186       {
00187          if (isLoaded(m_state))
00188          {
00189             shutdown();
00190          }
00191       }
00192       catch(Exception& e)
00193       {
00194          cerr << e << endl;
00195       }
00196       m_configItems = 0;
00197       m_state = E_STATE_INVALID; // just for the heck of it.
00198    }
00199    catch (Exception& e)
00200    {
00201       OW_LOG_ERROR(m_Logger, Format("Caught exception in CIMOMEnvironment::~CIMOMEnvironment(): %1", e));
00202    }
00203    catch (...)
00204    {
00205       // don't let exceptions escape!
00206    }
00207 }
00209 void
00210 CIMOMEnvironment::init()
00211 {
00212    // init() is called from a single-threaded state
00213    _clearSelectables();
00214 
00215    // The config file config item may be set by main before init() is called.
00216    _loadConfigItemsFromFile(getConfigItem(ConfigOpts::CONFIG_FILE_opt, OW_DEFAULT_CONFIG_FILE));
00217 
00218    // logger is treated special, so it goes in init() not startServices()
00219    _createLogger();
00220 }
00222 void
00223 CIMOMEnvironment::startServices()
00224 {
00225    // Split up into 3 sections:
00226    // 1. load
00227    // 2. init, initialized
00228    // 3. start, started
00229 
00230    // We start out single-threaded.  The start phase is when threads enter the picture.
00231 
00232    // This is a global thing, so handle it here.
00233    Socket::createShutDownMechanism();
00234 
00235    // load
00236    OW_LOG_DEBUG(m_Logger, "CIMOMEnvironment loading services");
00237 
00238    m_authorizerManager = new AuthorizerManager;
00239    m_services.push_back(ServiceIFCRef(SharedLibraryRef(), m_authorizerManager));
00240 
00241    m_providerManager = new ProviderManager;
00242    m_providerManager->load(ProviderIFCLoader::createProviderIFCLoader(
00243       this), this);
00244    m_services.push_back(ServiceIFCRef(SharedLibraryRef(), m_providerManager));
00245 
00246    m_cimRepository = new CIMRepository;
00247    m_services.push_back(ServiceIFCRef(SharedLibraryRef(), m_cimRepository));
00248 
00249    m_cimServer = RepositoryIFCRef(new CIMServer(this,
00250       m_providerManager, m_cimRepository, m_authorizerManager));
00251    m_services.push_back(ServiceIFCRef(SharedLibraryRef(), m_cimServer));
00252 
00253    _loadAuthorizer();  // old stuff
00254    _createAuthorizerManager();  // new stuff
00255    _createAuthManager();
00256    _loadRequestHandlers();
00257    _loadServices();
00258    if (!getConfigItem(ConfigOpts::HTTP_SERVER_SINGLE_THREAD_opt).equalsIgnoreCase("true"))
00259    {
00260       _createPollingManager();
00261       _createIndicationServer();
00262    }
00263 
00264    OW_LOG_DEBUG(m_Logger, "CIMOMEnvironment finished loading services");
00265 
00266    _sortServicesForDependencies();
00267 
00268    // init
00269 
00270    OW_LOG_DEBUG(m_Logger, "CIMOMEnvironment initializing services");
00271 
00272    {
00273       MutexLock l(m_stateGuard);
00274       m_state = E_STATE_INITIALIZING;
00275    }
00276 
00277    for (size_t i = 0; i < m_services.size(); i++)
00278    {
00279       OW_LOG_DEBUG(m_Logger, Format("CIMOM initializing service: %1", m_services[i]->getName()));
00280       m_services[i]->init(this);
00281    }
00282    {
00283       MutexLock l(m_stateGuard);
00284       m_state = E_STATE_INITIALIZED;
00285    }
00286    
00287    for (size_t i = 0; i < m_services.size(); i++)
00288    {
00289       OW_LOG_DEBUG(m_Logger, Format("CIMOM calling initialized() for service: %1", m_services[i]->getName()));
00290       m_services[i]->initialized();
00291    }
00292 
00293    OW_LOG_DEBUG(m_Logger, "CIMOMEnvironment finished initializing services");
00294 
00295    // start
00296    OW_LOG_DEBUG(m_Logger, "CIMOMEnvironment starting services");
00297    {
00298       MutexLock l(m_stateGuard);
00299       m_state = E_STATE_STARTING;
00300    }
00301 
00302    for (size_t i = 0; i < m_services.size(); i++)
00303    {
00304       OW_LOG_DEBUG(m_Logger, Format("CIMOM starting service: %1", m_services[i]->getName()));
00305       m_services[i]->start();
00306    }
00307    {
00308       MutexLock l(m_stateGuard);
00309       m_state = E_STATE_STARTED;
00310    }
00311 
00312    for (size_t i = 0; i < m_services.size(); i++)
00313    {
00314       OW_LOG_DEBUG(m_Logger, Format("CIMOM calling started() for service: %1", m_services[i]->getName()));
00315       m_services[i]->started();
00316    }
00317 
00318    OW_LOG_DEBUG(m_Logger, "CIMOMEnvironment finished starting services");
00319 }
00321 void
00322 CIMOMEnvironment::shutdown()
00323 {
00324 
00325    // notify all services of impending shutdown.
00326    OW_LOG_DEBUG(m_Logger, "CIMOMEnvironment notifying services of shutdown");
00327    // Do this in reverse order because of dependencies
00328    for (int i = int(m_services.size())-1; i >= 0; i--)
00329    {
00330       try
00331       {
00332          OW_LOG_DEBUG(m_Logger, Format("CIMOMEnvironment notifying service: %1", m_services[i]->getName()));
00333          m_services[i]->shuttingDown();
00334       }
00335       catch (Exception& e)
00336       {
00337          OW_LOG_ERROR(m_Logger, Format("Caught exception while calling shuttingDown(): %1", e));
00338       }
00339       catch (...)
00340       {
00341       }
00342    }
00343 
00344    // PHASE 1: SHUTDOWNS
00345    OW_LOG_DEBUG(m_Logger, "CIMOMEnvironment beginning shutdown process");
00346    {
00347       MutexLock l(m_stateGuard);
00348       m_state = E_STATE_SHUTTING_DOWN;
00349    }
00350 
00351    OW_LOG_DEBUG(m_Logger, "CIMOMEnvironment shutting down sockets");
00352    // this is a global thing, so do it here
00353    Socket::shutdownAllSockets();
00354 
00355    // Shutdown all services
00356    OW_LOG_DEBUG(m_Logger, "CIMOMEnvironment shutting down services");
00357    // Do this in reverse order because of dependencies
00358    for (int i = int(m_services.size())-1; i >= 0; i--)
00359    {
00360       try
00361       {
00362          OW_LOG_DEBUG(m_Logger, Format("CIMOMEnvironment shutting down service: %1", m_services[i]->getName()));
00363          m_services[i]->shutdown();
00364       }
00365       catch (Exception& e)
00366       {
00367          OW_LOG_ERROR(m_Logger, Format("Caught exception while calling shutdown(): %1", e));
00368       }
00369       catch (...)
00370       {
00371       }
00372    }
00373 
00374    {
00375       MutexLock l(m_stateGuard);
00376       m_state = E_STATE_SHUTDOWN;
00377    }
00378 
00379    // PHASE 2: unload/delete
00380 
00381    // get this lock here so that we delete everything atomically
00382    MutexLock ml(m_monitor);
00383 
00384    OW_LOG_DEBUG(m_Logger, "CIMOMEnvironment unloading and deleting services");
00385 
00386    m_pollingManager = 0;
00387    
00388    // Clear selectable objects
00389    try
00390    {
00391       _clearSelectables();
00392    }
00393    catch (Exception& e)
00394    {
00395       OW_LOG_ERROR(m_Logger, Format("Caught exception while calling _clearSelectables(): %1", e));
00396    }
00397    catch(...)
00398    {
00399    }
00400 
00401    // We need to unload these in the opposite order that
00402    // they were loaded because of bugs in shared library
00403    // handling on certain OSes.
00404    for (int i = int(m_services.size())-1; i >= 0; i--)
00405    {
00406       m_services[i].setNull();
00407    }
00408    m_services.clear();
00409    // Unload all request handlers
00410    m_reqHandlers.clear();
00411    // Unload the wql library if loaded
00412    m_wqlLib = 0;
00413    // Shutdown indication processing
00414    if (m_indicationServer)
00415    {
00416       m_indicationServer.setNull();
00417       m_indicationRepLayerLib = 0;
00418    }
00419    // Delete the authentication manager
00420    m_authManager = 0;
00421    // Delete the cim server
00422    m_cimServer = 0;
00423    // Delete the cim repository
00424    m_cimRepository = 0;
00425    // Delete the authorization manager
00426    m_authorizerManager = 0;
00427    // Delete the provider manager
00428    m_providerManager = 0;
00429 
00430    {
00431       MutexLock l(m_stateGuard);
00432       m_state = E_STATE_UNLOADED;
00433    }
00434 
00435    OW_LOG_DEBUG(m_Logger, "CIMOMEnvironment has shut down");
00436 }
00438 ProviderManagerRef
00439 CIMOMEnvironment::getProviderManager() const
00440 {
00441    {
00442       MutexLock l(m_stateGuard);
00443       if (!isLoaded(m_state))
00444       {
00445          OW_THROW(CIMOMEnvironmentException, "CIMOMEnvironment::getProviderManager() called when state is not constructed");
00446       }
00447    }
00448    OW_ASSERT(m_providerManager);
00449    return m_providerManager;
00450 }
00452 void
00453 CIMOMEnvironment::_createAuthManager()
00454 {
00455    m_authManager = AuthManagerRef(new AuthManager);
00456    m_services.push_back(ServiceIFCRef(SharedLibraryRef(), m_authManager));
00457 }
00459 void
00460 CIMOMEnvironment::_createPollingManager()
00461 {
00462    m_pollingManager = PollingManagerRef(new PollingManager(m_providerManager));
00463    m_services.push_back(ServiceIFCRef(SharedLibraryRef(), m_pollingManager));
00464 }
00466 void
00467 CIMOMEnvironment::_createIndicationServer()
00468 {
00469    // Determine if user has disabled indication exportation
00470    m_indicationsDisabled = getConfigItem(
00471       ConfigOpts::DISABLE_INDICATIONS_opt, OW_DEFAULT_DISABLE_INDICATIONS).equalsIgnoreCase("true");
00472    if (!m_indicationsDisabled)
00473    {
00474       // load the indication server library
00475       String indicationLib = getConfigItem(ConfigOpts::OWLIBDIR_opt, OW_DEFAULT_OWLIBDIR);
00476       if (!indicationLib.endsWith(OW_FILENAME_SEPARATOR))
00477       {
00478          indicationLib += OW_FILENAME_SEPARATOR;
00479       }
00480       indicationLib += "libowindicationserver"OW_SHAREDLIB_EXTENSION;
00481       m_indicationServer = SafeLibCreate<IndicationServer>::loadAndCreateObject(
00482             indicationLib, "createIndicationServer", getLogger(COMPONENT_NAME));
00483       if (!m_indicationServer)
00484       {
00485 
00486          OW_LOG_FATAL_ERROR(m_Logger, Format("CIMOM Failed to load indication server"
00487             " from library %1. Indication are currently DISABLED!",
00488             indicationLib));
00489          OW_THROW(CIMOMEnvironmentException, "Failed to load indication server");
00490       }
00491       m_services.push_back(m_indicationServer);
00492    }
00493 }
00495 void
00496 CIMOMEnvironment::_loadRequestHandlers()
00497 {
00498    m_reqHandlers.clear();
00499    int reqHandlerCount = 0;
00500    const StringArray libPaths = getMultiConfigItem(
00501       ConfigOpts::REQUEST_HANDLER_PATH_opt, 
00502       String(OW_DEFAULT_REQUEST_HANDLER_PATH).tokenize(OW_PATHNAME_SEPARATOR),
00503       OW_PATHNAME_SEPARATOR);
00504    for (size_t i = 0; i < libPaths.size(); ++i)
00505    {
00506       String libPath(libPaths[i]);
00507       if (!libPath.endsWith(OW_FILENAME_SEPARATOR))
00508       {
00509          libPath += OW_FILENAME_SEPARATOR;
00510       }
00511       OW_LOG_INFO(m_Logger, Format("CIMOM loading request handlers from"
00512          " directory %1", libPath));
00513       StringArray dirEntries;
00514       if (!FileSystem::getDirectoryContents(libPath, dirEntries))
00515       {
00516          OW_LOG_FATAL_ERROR(m_Logger, Format("CIMOM failed getting the contents of the"
00517             " request handler directory: %1", libPath));
00518          OW_THROW(CIMOMEnvironmentException, "No RequestHandlers");
00519       }
00520       for (size_t i = 0; i < dirEntries.size(); i++)
00521       {
00522          if (!dirEntries[i].endsWith(OW_SHAREDLIB_EXTENSION))
00523          {
00524             continue;
00525          }
00526 #ifdef OW_DARWIN
00527                if (dirEntries[i].indexOf(OW_VERSION) != String::npos)
00528                {
00529                      continue;
00530                }
00531 #endif // OW_DARWIN
00532          String libName = libPath;
00533          libName += dirEntries[i];
00534          RequestHandlerIFCRef rh =
00535             SafeLibCreate<RequestHandlerIFC>::loadAndCreateObject(
00536                libName, "createRequestHandler", getLogger(COMPONENT_NAME));
00537          if (rh)
00538          {
00539             ++reqHandlerCount;
00540             rh->setEnvironment(this);
00541             StringArray supportedContentTypes = rh->getSupportedContentTypes();
00542             OW_LOG_INFO(m_Logger, Format("CIMOM loaded request handler from file: %1",
00543                libName));
00544    
00545             ReqHandlerDataRef rqData(new ReqHandlerData);
00546             rqData->filename = libName;
00547             rqData->rqIFCRef = rh;
00548             rqData->dt.setToCurrent();
00549             for (StringArray::const_iterator iter = supportedContentTypes.begin();
00550                  iter != supportedContentTypes.end(); iter++)
00551             {
00552                MutexLock ml(m_reqHandlersLock);
00553                m_reqHandlers[(*iter)] = rqData;
00554                ml.release();
00555                OW_LOG_INFO(m_Logger, Format(
00556                   "CIMOM associating Content-Type %1 with Request Handler %2",
00557                   *iter, libName));
00558             }
00559             m_services.push_back(rh);
00560          }
00561          else
00562          {
00563             OW_LOG_FATAL_ERROR(m_Logger, Format("CIMOM failed to load request handler from file:"
00564                " %1", libName));
00565             OW_THROW(CIMOMEnvironmentException, "Invalid request handler");
00566          }
00567       }
00568    }
00569    OW_LOG_INFO(m_Logger, Format("CIMOM: Handling %1 Content-Types from %2 Request Handlers",
00570       m_reqHandlers.size(), reqHandlerCount));
00571 }
00573 void
00574 CIMOMEnvironment::_loadServices()
00575 {
00576    const StringArray libPaths = getMultiConfigItem(
00577       ConfigOpts::SERVICES_PATH_opt, String(OW_DEFAULT_SERVICES_PATH).tokenize(OW_PATHNAME_SEPARATOR), OW_PATHNAME_SEPARATOR);
00578    for (size_t i = 0; i < libPaths.size(); ++i)
00579    {
00580       String libPath(libPaths[i]);
00581       if (!libPath.endsWith(OW_FILENAME_SEPARATOR))
00582       {
00583          libPath += OW_FILENAME_SEPARATOR;
00584       }
00585       OW_LOG_INFO(m_Logger, Format("CIMOM loading services from directory %1",
00586          libPath));
00587       StringArray dirEntries;
00588       if (!FileSystem::getDirectoryContents(libPath, dirEntries))
00589       {
00590          OW_LOG_FATAL_ERROR(m_Logger, Format("CIMOM failed getting the contents of the"
00591             " services directory: %1", libPath));
00592          OW_THROW(CIMOMEnvironmentException, "No Services");
00593       }
00594       for (size_t i = 0; i < dirEntries.size(); i++)
00595       {
00596          if (!dirEntries[i].endsWith(OW_SHAREDLIB_EXTENSION))
00597          {
00598             continue;
00599          }
00600    #ifdef OW_DARWIN
00601          if (dirEntries[i].indexOf(OW_VERSION) != String::npos)
00602          {
00603                continue;
00604          }
00605    #endif // OW_DARWIN
00606          String libName = libPath;
00607          libName += dirEntries[i];
00608          ServiceIFCRef srv =
00609             SafeLibCreate<ServiceIFC>::loadAndCreateObject(libName,
00610                "createService", getLogger(COMPONENT_NAME));
00611          if (srv)
00612          {
00613             m_services.push_back(srv);
00614             OW_LOG_INFO(m_Logger, Format("CIMOM loaded service from file: %1", libName));
00615          }
00616          else
00617          {
00618             OW_LOG_FATAL_ERROR(m_Logger, Format("CIMOM failed to load service from library: %1",
00619                libName));
00620             OW_THROW(CIMOMEnvironmentException, "Invalid service");
00621          }
00622       }
00623    }
00624    OW_LOG_INFO(m_Logger, Format("CIMOM: Number of services loaded: %1",
00625       m_services.size()));
00626 }
00627 
00629 namespace
00630 {
00631 LogAppender::ConfigMap getAppenderConfig(const ConfigFile::ConfigMap& configItems)
00632 {
00633    LogAppender::ConfigMap appenderConfig;
00634    for (ConfigFile::ConfigMap::const_iterator iter = configItems.begin(); iter != configItems.end(); ++iter)
00635    {
00636       if (iter->first.startsWith("log") && iter->second.size() > 0)
00637       {
00638          appenderConfig[iter->first] = iter->second.back().value;
00639       }
00640    }
00641    return appenderConfig;
00642 }
00643 
00644 } // end anonymous namespace
00646 void
00647 CIMOMEnvironment::_createLogger()
00648 {
00649    using namespace ConfigOpts;
00650    Array<LogAppenderRef> appenders;
00651    
00652    StringArray additionalLogs = getMultiConfigItem(ADDITIONAL_LOGS_opt, StringArray(), " \t");
00653 
00654    // this also gets set if owcimomd is run with -d
00655    bool debugFlag = getConfigItem(DEBUGFLAG_opt, OW_DEFAULT_DEBUGFLAG).equalsIgnoreCase("true");
00656    if ( debugFlag )
00657    {
00658       // stick it at the beginning as a possible slight logging performance optimization
00659       additionalLogs.insert(additionalLogs.begin(), LOG_DEBUG_LOG_NAME);
00660    }
00661 
00662    for (size_t i = 0; i < additionalLogs.size(); ++i)
00663    {
00664       const String& logName(additionalLogs[i]);
00665 
00666       String logMainType = getConfigItem(Format(LOG_1_TYPE_opt, logName), OW_DEFAULT_LOG_1_TYPE);
00667       String logMainComponents = getConfigItem(Format(LOG_1_COMPONENTS_opt, logName), OW_DEFAULT_LOG_1_COMPONENTS);
00668       String logMainCategories = getConfigItem(Format(LOG_1_CATEGORIES_opt, logName));
00669       if (logMainCategories.empty())
00670       {
00671          // convert level into categories
00672          String logMainLevel = getConfigItem(Format(LOG_1_LEVEL_opt, logName), OW_DEFAULT_LOG_1_LEVEL);
00673          if (logMainLevel.equalsIgnoreCase(Logger::STR_DEBUG_CATEGORY))
00674          {
00675             logMainCategories = Logger::STR_DEBUG_CATEGORY + " " + Logger::STR_INFO_CATEGORY + " " + Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
00676          }
00677          else if (logMainLevel.equalsIgnoreCase(Logger::STR_INFO_CATEGORY))
00678          {
00679             logMainCategories = Logger::STR_INFO_CATEGORY + " " + Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
00680          }
00681          else if (logMainLevel.equalsIgnoreCase(Logger::STR_ERROR_CATEGORY))
00682          {
00683             logMainCategories = Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
00684          }
00685          else if (logMainLevel.equalsIgnoreCase(Logger::STR_FATAL_CATEGORY))
00686          {
00687             logMainCategories = Logger::STR_FATAL_CATEGORY;
00688          }
00689       }
00690       String logMainFormat = getConfigItem(Format(LOG_1_FORMAT_opt, logName), OW_DEFAULT_LOG_1_FORMAT);
00691 
00692       appenders.push_back(LogAppender::createLogAppender(logName, logMainComponents.tokenize(), logMainCategories.tokenize(),
00693          logMainFormat, logMainType, getAppenderConfig(*m_configItems)));
00694    }
00695 
00696 
00697    // This one will eventually be handled the same as all other logs by just sticking "main" in the additionalLogs array
00698    // but we need to handle deprecated options for now, so it needs special treatment.
00699    String logName(LOG_MAIN_LOG_NAME);
00700    String logMainType = getConfigItem(Format(LOG_1_TYPE_opt, logName));
00701    String logMainComponents = getConfigItem(Format(LOG_1_COMPONENTS_opt, logName), OW_DEFAULT_LOG_1_COMPONENTS);
00702    String logMainCategories = getConfigItem(Format(LOG_1_CATEGORIES_opt, logName));
00703    String logMainLevel = getConfigItem(Format(LOG_1_LEVEL_opt, logName));
00704    String logMainFormat = getConfigItem(Format(LOG_1_FORMAT_opt, logName), OW_DEFAULT_LOG_1_FORMAT);
00705 
00706    // map the old log_location onto log.main.type and log.main.location if necessary
00707    if (logMainType.empty())
00708    {
00709       String deprecatedLogLocation = getConfigItem(ConfigOpts::LOG_LOCATION_opt, OW_DEFAULT_LOG_LOCATION);
00710       if (deprecatedLogLocation.empty() || deprecatedLogLocation.equalsIgnoreCase("syslog"))
00711       {
00712          logMainType = "syslog";
00713       }
00714       else if (deprecatedLogLocation.equalsIgnoreCase("null"))
00715       {
00716          logMainType = "null";
00717       }
00718       else
00719       {
00720          logMainType = "file";
00721          setConfigItem(Format(LOG_1_LOCATION_opt, logName), deprecatedLogLocation);
00722       }
00723    }
00724 
00725    // map the old log_level onto log.main.level if necessary
00726    if (logMainCategories.empty() && logMainLevel.empty())
00727    {
00728       String deprecatedLogLevel = getConfigItem(ConfigOpts::LOG_LEVEL_opt);
00729       if (deprecatedLogLevel.empty())
00730       {
00731          logMainLevel = OW_DEFAULT_LOG_1_LEVEL;
00732       }
00733       else
00734       {
00735          // old used "fatalerror", now we just use FATAL
00736          if (deprecatedLogLevel.equalsIgnoreCase("fatalerror"))
00737          {
00738             logMainLevel = Logger::STR_FATAL_CATEGORY;
00739          }
00740          else
00741          {
00742             deprecatedLogLevel.toUpperCase();
00743             logMainLevel = deprecatedLogLevel;
00744          }
00745       }
00746    }
00747    
00748    // convert level into categories
00749    if (logMainCategories.empty())
00750    {
00751       // convert level into categories
00752       String logMainLevel = getConfigItem(Format(LOG_1_LEVEL_opt, logName), OW_DEFAULT_LOG_1_LEVEL);
00753       if (logMainLevel.equalsIgnoreCase(Logger::STR_DEBUG_CATEGORY))
00754       {
00755          logMainCategories = Logger::STR_DEBUG_CATEGORY + " " + Logger::STR_INFO_CATEGORY + " " + Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
00756       }
00757       else if (logMainLevel.equalsIgnoreCase(Logger::STR_INFO_CATEGORY))
00758       {
00759          logMainCategories = Logger::STR_INFO_CATEGORY + " " + Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
00760       }
00761       else if (logMainLevel.equalsIgnoreCase(Logger::STR_ERROR_CATEGORY))
00762       {
00763          logMainCategories = Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
00764       }
00765       else if (logMainLevel.equalsIgnoreCase(Logger::STR_FATAL_CATEGORY))
00766       {
00767          logMainCategories = Logger::STR_FATAL_CATEGORY;
00768       }
00769    }
00770 
00771    appenders.push_back(LogAppender::createLogAppender(logName, logMainComponents.tokenize(), logMainCategories.tokenize(),
00772       logMainFormat, logMainType, getAppenderConfig(*m_configItems)));
00773 
00774 
00775    m_Logger = new AppenderLogger(COMPONENT_NAME, appenders);
00776 }
00778 void
00779 CIMOMEnvironment::_loadConfigItemsFromFile(const String& filename)
00780 {
00781    OW_LOG_DEBUG(m_Logger, "\nUsing config file: " + filename);
00782    ConfigFile::loadConfigFile(filename, *m_configItems);
00783    StringArray configDirs = ConfigFile::getMultiConfigItem(*m_configItems, 
00784       ConfigOpts::ADDITIONAL_CONFIG_FILES_DIRS_opt, 
00785       String(OW_DEFAULT_ADDITIONAL_CONFIG_FILES_DIRS).tokenize(OW_PATHNAME_SEPARATOR), 
00786       OW_PATHNAME_SEPARATOR);
00787 }
00789 bool
00790 CIMOMEnvironment::authenticate(String &userName, const String &info,
00791    String &details, OperationContext& context) const
00792 {
00793    {
00794       MutexLock l(m_stateGuard);
00795       if (!isInitialized(m_state))
00796       {
00797          return false;
00798       }
00799    }
00800    MutexLock ml(m_monitor);
00801    OW_ASSERT(m_authManager);
00802    return m_authManager->authenticate(userName, info, details, context);
00803 }
00805 String
00806 CIMOMEnvironment::getConfigItem(const String &name, const String& defRetVal) const
00807 {
00808    return ConfigFile::getConfigItem(*m_configItems, name, defRetVal);
00809 }
00810 
00812 StringArray
00813 CIMOMEnvironment::getMultiConfigItem(const String &itemName, 
00814    const StringArray& defRetVal, const char* tokenizeSeparator) const
00815 {
00816    return ConfigFile::getMultiConfigItem(*m_configItems, itemName, defRetVal, tokenizeSeparator);
00817 }
00818 
00820 CIMOMHandleIFCRef
00821 CIMOMEnvironment::getWQLFilterCIMOMHandle(const CIMInstance& inst,
00822       OperationContext& context) const
00823 {
00824    {
00825       MutexLock l(m_stateGuard);
00826       if (!isLoaded(m_state))
00827       {
00828          OW_THROW(CIMOMEnvironmentException, "CIMOMEnvironment::getWQLFilterCIMOMHandle() called when state is not initialized");
00829       }
00830    }
00831    OW_ASSERT(m_cimServer);
00832    return CIMOMHandleIFCRef(new LocalCIMOMHandle(
00833       const_cast<CIMOMEnvironment *>(this),
00834       RepositoryIFCRef(new WQLFilterRep(inst, m_cimServer)), context));
00835 }
00836 
00838 CIMOMHandleIFCRef
00839 CIMOMEnvironment::getCIMOMHandle(OperationContext& context,
00840    EBypassProvidersFlag bypassProviders,
00841    ELockingFlag locking) const
00842 {
00843    return getCIMOMHandle(context, E_SEND_INDICATIONS, bypassProviders, locking);
00844 }
00845 
00847 CIMOMHandleIFCRef
00848 CIMOMEnvironment::getCIMOMHandle(OperationContext& context,
00849    ESendIndicationsFlag sendIndications,
00850    EBypassProvidersFlag bypassProviders,
00851    ELockingFlag locking) const
00852 {
00853    {
00854       MutexLock l(m_stateGuard);
00855       if (!isLoaded(m_state))
00856       {
00857          OW_THROW(CIMOMEnvironmentException, "CIMOMEnvironment::getCIMOMHandle() called when state is not loaded.");
00858       }
00859    }
00860    MutexLock ml(m_monitor);
00861    OW_ASSERT(m_cimServer);
00862 
00863    // Here we construct a pipeline.  Currently it looks like:
00864    // LocalCIMOMHandle -> [ Authorizer -> ] [Indication Rep Layer -> ] [ CIM Server -> ] CIM Repository
00865 
00866    RepositoryIFCRef rref;
00867    if (bypassProviders == E_BYPASS_PROVIDERS)
00868    {
00869       rref = m_cimRepository;
00870    }
00871    else
00872    {
00873       rref = m_cimServer;
00874    }
00875 
00876    if (sendIndications == E_SEND_INDICATIONS && m_indicationServer && !m_indicationsDisabled)
00877    {
00878       SharedLibraryRepositoryIFCRef irl = _getIndicationRepLayer(rref);
00879       if (irl)
00880       {
00881          rref = RepositoryIFCRef(new SharedLibraryRepository(irl));
00882       }
00883    }
00884    if (m_authorizer)
00885    {
00886       AuthorizerIFC* p = m_authorizer->clone();
00887       p->setSubRepositoryIFC(rref);
00888       rref = RepositoryIFCRef(new SharedLibraryRepository(SharedLibraryRepositoryIFCRef(m_authorizer.getLibRef(), RepositoryIFCRef(p))));
00889    }
00890 
00891    return CIMOMHandleIFCRef(new LocalCIMOMHandle(const_cast<CIMOMEnvironment*>(this), rref,
00892       context, locking == E_LOCKING ? LocalCIMOMHandle::E_LOCKING : LocalCIMOMHandle::E_NO_LOCKING));
00893 }
00895 WQLIFCRef
00896 CIMOMEnvironment::getWQLRef() const
00897 {
00898    {
00899       MutexLock l(m_stateGuard);
00900       if (!isLoaded(m_state))
00901       {
00902          OW_THROW(CIMOMEnvironmentException, "CIMOMEnvironment::getWQLRef() called when state is not loaded");
00903       }
00904    }
00905    MutexLock ml(m_monitor);
00906    if (!m_wqlLib)
00907    {
00908       String libname = getConfigItem(ConfigOpts::WQL_LIB_opt, OW_DEFAULT_WQL_LIB);
00909       OW_LOG_DEBUG(m_Logger, Format("CIMOM loading wql library %1", libname));
00910       SharedLibraryLoaderRef sll =
00911          SharedLibraryLoader::createSharedLibraryLoader();
00912       m_wqlLib = sll->loadSharedLibrary(libname, m_Logger);
00913       if (!m_wqlLib)
00914       {
00915          OW_LOG_ERROR(m_Logger, Format("CIMOM Failed to load WQL Libary: %1", libname));
00916          return WQLIFCRef();
00917       }
00918    }
00919    return  WQLIFCRef(m_wqlLib, SafeLibCreate<WQLIFC>::create(
00920       m_wqlLib, "createWQL", m_Logger));
00921 }
00923 SharedLibraryRepositoryIFCRef
00924 CIMOMEnvironment::_getIndicationRepLayer(const RepositoryIFCRef& rref) const
00925 {
00926    SharedLibraryRepositoryIFCRef retref;
00927    if (!m_indicationRepLayerDisabled)
00928    {
00929       MutexLock ml(m_indicationLock);
00930       if (!m_indicationRepLayerLib)
00931       {
00932          const String libPath = getConfigItem(ConfigOpts::OWLIBDIR_opt, OW_DEFAULT_OWLIBDIR) + OW_FILENAME_SEPARATOR;
00933          const String libBase = "libowindicationreplayer";
00934          String libname = libPath + libBase + OW_SHAREDLIB_EXTENSION;
00935          OW_LOG_DEBUG(m_Logger, Format("CIMOM loading indication libary %1",
00936             libname));
00937          SharedLibraryLoaderRef sll =
00938             SharedLibraryLoader::createSharedLibraryLoader();
00939 
00940          if (!sll)
00941          {
00942             m_indicationRepLayerDisabled = true;
00943             OW_LOG_FATAL_ERROR(m_Logger, Format("CIMOM failed to create SharedLibraryLoader"
00944                " library %1", libname));
00945             return retref;
00946          }
00947          m_indicationRepLayerLib = sll->loadSharedLibrary(libname, m_Logger);
00948          if (!m_indicationRepLayerLib)
00949          {
00950             m_indicationRepLayerDisabled = true;
00951             OW_LOG_FATAL_ERROR(m_Logger, Format("CIMOM failed to load indication rep layer"
00952                " library %1", libname));
00953             return retref;
00954          }
00955       }
00956       IndicationRepLayer* pirep =
00957          SafeLibCreate<IndicationRepLayer>::create(
00958             m_indicationRepLayerLib, "createIndicationRepLayer", m_Logger);
00959       if (pirep)
00960       {
00961          retref = SharedLibraryRepositoryIFCRef(m_indicationRepLayerLib,
00962             RepositoryIFCRef(pirep));
00963          pirep->setCIMServer(rref);
00964       }
00965       else
00966       {
00967          m_indicationRepLayerDisabled = true;
00968          m_indicationRepLayerLib = 0;
00969       }
00970    }
00971    return retref;
00972 }
00973 
00975 void
00976 CIMOMEnvironment::_loadAuthorizer()
00977 {
00978    OW_ASSERT(!m_authorizer);
00979    String libname = getConfigItem(ConfigOpts::AUTHORIZATION_LIB_opt);
00980 
00981    // no authorization requested
00982    if (libname.empty())
00983    {
00984       return;
00985    }
00986 
00987    OW_LOG_DEBUG(m_Logger, Format("CIMOM loading authorization libary %1",
00988                libname));
00989    SharedLibraryLoaderRef sll =
00990       SharedLibraryLoader::createSharedLibraryLoader();
00991    if (!sll)
00992    {
00993       String msg = Format("CIMOM failed to create SharedLibraryLoader."
00994                      " library %1", libname);
00995       OW_LOG_FATAL_ERROR(m_Logger, msg);
00996       OW_THROW(CIMOMEnvironmentException, msg.c_str());
00997    }
00998    SharedLibraryRef authorizerLib = sll->loadSharedLibrary(libname, m_Logger);
00999    if (!authorizerLib)
01000    {
01001       String msg = Format("CIMOM failed to load authorization"
01002                      " library %1", libname);
01003       OW_LOG_FATAL_ERROR(m_Logger, msg);
01004       OW_THROW(CIMOMEnvironmentException, msg.c_str());
01005    }
01006    AuthorizerIFC* p =
01007       SafeLibCreate<AuthorizerIFC>::create(
01008          authorizerLib, "createAuthorizer", m_Logger);
01009    if (!p)
01010    {
01011       String msg = Format("CIMOM failed to load authorization"
01012                      " library %1", libname);
01013       OW_LOG_FATAL_ERROR(m_Logger, msg);
01014       OW_THROW(CIMOMEnvironmentException, msg.c_str());
01015    }
01016    m_authorizer = AuthorizerIFCRef(authorizerLib,
01017                            AuthorizerIFCRef::element_type(p));
01018 
01019    m_services.push_back(m_authorizer);
01020 }
01022 void
01023 CIMOMEnvironment::_createAuthorizerManager()
01024 {
01025    // m_authorizerManager should actually be a valid AuthorizerManager
01026    // already, but it doesn't have a authorizer loaded yet.
01027    // It is also already added to the m_services array.
01028 
01029    String libname = getConfigItem(ConfigOpts::AUTHORIZATION2_LIB_opt);
01030 
01031    // no authorization requested
01032    if (libname.empty())
01033    {
01034       return;
01035    }
01036 
01037    OW_LOG_DEBUG(m_Logger, Format("CIMOM loading authorization libary %1", libname));
01038 
01039    SharedLibraryLoaderRef sll =
01040       SharedLibraryLoader::createSharedLibraryLoader();
01041    if (!sll)
01042    {
01043       String msg = Format("CIMOM failed to create SharedLibraryLoader."
01044          " library %1", libname);
01045       OW_LOG_FATAL_ERROR(m_Logger, msg);
01046       OW_THROW(CIMOMEnvironmentException, msg.c_str());
01047    }
01048    SharedLibraryRef authorizerLib = sll->loadSharedLibrary(libname, m_Logger);
01049    if (!authorizerLib)
01050    {
01051       String msg = Format("CIMOM failed to load authorization"
01052          " library %1", libname);
01053       OW_LOG_FATAL_ERROR(m_Logger, msg);
01054       OW_THROW(CIMOMEnvironmentException, msg.c_str());
01055    }
01056    Authorizer2IFC* p =
01057       SafeLibCreate<Authorizer2IFC>::create(
01058          authorizerLib, "createAuthorizer2", m_Logger);
01059    if (!p)
01060    {
01061       String msg = Format("CIMOM failed to load authorization"
01062          " library %1", libname);
01063       OW_LOG_FATAL_ERROR(m_Logger, msg);
01064       OW_THROW(CIMOMEnvironmentException, msg.c_str());
01065    }
01066 
01067    m_authorizerManager->setAuthorizer(
01068       Authorizer2IFCRef(authorizerLib,Authorizer2IFCRef::element_type(p)));
01069 }
01071 RequestHandlerIFCRef
01072 CIMOMEnvironment::getRequestHandler(const String &id) const
01073 {
01074    RequestHandlerIFCRef ref;
01075    {
01076       MutexLock l(m_stateGuard);
01077       if (!isInitialized(m_state))
01078       {
01079          return ref;
01080       }
01081    }
01082    MutexLock ml(m_reqHandlersLock);
01083    ReqHandlerMap::iterator iter =
01084          m_reqHandlers.find(id);
01085    if (iter != m_reqHandlers.end())
01086    {
01087       if (!iter->second->rqIFCRef)
01088       {
01089          iter->second->rqIFCRef =
01090             SafeLibCreate<RequestHandlerIFC>::loadAndCreateObject(
01091                iter->second->filename, "createRequestHandler", getLogger(COMPONENT_NAME));
01092          
01093          // re-add it to m_services and resort them.
01094          m_services.push_back(iter->second->rqIFCRef);
01095          const_cast<CIMOMEnvironment*>(this)->_sortServicesForDependencies();
01096       }
01097       if (iter->second->rqIFCRef)
01098       {
01099          ref = RequestHandlerIFCRef(iter->second->rqIFCRef.getLibRef(),
01100             iter->second->rqIFCRef->clone());
01101          iter->second->dt.setToCurrent();
01102          ref->setEnvironment(const_cast<CIMOMEnvironment*>(this));
01103          OW_LOG_DEBUG(m_Logger, Format("Request Handler %1 handling request for content type %2",
01104             iter->second->filename, id));
01105       }
01106       else
01107       {
01108          OW_LOG_ERROR(m_Logger, Format(
01109             "Error loading request handler library %1 for content type %2",
01110             iter->second->filename, id));
01111       }
01112    }
01113    return ref;
01114 }
01116 void
01117 CIMOMEnvironment::unloadReqHandlers()
01118 {
01119    //OW_LOG_DEBUG(m_Logger, "Running unloadReqHandlers()");
01120    Int32 ttl;
01121    try
01122    {
01123       ttl = getConfigItem(ConfigOpts::REQUEST_HANDLER_TTL_opt, OW_DEFAULT_REQUEST_HANDLER_TTL).toInt32();
01124    }
01125    catch (const StringConversionException&)
01126    {
01127       OW_LOG_ERROR(m_Logger, Format("Invalid value (%1) for %2 config item.",
01128          getConfigItem(ConfigOpts::REQUEST_HANDLER_TTL_opt, OW_DEFAULT_REQUEST_HANDLER_TTL),
01129          ConfigOpts::REQUEST_HANDLER_TTL_opt));
01130    }
01131    if (ttl < 0)
01132    {
01133       OW_LOG_DEBUG(m_Logger, "Non-Positive TTL for Request Handlers: OpenWBEM will not unload request handlers.");
01134       return;
01135    }
01136    DateTime dt;
01137    dt.setToCurrent();
01138    MutexLock ml(m_reqHandlersLock);
01139    for (ReqHandlerMap::iterator iter = m_reqHandlers.begin();
01140         iter != m_reqHandlers.end(); ++iter)
01141    {
01142       if (iter->second->rqIFCRef)
01143       {
01144          DateTime rqDT = iter->second->dt;
01145          rqDT.addMinutes(ttl);
01146          if (rqDT < dt)
01147          {
01148             // remove it from m_services
01149             for (size_t i = 0; i < m_services.size(); ++i)
01150             {
01151                if (m_services[i].get() == iter->second->rqIFCRef.get())
01152                {
01153                   m_services.remove(i);
01154                   break;
01155                }
01156             }
01157             iter->second->rqIFCRef.setNull();
01158             OW_LOG_DEBUG(m_Logger, Format("Unloaded request handler lib %1 for content type %2",
01159                iter->second->filename, iter->first));
01160          }
01161       }
01162    }
01163 }
01165 LoggerRef
01166 CIMOMEnvironment::getLogger() const
01167 {
01168    OW_ASSERT(m_Logger);
01169    return m_Logger->clone();
01170 }
01172 LoggerRef
01173 CIMOMEnvironment::getLogger(const String& componentName) const
01174 {
01175    OW_ASSERT(m_Logger);
01176    LoggerRef rv(m_Logger->clone());
01177    rv->setDefaultComponent(componentName);
01178    return rv;
01179 }
01181 IndicationServerRef
01182 CIMOMEnvironment::getIndicationServer() const
01183 {
01184    return m_indicationServer;
01185 }
01187 PollingManagerRef
01188 CIMOMEnvironment::getPollingManager() const
01189 {
01190    return m_pollingManager;
01191 }
01193 void
01194 CIMOMEnvironment::clearConfigItems()
01195 {
01196    m_configItems->clear();
01197 }
01199 void
01200 CIMOMEnvironment::setConfigItem(const String &item,
01201    const String &value, EOverwritePreviousFlag overwritePrevious)
01202 {
01203    ConfigFile::setConfigItem(*m_configItems, item, value, 
01204       overwritePrevious == E_OVERWRITE_PREVIOUS ? ConfigFile::E_OVERWRITE_PREVIOUS : ConfigFile::E_PRESERVE_PREVIOUS);
01205 }
01207 void
01208 CIMOMEnvironment::runSelectEngine() const
01209 {
01210    OW_ASSERT(m_selectables.size() == m_selectableCallbacks.size());
01211    SelectEngine engine;
01212    // Insure the signal pipe is at the front of the select list
01213    engine.addSelectableObject(Platform::getSigSelectable(),
01214       SelectableCallbackIFCRef(new SelectEngineStopper(engine)));
01215    
01216    for (size_t i = 0; i < m_selectables.size(); ++i)
01217    {
01218       engine.addSelectableObject(m_selectables[i], m_selectableCallbacks[i]);
01219    }
01220    engine.go();
01221 }
01223 void
01224 CIMOMEnvironment::_clearSelectables()
01225 {
01226    MutexLock ml(m_selectableLock);
01227    m_selectables.clear();
01228    m_selectableCallbacks.clear();
01229 }
01231 void
01232 CIMOMEnvironment::addSelectable(const SelectableIFCRef& obj,
01233    const SelectableCallbackIFCRef& cb)
01234 {
01235    MutexLock ml(m_selectableLock);
01236    m_selectables.push_back(obj);
01237    m_selectableCallbacks.push_back(cb);
01238 }
01240 void
01241 CIMOMEnvironment::removeSelectable(const SelectableIFCRef& obj)
01242 {
01243    MutexLock ml(m_selectableLock);
01244     for (size_t i = 0; i < m_selectables.size(); i++)
01245     {
01246         if (obj == m_selectables[i])
01247         {
01248             m_selectables.remove(i);
01249             m_selectableCallbacks.remove(i);
01250             --i;
01251             continue;
01252         }
01253     }
01254 }
01256 void
01257 CIMOMEnvironment::exportIndication(const CIMInstance& instance,
01258    const String& instNS)
01259 {
01260    OW_LOG_DEBUG(m_Logger, "CIMOMEnvironment::exportIndication");
01261    if (m_indicationServer && !m_indicationsDisabled)
01262    {
01263       OW_LOG_DEBUG(m_Logger, "CIMOMEnvironment::exportIndication - calling indication"
01264          " server");
01265       m_indicationServer->processIndication(instance, instNS);
01266    }
01267 }
01269 IndicationRepLayerMediatorRef
01270 CIMOMEnvironment::getIndicationRepLayerMediator() const
01271 {
01272    return m_indicationRepLayerMediatorRef;
01273 }
01275 RepositoryIFCRef
01276 CIMOMEnvironment::getRepository() const
01277 {
01278    return m_cimRepository;
01279 }
01281 AuthorizerManagerRef
01282 CIMOMEnvironment::getAuthorizerManager() const
01283 {
01284    return m_authorizerManager;
01285 }
01286 
01288 void
01289 CIMOMEnvironment::unloadProviders()
01290 {
01291    m_providerManager->unloadProviders(createProvEnvRef(this));
01292 }
01293 
01294 namespace
01295 {
01296 
01298 struct Node
01299 {
01300    Node(const String& name_, size_t index_ = ~0)
01301       : name(name_)
01302       , index(index_)
01303    {}
01304 
01305    String name;
01306    size_t index;
01307 };
01308 
01310 bool operator!=(const Node& x, const Node& y)
01311 {
01312    return x.name != y.name;
01313 }
01314 
01316 bool operator<(const Node& x, const Node& y)
01317 {
01318    return x.name < y.name;
01319 }
01320 
01322 Node INVALID_NODE("", ~0);
01323 
01325 class ServiceDependencyGraph
01326 {
01327 public:
01328    // returns false if serviceName has already been inserted, true otherwise
01329    bool addNode(const String& serviceName, size_t index);
01330    // returns false if serviceName already has a dependency on dependentServiceName, true otherwise
01331    // precondition: a node for serviceName has already been added via addNode()
01332    bool addDependency(const String& serviceName, const String& dependentServiceName);
01333    Node findIndependentNode() const;
01334    void removeNode(const String& serviceName);
01335    bool empty() const;
01336    Array<Node> getNodes() const;
01337 
01338 private:
01339    typedef std::map<Node, std::set<String> > deps_t;
01340    deps_t m_deps;
01341 };
01342 
01344 bool
01345 ServiceDependencyGraph::addNode(const String& serviceName, size_t index)
01346 {
01347    return m_deps.insert(std::make_pair(Node(serviceName, index), deps_t::mapped_type())).second;
01348 }
01349 
01351 bool
01352 ServiceDependencyGraph::addDependency(const String& serviceName, const String& dependentServiceName)
01353 {
01354    return m_deps.find(serviceName)->second.insert(dependentServiceName).second;
01355 }
01356 
01358 Node
01359 ServiceDependencyGraph::findIndependentNode() const
01360 {
01361    for (deps_t::const_iterator nodeiter(m_deps.begin()); nodeiter != m_deps.end(); ++nodeiter)
01362    {
01363       if (nodeiter->second.empty())
01364       {
01365          return nodeiter->first;
01366       }
01367    }
01368    
01369    // didn't find any :-(
01370    return INVALID_NODE;
01371 }
01372 
01374 void
01375 ServiceDependencyGraph::removeNode(const String& serviceName)
01376 {
01377    // remove it from all dependency lists
01378    for (deps_t::iterator nodeiter(m_deps.begin()); nodeiter != m_deps.end(); ++nodeiter)
01379    {
01380       nodeiter->second.erase(serviceName);
01381    }
01382    m_deps.erase(serviceName);
01383 }
01384 
01386 bool
01387 ServiceDependencyGraph::empty() const
01388 {
01389    return m_deps.empty();
01390 }
01391 
01393 Array<Node>
01394 ServiceDependencyGraph::getNodes() const
01395 {
01396    Array<Node> rv;
01397    rv.reserve(m_deps.size());
01398    for (deps_t::const_iterator nodeiter(m_deps.begin()); nodeiter != m_deps.end(); ++nodeiter)
01399    {
01400       rv.push_back(nodeiter->first);
01401    }
01402    return rv;
01403 }
01404 
01405 } // end anonymous namespace
01406 
01408 void
01409 CIMOMEnvironment::_sortServicesForDependencies()
01410 {
01411    // All services can specify a name and dependencies. If a service has an empty name, it can't be specified
01412    // as a dependency, and our algorithm requires that each service has a name, so if any have an empty name,
01413    // they'll just be put at the beginning of the list.
01414 
01415    // We need to make sure that a service is initialized before any other services which depend on it.
01416    // The depedencies reported by the services make a graph.  If it's not a DAG (i.e. contains cycles), we
01417    // can't turn it into a list of what to do, and we'll detect that and throw an exception. Doing a topological
01418    // sort on the graph will yield the order we need.
01419    //
01420    // The process is quite simple conceptually:
01421    // while (the graph has a node with no antecedents)
01422    //    remove one such node from the graph and add it to the list
01423    //
01424    // if (the graph is not empty)
01425    //    the graph contains a cycle
01426    // else
01427    //    success
01428    
01429    Array<ServiceIFCRef> sortedServices;
01430 
01431    // first build the graph
01432    ServiceDependencyGraph depGraph;
01433    // step 1 insert all the nodes and handle the no-names.
01434    for (size_t i = 0; i < m_services.size(); ++i)
01435    {
01436       String name = m_services[i]->getName();
01437       if (name == "")
01438       {
01439          // no name == no depedency tracking, just do it at the beginning.
01440          sortedServices.push_back(m_services[i]);
01441          OW_LOG_DEBUG(m_Logger, "Found service with no name, adding to sortedServices");
01442       }
01443       else
01444       {
01445          OW_LOG_DEBUG(m_Logger, Format("Adding node for service %1", name));
01446          if (!depGraph.addNode(name, i))
01447          {
01448             OW_THROW(CIMOMEnvironmentException, Format("Invalid: 2 services with the same name: %1", name).c_str());
01449          }
01450          
01451       }
01452    }
01453 
01454    // step 2 insert all the dependencies
01455    for (size_t i = 0; i < m_services.size(); ++i)
01456    {
01457       String name = m_services[i]->getName();
01458       if (name != "")
01459       {
01460          StringArray deps(m_services[i]->getDependencies());
01461          for (size_t j = 0; j < deps.size(); ++j)
01462          {
01463             OW_LOG_DEBUG(m_Logger, Format("Adding dependency for service %1->%2", name, deps[j]));
01464             if (!depGraph.addDependency(name, deps[j]))
01465             {
01466                OW_THROW(CIMOMEnvironmentException, Format("Invalid: service %1 has duplicate dependencies: %2", name, deps[j]).c_str());
01467             }
01468          }
01469 
01470          // these are just the opposite direction than the dependencies
01471          StringArray dependentServices(m_services[i]->getDependentServices());
01472          for (size_t j = 0; j < dependentServices.size(); ++j)
01473          {
01474             OW_LOG_DEBUG(m_Logger, Format("Adding dependency for service %1->%2", dependentServices[j], name));
01475             if (!depGraph.addDependency(dependentServices[j], name))
01476             {
01477                OW_THROW(CIMOMEnvironmentException, Format("Invalid: service %1 has duplicate dependencies: %2", dependentServices[j], name).c_str());
01478             }
01479          }
01480       }
01481    }
01482 
01483    // now do the topological sort
01484    Node curNode = depGraph.findIndependentNode();
01485    while (curNode != INVALID_NODE)
01486    {
01487       OW_LOG_DEBUG(m_Logger, Format("Found service with satisfied dependencies: %1", curNode.name));
01488       sortedServices.push_back(m_services[curNode.index]);
01489       depGraph.removeNode(curNode.name);
01490       curNode = depGraph.findIndependentNode();
01491    }
01492 
01493    if (!depGraph.empty())
01494    {
01495       OW_LOG_FATAL_ERROR(m_Logger, "Service dependency graph contains a cycle:");
01496       Array<Node> nodes(depGraph.getNodes());
01497       for (size_t i = 0; i < nodes.size(); ++i)
01498       {
01499          OW_LOG_FATAL_ERROR(m_Logger, Format("Service: %1", nodes[i].name));
01500       }
01501       OW_THROW(CIMOMEnvironmentException, "Service dependency graph contains a cycle");
01502    }
01503 
01504    m_services = sortedServices;
01505 }
01506 
01507 } // end namespace OW_NAMESPACE
01508 

Generated on Thu Feb 9 08:47:53 2006 for openwbem by  doxygen 1.4.6