1 //%2006////////////////////////////////////////////////////////////////////////
3 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
11 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //==============================================================================
32 //%/////////////////////////////////////////////////////////////////////////////
33 #include <Pegasus/Common/Config.h>
34 #include <Pegasus/Common/Constants.h>
35 #include <Pegasus/Common/PegasusAssert.h>
36 #include <Pegasus/Common/StringConversion.h>
37 #include <Pegasus/Common/Tracer.h>
38 #include <Pegasus/Common/XmlWriter.h>
40 #include "CIMCLIClient.h"
41 #include "ObjectBuilder.h"
42 #include "CIMCLICommon.h"
45 PEGASUS_NAMESPACE_BEGIN
49 // Cleans an input array by removing the { } tokens that surround
50 // the array. Does nothing if they do not exist. If there is
51 // an unmatched set, an error is generated.
52 // Allows the user to input array definitions surrounded by { }
54 void _cleanArray(String& x)
56 if (x[0] == '{' && x[x.size()] == '}')
61 else if(x[0] == '{' || x[x.size()] == '}')
63 cerr << "Error: Parse Error: Array " << x << endl;
64 exit(CIMCLI_INPUT_ERR);
68 // FUTURE - Expand this for other date time literals suchs as TODAY
70 CIMDateTime _getDateTime(const String& str)
72 if (String::equalNoCase(str,"NOW"))
74 return CIMDateTime::getCurrentDateTime();
76 return CIMDateTime(str);
79 Boolean _StringToBoolean(const String& x)
81 if (String::equalNoCase(x,"true"))
85 else if (String::equalNoCase(x,"false"))
89 cerr << "Parse Error: Boolean Parmeter " << x << endl;
90 exit(CIMCLI_INPUT_ERR);
94 Uint32 _includesType(const String& name)
96 // FUTURE KS add code. For now this is null because we do not
97 // support the data type option on input.
101 /* Parser for comma-separated-strings (csv). This parser takes into
102 account quoted strings the " character and returns everything
103 within a quoted block in the string in one batch. It also
104 considers the backslash "\" escape character to escape single
107 csvStringParse x (inputstring, ",");
109 rtnString = x.next();
114 /* Define a string to parse for comma separated values and the
117 csvStringParse(const String& csvString, const int separator)
119 _inputString = csvString;
120 _separator = separator;
122 _end = csvString.size();
125 /* determine if there is more to parse
126 @return true if there is more to parse
130 return (_idx < _end)? true : false;
133 /* get next string from input. Note that this will continue to
134 return empty strings if you parse past the point where more()
141 parsestate state = NOTINQUOTE;
143 while ((_idx <= _end) && (_inputString[_idx]))
145 char idxchar = _inputString[_idx];
160 if (idxchar == _separator)
166 rtnValue.append(idxchar);
171 // add next character and set NOTINQUOTE State
173 rtnValue.append(idxchar);
177 // append all but quote character
185 rtnValue.append(idxchar);
195 enum parsestate {INDQUOTE, INSQUOTE, NOTINQUOTE};
202 Sint64 _strToSint(const char* str, CIMType type)
206 (StringConversion::stringToSint64(
207 str, StringConversion::decimalStringToUint64, s64) ||
208 StringConversion::stringToSint64(
209 str, StringConversion::hexStringToUint64, s64) ||
210 StringConversion::stringToSint64(
211 str, StringConversion::octalStringToUint64, s64) ||
212 StringConversion::stringToSint64(
213 str, StringConversion::binaryStringToUint64, s64)) &&
214 StringConversion::checkSintBounds(s64, type);
217 printf("Parse Error: Value conversion error. %s. type %s\n",
218 str, cimTypeToString(type));
224 Uint64 _strToUint(const char* str, CIMType type)
228 (StringConversion::decimalStringToUint64(str, u64) ||
229 StringConversion::hexStringToUint64(str, u64) ||
230 StringConversion::octalStringToUint64(str, u64) ||
231 StringConversion::binaryStringToUint64(str, u64)) &&
232 StringConversion::checkUintBounds(u64, type);
236 fprintf(stderr,"Parse Error: Value conversion error. %s. type %s\n",
237 str, cimTypeToString(type));
238 exit(CIMCLI_INPUT_ERR);
244 /* Convert a single string provided as input into a CIM variable
245 and place it in a CIMValue.
246 @param str char* representing string to be parsed.
247 @param type CIMType expected.
248 @return CIMValue with the new value.
250 Real64 _strToReal(const char * str, CIMType type)
254 if (!StringConversion::stringToReal64(str, r64))
256 fprintf(stderr, "Parse Error: Value conversion error. %s. type %s\n",
257 str, cimTypeToString(type));
258 exit(CIMCLI_INPUT_ERR);
263 /* Convert a single string provided as input into a CIM variable
264 and place it in a CIMValue.
265 @param str char* representing string to be parsed.
266 @param type CIMType expected.
267 @return CIMValue with the new value. If the parse fails, this function
268 terminates with an exit CIMCLI_INPUT_ERR.
270 static CIMValue _stringToScalarValue(const char* str, CIMType type)
276 case CIMTYPE_BOOLEAN:
277 return CIMValue(_StringToBoolean(str));
280 return CIMValue(Uint8(_strToUint(str, type)));
283 return CIMValue(Sint8(_strToSint(str, type)));
286 return CIMValue(Uint16(_strToUint(str, type)));
289 return CIMValue(Sint16(_strToSint(str, type)));
292 return CIMValue(Uint32(_strToUint(str, type)));
295 return CIMValue(Sint32(_strToSint(str, type)));
298 return CIMValue(Uint64(_strToUint(str, type)));
301 return CIMValue(Sint64(_strToSint(str, type)));
304 return CIMValue(Real32(_strToReal(str, type)));
307 return CIMValue(Real64(_strToReal(str, type)));
310 return CIMValue(String(str));
312 case CIMTYPE_DATETIME:
313 return CIMValue(_getDateTime(str));
316 cerr << "Error: Parser Error. Data type " << cimTypeToString(type)
317 << " not allowed" << endl;
318 exit(CIMCLI_INPUT_ERR);
323 Parse out comma-separated values from input string and build the
324 CIMValue array representing the input for array type input entities.
325 @param str const char * containing the comma-separated values
326 to be parsed. All value elements in the CSV string must be
327 parsable to the same type.
328 @param v CIMValue into which the resulting values are added to
330 @return Returns complete CIMValue.
332 Boolean _buildArrayValue(
336 CIMType type = val.getType();
337 Uint32 arrayDimension = val.getArraySize();
339 csvStringParse strl((String)String(str), ',');
343 case CIMTYPE_BOOLEAN:
349 a.append(_StringToBoolean(strl.next()));
359 a.append(_strToUint(strl.next().getCString(), type));
368 a.append(_strToSint(strl.next().getCString(), type));
377 a.append(_strToUint(strl.next().getCString(), type));
386 a.append(_strToSint(strl.next().getCString(), type));
395 a.append(_strToUint(strl.next().getCString(), type));
404 a.append(_strToSint(strl.next().getCString(), type));
413 a.append(_strToUint(strl.next().getCString(), type));
422 a.append(_strToSint(strl.next().getCString(), type));
431 a.append(_strToUint(strl.next().getCString(), type));
440 a.append(_strToSint(strl.next().getCString(), type));
449 a.append(strl.next());
453 case CIMTYPE_DATETIME:
455 Array<CIMDateTime> a;
458 a.append(_getDateTime(strl.next()));
463 cout << "Error: Parse Error. Data type " << cimTypeToString(type)
464 << " not allowed" << endl;
465 exit(CIMCLI_INPUT_ERR);
471 Create a method parameter from the tokenized information for the
472 method name, value, type, etc.
474 CIMParamValue _createMethodParamValue( const CIMName& name,
476 const CIMParameter& thisParam,
478 const CIMNamespaceName& nameSpace)
480 CIMType type = thisParam.getType();
481 String paramName = thisParam.getName().getString();
483 CIMValue vp(type,thisParam.isArray());
487 _buildArrayValue(value.getCString(), vp );
488 // set the value array into the property value
489 return CIMParamValue(paramName,vp,true);
494 v = _stringToScalarValue(value.getCString(), vp.getType());
495 return CIMParamValue(paramName,v,true);
498 // should never get here
499 return CIMParamValue();
502 /******************************************************************
504 * ObjectBuilder Class. Creates instances and parameters from
505 * name/value pairs received and the corresponding class
508 *******************************************************************/
510 Constructor, sets up a single object with the input pairs
511 and the definition to get the class required for the
512 parsing and entity building.
514 ObjectBuilder::ObjectBuilder(
515 const Array<String>& inputPairs,
517 const CIMNamespaceName& nameSpace,
518 const CIMName& className,
519 const CIMPropertyList& cimPropertyList,
522 // get the class. Exceptions including class_not_found are automatic
523 // not localOnly (Need all properties), get qualifiers and classOrigin
524 // since we can filter them out later
527 _className = className;
529 _thisClass = client.getClass(nameSpace, className,
530 false,true,true,cimPropertyList);
532 _nameSpace = nameSpace;
533 if (inputPairs.size() != 0)
535 /* Here loop starts from 1, since the Class Name is first parameter
536 and we want only the property name and value here
538 for (Uint32 i = 1 ; i < inputPairs.size() ; i++)
544 // parse each pair and eliminate any illegal returns
545 if ((sep = _parseValuePair(inputPairs[i], name, value)) != ILLEGAL)
547 _featureNameList.append(CIMName(name));
548 _valueStringList.append(value);
549 _parseType.append(sep);
553 cerr << "Parse Failed " << inputPairs[i] << endl;
559 // This loop displays all the names and
560 // property values of the instance
561 for (Uint32 i=0; i < _featureNameList.size(); i++)
563 cout << "Name= " << _featureNameList[i].getString()
564 << ", valueString= " << _valueStringList[i] << endl;
570 ObjectBuilder::~ObjectBuilder()
574 Array<CIMName> ObjectBuilder::getPropertyList()
576 return _featureNameList;
579 const CIMClass ObjectBuilder::getTargetClass()
584 CIMObjectPath ObjectBuilder::buildCIMObjectPath()
586 CIMInstance testInstance = buildInstance(
590 CIMObjectPath thisPath = testInstance.buildPath(_thisClass);
595 Parse the input string to separate out the strings for name and
596 value components. The name component must be a CIM_Name and contain
597 only alphanumerics and _ characters. The value is optional.
598 The possible separators are today
599 "=" and "!". and no value component is allowed after the ! separator
601 Uint32 ObjectBuilder::_parseValuePair(const String& input,
605 _termType terminator;
606 value = String::EMPTY;
608 Boolean separatorFound = false;
609 for (Uint32 i = 0 ; i < input.size() ; i++)
611 if ((input[i] != '=') && (input[i] != '!'))
613 name.append(input[i]);
615 else //separator character found
625 separatorFound = true;
630 // separator must be found
633 cerr << "Parse error: No separator " << input << endl;
636 // There must be a name entity
637 if (name.size() == 0)
639 cerr << "Parse error: No name component " << input << endl;
642 // value component is optional but sets different _termType values
643 if (input.size() == name.size() + 1)
645 if (terminator == EXCLAM)
654 value = input.subString(name.size() + 1, PEG_NOT_FOUND);
658 Build an instance from the information in the ObjectBuilder
661 CIMInstance ObjectBuilder::buildInstance(
662 Boolean includeQualifiers,
663 Boolean includeClassOrigin,
664 const CIMPropertyList& propertyList)
666 // create the instance skeleton with the defined properties
667 CIMInstance newInstance = _thisClass.buildInstance(
672 Array<CIMName> myPropertyList;
675 // Set all the input property values into the instance
676 for (Uint32 index = 0; index < _featureNameList.size(); index++)
678 if ((propertyPos = _thisClass.findProperty(
679 _featureNameList[index])) == PEG_NOT_FOUND)
681 cerr << "Warning property Name "
682 << _featureNameList[index].getString()
683 << " Input value " << _valueStringList[index]
684 << " not in class: " << _thisClass.getClassName().getString()
690 // get value for this property from built instance
692 CIMProperty ip = newInstance.getProperty(propertyPos);
693 CIMValue iv = ip.getValue();
695 // If input not NULL type (ends with =) set the value component
696 // into property. NULL input sets whatever is in the class into
697 // the instance (done by buildInstance);
698 if (_parseType[index] == EXCLAM)
700 if (iv.getType() == CIMTYPE_STRING)
702 iv.set(String::EMPTY);
707 cerr << "Error: " << ip.getName().getString()
708 << "! parameter terminator allowed only on String types "
710 exit(CIMCLI_INPUT_ERR);
713 else if (_parseType[index] == VALUE)
717 _cleanArray(_valueStringList[index]);
718 if (!_buildArrayValue(
719 _valueStringList[index].getCString(), iv))
721 cerr << "Parse Error: parameter "
722 << _featureNameList[index].getString()
724 << _valueStringList[index] << endl;
725 exit(CIMCLI_INPUT_ERR);
730 // Replace property value in new instance
731 iv = _stringToScalarValue(
732 _valueStringList[index].getCString(), ip.getType());
737 else if(_parseType[index] == NO_VALUE)
741 else if(_parseType[index] == ILLEGAL)
746 myPropertyList.append(CIMName(_featureNameList[index]));
749 // Delete any properties not on the property list
753 CIMPropertyList(myPropertyList));
755 // Display the Instance if verbose
758 cout << "Instance Built" << endl;
759 XmlWriter::printInstanceElement(newInstance, cout);
765 Array<CIMParamValue> ObjectBuilder::buildMethodParameters()
767 Array<CIMParamValue> params;
771 CIMMethod thisClassMethod;
773 if ((methodPos = _thisClass.findMethod(_methodName)) == PEG_NOT_FOUND)
775 cerr << "Error: method " << _methodName.getString()
776 << " Not method in the class " << _className.getString()
778 exit(CIMCLI_INPUT_ERR);
782 thisClassMethod = _thisClass.getMethod(methodPos);
785 // find parameter for each input.
786 for (Uint32 index = 0; index < _featureNameList.size(); index++)
789 if ((parameterPos = thisClassMethod.findParameter(
790 CIMName(_featureNameList[index]))) == PEG_NOT_FOUND)
792 cerr << "Error: parameter " << _featureNameList[index].getString()
793 << " not valid method parameter in class "
794 << _className.getString()
796 exit(CIMCLI_INPUT_ERR);
799 CIMParameter thisParameter = thisClassMethod.getParameter(parameterPos);
801 CIMParamValue localParamValue = _createMethodParamValue(
802 _featureNameList[index],
803 _valueStringList[index],
810 // successful addition of parameter value
811 params.append(localParamValue);
815 // error adding parameter value
816 cerr << "Error: Parsing Error adding parameter"
817 << _featureNameList[index].getString() << " "
818 << _valueStringList[index] << endl;
819 exit(CIMCLI_INPUT_ERR);
825 void ObjectBuilder::setMethod(CIMName& name)
830 PEGASUS_NAMESPACE_END