int WS_GetInstance()

in Unix/wsman/wsmanparser.c [821:1191]


int WS_GetInstance(
    XML* xml,
    XML_Elem *start,
    Batch*  dynamicBatch,
    MI_Instance** dynamicInstanceParams,
    MI_Uint32 rqtAction)
{
    XML_Elem e;
    const TChar* propNameA = 0;
    MI_Value valueA;
    MI_Type typeA = MI_BOOLEAN;
    const TChar* propNamePrev = 0;
    MI_Value valuePrev;
    MI_Type typePrev = MI_BOOLEAN;

    memset(&valueA, 0, sizeof(valueA));

    /* extract all parameters */
    for (;;)
    {
#ifndef DISABLE_SHELL
        MI_Instance *embeddedShellInstance = NULL;
#endif

        if (GetNextSkipCharsAndComments(xml, &e) != 0)
            RETURN(-1);

        /* Look for closing instance element */

        if (e.type == XML_END && Tcscmp(e.data.data, start->data.data) == 0)
        {
            break;
        }

        /* skip possible comments */
        if (e.type != XML_START)
            continue;

        /* allocate new instance if needed */
        if (!*dynamicInstanceParams)
        {
            MI_Result r;
            TChar* cn = NULL;

            // We are trying to parse an Instance, The type of the instance may be specified
            // as a attribute Type or it is same as the element name. We'll attempt to get the
            // type from attribute ... if not we'll use the element name.
            // TODO: At this time we don't have the NS support in the XML parser, so using hardcoded
            // 'xsi:type (good for windows client) once we get the NS support this code should be
            // updated.
            const TChar* typeName = XML_Elem_GetAttr(start, PAL_T('x'), PAL_T("type"));

            if(typeName)
            {
                TChar* typeStart;
                cn = Batch_Tcsdup(dynamicBatch, typeName);

                if (!cn)
                {
                    trace_BatchTcsDup_Failed();
                    RETURN(-1);
                }

                // Trim the _Type from the name.
                typeStart = Tcsrchr(cn, '_');
                if( typeStart )
                {
                    *typeStart = PAL_T('\0');

                    /* trim namespace start too */
                    {
                        TChar* afterColon;
                        afterColon = Tcschr(cn, PAL_T(':'));
                        if (afterColon)
                        {
                            afterColon++;
                            cn = afterColon;
                        }
                    }
                }
                else
                {
                    trace_XsiTypeInvalidValue( cn );
                    RETURN(-1);
                    // cn is allocated on the batch, so it will be release along with it anyway
                }
            }
            else
            {
                cn = Batch_Tcsdup(dynamicBatch, start->data.data);
                if (!cn)
                {
                    trace_BatchTcsDup_Failed();
                    RETURN(-1);
                }
            }

            r = Instance_NewDynamic(
                dynamicInstanceParams,
                cn,
                MI_FLAG_CLASS,
                dynamicBatch);

            if (MI_RESULT_OK != r)
                RETURN(-1);

#ifndef DISABLE_SHELL
            if (rqtAction == WSMANTAG_ACTION_SHELL_COMMAND)
            {
               /* If this is the shell Receive Response then we have optional CommandId attribute that 
                * needs to be extracted and put in 
                * the instance
                */
                const TChar* commandId = XML_Elem_GetAttr(start, 0, PAL_T("CommandId"));
                if (commandId)
                {
                    MI_Value value;
                    value.string = (TChar*) commandId;
                    if (__MI_Instance_AddElement(*dynamicInstanceParams, MI_T("CommandId"), &value, MI_STRING, 0) != MI_RESULT_OK)
                    {
                        RETURN(-1);
                    }
                }
            }
#endif
        }

#ifndef DISABLE_SHELL
        if (rqtAction == WSMANTAG_ACTION_SHELL_RECEIVE_RESPONSE)
        {
            MI_Result r;
            const TChar *tmpStr;

            /* Stream and Command State are both embedded instances that require multiple 
             * attributes to get extracted
             */
             r = Instance_NewDynamic(
                    &embeddedShellInstance,
                    e.data.data,
                    MI_FLAG_CLASS,
                    dynamicBatch);

            if (MI_RESULT_OK != r)
                    RETURN(-1);

            /* Both parameters have optional commandId's */
            tmpStr = XML_Elem_GetAttr(&e, 0, PAL_T("CommandId"));
            if (tmpStr)
            {
                MI_Value value;
                value.string = (TChar*) tmpStr;
                if (__MI_Instance_AddElement(embeddedShellInstance, MI_T("CommandId"), &value, MI_STRING, 0) != MI_RESULT_OK)
                {
                    RETURN(-1);
                }
            }

            if (Tcscmp(e.data.data, MI_T("Stream")) == 0)
            {
                tmpStr = XML_Elem_GetAttr(&e, 0, PAL_T("Name"));
                if (tmpStr)
                {
                    MI_Value value;
                    value.string = (TChar*) tmpStr;
                    if (__MI_Instance_AddElement(embeddedShellInstance, MI_T("streamName"), &value, MI_STRING, 0) != MI_RESULT_OK)
                    {
                        RETURN(-1);
                    }
                }

                tmpStr = XML_Elem_GetAttr(&e, 0, PAL_T("End"));
                if (tmpStr && (Tcscmp(tmpStr, MI_T("true")) == 0 || Tcscmp(tmpStr, MI_T("1")) == 0))
                {
                    MI_Value value;
                    value.boolean = 1;
                    if (__MI_Instance_AddElement(embeddedShellInstance, MI_T("endOfStream"), &value, MI_BOOLEAN, 0) != MI_RESULT_OK)
                    {
                        RETURN(-1);
                    }
                }
            }
            else if (Tcscmp(e.data.data, MI_T("CommandState")) == 0)
            {
                tmpStr = XML_Elem_GetAttr(&e, 0, PAL_T("State"));
                if (tmpStr)
                {
                    MI_Value value;
                    value.string = (TChar*) tmpStr;
                    if (__MI_Instance_AddElement(embeddedShellInstance, MI_T("State"), &value, MI_STRING, 0) != MI_RESULT_OK)
                    {
                        RETURN(-1);
                    }
                }

            }
        }
#endif
 
        /* add next property to the instance */
        if (e.data.size > 0) /* element name should have some data in it */
        {
            MI_Result r;
            MI_Value value;
            MI_Type type = MI_BOOLEAN;
            const TChar* propNameChar;
            const TChar* propName;
            MI_Boolean null;

            propNameChar = e.data.data;

            /* Position propName one beyond ':' character */
            propName = Batch_Tcsdup(dynamicBatch, propNameChar);

            if (!propName)
            {
                trace_BatchTcsDup_Failed();
                RETURN(-1);
            }

            type = MI_BOOLEAN;

            if (_GetSingleProperty(
                xml,
                &e,
                dynamicBatch,
                e.data.namespaceId,
                propNameChar,
                &value,
                &type,
                &null, 
                rqtAction) != 0)
            {
                trace_GetSingleProperty_Failed( tcs(propNameChar) );
                RETURN(-1);
            }
#ifndef DISABLE_SHELL
            if (rqtAction == WSMANTAG_ACTION_SHELL_RECEIVE_RESPONSE)
            {
                if (Tcscmp(propName, MI_T("Stream")) == 0)
                {
                    /* Add the data into the embedded object */
                    r = MI_Instance_AddElement(embeddedShellInstance, MI_T("data"), &value, type, MI_FLAG_BORROW);
                    if (MI_RESULT_OK != r)
                        RETURN(-1);
                }

                /* Now make our embedded instance become the real data to add */
                value.instance = embeddedShellInstance;
                type = MI_INSTANCE;
                null = MI_FALSE;
            }
#endif

            if (null)
            {
                /* Skip null attributes */
                continue;
            }

            /* Did we collect array's items? */
            if (propNameA)
            {
                /* if we have array and new property matches array - add new item to the array */
                if (0 == Tcscmp(propNameA, propName))
                {
                    if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &value, type))
                        RETURN(-1);
                }
                else
                {
                    r = MI_Instance_AddElement(*dynamicInstanceParams, propNameA, &valueA,
                        typeA, MI_FLAG_BORROW);

                    if (MI_RESULT_OK != r)
                        RETURN(-1);

                    /* Clear array prop name */
                    propNameA = 0;

                    propNamePrev = propName;
                    valuePrev = value;
                    typePrev = type;
                }
            }
            else if (propNamePrev)
            {
                /* Check if name is the same and we need to create an array */
                if (0 == Tcscmp(propNamePrev, propName))
                {
                    /* create array */
                    valueA.array.size = 0;
                    valueA.array.data = 0;

                    typeA = type | MI_ARRAY_BIT;
                    propNameA = propName;

                    if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &valuePrev, typePrev))
                        RETURN(-1);

                    if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &value, type))
                        RETURN(-1);

                }
                else
                {
                    r = MI_Instance_AddElement(
                        *dynamicInstanceParams,
                        propNamePrev,
                        &valuePrev,
                        typePrev,
                        MI_FLAG_BORROW);

                    /* Note that the MI_RESULT_ALREADY_EXISTS error is okay
                     * for key properties added when the selector set was
                     * parsed earlier.
                     */
                    if (r != MI_RESULT_OK && r != MI_RESULT_ALREADY_EXISTS)
                    {
                        RETURN(-1);
                    }

                    propNamePrev = propName;
                    valuePrev = value;
                    typePrev = type;
               }

            }
            else
            {
                /* collecting first item */
                propNamePrev = propName;
                valuePrev = value;
                typePrev = type;
            }
        }
    }

    /* if last property was array - add it */
    if (propNameA)
    {
        MI_Result r;

        r = MI_Instance_AddElement(*dynamicInstanceParams, propNameA, &valueA,
            typeA, MI_FLAG_BORROW);

        if (MI_RESULT_OK != r)
            RETURN(-1);
    }
    else if (propNamePrev)
    {
        MI_Result r;

        r = MI_Instance_AddElement(*dynamicInstanceParams, propNamePrev, &valuePrev,
            typePrev, MI_FLAG_BORROW);

        /* Note that the MI_RESULT_ALREADY_EXISTS error is okay
        * for key properties added when the selector set was
        * parsed earlier.
        */
        if (r != MI_RESULT_OK && r != MI_RESULT_ALREADY_EXISTS)
        {
            RETURN(-1);
        }
    }

    /* check closing tag */
    if (Tcscmp(e.data.data, start->data.data) != 0)
        RETURN(-1);

    return 0;
}