OW_CIMRepository2.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2002 Center 7, 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 Center 7 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 Center 7, 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 #include "OW_config.h"
00031 #include "OW_CIMRepository2.hpp"
00032 #include "OW_FileSystem.hpp"
00033 #include "OW_CIMValueCast.hpp"
00034 #include "OW_CIMOMHandleIFC.hpp"
00035 #include "OW_ConfigOpts.hpp"
00036 #include "OW_Format.hpp"
00037 #include "OW_WQLIFC.hpp"
00038 #include "OW_Assertion.hpp"
00039 #include "OW_IOException.hpp"
00040 #include "OW_CIMParamValue.hpp"
00041 #include "OW_ConfigOpts.hpp"
00042 #include "OW_Map.hpp"
00043 #include "OW_CIMQualifierType.hpp"
00044 #include "OW_CIMClass.hpp"
00045 #include "OW_CIMInstance.hpp"
00046 #include "OW_CIMProperty.hpp"
00047 #include "OW_CIMValue.hpp"
00048 #include "OW_CIMQualifier.hpp"
00049 #include "OW_CIMObjectPath.hpp"
00050 #include "OW_Logger.hpp"
00051 #include "OW_dbUtils.hpp"
00052 
00053 namespace OW_NAMESPACE
00054 {
00055 
00056 OW_DEFINE_EXCEPTION(CIMRepository2);
00057 
00058 using namespace WBEMFlags;
00059 
00060 
00062 namespace
00063 {
00064 LoggerRef g_logger;
00065 void dbErrorCallback(const char *errpfx, char *msg)
00066 {
00067    // have to use the global here since we can't pass in any sort of handle into db :-(
00068    if (g_logger)
00069    {
00070       OW_LOG_ERROR(g_logger, msg);
00071    }
00072 }
00073 }
00074 
00076 CIMRepository2::CIMRepository2(ServiceEnvironmentIFCRef env)
00077    : RepositoryIFC()
00078    , m_iStore(env)
00079    , m_mStore(env)
00080 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00081    , m_classAssocDb(env)
00082    , m_instAssocDb(env)
00083 #endif
00084    , m_env(env)
00085    , m_checkReferentialIntegrity(false)
00086    , m_dbenv(0)
00087 {
00088    g_logger = m_env->getLogger(COMPONENT_NAME);
00089 
00090    if (m_env->getConfigItem(ConfigOpts::CHECK_REFERENTIAL_INTEGRITY_opt,
00091       OW_DEFAULT_CHECK_REFERENTIAL_INTEGRITY).equalsIgnoreCase("true"))
00092    {
00093       m_checkReferentialIntegrity = true;
00094    }
00095 
00096    OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 initializing with libdb version: %1", ::db_version(0, 0, 0)));
00097 
00098 }
00100 CIMRepository2::~CIMRepository2()
00101 {
00102    try
00103    {
00104       close();
00105    }
00106    catch (...)
00107    {
00108       // don't let exceptions escape
00109    }
00110 }
00111 
00113 namespace
00114 {
00115 class DBTransactionScope
00116 {
00117 public:
00118    DBTransactionScope(::DB_ENV* env)
00119       : m_tid(0)
00120    {
00121       OW_ASSERT(env != 0);
00122       int ret = env->txn_begin(env, 0, &m_tid, 0);
00123       dbUtils::checkReturn(ret, "txn_begin");
00124    }
00125    ~DBTransactionScope()
00126    {
00127       if (m_tid != 0)
00128       {
00129          try
00130          {
00131             abort();
00132          }
00133          catch (...)
00134          {
00135             // can't let exceptions escape
00136          }
00137       }
00138    }
00139    void commit()
00140    {
00141       OW_ASSERT(m_tid != 0);
00142       int ret = m_tid->commit(m_tid, 0);
00143       dbUtils::checkReturn(ret, "txn_commit");
00144       m_tid = 0;
00145    }
00146    void abort()
00147    {
00148       OW_ASSERT(m_tid != 0);
00149       int ret = m_tid->abort(m_tid);
00150       dbUtils::checkReturn(ret, "txn_abort");
00151       m_tid = 0;
00152    }
00153 
00154    operator ::DB_TXN*()
00155    {
00156       return m_tid;
00157    }
00158 
00159 private:
00160    ::DB_TXN* m_tid;
00161 };
00162 } // end unnamed namespace
00163 
00165 void
00166 CIMRepository2::open(const String& path)
00167 {
00168    FileSystem::makeDirectory(path, 0700);
00169    if (!FileSystem::exists(path))
00170    {
00171       String msg("failed to create directory: " );
00172       msg += path;
00173       OW_THROW(IOException, msg.c_str());
00174    }
00175    else
00176    {
00177       if (!FileSystem::canWrite(path))
00178       {
00179          String msg("don't have write access to directory: ");
00180          msg += path;
00181          OW_THROW(IOException, msg.c_str());
00182       }
00183    }
00184    String fname = path;
00185    if (!fname.endsWith(String(OW_FILENAME_SEPARATOR)))
00186    {
00187       fname += OW_FILENAME_SEPARATOR;
00188    }
00189    
00190    // Create a db environment object and initialize it for error
00191    // reporting.
00192    int ret;
00193    if ((ret = ::db_env_create(&m_dbenv, 0)) != 0)
00194    {
00195       OW_THROW(CIMRepository2Exception, format("::db_env_create() failed: %1(%2)", ret, ::db_strerror(ret)).c_str());
00196    }
00197    m_dbenv->set_errcall(m_dbenv, dbErrorCallback);
00198    m_dbenv->set_errpfx(m_dbenv, "CIMRepository2");
00199 
00200    // We want to specify the shared memory buffer pool cachesize,
00201    // but everything else is the default.
00202    const int size = 64 * 1024;
00203    if ((ret = m_dbenv->set_cachesize(m_dbenv, 0, size, 0)) != 0)
00204    {
00205       m_dbenv->close(m_dbenv, 0);
00206       OW_THROW(CIMRepository2Exception, format("m_dbenv->set_cachesize() failed: %1(%2)", ret, ::db_strerror(ret)).c_str());
00207    }
00208 
00209 #ifdef OW_DEBUG
00210    m_dbenv->set_verbose(m_dbenv,DB_VERB_CHKPOINT | DB_VERB_DEADLOCK | DB_VERB_RECOVERY | DB_VERB_REPLICATION | DB_VERB_WAITSFOR, 1);
00211 #endif
00212 
00213 
00214    // Open the db environment with full transactional support.
00215    // DB_CREATE creates the db env if this is the first time we're running.  It's also required if DB_RECOVER is specified.
00216    // DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN initializes the sub-systems we need for transactions.
00217    // DB_PRIVATE is used since we (currently) only access the db from the cimom.  Recovery has to run single-threaded and we don't have any way of
00218    // ensuring that if multiple processes are involved.  If the cimom is changed to use a fork() model this should be changed.
00219    // DB_THREAD since we are multi-threaded.  This shouldn't be removed if the cimom is changed to fork() for each connection unless all threads are removed.
00220    // DB_RECOVER replays the transaction logs and will clean up the db if the cimom didn't correctly shut down previously.
00221    ret = m_dbenv->open(m_dbenv, fname.c_str(),
00222       DB_CREATE |
00223       DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN |
00224       DB_PRIVATE |
00225       DB_THREAD |
00226       DB_RECOVER,
00227       0600);
00228    dbUtils::checkReturn(ret, "m_dbenv->open");
00229 
00230    // opens happen in the context of a transaction
00231    DBTransactionScope tid(m_dbenv);
00232    m_iStore.open(m_dbenv, tid);
00233 
00234    m_mStore.open(m_dbenv, tid);
00235 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00236    m_classAssocDb.open("classassoc", m_dbenv, tid);
00237    m_instAssocDb.open("instanceassoc", m_dbenv, tid);
00238 #endif
00239    tid.commit();
00240 }
00242 void
00243 CIMRepository2::close()
00244 {
00245    m_iStore.close();
00246    m_mStore.close();
00247 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00248    m_classAssocDb.close();
00249    m_instAssocDb.close();
00250 #endif
00251    if (m_dbenv)
00252    {
00253       m_dbenv->close(m_dbenv, 0);
00254       m_dbenv = 0;
00255    }
00256 }
00257 #ifndef OW_DISABLE_INSTANCE_MANIPULATION
00258 
00259 void
00260 CIMRepository2::createNameSpace(const String& ns,
00261    OperationContext& context)
00262 {
00263    m_mStore.createNameSpace(ns, context);
00264 
00265    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00266    {
00267       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 created namespace: %1", ns));
00268    }
00269 }
00271 void
00272 CIMRepository2::deleteNameSpace(const String& ns,
00273    OperationContext& context)
00274 {
00275    m_mStore.deleteNameSpace(ns, context);
00276    
00277    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00278    {
00279       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 deleted namespace: %1", ns));
00280    }
00281 }
00282 #endif
00283 
00284 void
00285 CIMRepository2::enumNameSpace(StringResultHandlerIFC& result,
00286    OperationContext& context)
00287 {
00288    m_mStore.enumNameSpace(result, context);
00289    
00290    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00291    {
00292       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), "CIMRepository2 enumerated namespaces");
00293    }
00294 }
00296 CIMQualifierType
00297 CIMRepository2::getQualifierType(const String& ns,
00298    const String& qualifierName,
00299    OperationContext&)
00300 {
00301    CIMQualifierType rv = m_mStore.getQualifierType(ns, qualifierName);
00302    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00303    {
00304       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 getting qualifier type: %1",
00305          CIMObjectPath(qualifierName,ns).toString()));
00306    }
00307    return rv;
00308 }
00309 #ifndef OW_DISABLE_QUALIFIER_DECLARATION
00310 
00311 void
00312 CIMRepository2::enumQualifierTypes(
00313    const String& ns,
00314    CIMQualifierTypeResultHandlerIFC& result,
00315    OperationContext&)
00316 {
00317    m_mStore.enumQualifierTypes(ns, result);
00318    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00319    {
00320       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 enumerated qualifiers in namespace: %1", ns));
00321    }
00322 }
00324 void
00325 CIMRepository2::deleteQualifierType(const String& ns, const String& qualName,
00326    OperationContext&)
00327 {
00328    // TODO: What happens if the qualifier is being used???
00329    if (!m_mStore.deleteQualifierType(ns, qualName))
00330    {
00331       if (m_mStore.nameSpaceExists(ns))
00332       {
00333          OW_THROWCIMMSG(CIMException::NOT_FOUND,
00334             String(ns + "/" + qualName).c_str());
00335       }
00336       else
00337       {
00338          OW_THROWCIMMSG(CIMException::INVALID_NAMESPACE,
00339             String(ns + "/" + qualName).c_str());
00340       }
00341    }
00342    
00343    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00344    {
00345       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 deleted qualifier type: %1 in namespace: %2", qualName, ns));
00346    }
00347 }
00349 void
00350 CIMRepository2::setQualifierType(
00351    const String& ns,
00352    const CIMQualifierType& qt, OperationContext&)
00353 {
00354    m_mStore.setQualifierType(ns, qt);
00355    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00356    {
00357       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 set qualifier type: %1 in "
00358          "namespace: %2", qt.toString(), ns));
00359    }
00360 }
00361 #endif // #ifndef OW_DISABLE_QUALIFIER_DECLARATION
00362 
00363 CIMClass
00364 CIMRepository2::getClass(
00365    const String& ns, const String& className,
00366    ELocalOnlyFlag localOnly, EIncludeQualifiersFlag includeQualifiers,
00367    EIncludeClassOriginFlag includeClassOrigin, const StringArray* propertyList,
00368    OperationContext&)
00369 {
00370    CIMClass theClass(CIMNULL);
00371    CIMException::ErrNoType rval = m_mStore.getCIMClass(ns, className,
00372       localOnly, includeQualifiers, includeClassOrigin, propertyList,
00373       theClass);
00374    checkGetClassRvalAndThrow(rval, ns, className);
00375    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00376    {
00377       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 got class: %1 from "
00378          "namespace: %2", theClass.getName(), ns));
00379    }
00380    return theClass;
00381 }
00383 CIMClass
00384 CIMRepository2::_getClass(const String& ns, const String& className)
00385 {
00386    CIMClass theClass(CIMNULL);
00387    CIMException::ErrNoType rval = m_mStore.getCIMClass(ns, className, E_NOT_LOCAL_ONLY, E_INCLUDE_QUALIFIERS, E_INCLUDE_CLASS_ORIGIN, 0, theClass);
00388    checkGetClassRvalAndThrow(rval, ns, className);
00389    return theClass;
00390 }
00392 CIMClass
00393 CIMRepository2::_instGetClass(const String& ns, const String& className)
00394 {
00395    CIMClass theClass(CIMNULL);
00396    CIMException::ErrNoType rval = m_mStore.getCIMClass(ns, className, E_NOT_LOCAL_ONLY, E_INCLUDE_QUALIFIERS, E_INCLUDE_CLASS_ORIGIN, 0, theClass);
00397    checkGetClassRvalAndThrowInst(rval, ns, className);
00398    return theClass;
00399 }
00400 #ifndef OW_DISABLE_SCHEMA_MANIPULATION
00401 
00402 namespace
00403 {
00404    class CIMClassDeleter : public CIMClassResultHandlerIFC
00405    {
00406    public:
00407       CIMClassDeleter(MetaRepository2& mr, const String& ns_,
00408          InstanceRepository2& mi
00409 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00410          , AssocDb2& m_assocDb_
00411 #endif
00412          )
00413       : m_mStore(mr)
00414       , ns(ns_)
00415       , m_iStore(mi)
00416 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00417       , m_assocDb(m_assocDb_)
00418 #endif
00419       {}
00420    protected:
00421       virtual void doHandle(const CIMClass &c)
00422       {
00423          String cname = c.getName();
00424          // TODO: this doesn't work quite right. Fix deleteInstance to also delete
00425          // associations, then we could just call enumInstances and then
00426          // deleteInstance for all instances.
00427          // delete any instances of the class
00428          //m_iStore.deleteClass(ns, cname);
00429 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00430          // remove class from association index
00431          if (c.isAssociation())
00432          {
00433             m_assocDb.deleteEntries(ns,c);
00434          }
00435 #endif
00436          if (!m_mStore.deleteClass(ns, cname))
00437          {
00438             OW_THROWCIM(CIMException::NOT_FOUND);
00439          }
00440       }
00441    private:
00442       MetaRepository2& m_mStore;
00443       const String& ns;
00444       InstanceRepository2& m_iStore;
00445 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00446       AssocDb2& m_assocDb;
00447 #endif
00448    };
00449 }
00451 CIMClass
00452 CIMRepository2::deleteClass(const String& ns, const String& className,
00453    OperationContext& acl)
00454 {
00455    CIMClass cc = _getClass(ns, className);
00456    OW_ASSERT(cc);
00457    // TODO: delete associations to the instances we delete
00458    CIMClassDeleter ccd(m_mStore, ns, m_iStore
00459 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00460       , m_classAssocDb
00461 #endif
00462       );
00463    this->enumClasses(ns, className, ccd,
00464       E_DEEP, E_LOCAL_ONLY,
00465       E_EXCLUDE_QUALIFIERS,
00466       E_EXCLUDE_CLASS_ORIGIN,
00467       acl);
00468    ccd.handle(cc);
00469    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00470    {
00471       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 deleted class: %1:%2",
00472          ns, className));
00473    }
00474    return cc;
00475 }
00477 void
00478 CIMRepository2::createClass(const String& ns, const CIMClass& cimClass_,
00479    OperationContext&)
00480 {
00481    // m_mStore.createClass modifies cimClass to be consistent with base
00482    // classes, etc.
00483    CIMClass cimClass(cimClass_);
00484    m_mStore.createClass(ns, cimClass);
00485    // we need to re-get the class, so that it will be consistent.  currently
00486    // cimClass only contains "unique" items that are added in the child class.
00487    cimClass = _getClass(ns, cimClass.getName());
00488 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00489    if (cimClass.isAssociation())
00490    {
00491       m_classAssocDb.addEntries(ns,cimClass);
00492    }
00493 #endif
00494    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00495    {
00496       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("Created class: %1:%2", ns, cimClass.toMOF()));
00497    }
00498 }
00500 CIMClass
00501 CIMRepository2::modifyClass(
00502    const String& ns,
00503    const CIMClass& cc,
00504    OperationContext&)
00505 {
00506    OW_ASSERT(cc);
00507    CIMClass origClass = _getClass(ns, cc.getName());
00508    // TODO: this needs to update the subclasses of the modified class.
00509    //       If that's not possible, then we need to throw a
00510    //       CLASS_HAS_CHILDREN CIMException.
00511    // TODO: Need to update the instances of the class and any subclasses.
00512    //       If that's not possible, then we need to throw a
00513    //       CLASS_HAS_INSTANCES CIMException.
00514    m_mStore.modifyClass(ns, cc);
00515    OW_ASSERT(origClass);
00516    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00517    {
00518       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("Modified class: %1:%2 from %3 to %4", ns,
00519          cc.getName(), origClass.toMOF(), cc.toMOF()));
00520    }
00521    return origClass;
00522 }
00523 #endif // #ifndef OW_DISABLE_SCHEMA_MANIPULATION
00524 
00525 void
00526 CIMRepository2::enumClasses(const String& ns,
00527       const String& className,
00528       CIMClassResultHandlerIFC& result,
00529       EDeepFlag deep, ELocalOnlyFlag localOnly, EIncludeQualifiersFlag includeQualifiers,
00530       EIncludeClassOriginFlag includeClassOrigin, OperationContext&)
00531 {
00532    m_mStore.enumClass(ns, className,
00533       result, deep,
00534       localOnly, includeQualifiers, includeClassOrigin);
00535    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00536    {
00537       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 enumerated classes: %1:%2", ns,
00538          className));
00539    }
00540 }
00542 void
00543 CIMRepository2::enumClassNames(
00544    const String& ns,
00545    const String& className,
00546    StringResultHandlerIFC& result,
00547    EDeepFlag deep, OperationContext&)
00548 {
00549    m_mStore.enumClassNames(ns, className, result, deep);
00550    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00551    {
00552       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 enumerated class names: %1:%2", ns,
00553          className));
00554    }
00555 }
00557 namespace {
00558 class stringArrayBuilder : public StringResultHandlerIFC
00559 {
00560 public:
00561    stringArrayBuilder(StringArray& result)
00562       : m_result(result)
00563    {}
00564    void doHandle(const String& name)
00565    {
00566       m_result.push_back(name);
00567    }
00568 private:
00569    StringArray& m_result;
00570 };
00571 // utility function
00572 StringArray getClassChildren(MetaRepository2& rep, const String& ns, const String& clsName)
00573 {
00574    StringArray result;
00575    stringArrayBuilder handler(result);
00576    rep.enumClassNames(ns, clsName, handler, E_DEEP);
00577    return result;
00578 }
00579 }
00581 void
00582 CIMRepository2::enumInstanceNames(
00583    const String& ns,
00584    const String& className,
00585    CIMObjectPathResultHandlerIFC& result,
00586    EDeepFlag deep,
00587    OperationContext&)
00588 {
00589    CIMClass theClass = _instGetClass(ns, className);
00590    m_iStore.getInstanceNames(ns, theClass, result);
00591    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00592    {
00593       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 enumerated instance names: %1:%2", ns,
00594          className));
00595    }
00596    if (!deep)
00597    {
00598       return;
00599    }
00600    // This code probably won't ever be executed, because CIMServer
00601    // has to do each class at a time because of providers, and will
00602    // thus only call us with deep=false.
00603    // If the situation ever changes, fix and enable the code below.
00604    OW_THROWCIMMSG(CIMException::FAILED, "Internal server error");
00605    // TODO: Switch this to use a callback interface.
00606    /*
00607    StringArray classNames = m_mStore.getClassChildren(ns,
00608       theClass.getName());
00609    for (size_t i = 0; i < classNames.size(); i++)
00610    {
00611       theClass = _instGetClass(ns, classNames[i]);
00612       m_iStore.getInstanceNames(ns, theClass, result);
00613       if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00614       {
00615          OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 enumerated derived instance names: %1:%2", ns,
00616             classNames[i]));
00617       }
00618    }
00619    */
00620 }
00622 namespace {
00623 class instEnumerator : public StringResultHandlerIFC
00624 {
00625 public:
00626    instEnumerator(CIMRepository2& rep_,
00627       const String& ns_,
00628       const CIMClass& theTopClass_,
00629       CIMInstanceResultHandlerIFC& result_,
00630       EDeepFlag deep_,
00631       ELocalOnlyFlag localOnly_,
00632       EIncludeQualifiersFlag includeQualifiers_,
00633       EIncludeClassOriginFlag includeClassOrigin_,
00634       const StringArray* propertyList_)
00635       : rep(rep_)
00636       , ns(ns_)
00637       , theTopClass(theTopClass_)
00638       , result(result_)
00639       , deep(deep_)
00640       , localOnly(localOnly_)
00641       , includeQualifiers(includeQualifiers_)
00642       , includeClassOrigin(includeClassOrigin_)
00643       , propertyList(propertyList_)
00644    {}
00645    void doHandle(const String& className)
00646    {
00647       CIMClass theClass = rep._instGetClass(ns, className);
00648       rep.m_iStore.getCIMInstances(ns, className, theTopClass, theClass, result,
00649          deep, localOnly, includeQualifiers, includeClassOrigin, propertyList);
00650       if (rep.m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00651       {
00652          OW_LOG_DEBUG(rep.m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 Enumerated derived instances: %1:%2", ns, className));
00653       }
00654    }
00655 private:
00656    CIMRepository2& rep;
00657    const String& ns;
00658    const CIMClass& theTopClass;
00659    CIMInstanceResultHandlerIFC& result;
00660    EDeepFlag deep;
00661    ELocalOnlyFlag localOnly;
00662    EIncludeQualifiersFlag includeQualifiers;
00663    EIncludeClassOriginFlag includeClassOrigin;
00664    const StringArray* propertyList;
00665 };
00666 } // end unnamed namespace
00668 void
00669 CIMRepository2::enumInstances(
00670    const String& ns,
00671    const String& className,
00672    CIMInstanceResultHandlerIFC& result, EDeepFlag deep,
00673    ELocalOnlyFlag localOnly,
00674    EIncludeQualifiersFlag includeQualifiers,
00675    EIncludeClassOriginFlag includeClassOrigin,
00676    const StringArray* propertyList,
00677    EEnumSubclassesFlag enumSubclasses, OperationContext&)
00678 {
00679    // deep means a different thing here than for enumInstanceNames.  See the spec.
00680    CIMClass theTopClass = _instGetClass(ns, className);
00681    m_iStore.getCIMInstances(ns, className, theTopClass, theTopClass, result,
00682       deep, localOnly, includeQualifiers, includeClassOrigin, propertyList);
00683    
00684    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00685    {
00686       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 Enumerated instances: %1:%2", ns,
00687          className));
00688    }
00689    if (enumSubclasses)
00690    {
00691       instEnumerator ie(*this, ns, theTopClass, result, deep, localOnly, includeQualifiers, includeClassOrigin, propertyList);
00692       m_mStore.enumClassNames(ns, className, ie, E_DEEP);
00693    }
00694 }
00696 CIMInstance
00697 CIMRepository2::getInstance(
00698    const String& ns,
00699    const CIMObjectPath& instanceName,
00700    ELocalOnlyFlag localOnly,
00701    EIncludeQualifiersFlag includeQualifiers,
00702    EIncludeClassOriginFlag includeClassOrigin,
00703    const StringArray* propertyList, OperationContext& context)
00704 {
00705    return getInstance(ns, instanceName, localOnly, includeQualifiers, includeClassOrigin,
00706       propertyList, NULL, context);
00707 }
00709 CIMInstance
00710 CIMRepository2::getInstance(
00711    const String& ns,
00712    const CIMObjectPath& instanceName,
00713    ELocalOnlyFlag localOnly,
00714    EIncludeQualifiersFlag includeQualifiers, EIncludeClassOriginFlag includeClassOrigin,
00715    const StringArray* propertyList, CIMClass* pOutClass,
00716    OperationContext&)
00717 {
00718    StringArray lpropList;
00719    if (propertyList)
00720    {
00721       lpropList = *propertyList;
00722    }
00723    CIMInstance ci(CIMNULL);
00724    CIMClass cc(_instGetClass(ns, instanceName.getClassName()));
00725    ci = m_iStore.getCIMInstance(ns, instanceName, cc, localOnly,
00726       includeQualifiers, includeClassOrigin, propertyList);
00727    OW_ASSERT(ci);
00728    if (pOutClass)
00729    {
00730       *pOutClass = cc;
00731    }
00732    
00733    return ci;
00734 }
00735 #ifndef OW_DISABLE_INSTANCE_MANIPULATION
00736 
00737 CIMInstance
00738 CIMRepository2::deleteInstance(const String& ns, const CIMObjectPath& cop_,
00739    OperationContext& acl)
00740 {
00741    CIMObjectPath cop(cop_);
00742    cop.setNameSpace(ns);
00743    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00744    {
00745       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2::deleteInstance.  cop = %1",
00746          cop.toString()));
00747    }
00748    CIMClass theClass(CIMNULL);
00749    CIMInstance oldInst = getInstance(ns, cop, E_NOT_LOCAL_ONLY, E_INCLUDE_QUALIFIERS, E_INCLUDE_CLASS_ORIGIN, NULL,
00750       &theClass, acl);
00751 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00752    // Ensure no associations exist for this instance
00753    if (m_instAssocDb.hasAssocEntries(ns, cop))
00754    {
00755       // TODO: Revisit this.  Instead of throwing, it is allowed in the
00756       // spec to to delete the associations that reference the instance.
00757       // See http://dmtf.org/standards/documents/WBEM/DSP200.html
00758       //   2.3.2.4. DeleteInstance
00759       OW_THROWCIMMSG(CIMException::FAILED,
00760          format("Instance %1 has associations", cop.toString()).c_str());
00761    }
00762    // TODO: It would be good to check for Min(1) relationships to the
00763    // instance.
00764    
00765    // If we're deleting an association instance, then remove all
00766    // traces of it in the association database.
00767    if (theClass.isAssociation())
00768    {
00769       m_instAssocDb.deleteEntries(ns, oldInst);
00770    }
00771 #endif
00772    // Delete the instance from the instance repository
00773    m_iStore.deleteInstance(ns, cop, theClass);
00774    OW_ASSERT(oldInst);
00775    return oldInst;
00776 }
00778 CIMObjectPath
00779 CIMRepository2::createInstance(
00780    const String& ns,
00781    const CIMInstance& ci,
00782    OperationContext&)
00783 {
00784    CIMObjectPath rval(ns, ci);
00785    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00786    {
00787       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2::createInstance.  ns = %1, "
00788          "instance = %2", ns, ci.toMOF()));
00789    }
00790    CIMClass theClass = _instGetClass(ns, ci.getClassName());
00791    if (m_checkReferentialIntegrity)
00792    {
00793       if (theClass.isAssociation())
00794       {
00795          CIMPropertyArray pra = ci.getProperties(
00796             CIMDataType::REFERENCE);
00797          for (size_t j = 0; j < pra.size(); j++)
00798          {
00799             CIMValue cv = pra[j].getValue();
00800             if (!cv)
00801             {
00802                OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00803                   "Association has a NULL reference");
00804             }
00805             CIMObjectPath op(CIMNULL);
00806             cv.get(op);
00807             if (!op)
00808             {
00809                OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00810                   "Association has a NULL reference");
00811             }
00812             CIMClass rcc(CIMNULL);
00813             try
00814             {
00815                rcc = _instGetClass(ns,op.getClassName());
00816                m_iStore.getCIMInstance(ns, op,rcc,E_NOT_LOCAL_ONLY,E_INCLUDE_QUALIFIERS,E_INCLUDE_CLASS_ORIGIN,0);
00817             }
00818             catch (CIMException&)
00819             {
00820                OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00821                   format("Association references an invalid instance:"
00822                      " %1", op.toString()).c_str());
00823             }
00824          }
00825       }
00826       _validatePropagatedKeys(ns, ci, theClass);
00827    }
00828    //TODO: _checkRequiredProperties(theClass, ci);
00829    m_iStore.createInstance(ns, theClass, ci);
00830 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00831    if (theClass.isAssociation())
00832    {
00833       m_instAssocDb.addEntries(ns, ci);
00834    }
00835 #endif
00836    OW_ASSERT(rval);
00837    return rval;
00838 }
00840 CIMInstance
00841 CIMRepository2::modifyInstance(
00842    const String& ns,
00843    const CIMInstance& modifiedInstance,
00844    EIncludeQualifiersFlag includeQualifiers,
00845    const StringArray* propertyList,
00846    OperationContext& acl)
00847 {
00848    CIMClass theClass(CIMNULL);
00849    CIMObjectPath cop(ns, modifiedInstance);
00850    CIMInstance oldInst = getInstance(ns, cop, E_NOT_LOCAL_ONLY, E_INCLUDE_QUALIFIERS, E_INCLUDE_CLASS_ORIGIN, NULL,
00851       &theClass, acl);
00852    //TODO: _checkRequiredProperties(theClass, modifiedInstance);
00853    m_iStore.modifyInstance(ns, cop, theClass, modifiedInstance, oldInst, includeQualifiers, propertyList);
00854    // No need to update the assoc db.  All references are keys, and thus can't be changed.
00855    OW_ASSERT(oldInst);
00856    return oldInst;
00857 }
00859 void
00860 CIMRepository2::setProperty(
00861    const String& ns,
00862    const CIMObjectPath& name,
00863    const String& propertyName, const CIMValue& valueArg,
00864    OperationContext& context)
00865 {
00866    CIMClass theClass = _instGetClass(ns, name.getClassName());
00867    CIMProperty cp = theClass.getProperty(propertyName);
00868    if (!cp)
00869    {
00870       OW_THROWCIMMSG(CIMException::NO_SUCH_PROPERTY,
00871          propertyName.c_str());
00872    }
00873    // Ensure value passed in is right data type
00874    CIMValue cv(valueArg);
00875    if (cv && (cp.getDataType().getType() != cv.getType()))
00876    {
00877       try
00878       {
00879          // this throws a FAILED CIMException if it can't convert
00880          cv = CIMValueCast::castValueToDataType(cv, cp.getDataType());
00881       }
00882       catch (CIMException& ce)
00883       {
00884          // translate FAILED to TYPE_MISMATCH
00885          if (ce.getErrNo() == CIMException::FAILED)
00886          {
00887             ce.setErrNo(CIMException::TYPE_MISMATCH);
00888          }
00889          throw ce;
00890       }
00891    }
00892    CIMInstance ci = getInstance(ns, name, E_NOT_LOCAL_ONLY, E_INCLUDE_QUALIFIERS, E_INCLUDE_CLASS_ORIGIN, NULL,
00893       NULL, context);
00894    if (!ci)
00895    {
00896       OW_THROWCIMMSG(CIMException::NOT_FOUND, name.toString().c_str());
00897    }
00898    CIMProperty tcp = ci.getProperty(propertyName);
00899    if (cp.isKey() && tcp.getValue() && !tcp.getValue().equal(cv))
00900    {
00901       String msg("Cannot modify key property: ");
00902       msg += cp.getName();
00903       OW_THROWCIMMSG(CIMException::FAILED, msg.c_str());
00904    }
00905    cp.setValue(cv);
00906    ci.setProperty(cp);
00907    StringArray props;
00908    props.push_back(propertyName);
00909    modifyInstance(ns, ci, E_INCLUDE_QUALIFIERS, &props, context);
00910 }
00911 #endif // #ifndef OW_DISABLE_INSTANCE_MANIPULATION
00912 
00913 CIMValue
00914 CIMRepository2::getProperty(
00915    const String& ns,
00916    const CIMObjectPath& name,
00917    const String& propertyName, OperationContext& context)
00918 {
00919    CIMClass theClass = _instGetClass(ns,name.getClassName());
00920    CIMProperty cp = theClass.getProperty(propertyName);
00921    if (!cp)
00922    {
00923       OW_THROWCIMMSG(CIMException::NO_SUCH_PROPERTY,
00924          propertyName.c_str());
00925    }
00926    CIMInstance ci = getInstance(ns, name, E_NOT_LOCAL_ONLY, E_INCLUDE_QUALIFIERS, E_INCLUDE_CLASS_ORIGIN, NULL,
00927       NULL, context);
00928    CIMProperty prop = ci.getProperty(propertyName);
00929    if (!prop)
00930    {
00931       OW_THROWCIMMSG(CIMException::NO_SUCH_PROPERTY,
00932          propertyName.c_str());
00933    }
00934    return prop.getValue();
00935 }
00937 CIMValue
00938 CIMRepository2::invokeMethod(
00939    const String&,
00940    const CIMObjectPath&,
00941    const String&, const CIMParamValueArray&,
00942    CIMParamValueArray&, OperationContext&)
00943 {
00944    OW_THROWCIM(CIMException::NOT_SUPPORTED);
00945 }
00947 void
00948 CIMRepository2::execQuery(
00949    const String&,
00950    CIMInstanceResultHandlerIFC&,
00951    const String&,
00952    const String&, OperationContext&)
00953 {
00954    OW_THROWCIM(CIMException::NOT_SUPPORTED);
00955 }
00956 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00957 
00958 void
00959 CIMRepository2::associators(
00960    const String& ns,
00961    const CIMObjectPath& path,
00962    CIMInstanceResultHandlerIFC& result,
00963    const String& assocClass, const String& resultClass,
00964    const String& role, const String& resultRole,
00965    EIncludeQualifiersFlag includeQualifiers, EIncludeClassOriginFlag includeClassOrigin,
00966    const StringArray* propertyList, OperationContext& context)
00967 {
00968    _commonAssociators(ns, path, assocClass, resultClass, role, resultRole,
00969       includeQualifiers, includeClassOrigin, propertyList, &result, 0, 0,
00970       context);
00971 }
00973 void
00974 CIMRepository2::associatorsClasses(
00975    const String& ns,
00976    const CIMObjectPath& path,
00977    CIMClassResultHandlerIFC& result,
00978    const String& assocClass, const String& resultClass,
00979    const String& role, const String& resultRole,
00980    EIncludeQualifiersFlag includeQualifiers, EIncludeClassOriginFlag includeClassOrigin,
00981    const StringArray* propertyList, OperationContext& context)
00982 {
00983    _commonAssociators(ns, path, assocClass, resultClass, role, resultRole,
00984       includeQualifiers, includeClassOrigin, propertyList, 0, 0, &result,
00985       context);
00986 }
00988 void
00989 CIMRepository2::associatorNames(
00990    const String& ns,
00991    const CIMObjectPath& path,
00992    CIMObjectPathResultHandlerIFC& result,
00993    const String& assocClass, const String& resultClass,
00994    const String& role, const String& resultRole,
00995    OperationContext& context)
00996 {
00997    _commonAssociators(ns, path, assocClass, resultClass, role, resultRole,
00998       E_EXCLUDE_QUALIFIERS, E_EXCLUDE_CLASS_ORIGIN, 0, 0, &result, 0, context);
00999 }
01001 void
01002 CIMRepository2::references(
01003    const String& ns,
01004    const CIMObjectPath& path,
01005    CIMInstanceResultHandlerIFC& result,
01006    const String& resultClass, const String& role,
01007    EIncludeQualifiersFlag includeQualifiers, EIncludeClassOriginFlag includeClassOrigin,
01008    const StringArray* propertyList, OperationContext& context)
01009 {
01010    _commonReferences(ns, path, resultClass, role, includeQualifiers,
01011       includeClassOrigin, propertyList, &result, 0, 0, context);
01012 }
01014 void
01015 CIMRepository2::referencesClasses(
01016    const String& ns,
01017    const CIMObjectPath& path,
01018    CIMClassResultHandlerIFC& result,
01019    const String& resultClass, const String& role,
01020    EIncludeQualifiersFlag includeQualifiers, EIncludeClassOriginFlag includeClassOrigin,
01021    const StringArray* propertyList, OperationContext& context)
01022 {
01023    _commonReferences(ns, path, resultClass, role, includeQualifiers,
01024       includeClassOrigin, propertyList, 0, 0, &result, context);
01025 }
01027 void
01028 CIMRepository2::referenceNames(
01029    const String& ns,
01030    const CIMObjectPath& path,
01031    CIMObjectPathResultHandlerIFC& result,
01032    const String& resultClass, const String& role,
01033    OperationContext& context)
01034 {
01035    _commonReferences(ns, path, resultClass, role, E_EXCLUDE_QUALIFIERS, E_EXCLUDE_CLASS_ORIGIN, 0, 0, &result, 0,
01036       context);
01037 }
01039 namespace
01040 {
01041    class assocClassBuilder : public CIMClassResultHandlerIFC
01042    {
01043    public:
01044       assocClassBuilder(
01045          CIMClassArray& Assocs_)
01046       : Assocs(Assocs_)
01047       {}
01048    protected:
01049       virtual void doHandle(const CIMClass &cc)
01050       {
01051          if (!cc.isAssociation())
01052          {
01053             OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
01054                format("class %1 is not an association", cc.getName()).c_str());
01055          }
01056          Assocs.append(cc);
01057       }
01058    private:
01059       CIMClassArray& Assocs;
01060    };
01061 }
01063 void
01064 CIMRepository2::_commonReferences(
01065    const String& ns,
01066    const CIMObjectPath& path_,
01067    const String& resultClass, const String& role,
01068    EIncludeQualifiersFlag includeQualifiers, EIncludeClassOriginFlag includeClassOrigin,
01069    const StringArray* propertyList, CIMInstanceResultHandlerIFC* piresult,
01070    CIMObjectPathResultHandlerIFC* popresult,
01071    CIMClassResultHandlerIFC* pcresult, OperationContext& context)
01072 {
01073    CIMObjectPath path(path_);
01074    path.setNameSpace(ns);
01075    if (!m_mStore.nameSpaceExists(ns))
01076    {
01077       OW_THROWCIMMSG(CIMException::INVALID_NAMESPACE, ns.c_str());
01078    }
01079    // Get all association classes from the repository
01080    // If the result class was specified, only children of it will be
01081    // returned.
01082    CIMClassArray Assocs;
01083    assocClassBuilder assocClassResult(Assocs);
01084    _getAssociationClasses(ns, resultClass, path.getClassName(), assocClassResult, role, context);
01085    StringArray resultClassNames;
01086    for (size_t i = 0; i < Assocs.size(); i++)
01087    {
01088       resultClassNames.append(Assocs[i].getName());
01089    }
01090    SortedVectorSet<String> resultClassNamesSet(resultClassNames.begin(), resultClassNames.end());
01091    if (path.isClassPath())
01092    {
01093       // Process all of the association classes without providers
01094       _staticReferencesClass(path,
01095          resultClass.empty() ? 0 : &resultClassNamesSet,
01096          role, includeQualifiers, includeClassOrigin, propertyList, popresult, pcresult, context);
01097    }
01098    else // it's an instance path
01099    {
01100       // Process all of the association classes without providers
01101       if (piresult != 0)
01102       {
01103          // do instances
01104          _staticReferences(path,
01105             resultClass.empty() ? 0 : &resultClassNamesSet, role,
01106             includeQualifiers, includeClassOrigin, propertyList, *piresult, context);
01107       }
01108       else if (popresult != 0)
01109       {
01110          // do names (object paths)
01111          _staticReferenceNames(path,
01112             resultClass.empty() ? 0 : &resultClassNamesSet, role,
01113             *popresult);
01114       }
01115       else
01116       {
01117          OW_ASSERT(0);
01118       }
01119    }
01120 }
01121 namespace
01122 {
01124    class staticReferencesObjectPathResultHandler : public AssocDbEntry2ResultHandlerIFC
01125    {
01126    public:
01127       staticReferencesObjectPathResultHandler(
01128          CIMObjectPathResultHandlerIFC& result_)
01129       : result(result_)
01130       {}
01131    protected:
01132       virtual void doHandle(const AssocDbEntry2::entry &e)
01133       {
01134          result.handle(e.m_associationPath);
01135       }
01136    private:
01137       CIMObjectPathResultHandlerIFC& result;
01138    };
01139    
01141    class staticReferencesClassResultHandler : public AssocDbEntry2ResultHandlerIFC
01142    {
01143    public:
01144       staticReferencesClassResultHandler(
01145          CIMClassResultHandlerIFC& result_,
01146          CIMRepository2& server_,
01147          String& ns_,
01148          EIncludeQualifiersFlag includeQualifiers_,
01149          EIncludeClassOriginFlag includeClassOrigin_,
01150          const StringArray* propList_,
01151          OperationContext& context_)
01152       : result(result_)
01153       , server(server_)
01154       , ns(ns_)
01155       , includeQualifiers(includeQualifiers_)
01156       , includeClassOrigin(includeClassOrigin_)
01157       , propList(propList_)
01158       , context(context_)
01159       {}
01160    protected:
01161       virtual void doHandle(const AssocDbEntry2::entry &e)
01162       {
01163          CIMObjectPath cop = e.m_associationPath;
01164          if (cop.getNameSpace().empty())
01165          {
01166             cop.setNameSpace(ns);
01167          }
01168          CIMClass cc = server.getClass(cop.getNameSpace(),
01169             cop.getClassName(), E_NOT_LOCAL_ONLY, includeQualifiers,
01170             includeClassOrigin, propList, context);
01171          result.handle(cc);
01172       }
01173    private:
01174       CIMClassResultHandlerIFC& result;
01175       CIMRepository2& server;
01176       String& ns;
01177       EIncludeQualifiersFlag includeQualifiers;
01178       EIncludeClassOriginFlag includeClassOrigin;
01179       const StringArray* propList;
01180       OperationContext& context;
01181    };
01183    class staticAssociatorsInstResultHandler : public AssocDbEntry2ResultHandlerIFC
01184    {
01185    public:
01186       staticAssociatorsInstResultHandler(
01187          OperationContext& intAclInfo_,
01188          CIMRepository2& server_,
01189          CIMInstanceResultHandlerIFC& result_,
01190          EIncludeQualifiersFlag includeQualifiers_,
01191          EIncludeClassOriginFlag includeClassOrigin_,
01192          const StringArray* propertyList_)
01193       : intAclInfo(intAclInfo_)
01194       , server(server_)
01195       , result(result_)
01196       , includeQualifiers(includeQualifiers_)
01197       , includeClassOrigin(includeClassOrigin_)
01198       , propertyList(propertyList_)
01199       {}
01200    protected:
01201       virtual void doHandle(const AssocDbEntry2::entry &e)
01202       {
01203          CIMObjectPath op = e.m_associatedObject;
01204          CIMInstance ci = server.getInstance(op.getNameSpace(), op, E_NOT_LOCAL_ONLY,
01205             includeQualifiers,includeClassOrigin,propertyList,intAclInfo);
01206          result.handle(ci);
01207       }
01208    private:
01209       OperationContext& intAclInfo;
01210       CIMRepository2& server;
01211       CIMInstanceResultHandlerIFC& result;
01212       EIncludeQualifiersFlag includeQualifiers;
01213       EIncludeClassOriginFlag includeClassOrigin;
01214       const StringArray* propertyList;
01215    };
01216    
01218    class staticReferencesInstResultHandler : public AssocDbEntry2ResultHandlerIFC
01219    {
01220    public:
01221       staticReferencesInstResultHandler(OperationContext& intAclInfo_,
01222          CIMRepository2& server_,
01223          CIMInstanceResultHandlerIFC& result_,
01224          EIncludeQualifiersFlag includeQualifiers_,
01225          EIncludeClassOriginFlag includeClassOrigin_,
01226          const StringArray* propertyList_)
01227       : intAclInfo(intAclInfo_)
01228       , server(server_)
01229       , result(result_)
01230       , includeQualifiers(includeQualifiers_)
01231       , includeClassOrigin(includeClassOrigin_)
01232       , propertyList(propertyList_)
01233       {}
01234    protected:
01235       virtual void doHandle(const AssocDbEntry2::entry &e)
01236       {
01237          CIMObjectPath op = e.m_associationPath;
01238          CIMInstance ci = server.getInstance(op.getNameSpace(), op, E_NOT_LOCAL_ONLY,
01239             includeQualifiers,includeClassOrigin,propertyList,intAclInfo);
01240          result.handle(ci);
01241       }
01242    private:
01243       OperationContext& intAclInfo;
01244       CIMRepository2& server;
01245       CIMInstanceResultHandlerIFC& result;
01246       EIncludeQualifiersFlag includeQualifiers;
01247       EIncludeClassOriginFlag includeClassOrigin;
01248       const StringArray* propertyList;
01249    };
01250 }
01252 void
01253 CIMRepository2::_staticReferences(const CIMObjectPath& path,
01254    const SortedVectorSet<String>* refClasses, const String& role,
01255    EIncludeQualifiersFlag includeQualifiers, EIncludeClassOriginFlag includeClassOrigin,
01256    const StringArray* propertyList, CIMInstanceResultHandlerIFC& result,
01257    OperationContext& context)
01258 {
01259    staticReferencesInstResultHandler handler(context, *this, result,
01260       includeQualifiers, includeClassOrigin, propertyList);
01261    m_instAssocDb.getAllEntries(path,
01262       refClasses, 0, role, String(), handler);
01263 }
01265 void
01266 CIMRepository2::_staticReferenceNames(const CIMObjectPath& path,
01267    const SortedVectorSet<String>* refClasses, const String& role,
01268    CIMObjectPathResultHandlerIFC& result)
01269 {
01270    staticReferencesObjectPathResultHandler handler(result);
01271    m_instAssocDb.getAllEntries(path,
01272       refClasses, 0, role, String(), handler);
01273 }
01275 void
01276 CIMRepository2::_commonAssociators(
01277    const String& ns,
01278    const CIMObjectPath& path_,
01279    const String& assocClassName, const String& resultClass,
01280    const String& role, const String& resultRole,
01281    EIncludeQualifiersFlag includeQualifiers, EIncludeClassOriginFlag includeClassOrigin,
01282    const StringArray* propertyList,
01283    CIMInstanceResultHandlerIFC* piresult,
01284    CIMObjectPathResultHandlerIFC* popresult,
01285    CIMClassResultHandlerIFC* pcresult,
01286    OperationContext& context)
01287 {
01288    CIMObjectPath path(path_);
01289    path.setNameSpace(ns);
01290    if (!m_mStore.nameSpaceExists(ns))
01291    {
01292       OW_THROWCIMMSG(CIMException::INVALID_NAMESPACE, ns.c_str());
01293    }
01294    // Get association classes from the association repository
01295    CIMClassArray Assocs;
01296    assocClassBuilder assocClassResult(Assocs);
01297    _getAssociationClasses(ns, assocClassName, path.getClassName(), assocClassResult, role, context);
01298    // If the result class was specified, get a list of all the classes the
01299    // objects must be instances of.
01300    StringArray resultClassNames;
01301    if (!resultClass.empty())
01302    {
01303       resultClassNames = getClassChildren(m_mStore, ns, resultClass);
01304       resultClassNames.append(resultClass);
01305    }
01306    StringArray assocClassNames;
01307    for (size_t i = 0; i < Assocs.size(); i++)
01308    {
01309       assocClassNames.append(Assocs[i].getName());
01310    }
01311    SortedVectorSet<String> assocClassNamesSet(assocClassNames.begin(),
01312          assocClassNames.end());
01313    SortedVectorSet<String> resultClassNamesSet(resultClassNames.begin(),
01314          resultClassNames.end());
01315    if (path.isClassPath())
01316    {
01317       // Process all of the association classes without providers
01318       _staticAssociatorsClass(path, assocClassName.empty() ? 0 : &assocClassNamesSet,
01319          resultClass.empty() ? 0 : &resultClassNamesSet,
01320          role, resultRole, includeQualifiers, includeClassOrigin, propertyList, popresult, pcresult, context);
01321    }
01322    else // it's an instance path
01323    {
01324       // Process all of the association classes without providers
01325       if (piresult != 0)
01326       {
01327          // do instances
01328          _staticAssociators(path, assocClassName.empty() ? 0 : &assocClassNamesSet,
01329             resultClass.empty() ? 0 : &resultClassNamesSet, role, resultRole,
01330             includeQualifiers, includeClassOrigin, propertyList, *piresult, context);
01331       }
01332       else if (popresult != 0)
01333       {
01334          // do names (object paths)
01335          _staticAssociatorNames(path, assocClassName.empty() ? 0 : &assocClassNamesSet,
01336             resultClass.empty() ? 0 : &resultClassNamesSet, role, resultRole,
01337             *popresult);
01338       }
01339       else
01340       {
01341          OW_ASSERT(0);
01342       }
01343    }
01344 }
01346 void
01347 CIMRepository2::_staticAssociators(const CIMObjectPath& path,
01348    const SortedVectorSet<String>* passocClasses,
01349    const SortedVectorSet<String>* presultClasses,
01350    const String& role, const String& resultRole,
01351    EIncludeQualifiersFlag includeQualifiers, EIncludeClassOriginFlag includeClassOrigin,
01352    const StringArray* propertyList, CIMInstanceResultHandlerIFC& result,
01353    OperationContext& context)
01354 {
01355    staticAssociatorsInstResultHandler handler(context, *this, result,
01356       includeQualifiers, includeClassOrigin, propertyList);
01357    m_instAssocDb.getAllEntries(path,
01358       passocClasses, presultClasses, role, resultRole, handler);
01359       
01360 }
01361 namespace
01362 {
01364    class staticAssociatorsObjectPathResultHandler : public AssocDbEntry2ResultHandlerIFC
01365    {
01366    public:
01367       staticAssociatorsObjectPathResultHandler(
01368          CIMObjectPathResultHandlerIFC& result_)
01369       : result(result_)
01370       {}
01371    protected:
01372       virtual void doHandle(const AssocDbEntry2::entry &e)
01373       {
01374          result.handle(e.m_associatedObject);
01375       }
01376    private:
01377       CIMObjectPathResultHandlerIFC& result;
01378    };
01379    
01381    class staticAssociatorsClassResultHandler : public AssocDbEntry2ResultHandlerIFC
01382    {
01383    public:
01384       staticAssociatorsClassResultHandler(
01385          CIMClassResultHandlerIFC& result_,
01386          CIMRepository2& server_,
01387          String& ns_,
01388          EIncludeQualifiersFlag includeQualifiers_,
01389          EIncludeClassOriginFlag includeClassOrigin_,
01390          const StringArray* propList_,
01391          OperationContext& context_)
01392       : result(result_)
01393       , server(server_)
01394       , ns(ns_)
01395       , includeQualifiers(includeQualifiers_)
01396       , includeClassOrigin(includeClassOrigin_)
01397       , propList(propList_)
01398       , context(context_)
01399       {}
01400    protected:
01401       virtual void doHandle(const AssocDbEntry2::entry &e)
01402       {
01403          CIMObjectPath cop = e.m_associatedObject;
01404          if (cop.getNameSpace().empty())
01405          {
01406             cop.setNameSpace(ns);
01407          }
01408          CIMClass cc = server.getClass(cop.getNameSpace(),
01409             cop.getClassName(), E_NOT_LOCAL_ONLY, includeQualifiers,
01410             includeClassOrigin, propList, context);
01411          result.handle(cc);
01412       }
01413    private:
01414       CIMClassResultHandlerIFC& result;
01415       CIMRepository2& server;
01416       String& ns;
01417       EIncludeQualifiersFlag includeQualifiers;
01418       EIncludeClassOriginFlag includeClassOrigin;
01419       const StringArray* propList;
01420       OperationContext& context;
01421    };
01422 }
01424 void
01425 CIMRepository2::_staticAssociatorNames(const CIMObjectPath& path,
01426    const SortedVectorSet<String>* passocClasses,
01427    const SortedVectorSet<String>* presultClasses,
01428    const String& role, const String& resultRole,
01429    CIMObjectPathResultHandlerIFC& result)
01430 {
01431    staticAssociatorsObjectPathResultHandler handler(result);
01432    m_instAssocDb.getAllEntries(path,
01433       passocClasses, presultClasses, role, resultRole, handler);
01434       
01435 }
01437 void
01438 CIMRepository2::_staticAssociatorsClass(
01439    const CIMObjectPath& path,
01440    const SortedVectorSet<String>* assocClassNames,
01441    const SortedVectorSet<String>* resultClasses,
01442    const String& role, const String& resultRole,
01443    EIncludeQualifiersFlag includeQualifiers, EIncludeClassOriginFlag includeClassOrigin,
01444    const StringArray* propertyList, CIMObjectPathResultHandlerIFC* popresult,
01445    CIMClassResultHandlerIFC* pcresult,
01446    OperationContext& context)
01447 {
01448    // need to run the query for every superclass of the class arg.
01449    CIMName curClsName = path.getClassName();
01450    CIMObjectPath curPath = path;
01451    while (!curClsName.empty())
01452    {
01453       if (popresult != 0)
01454       {
01455          staticAssociatorsObjectPathResultHandler handler(*popresult);
01456          m_classAssocDb.getAllEntries(curPath, assocClassNames, resultClasses, role, resultRole,
01457             handler);
01458       }
01459       else if (pcresult != 0)
01460       {
01461          String ns = path.getNameSpace();
01462          staticAssociatorsClassResultHandler handler(*pcresult,*this,
01463             ns, includeQualifiers, includeClassOrigin,
01464             propertyList, context);
01465          m_classAssocDb.getAllEntries(curPath, assocClassNames, resultClasses, role, resultRole,
01466             handler);
01467       }
01468       else
01469       {
01470          OW_ASSERT(0);
01471       }
01472       // get the current class so we can get the name of the superclass
01473       CIMClass theClass = _getClass(curPath.getNameSpace(), curPath.getClassName());
01474       curClsName = theClass.getSuperClass();
01475       curPath.setClassName(curClsName);
01476    }
01477 }
01479 void
01480 CIMRepository2::_staticReferencesClass(const CIMObjectPath& path,
01481    const SortedVectorSet<String>* resultClasses,
01482    const String& role,
01483    EIncludeQualifiersFlag includeQualifiers, EIncludeClassOriginFlag includeClassOrigin,
01484    const StringArray* propertyList,
01485    CIMObjectPathResultHandlerIFC* popresult,
01486    CIMClassResultHandlerIFC* pcresult,
01487    OperationContext& context)
01488 {
01489    // need to run the query for every superclass of the class arg.
01490    CIMName curClsName = path.getClassName();
01491    CIMObjectPath curPath = path;
01492    while (!curClsName.empty())
01493    {
01494       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("curPath = %1", curPath.toString()));
01495       if (popresult != 0)
01496       {
01497          staticReferencesObjectPathResultHandler handler(*popresult);
01498          m_classAssocDb.getAllEntries(curPath, resultClasses, 0, role, String(),
01499             handler);
01500       }
01501       else if (pcresult != 0)
01502       {
01503          String ns = path.getNameSpace();
01504          staticReferencesClassResultHandler handler(*pcresult,*this,
01505             ns, includeQualifiers, includeClassOrigin,
01506             propertyList, context);
01507          m_classAssocDb.getAllEntries(curPath, resultClasses, 0, role, String(),
01508             handler);
01509       }
01510       else
01511       {
01512          OW_ASSERT(0);
01513       }
01514       // get the current class so we can get the name of the superclass
01515       CIMClass theClass = _getClass(curPath.getNameSpace(), curPath.getClassName());
01516       curClsName = theClass.getSuperClass();
01517       curPath.setClassName(curClsName);
01518    }
01519 }
01521 namespace
01522 {
01523    class assocHelper : public CIMClassResultHandlerIFC
01524    {
01525    public:
01526       assocHelper(
01527          CIMClassResultHandlerIFC& handler_,
01528          MetaRepository2& m_mStore_,
01529          const String& ns_)
01530       : handler(handler_)
01531       , m_mStore(m_mStore_)
01532       , ns(ns_)
01533       {}
01534    protected:
01535       virtual void doHandle(const CIMClass &cc)
01536       {
01537          handler.handle(cc);
01538          m_mStore.enumClass(ns, cc.getName(), handler, E_DEEP, E_NOT_LOCAL_ONLY, E_INCLUDE_QUALIFIERS, E_INCLUDE_CLASS_ORIGIN);
01539       }
01540    private:
01541       CIMClassResultHandlerIFC& handler;
01542       MetaRepository2& m_mStore;
01543       const String& ns;
01544    };
01545 }
01547 void
01548 CIMRepository2::_getAssociationClasses(const String& ns,
01549       const String& assocClassName, const String& className,
01550       CIMClassResultHandlerIFC& result, const String& role,
01551       OperationContext& context)
01552 {
01553    if (!assocClassName.empty())
01554    {
01555       // they gave us a class name so we can use the class association index
01556       // to only look at the ones that could provide associations
01557       m_mStore.enumClass(ns, assocClassName, result, E_DEEP, E_NOT_LOCAL_ONLY, E_INCLUDE_QUALIFIERS, E_INCLUDE_CLASS_ORIGIN);
01558       CIMClass cc(CIMNULL);
01559       CIMException::ErrNoType rc = m_mStore.getCIMClass(ns, assocClassName, E_NOT_LOCAL_ONLY, E_INCLUDE_QUALIFIERS, E_INCLUDE_CLASS_ORIGIN, 0, cc);
01560       if (rc != CIMException::SUCCESS)
01561       {
01562          OW_THROWCIM(CIMException::FAILED);
01563       }
01564       result.handle(cc);
01565    }
01566    else
01567    {
01568       // need to get all the assoc classes with dynamic providers
01569       CIMObjectPath cop(className, ns);
01570       _staticReferencesClass(cop,0,role,E_INCLUDE_QUALIFIERS,E_EXCLUDE_CLASS_ORIGIN,0,0,&result, context);
01571       // TODO: test if this is faster
01572       //assocHelper helper(result, m_mStore, ns);
01573       //m_mStore.getTopLevelAssociations(ns, helper);
01574    }
01575 }
01576 #endif // #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
01577 
01578 void
01579 CIMRepository2::checkGetClassRvalAndThrow(CIMException::ErrNoType rval,
01580    const String& ns, const String& className)
01581 {
01582    if (rval != CIMException::SUCCESS)
01583    {
01584       // check whether the namespace was invalid or not
01585       if (rval == CIMException::NOT_FOUND)
01586       {
01587          if (!m_mStore.nameSpaceExists(ns))
01588          {
01589             OW_THROWCIMMSG(CIMException::INVALID_NAMESPACE, ns.c_str());
01590          }
01591       }
01592       OW_THROWCIMMSG(rval, CIMObjectPath(className, ns).toString().c_str());
01593    }
01594 }
01595 void
01596 CIMRepository2::checkGetClassRvalAndThrowInst(CIMException::ErrNoType rval,
01597    const String& ns, const String& className)
01598 {
01599    if (rval != CIMException::SUCCESS)
01600    {
01601       // check whether the namespace was invalid or not
01602       if (rval == CIMException::NOT_FOUND)
01603       {
01604          if (!m_mStore.nameSpaceExists(ns))
01605          {
01606             OW_THROWCIMMSG(CIMException::INVALID_NAMESPACE, ns.c_str());
01607          }
01608          else
01609          {
01610             rval = CIMException::INVALID_CLASS;
01611          }
01612       }
01613       OW_THROWCIMMSG(rval, CIMObjectPath(className, ns).toString().c_str());
01614    }
01615 }
01617 namespace
01618 {
01619    class ClassNameArrayBuilder : public CIMObjectPathResultHandlerIFC
01620    {
01621    public:
01622       ClassNameArrayBuilder(StringArray& names_)
01623       : names(names_)
01624       {}
01625       void doHandle(const CIMObjectPath& op)
01626       {
01627          names.push_back(op.getClassName());
01628       }
01629    private:
01630       StringArray& names;
01631    };
01632 }
01634 void
01635 CIMRepository2::_validatePropagatedKeys(const String& ns,
01636    const CIMInstance& ci, const CIMClass& theClass)
01637 {
01638    CIMObjectPathArray rv;
01639    CIMPropertyArray kprops = theClass.getKeys();
01640    if (kprops.size() == 0)
01641    {
01642       return;
01643    }
01644    Map<String, CIMPropertyArray> theMap;
01645    Bool hasPropagatedKeys = false;
01646    // Look at all propagated key properties
01647    for (size_t i = 0; i < kprops.size(); i++)
01648    {
01649       CIMQualifier cq = kprops[i].getQualifier(
01650          CIMQualifier::CIM_QUAL_PROPAGATED);
01651       if (!cq)
01652       {
01653          continue;
01654       }
01655       hasPropagatedKeys = true;
01656       CIMValue cv = cq.getValue();
01657       if (!cv)
01658       {
01659          continue;
01660       }
01661       String cls;
01662       cv.get(cls);
01663       if (cls.empty())
01664       {
01665          continue;
01666       }
01667       size_t idx = cls.indexOf('.');
01668       String ppropName;
01669       if (idx != String::npos)
01670       {
01671          ppropName = cls.substring(idx+1);
01672          cls = cls.substring(0,idx);
01673       }
01674       CIMProperty cp = ci.getProperty(kprops[i].getName());
01675       if (!cp || !cp.getValue())
01676       {
01677          OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
01678             format("Cannot create instance. Propagated key field missing:"
01679                " %1", kprops[i].getName()).c_str());
01680       }
01681       if (!ppropName.empty())
01682       {
01683          // We need to use the propagated property name, not the property
01684          // name on ci.  e.g. Given
01685          // [Propagated("fooClass.fooPropName")] string myPropName;
01686          // we need to check for fooPropName as the key to the propagated
01687          // instance, not myPropName.
01688          cp.setName(ppropName);
01689       }
01690       theMap[cls].append(cp);
01691    }
01692    if (!hasPropagatedKeys)
01693    {
01694       return;
01695    }
01696    if (theMap.size() == 0)
01697    {
01698       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
01699          "Cannot create instance. Propagated key properties missing");
01700    }
01701    CIMObjectPath op(ns, ci);
01702    Map<String, CIMPropertyArray>::iterator it = theMap.begin();
01703    while (it != theMap.end())
01704    {
01705       String clsname = it->first;
01706       
01707       // since we don't know what class the keys refer to, we get all subclasses
01708       // and try calling getInstance for each to see if we can find one with
01709       // the matching keys.
01710       StringArray classes = getClassChildren(m_mStore, ns,
01711          theClass.getName());
01712       classes.push_back(clsname);
01713       op.setKeys(it->second);
01714       bool found = false;
01715       for (size_t i = 0; i < classes.size(); ++i)
01716       {
01717          op.setClassName(classes[i]);
01718          try
01719          {
01720             CIMClass c = _instGetClass(ns,classes[i]);
01721             m_iStore.getCIMInstance(ns, op, c, E_NOT_LOCAL_ONLY, E_INCLUDE_QUALIFIERS, E_INCLUDE_CLASS_ORIGIN, 0);
01722             // if the previous line didn't throw, then we found it.
01723             found = true;
01724             break;
01725          }
01726          catch (const CIMException&)
01727          {
01728          }
01729       }
01730       if (!found)
01731       {
01732          OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
01733             format("Propagated keys refer to non-existent object: %1",
01734                op.toString()).c_str());
01735       }
01736       ++it;
01737    }
01738 }
01739 
01741 void
01742 CIMRepository2::beginOperation(WBEMFlags::EOperationFlag op, OperationContext& context)
01743 {
01744 }
01745 
01747 void
01748 CIMRepository2::endOperation(WBEMFlags::EOperationFlag op, OperationContext& context, WBEMFlags::EOperationResultFlag result)
01749 {
01750 }
01751 
01752 } // end namespace OW_NAMESPACE
01753 

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