OW_InstanceRepository.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_InstanceRepository.hpp"
00038 #include "OW_DataStreams.hpp"
00039 #include "OW_StringBuffer.hpp"
00040 #include "OW_CIMException.hpp"
00041 #include "OW_CIMProperty.hpp"
00042 #include "OW_CIMInstance.hpp"
00043 #include "OW_CIMClass.hpp"
00044 #include "OW_CIMObjectPath.hpp"
00045 #include "OW_CIMValue.hpp"
00046 #include "OW_CIMQualifier.hpp"
00047 #include "OW_CIMFlavor.hpp"
00048 #include "OW_Format.hpp"
00049 #include "OW_CIMValueCast.hpp"
00050 #include "OW_IOException.hpp"
00051 
00052 namespace OW_NAMESPACE
00053 {
00054 
00055 using namespace WBEMFlags;
00056 
00057 namespace
00058 {
00059 
00060 const char NS_SEPARATOR_C(':');
00061 
00062 } // end unnamed namespace
00064 String
00065 InstanceRepository::makeInstanceKey(const String& ns, const CIMObjectPath& cop,
00066    const CIMClass& theClass)
00067 {
00068    if (!cop)
00069    {
00070       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, "no object path");
00071    }
00072    // Start return value with the namespace
00073    StringBuffer rv(makeClassKey(ns, cop.getClassName()));
00074    rv += NS_SEPARATOR_C;
00075    CIMPropertyArray kprops = theClass.getKeys();
00076    if (kprops.size() == 0)
00077    {
00078       rv += cop.getClassName();
00079       return rv.releaseString();
00080       // don't do this to allow for singleton classes without keys.
00081       //OW_THROWCIMMSG(CIMException::INVALID_CLASS,
00082       // Format("No key properties for class: %1", theClass.getName()).c_str());
00083    }
00084    String oclass = kprops[0].getOriginClass().toLowerCase();
00085    if (oclass.empty())
00086    {
00087       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00088          Format("No orgin class for key property on class: %1",
00089             theClass.getName()).c_str());
00090    }
00091    rv += oclass;
00092    // Get keys from object path
00093    CIMPropertyArray pra = cop.getKeys();
00094    if (pra.size() == 0)
00095    {
00096       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00097          "object path has no keys");
00098    }
00099    for (size_t i = 0; i < pra.size(); i++)
00100    {
00101       if (!pra[i].getValue())
00102       {
00103          OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00104             Format("object path (%1) has key (%2) with NULL value", cop, pra[i].getName()).c_str());
00105       }
00106    }
00107    // If not all the key properties were specified, throw an exception
00108    if (pra.size() < kprops.size())
00109    {
00110       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00111          Format("Model path is missing keys: %1", cop.toString()).c_str());
00112    }
00113    // TODO: Is this necessary?
00114    if (pra.size() == 1)
00115    {
00116       // If only one key property in object path, ensure it is
00117       // a key property in the class
00118       String pname = pra[0].getName().toLowerCase();
00119       if (!pname.empty() && !pname.equalsIgnoreCase(kprops[0].getName()))
00120       {
00121          OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00122             Format("Property in model path is not a key: %1", pname).c_str());
00123       }
00124       rv += '.';
00125       rv += pname;
00126       rv += '=';
00127       CIMValue cv = CIMValueCast::castValueToDataType(pra[0].getValue(),
00128          kprops[0].getDataType());
00129       if (cv.getType() == CIMDataType::REFERENCE)
00130       {
00131          CIMObjectPath cop(cv.toCIMObjectPath());
00132          if (cop.getNameSpace().empty())
00133          {
00134             cop.setNameSpace(ns);
00135             cv = CIMValue(cop);
00136          }
00137       }
00138       rv += cv.toString();
00139       return rv.releaseString();
00140    }
00141    // TODO: Is this necessary?
00142    // Ensure no non-key properties were specified in the path
00143    for (size_t i = 0; i < pra.size(); i++)
00144    {
00145       String pname = pra[i].getName();
00146       size_t j = 0;
00147       for (; j < kprops.size(); j++)
00148       {
00149          if (pname.equalsIgnoreCase(kprops[j].getName()))
00150          {
00151             CIMValue cv = CIMValueCast::castValueToDataType(
00152                pra[i].getValue(), kprops[j].getDataType());
00153             if (cv.getType() == CIMDataType::REFERENCE)
00154             {
00155                CIMObjectPath cop(cv.toCIMObjectPath());
00156                if (cop.getNameSpace().empty())
00157                {
00158                   cop.setNameSpace(ns);
00159                   cv = CIMValue(cop);
00160                }
00161             }
00162             pra[i].setValue(cv);
00163             break;
00164          }
00165       }
00166       if (j == kprops.size())
00167       {
00168          OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00169             Format("Property in model path is not a key: %1", pname).c_str());
00170       }
00171    }
00172 
00173    HDBUtilKeyArray kra(pra);
00174    kra.toString(rv);
00175    return rv.releaseString();
00176 }
00178 String
00179 InstanceRepository::makeClassKey(const String& ns,
00180    const String& className)
00181 {
00182    String rv(ns);
00183    rv += NS_SEPARATOR_C;
00184    rv += className;
00185    return rv.toLowerCase();
00186 }
00188 void
00189 InstanceRepository::getInstanceNames(const String& ns,
00190    const CIMClass& theClass, CIMObjectPathResultHandlerIFC& result)
00191 {
00192    throwIfNotOpen();
00193    String className = theClass.getName();
00194    HDBHandleLock hdl(this, getHandle());
00195    String ckey = makeClassKey(ns, className);
00196    HDBNode clsNode = hdl->getNode(ckey);
00197    if (!clsNode)
00198    {
00199       OW_THROWCIM(CIMException::INVALID_CLASS);
00200    }
00201    if (!clsNode.areAllFlagsOn(HDBCLSNODE_FLAG))
00202    {
00203       OW_THROW(IOException, "Expected class name node for instances");
00204    }
00205    HDBNode node = hdl->getFirstChild(clsNode);
00206    while (node)
00207    {
00208       CIMInstance ci(CIMNULL);
00209       nodeToCIMObject(ci, node);
00210       ci.syncWithClass(theClass, E_INCLUDE_QUALIFIERS); // need to do this to set up the keys
00211       CIMObjectPath op(ci.getClassName(), ns);
00212       op.setKeys(ci.getKeyValuePairs());
00213       result.handle(op);
00214       node = hdl->getNextSibling(node);
00215    }
00216 }
00217 
00219 void
00220 InstanceRepository::getCIMInstances(
00221    const String& ns,
00222    const String& className,
00223    const CIMClass& requestedClass,
00224    const CIMClass& theClass, CIMInstanceResultHandlerIFC& result,
00225    EDeepFlag deep, ELocalOnlyFlag localOnly, EIncludeQualifiersFlag includeQualifiers,
00226    EIncludeClassOriginFlag includeClassOrigin, const StringArray* propertyList)
00227 {
00228    throwIfNotOpen();
00229    HDBHandleLock hdl(this, getHandle());
00230    String ckey = makeClassKey(ns, className);
00231    HDBNode clsNode = hdl->getNode(ckey);
00232    if (!clsNode)
00233    {
00234       OW_THROWCIM(CIMException::INVALID_CLASS);
00235    }
00236    if (!clsNode.areAllFlagsOn(HDBCLSNODE_FLAG))
00237    {
00238       OW_THROW(IOException, "Expected class name node for instances");
00239    }
00240    HDBNode node = hdl->getFirstChild(clsNode);
00241    while (node)
00242    {
00243       CIMInstance ci(CIMNULL);
00244       nodeToCIMObject(ci, node);
00245       ci = ci.clone(localOnly,deep,includeQualifiers,includeClassOrigin,propertyList,requestedClass,theClass);
00246       result.handle(ci);
00247       node = hdl->getNextSibling(node);
00248    }
00249 }
00251 CIMInstance
00252 InstanceRepository::getCIMInstance(
00253    const String& ns,
00254    const CIMObjectPath& instanceName,
00255    const CIMClass& theClass, ELocalOnlyFlag localOnly,
00256    EIncludeQualifiersFlag includeQualifiers, EIncludeClassOriginFlag includeClassOrigin,
00257    const StringArray* propertyList)
00258 {
00259    throwIfNotOpen();
00260    String instanceKey = makeInstanceKey(ns, instanceName, theClass);
00261    HDBHandleLock hdl(this, getHandle());
00262    HDBNode node = hdl->getNode(instanceKey);
00263    if (!node)
00264    {
00265       CIMObjectPath cop(instanceName);
00266       cop.setNameSpace(ns);
00267       OW_THROWCIMMSG(CIMException::NOT_FOUND, cop.toString().c_str());
00268    }
00269    CIMInstance ci(CIMNULL);
00270    nodeToCIMObject(ci, node);
00271    ci.syncWithClass(theClass, E_INCLUDE_QUALIFIERS);
00272    
00273    // only filter if we need to
00274    if (propertyList
00275       || localOnly == E_LOCAL_ONLY
00276       || includeQualifiers == E_EXCLUDE_QUALIFIERS
00277       || includeClassOrigin == E_EXCLUDE_CLASS_ORIGIN)
00278    {
00279       ci = ci.clone(localOnly, includeQualifiers, includeClassOrigin,
00280          propertyList);
00281    }
00282    
00283    return ci;
00284 }
00285 #ifndef OW_DISABLE_INSTANCE_MANIPULATION
00286 
00287 void
00288 InstanceRepository::deleteInstance(const String& ns, const CIMObjectPath& cop,
00289    const CIMClass& theClass)
00290 {
00291    throwIfNotOpen();
00292    String instanceKey = makeInstanceKey(ns, cop, theClass);
00293    HDBHandleLock hdl(this, getHandle());
00294    HDBNode node = hdl->getNode(instanceKey);
00295    if (!node)
00296    {
00297       CIMObjectPath cop2(cop);
00298       cop2.setNameSpace(ns);
00299       OW_THROWCIMMSG(CIMException::NOT_FOUND, cop2.toString().c_str());
00300    }
00301    // Ensure the node belongs to an CIMInstance before we delete it.
00302    // If it's not, an exception will be thrown
00303    CIMInstance ci(CIMNULL);
00304    nodeToCIMObject(ci, node);
00305    hdl->removeNode(node);
00306 }
00308 void
00309 InstanceRepository::createInstance(const String& ns,
00310    const CIMClass& theClass, const CIMInstance& ci_)
00311 {
00312    throwIfNotOpen();
00313    HDBHandleLock hdl(this, getHandle());
00314    CIMInstance ci(ci_);
00315    String ckey = makeClassKey(ns, ci.getClassName());
00316    HDBNode clsNode = getNameSpaceNode(hdl, ckey);
00317    if (!clsNode)
00318    {
00319       // Theoretically this should never happen, but just in case...
00320       OW_THROWCIMMSG(CIMException::INVALID_CLASS, ci.getClassName().c_str());
00321    }
00322    // Create object path with keys from new instance
00323    CIMObjectPath icop(ns, ci);
00324    String instanceKey = makeInstanceKey(ns, icop, theClass);
00325    HDBNode node = hdl->getNode(instanceKey);
00326    if (node)
00327    {
00328       OW_THROWCIMMSG(CIMException::ALREADY_EXISTS, instanceKey.c_str());
00329    }
00330    _removeDuplicatedQualifiers(ci, theClass);
00331    DataOStream ostrm;
00332    ci.writeObject(ostrm);
00333    node = HDBNode(instanceKey, ostrm.length(), ostrm.getData());
00334    hdl.getHandle().addChild(clsNode, node);
00335 }
00337 // TODO: Is this function actually used?
00338 bool
00339 InstanceRepository::classHasInstances(const CIMObjectPath& classPath)
00340 {
00341    bool cc = false;
00342    throwIfNotOpen();
00343    HDBHandleLock hdl(this, getHandle());
00344    String ckey = makeClassKey(classPath.getNameSpace(),
00345       classPath.getClassName());
00346    HDBNode node = hdl->getNode(ckey);
00347    if (node)
00348    {
00349       if (!node.areAllFlagsOn(HDBCLSNODE_FLAG))
00350       {
00351          OW_THROW(IOException, "Expected class name node for instances");
00352       }
00353       cc = node.hasChildren();
00354    }
00355    return cc;
00356 }
00358 void
00359 InstanceRepository::modifyInstance(const String& ns,
00360    const CIMObjectPath& cop,
00361    const CIMClass& theClass, const CIMInstance& ci_,
00362    const CIMInstance& oldInst,
00363    EIncludeQualifiersFlag includeQualifiers,
00364    const StringArray* propertyList)
00365 {
00366    throwIfNotOpen();
00367    HDBHandleLock hdl(this, getHandle());
00368    CIMInstance ci(ci_.createModifiedInstance(oldInst,includeQualifiers,propertyList,theClass));
00369    // Now sync the new instance with the class. This will remove any properties
00370    // that shouldn't be on the instance and add properties that should be
00371    // there.
00372    ci.syncWithClass(theClass, E_INCLUDE_QUALIFIERS);
00373    // Ensure key values haven't changed
00374    CIMPropertyArray oldKeys = oldInst.getKeyValuePairs();
00375    for (size_t i = 0; i < oldKeys.size(); i++)
00376    {
00377       CIMProperty kprop = ci.getProperty(oldKeys[i].getName());
00378       if (!kprop)
00379       {
00380          String msg("Missing key value: ");
00381          msg += oldKeys[i].getName();
00382          OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, msg.c_str());
00383       }
00384       CIMValue cv1 = kprop.getValue();
00385       if (!cv1)
00386       {
00387          String msg("Missing key value: ");
00388          msg += kprop.getName();
00389          OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, msg.c_str());
00390       }
00391       CIMValue cv2 = oldKeys[i].getValue();
00392       if (!cv2)
00393       {
00394          String msg("Missing key value in object path: ");
00395          msg += oldKeys[i].getName();
00396          OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, msg.c_str());
00397       }
00398       if (!cv1.sameType(cv2))
00399       {
00400          String msg("Data type for key property changed! property: ");
00401          msg += kprop.getName();
00402          OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, msg.c_str());
00403       }
00404       if (!cv1.equal(cv2))
00405       {
00406          String msg("key value for instance changed: ");
00407          msg += kprop.getName();
00408          OW_THROWCIMMSG(CIMException::FAILED, msg.c_str());
00409       }
00410    }
00411    _removeDuplicatedQualifiers(ci, theClass);
00412    DataOStream ostrm;
00413    ci.writeObject(ostrm);
00414    String instanceKey = makeInstanceKey(ns, cop, theClass);
00415    HDBNode node = hdl->getNode(instanceKey);
00416    if (!node)
00417    {
00418       OW_THROWCIMMSG(CIMException::NOT_FOUND, cop.toString().c_str());
00419    }
00420    hdl.getHandle().updateNode(node, ostrm.length(), ostrm.getData());
00421 }
00422 #endif
00423 
00424 #if !defined(OW_DISABLE_INSTANCE_MANIPULATION) && !defined(OW_DISABLE_NAMESPACE_MANIPULATION)
00425 
00426 void
00427 InstanceRepository::deleteNameSpace(const String& nsName)
00428 {
00429    throwIfNotOpen();
00430    // ATTN: Do we need to do more later? Associations?
00431    GenericHDBRepository::deleteNameSpace(nsName);
00432 }
00434 int
00435 InstanceRepository::createNameSpace(const String& ns)
00436 {
00437    return GenericHDBRepository::createNameSpace(ns);
00438 }
00439 #endif // #if !defined(OW_DISABLE_INSTANCE_MANIPULATION) && !defined(OW_DISABLE_NAMESPACE_MANIPULATION)
00440 
00441 #ifndef OW_DISABLE_SCHEMA_MANIPULATION
00442 
00443 void
00444 InstanceRepository::createClass(const String& ns,
00445    const CIMClass& cimClass)
00446 {
00447    throwIfNotOpen();
00448    HDBHandleLock hdl(this, getHandle());
00449    HDBNode pnode = getNameSpaceNode(hdl, ns);
00450    if (!pnode)
00451    {
00452       OW_THROWCIMMSG(CIMException::INVALID_NAMESPACE,
00453          ns.c_str());
00454    }
00455    String ckey = makeClassKey(ns, cimClass.getName());
00456    HDBNode node = hdl->getNode(ckey);
00457    if (node)
00458    {
00459       OW_THROWCIMMSG(CIMException::ALREADY_EXISTS, ckey.c_str());
00460    }
00461    node = HDBNode(ckey, ckey.length()+1,
00462       reinterpret_cast<const unsigned char*>(ckey.c_str()));
00463    hdl->turnFlagsOn(node, HDBNSNODE_FLAG | HDBCLSNODE_FLAG);
00464    hdl->addChild(pnode, node);
00465 }
00467 void
00468 InstanceRepository::deleteClass(const String& ns,
00469    const String& className)
00470 {
00471    throwIfNotOpen();
00472    HDBHandleLock hdl(this, getHandle());
00473    String ckey = makeClassKey(ns, className);
00474    HDBNode node = hdl->getNode(ckey);
00475    if (node)
00476    {
00477       if (!node.areAllFlagsOn(HDBCLSNODE_FLAG))
00478       {
00479          OW_THROW(IOException, "Expected class name node for instances");
00480       }
00481    }
00482    hdl->removeNode(ckey);
00483 }
00484 #endif // #ifndef OW_DISABLE_SCHEMA_MANIPULATION
00485 #ifndef OW_DISABLE_INSTANCE_MANIPULATION
00486 
00487 void InstanceRepository::_removeDuplicatedQualifiers(CIMInstance& inst,
00488    const CIMClass& theClass)
00489 {
00490    CIMQualifierArray quals(inst.getQualifiers());
00491    CIMQualifierArray newQuals;
00492    for (size_t i = 0; i < quals.size(); ++i)
00493    {
00494       CIMQualifier& iq = quals[i];
00495       CIMQualifier cq = theClass.getQualifier(iq.getName());
00496       if (!cq)
00497       {
00498          newQuals.push_back(iq);
00499          continue;
00500       }
00501       if (iq.getValue() != cq.getValue())
00502       {
00503          newQuals.push_back(iq);
00504          continue;
00505       }
00506    }
00507    inst.setQualifiers(newQuals);
00508    CIMPropertyArray props = inst.getProperties();
00509    for (size_t i = 0; i < props.size(); ++i)
00510    {
00511       CIMProperty& p = props[i];
00512       CIMProperty clsp = theClass.getProperty(p.getName());
00513       CIMQualifierArray quals(p.getQualifiers());
00514       CIMQualifierArray newQuals;
00515       for (size_t j = 0; j < quals.size(); ++j)
00516       {
00517          CIMQualifier& ipq = quals[j];
00518          CIMQualifier cpq = clsp.getQualifier(ipq.getName());
00519          if (!cpq)
00520          {
00521             newQuals.push_back(ipq);
00522             continue;
00523          }
00524          if (ipq.getValue() != cpq.getValue())
00525          {
00526             newQuals.push_back(ipq);
00527             continue;
00528          }
00529       }
00530       p.setQualifiers(newQuals);
00531    }
00532    inst.setProperties(props);
00533 }
00534 #endif // #ifndef OW_DISABLE_INSTANCE_MANIPULATION
00535 
00536 } // end namespace OW_NAMESPACE
00537 

Generated on Thu Feb 9 08:48:01 2006 for openwbem by  doxygen 1.4.6