Exemple #1
0
/**
    ATTN-RK: The DMTF specification for the string form of an
    object path makes it impossible for a parser to distinguish
    between a key values of String type and Reference type.

    Given the ambiguity, this implementation takes a guess at the
    type of a quoted key value.  If the value can be parsed into
    a CIMObjectPath with at least one key binding, the type is
    set to REFERENCE.  Otherwise, the type is set to STRING.
    Note: This algorithm appears to be in line with what the Sun
    WBEM Services implementation does.

    To be totally correct, it would be necessary to retrieve the
    class definition and look up the types of the key properties
    to determine how to interpret the key values.  This is clearly
    too inefficient for internal transformations between
    CIMObjectPaths and String values.
*/
void _parseKeyBindingPairs(
    const String& objectName,
    char*& p,
    Array<CIMKeyBinding>& keyBindings)
{
    // Get the key-value pairs:

    while (*p)
    {
        // Get key part:

        char* equalsign = strchr(p, '=');
        if (!equalsign)
        {
            MessageLoaderParms mlParms(
                "Common.CIMObjectPath.INVALID_KEYVALUEPAIR",
                "$0, reason:\"invalid key-value pair, missing equal sign\"",
                objectName);
            throw MalformedObjectNameException(mlParms);
        }

        *equalsign = 0;

        if (!CIMName::legal(p))
        {
            MessageLoaderParms mlParms(
                "Common.CIMObjectPath.INVALID_KEYNAME",
                "$0, reason:\"invalid key-value pair, invalid key name:$1\"",
                objectName,
                p);
            throw MalformedObjectNameException(mlParms);
        }

        CIMName keyName (p);

        // Get the value part:

        String valueString;
        p = equalsign + 1;
        CIMKeyBinding::Type type;

        if (*p == '"')
        {
            // Could be CIMKeyBinding::STRING or CIMKeyBinding::REFERENCE

            p++;

            Buffer keyValueUTF8(128);

            while (*p && *p != '"')
            {
                if (*p == '\\')
                {
                    p++;

                    if ((*p != '\\') && (*p != '"'))
                    {
                        MessageLoaderParms mlParms(
                            "Common.CIMObjectPath.INVALID_KEYVALUE",
                            "$0, reason:\"invalid key-value pair, "
                                "malformed value\"",
                            objectName);
                        throw MalformedObjectNameException(mlParms);
                    }
                }

                keyValueUTF8.append(*p++);
            }

            if (*p++ != '"')
            {
                MessageLoaderParms mlParms(
                    "Common.CIMObjectPath.INVALID_KEYVALUEPAIR_MISSINGQUOTE",
                    "$0, reason:\"invalid key-value pair, "
                        "missing quote in key value\"",
                    objectName);
                throw MalformedObjectNameException(mlParms);
            }

            // Convert the UTF-8 value to a UTF-16 String

            valueString.assign(
                (const char*)keyValueUTF8.getData(),
                keyValueUTF8.size());

            /*
                Guess at the type of this quoted key value.  If the value
                can be parsed into a CIMObjectPath with at least one key
                binding, the type is assumed to be a REFERENCE.  Otherwise,
                the type is set to STRING.  (See method header for details.)
             */
            type = CIMKeyBinding::STRING;

            /* Performance shortcut will check for
               equal sign instead of doing the full
               CIMObjectPath creation and exception handling
            */
            if (strchr(keyValueUTF8.getData(), '='))
            {
                // found an equal sign, high probability for a reference
                try
                {
                    CIMObjectPath testForPath(valueString);
                    if (testForPath.getKeyBindings().size() > 0)
                    {
                        // We've found a reference value!
                        type = CIMKeyBinding::REFERENCE;
                    }
                }
                catch (const Exception &)
                {
                    // Not a reference value; leave type as STRING
                }
            }
        }
        else if (toupper(*p) == 'T' || toupper(*p) == 'F')
        {
            type = CIMKeyBinding::BOOLEAN;

            char* r = p;
            Uint32 n = 0;

            while (*r && *r != ',')
            {
                *r = toupper(*r);
                r++;
                n++;
            }

            if (!(((strncmp(p, "TRUE", n) == 0) && n == 4) ||
                  ((strncmp(p, "FALSE", n) == 0) && n == 5)))
            {
                MessageLoaderParms mlParms(
                    "Common.CIMObjectPath.INVALID_BOOLVALUE",
                    "$0, reason:\"invalid key-value pair, "
                        "value should be TRUE or FALSE\"",
                    objectName);
                throw MalformedObjectNameException(mlParms);
            }

            valueString.assign(p, n);

            p = p + n;
        }
        else
        {
            type = CIMKeyBinding::NUMERIC;

            char* r = p;
            Uint32 n = 0;

            while (*r && *r != ',')
            {
                r++;
                n++;
            }

            Boolean isComma = false;
            if (*r)
            {
                *r = '\0';
                isComma = true;
            }

            if (*p == '-')
            {
                Sint64 x;
                if (!StringConversion::stringToSignedInteger(p, x))
                {
                    MessageLoaderParms mlParms(
                        "Common.CIMObjectPath.INVALID_NEGATIVNUMBER_VALUE",
                        "$0, reason:\"invalid key-value pair, "
                            "invalid negative number value $1\"",
                        objectName,
                        p);
                    throw MalformedObjectNameException(mlParms);
                }
            }
            else
            {
                Uint64 x;
                if (!StringConversion::stringToUnsignedInteger(p, x))
                {
                    MessageLoaderParms mlParms(
                        "Common.CIMObjectPath.INVALID_NEGATIVNUMBER_VALUE",
                        "$0, reason:\"invalid key-value pair, "
                            "invalid number value $1\"",
                        objectName,
                        p);
                    throw MalformedObjectNameException(mlParms);
                }
            }

            valueString.assign(p, n);

            if (isComma)
            {
                *r = ',';
            }

            p = p + n;
        }

        keyBindings.append(CIMKeyBinding(keyName.getString (), valueString,
            type));

        if (*p)
        {
            if (*p++ != ',')
            {
                MessageLoaderParms mlParms(
                    "Common.CIMObjectPath.INVALID_KEYVALUEPAIR_MISSCOMMA",
                    "$0, reason:\"invalid key-value pair, "
                        "next key-value pair has to start with comma\"",
                    objectName);
                throw MalformedObjectNameException(mlParms);
            }
        }
    }

    _Sort(keyBindings);
}
/**
    ATTN-RK: The DMTF specification for the string form of an
    object path makes it impossible for a parser to distinguish
    between a key values of String type and Reference type.

    Given the ambiguity, this implementation takes a guess at the
    type of a quoted key value.  If the value can be parsed into
    a CIMObjectPath with at least one key binding, the type is
    set to REFERENCE.  Otherwise, the type is set to STRING.
    Note: This algorithm appears to be in line with what the Sun
    WBEM Services implementation does.

    To be totally correct, it would be necessary to retrieve the
    class definition and look up the types of the key properties
    to determine how to interpret the key values.  This is clearly
    too inefficient for internal transformations between
    CIMObjectPaths and String values.
*/
void _parseKeyBindingPairs(
    const String& objectName,
    char*& p,
    Array<CIMKeyBinding>& keyBindings)
{
    // Get the key-value pairs:

    while (*p)
    {
        // Get key part:

        char* equalsign = strchr(p, '=');
        if (!equalsign)
        {
            throw MalformedObjectNameException(objectName);
        }

        *equalsign = 0;

        if (!CIMName::legal(p))
            throw MalformedObjectNameException(objectName);

        CIMName keyName (p);

        // Get the value part:

        String valueString;
        p = equalsign + 1;
        CIMKeyBinding::Type type;

        if (*p == '"')
        {
            // Could be CIMKeyBinding::STRING or CIMKeyBinding::REFERENCE

            p++;

            while (*p && *p != '"')
            {
                if (*p == '\\')
                {
                    *p++;

                    if ((*p != '\\') && (*p != '"'))
                    {
                        throw MalformedObjectNameException(objectName);
                    }
                }

                valueString.append(*p++);
            }

            if (*p++ != '"')
                throw MalformedObjectNameException(objectName);

            /*
                Guess at the type of this quoted key value.  If the value
                can be parsed into a CIMObjectPath with at least one key
                binding, the type is assumed to be a REFERENCE.  Otherwise,
                the type is set to STRING.  (See method header for details.)
             */
            type = CIMKeyBinding::STRING;

            try
            {
                CIMObjectPath testForPath(valueString);
                if (testForPath.getKeyBindings().size() > 0)
                {
                    // We've found a reference value!
                    type = CIMKeyBinding::REFERENCE;
                }
            }
            catch (const Exception &)
            {
                // Not a reference value; leave type as STRING
            }
        }
        else if (toupper(*p) == 'T' || toupper(*p) == 'F')
        {
            type = CIMKeyBinding::BOOLEAN;

            char* r = p;
            Uint32 n = 0;

            while (*r && *r != ',')
            {
                *r = toupper(*r);
                r++;
                n++;
            }

            if (!(((strncmp(p, "TRUE", n) == 0) && n == 4) ||
                  ((strncmp(p, "FALSE", n) == 0) && n == 5)))
                throw MalformedObjectNameException(objectName);

            valueString.assign(p, n);

            p = p + n;
        }
        else
        {
            type = CIMKeyBinding::NUMERIC;

            char* r = p;
            Uint32 n = 0;

            while (*r && *r != ',')
            {
                r++;
                n++;
            }

            Boolean isComma = false;
            if (*r)
            {
                *r = '\0';
                isComma = true;
            }

            Sint64 x;

            if (!XmlReader::stringToSignedInteger(p, x))
                throw MalformedObjectNameException(objectName);

            valueString.assign(p, n);

            if (isComma)
            {
                *r = ',';
            }

            p = p + n;
        }

        keyBindings.append(CIMKeyBinding(keyName.getString (), valueString,
            type));

        if (*p)
        {
            if (*p++ != ',')
            {
                throw MalformedObjectNameException(objectName);
            }
        }
    }

    _BubbleSort(keyBindings);
}