(file) Return to ObjectNormalizer.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

File: [Pegasus] / pegasus / src / Pegasus / Common / ObjectNormalizer.cpp (download)
Revision: 1.32, Tue May 2 19:26:59 2006 UTC (18 years, 2 months ago) by a.dunfey
Branch: MAIN
CVS Tags: TASK_BUG_5314_IPC_REFACTORING_ROOT, TASK_BUG_5314_IPC_REFACTORING_BRANCH, TASK_BUG_5314_IPC_REFACTORING-V1, TASK_BUG_5191_QUEUE_CONSOLIDATION_ROOT, TASK_BUG_5191_QUEUE_CONSOLIDATION_BRANCH, TASK-BUG4011_WinLocalConnect-root, TASK-BUG4011_WinLocalConnect-merged_out_to_branch, TASK-BUG4011_WinLocalConnect-merged_out_from_trunk, TASK-BUG4011_WinLocalConnect-merged_in_to_trunk, TASK-BUG4011_WinLocalConnect-merged_in_from_branch, TASK-BUG4011_WinLocalConnect-branch
Changes since 1.31: +165 -22 lines
BUG#: 4996
TITLE: PEP 233 Embedded Instance Support

DESCRIPTION:

Modifications to add support for the embedded instance type in Pegasus 2.6. Currently the functionality is off by default and must be enabled by defining at build time the variable PEGASUS_EMBEDDED_INSTANCE_SUPPORT with a value of "true".

//%2006////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
// IBM Corp.; EMC Corporation, The Open Group.
// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
// EMC Corporation; VERITAS Software Corporation; The Open Group.
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
// EMC Corporation; Symantec Corporation; The Open Group.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//==============================================================================
//
// Author: Chip Vincent (cvincent@us.ibm.com)
//
// Modified By:
//
//%/////////////////////////////////////////////////////////////////////////////

#include <Pegasus/Common/ObjectNormalizer.h>
#include <Pegasus/Common/ArrayInternal.h>

PEGASUS_NAMESPACE_BEGIN

CIMQualifier _processQualifier(
    CIMConstQualifier & referenceQualifier,
    CIMConstQualifier & cimQualifier)
{
    // check name
    if(!referenceQualifier.getName().equal(cimQualifier.getName()))
    {
        MessageLoaderParms message(
            "Common.ObjectNormalizer.INVALID_QUALIFIER_NAME",
            "Invalid qualifier name: $0",
            cimQualifier.getName().getString());

        throw CIMException(CIM_ERR_FAILED, message);
    }

    // check type
    if(referenceQualifier.getType() != cimQualifier.getType())
    {
        MessageLoaderParms message(
            "Common.ObjectNormalizer.INVALID_QUALIFIER_TYPE",
            "Invalid qualifier type: $0",
            cimQualifier.getName().getString());

        throw CIMException(CIM_ERR_FAILED, message);
    }

    CIMQualifier normalizedQualifier(
        referenceQualifier.getName(),
        referenceQualifier.getValue(),  // default value
        referenceQualifier.getFlavor(),
        referenceQualifier.getPropagated() == 0 ? false : true);

    // TODO: check override

    // update value
    if(!cimQualifier.getValue().isNull())
    {
        normalizedQualifier.setValue(cimQualifier.getValue());
    }

    return(normalizedQualifier);
}

CIMProperty ObjectNormalizer::_processProperty(
    CIMConstProperty & referenceProperty,
    CIMConstProperty & instProperty,
    Boolean includeQualifiers,
    Boolean includeClassOrigin,
    NormalizerContext * context,
    const CIMNamespaceName & nameSpace)
{
    // check name
    if(!referenceProperty.getName().equal(instProperty.getName()))
    {
        MessageLoaderParms message(
            "Common.ObjectNormalizer.INVALID_PROPERTY_NAME",
            "Invalid property name: $0",
            instProperty.getName().getString());

        throw CIMException(CIM_ERR_FAILED, message);
    }

    // check type
    CIMType referencePropType = referenceProperty.getType();
    CIMType instPropType = instProperty.getType();
    if(referencePropType != instPropType)
    {
#ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT
        // CMPI Providers cannot return a CIMTYPE_INSTANCE, so if the
        // referenceProperty type is CIMTYPE_INSTANCE and the instProperty
        // type is CIMTYPE_OBJECT, ignore the mismatch. The Normalizer
        // will correct it.
        if(referencePropType != CIMTYPE_INSTANCE ||
            instPropType != CIMTYPE_OBJECT)
#endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT
        {
            MessageLoaderParms message(
                "Common.ObjectNormalizer.INVALID_PROPERTY_TYPE",
                "Invalid property type: $0",
                instProperty.getName().getString());

            throw CIMException(CIM_ERR_FAILED, message);
        }
    }

    // TODO: check array size?

    CIMProperty normalizedProperty(
        referenceProperty.getName(),
        referenceProperty.getValue(),   // default value
        referenceProperty.getArraySize(),
        referenceProperty.getReferenceClassName(),
        CIMName(),
        false);

    // TODO: check override (especially for references)?

    // update value
    if(!instProperty.getValue().isNull())
    {
#ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT
        // This happens ONLY when the referencePropType is CIMTYPE_INSTANCE
        // and the cimPropType is CIMTYPE_OBJECT, otherwise an exception
        // would have been thrown. Correct the mismatch here.
        if(referencePropType != instPropType)
        {
            CIMObject tmpObject;
            instProperty.getValue().get(tmpObject);
            normalizedProperty.setValue(CIMInstance(tmpObject));
        }
        else
#endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT
        {
            normalizedProperty.setValue(instProperty.getValue());
        }
    }

    // update class origin
    if(includeClassOrigin)
    {
        normalizedProperty.setClassOrigin(referenceProperty.getClassOrigin());
    }

    // add qualifiers
    if(includeQualifiers)
    {
        // propagate class property qualifiers
        for(Uint32 i = 0, n = referenceProperty.getQualifierCount(); i < n; i++)
        {
            CIMConstQualifier referenceQualifier = referenceProperty.getQualifier(i);

            Uint32 pos = instProperty.findQualifier(referenceQualifier.getName());

            // update value if qualifier is present in the specified property
            if(pos != PEG_NOT_FOUND)
            {
                CIMConstQualifier cimQualifier = instProperty.getQualifier(pos);

                CIMQualifier normalizedQualifier =
                    _processQualifier(
                        referenceQualifier,
                        cimQualifier);

                normalizedProperty.addQualifier(normalizedQualifier);
            }
            else
            {
                normalizedProperty.addQualifier(referenceQualifier.clone());
            }
        }
    }
#ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT
#ifdef PEGASUS_SNIA_INTEROP_COMPATIBILITY
    else if(referenceProperty.getType() == CIMTYPE_INSTANCE)
    {
        Uin32 refPos = referenceProperty.findQualifier("EmbeddedInstance");
        Uin32 cimPos = instProperty.findQualifier("EmbeddedInstance");
        if(refPos != PEG_NOT_FOUND && cimPos == PEG_NOT_FOUND)
        {
            instProperty.addQualifier(refProperty.getQualifier(pos));
        }
    }
#endif

    // Check the type of the embedded instance against the class specified by
    // the EmbeddedInstance qualifier. We can only do this if the context
    // is non-zero.
    if(context != 0)
    {
        if(referenceProperty.getType() == CIMTYPE_INSTANCE)
        {
            Uint32 pos = referenceProperty.findQualifier("EmbeddedInstance");

            PEGASUS_ASSERT(pos != PEG_NOT_FOUND);

            String qualClassStr;
            referenceProperty.getQualifier(pos).getValue().get(
                qualClassStr);
            CIMName embedInstClassName(qualClassStr);
            Array<CIMName> embeddedInstSubclasses =
                context->enumerateClassNames(nameSpace, embedInstClassName,
                    true);
            embeddedInstSubclasses.append(embedInstClassName);

            Array<CIMInstance> embeddedInstances;
            if(referenceProperty.isArray())
            {
                instProperty.getValue().get(embeddedInstances);
            }
            else
            {
                CIMInstance embeddedInst;
                instProperty.getValue().get(embeddedInst);
                embeddedInstances.append(embeddedInst);
            }

            Array<CIMClass> embeddedClassDefs;
            for(Uint32 i = 0, n = embeddedInstances.size(); i < n; ++i)
            {
                CIMInstance & currentInstance = embeddedInstances[i];
                CIMName currentClassName = currentInstance.getClassName();
                if(Contains(embeddedInstSubclasses, currentClassName))
                {
                    CIMClass embeddedClassDef;
                    bool found = false;
                    for(Uint32 j = 0, m = embeddedClassDefs.size(); j < m;
                        ++j)
                    {
                        CIMClass & tmpClassDef = embeddedClassDefs[j];
                        if(tmpClassDef.getClassName() == currentClassName)
                        {
                            embeddedClassDef = tmpClassDef;
                            found = true;
                        }
                    }

                    if(!found)
                    {
                        embeddedClassDef = context->getClass(nameSpace,
                            currentClassName);
                        embeddedClassDefs.append(embeddedClassDef);
                    }

                    AutoPtr<NormalizerContext> tmpContext(context->clone());
                    ObjectNormalizer tmpNormalizer(embeddedClassDef,
                        includeQualifiers, includeClassOrigin, nameSpace,
                        tmpContext);
                    if(currentInstance.getPath().getKeyBindings().size()==0)
                    {
                        currentInstance.setPath(
                            currentInstance.buildPath(embeddedClassDef));
                    }
                    embeddedInstances[i] = tmpNormalizer.processInstance(currentInstance);
                }
                else
                {
                    MessageLoaderParms message(
                        "Common.ObjectNormalizer.INVALID_EMBEDDED_INSTANCE_TYPE",
                        "Found embedded instance of type $0: was expecting $1 for property $2",
                        currentClassName.getString(),
                        qualClassStr,
                        instProperty.getName().getString());

                    throw CIMException(CIM_ERR_FAILED, message);
                }
            }

            if(referenceProperty.isArray())
            {
              normalizedProperty.setValue(CIMValue(embeddedInstances));
            }
            else
            {
              normalizedProperty.setValue(CIMValue(embeddedInstances[0]));
            }
        }
    }
#endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT

    return(normalizedProperty);
}

ObjectNormalizer::ObjectNormalizer(void)
    : _includeQualifiers(false),
    _includeClassOrigin(false),
    _context(0)
{
}

ObjectNormalizer::ObjectNormalizer(
    const CIMClass & cimClass,
    Boolean includeQualifiers,
    Boolean includeClassOrigin,
    const CIMNamespaceName & nameSpace,
    AutoPtr<NormalizerContext> & context)
  : _cimClass(cimClass),
    _includeQualifiers(includeQualifiers),
    _includeClassOrigin(includeClassOrigin),
    _context(context),
    _nameSpace(nameSpace)
{
    if(!_cimClass.isUninitialized())
    {
        // ATTN: the following code is intended to expedite normalizing instances and instance object
        // paths by establishing the keys once now rather than multiple times later. it is biased
        // toward providers that return many instances with many properties.

        // build a reference object path within the class
        Array<CIMKeyBinding> keys;

        for(Uint32 i = 0, n = _cimClass.getPropertyCount(); i < n; i++)
        {
            CIMConstProperty referenceProperty = _cimClass.getProperty(i);

            Uint32 pos = referenceProperty.findQualifier("key");

            if((pos != PEG_NOT_FOUND) && (referenceProperty.getQualifier(pos).getValue().equal(CIMValue(true))))
            {
                if(referenceProperty.getType() == CIMTYPE_REFERENCE)
                {
                    // ATTN: a fake reference is inserted in the key so that the _BubbleSort() method
                    // in CIMObjectPath does not throw and exception. It implicitly validates keys of
                    // type REFERENCE so just place a dummy value for now. The value will be replaced
                    // by the normalized object later.
                    keys.append(CIMKeyBinding(referenceProperty.getName(), "class.key=\"value\"", CIMKeyBinding::REFERENCE));
                }
                else
                {
                    keys.append(CIMKeyBinding(referenceProperty.getName(), referenceProperty.getValue()));
                }
            }
        }

        // update class object path
        CIMObjectPath cimObjectPath(_cimClass.getPath());

        cimObjectPath.setKeyBindings(keys);

        _cimClass.setPath(cimObjectPath);
    }
}

CIMObjectPath ObjectNormalizer::processClassObjectPath(const CIMObjectPath & cimObjectPath) const
{
    // pre-check
    if(_cimClass.isUninitialized())
    {
        // do nothing
        return(cimObjectPath);
    }

    /*
    // ATTN: moving similar logic to the response handlers because this type of error should
    // be checked regardless with or without normalization enabled.
    if(cimObjectPath.getClassName().isNull())
    {
        throw CIMException(CIM_ERR_FAILED, "uninitialized object path");
    }
    */

    /*
    // ATTN: The following code is currently redundant because the CIMName object validates
    // legal names when it is constructed. It is included here for completeness.
    // check class name
    if(!CIMName(cimObjectPath.getClassName()).legal())
    {
        MessageLoaderParms message(
            "Common.ObjectNormalizer.INVALID_CLASS_NAME",
            "Invalid class name: $0",
            cimObjectPath.getClassName().getString());

        throw CIMException(CIM_ERR_FAILED, message);
    }
    */

    // check class type
    if(!_cimClass.getClassName().equal(cimObjectPath.getClassName()))
    {
        MessageLoaderParms message(
            "Common.ObjectNormalizer.INVALID_CLASS_TYPE",
            "Invalid class type: $0",
            cimObjectPath.getClassName().getString());

        throw CIMException(CIM_ERR_FAILED, message);
    }

    CIMObjectPath normalizedObjectPath(
        _cimClass.getPath().getHost(),
        _cimClass.getPath().getNameSpace(),
        _cimClass.getClassName());

    // ignore any keys, they are not part of a class object path

    return(normalizedObjectPath);
}

CIMObjectPath ObjectNormalizer::processInstanceObjectPath(const CIMObjectPath & cimObjectPath) const
{
    // pre-check
    if(_cimClass.isUninitialized())
    {
        // do nothing
        return(cimObjectPath);
    }

    /*
    // ATTN: moving similar logic to the response handlers because this type of error should
    // be checked regardless with or without normalization enabled.
    if(cimObjectPath.getClassName().isNull())
    {
        throw CIMException(CIM_ERR_FAILED, "uninitialized object path");
    }
    */

    /*
    // ATTN: The following code is currently redundant because the CIMName object validates
    // legal names when it is constructed. It is included here for completeness.
    // check class name
    if(!CIMName(cimObjectPath.getClassName()).legal())
    {
        MessageLoaderParms message(
            "Common.ObjectNormalizer.INVALID_CLASS_NAME",
            "Invalid class name: $0",
            cimObjectPath.getClassName().getString());

        throw CIMException(CIM_ERR_FAILED, message);
    }
    */

    // check class type
    if(!_cimClass.getClassName().equal(cimObjectPath.getClassName()))
    {
        MessageLoaderParms message(
            "Common.ObjectNormalizer.INVALID_CLASS_TYPE",
            "Invalid class type: $0",
            cimObjectPath.getClassName().getString());

        throw CIMException(CIM_ERR_FAILED, message);
    }

    CIMObjectPath normalizedObjectPath(
        _cimClass.getPath().getHost(),
        _cimClass.getPath().getNameSpace(),
        _cimClass.getClassName());

    Array<CIMKeyBinding> normalizedKeys;

    Array<CIMKeyBinding> referenceKeys = _cimClass.getPath().getKeyBindings();
    Array<CIMKeyBinding> cimKeys = cimObjectPath.getKeyBindings();

    for(Uint32 i = 0, n = referenceKeys.size(); i < n; i++)
    {
        CIMKeyBinding key;

        // override the value from the specified object
        for(Uint32 j = 0, m = cimKeys.size(); j < m; j++)
        {
            if(referenceKeys[i].getName().equal(cimKeys[j].getName()))
            {
                // check type
                if(referenceKeys[i].getType() != cimKeys[j].getType())
                {
                    MessageLoaderParms message(
                        "Common.ObjectNormalizer.INVALID_KEY_TYPE",
                        "Invalid key type: $0",
                        referenceKeys[i].getName().getString());

                    throw CIMException(CIM_ERR_FAILED, message);
                }

                key = CIMKeyBinding(referenceKeys[i].getName(), cimKeys[j].getValue(), referenceKeys[i].getType());

                break;
            }
        }

        // key not found
        if(key.getName().isNull())
        {
            MessageLoaderParms message(
                "Common.ObjectNormalizer.MISSING_KEY",
                "Missing key: $0",
                referenceKeys[i].getName().getString());

            throw CIMException(CIM_ERR_FAILED, message);
        }

        normalizedKeys.append(key);
    }

    normalizedObjectPath.setKeyBindings(normalizedKeys);

    return(normalizedObjectPath);
}

CIMInstance ObjectNormalizer::processInstance(const CIMInstance & cimInstance) const
{
    // pre-checks
    if(_cimClass.isUninitialized())
    {
        // do nothing
        return(cimInstance);
    }

    /*
    // ATTN: moving similar logic to the response handlers because this type of error should
    // be checked regardless with or without normalization enabled.
    if(cimInstance.isUninitialized())
    {
        throw CIMException(CIM_ERR_FAILED, "unintialized instance object.");
    }
    */

    CIMInstance normalizedInstance(_cimClass.getClassName());

    // proces object path
    normalizedInstance.setPath(processInstanceObjectPath(cimInstance.getPath()));

    // process instance qualifiers
    if(_includeQualifiers)
    {
        // propagate class qualifiers
        for(Uint32 i = 0, n = _cimClass.getQualifierCount(); i < n; i++)
        {
            CIMConstQualifier referenceQualifier = _cimClass.getQualifier(i);

            Uint32 pos = cimInstance.findQualifier(referenceQualifier.getName());

            // update value if qualifier is present in the specified property
            if(pos != PEG_NOT_FOUND)
            {
                CIMConstQualifier cimQualifier = cimInstance.getQualifier(pos);

                CIMQualifier normalizedQualifier =
                    _processQualifier(
                        referenceQualifier,
                        cimQualifier);

                normalizedInstance.addQualifier(normalizedQualifier);
            }
            else
            {
                normalizedInstance.addQualifier(referenceQualifier.clone());
            }
        }
    }

    // check property names and types. any properties in the class but not in the instance
    // are implicitly dropped.
    for(Uint32 i = 0, n = _cimClass.getPropertyCount(); i < n; i++)
    {
        CIMConstProperty referenceProperty = _cimClass.getProperty(i);

        Uint32 pos = cimInstance.findProperty(referenceProperty.getName());

        if(pos != PEG_NOT_FOUND)
        {
            CIMConstProperty cimProperty = cimInstance.getProperty(pos);

            CIMProperty normalizedProperty =
                _processProperty(
                    referenceProperty,
                    cimProperty,
                    _includeQualifiers,
                    _includeClassOrigin,
                    _context.get(),
                    _nameSpace);

            normalizedInstance.addProperty(normalizedProperty);
        }
    }

    return(normalizedInstance);
}

PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2