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

  1 mike  1.1 //BEGIN_LICENSE
  2           //
  3           // Copyright (c) 2000 The Open Group, BMC Software, Tivoli Systems, IBM
  4           //
  5           // Permission is hereby granted, free of charge, to any person obtaining a
  6           // copy of this software and associated documentation files (the "Software"),
  7           // to deal in the Software without restriction, including without limitation
  8           // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9           // and/or sell copies of the Software, and to permit persons to whom the
 10           // Software is furnished to do so, subject to the following conditions:
 11           //
 12           // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 13           // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 14           // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 15           // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 16           // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 17           // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 18           // DEALINGS IN THE SOFTWARE.
 19           //
 20           //END_LICENSE
 21           //BEGIN_HISTORY
 22 mike  1.1 //
 23           // Author:
 24           //
 25           // $Log$
 26           //
 27           //END_HISTORY
 28           
 29           #include <cstdlib>
 30           #include <cstdio>
 31           #include "ClassDecl.h"
 32           #include "QualifierDecl.h"
 33           #include "XmlWriter.h"
 34           #include "XmlParser.h"
 35           
 36           PEGASUS_NAMESPACE_BEGIN
 37           
 38           inline void AppendChar(Array<Sint8>& out, Char16 c)
 39           {
 40               out.append(Sint8(c));
 41           }
 42           
 43 mike  1.1 inline void AppendSpecialChar(Array<Sint8>& out, Char16 c)
 44           {
 45               // ATTN-B: Only UTF-8 handled for now.
 46           
 47               switch (c)
 48               {
 49           	case '&':
 50           	    out.append("&amp;", 5);
 51           	    break;
 52           
 53           	case '<':
 54           	    out.append("&lt;", 4);
 55           	    break;
 56           
 57           	case '>':
 58           	    out.append("&gt;", 4);
 59           	    break;
 60           
 61           	case '"':
 62           	    out.append("&quot;", 6);
 63           	    break;
 64 mike  1.1 
 65           	case '\'':
 66           	    out.append("&apos;", 6);
 67           	    break;
 68           
 69           	default:
 70           	    out.append(Sint8(c));
 71               }
 72           }
 73           
 74           void XmlWriter::append(Array<Sint8>& out, Char16 x)
 75           {
 76               AppendChar(out, x);
 77           }
 78           
 79           void XmlWriter::append(Array<Sint8>& out, Uint32 x)
 80           {
 81               char buffer[32];
 82               sprintf(buffer, "%d", x);
 83               append(out, buffer);
 84           }
 85 mike  1.1 
 86           void XmlWriter::append(Array<Sint8>& out, const char* str)
 87           {
 88               while (*str)
 89           	AppendChar(out, *str++);
 90           }
 91           
 92           void XmlWriter::appendSpecial(Array<Sint8>& out, Char16 x)
 93           {
 94               AppendSpecialChar(out, x);
 95           }
 96           
 97           void XmlWriter::appendSpecial(Array<Sint8>& out, char x)
 98           {
 99               AppendSpecialChar(out, Char16(x));
100           }
101           
102           void XmlWriter::appendSpecial(Array<Sint8>& out, const char* str)
103           {
104               while (*str)
105           	AppendSpecialChar(out, *str++);
106 mike  1.1 }
107           
108           void XmlWriter::appendSpecial(Array<Sint8>& out, const String& str)
109           {
110               const Char16* tmp = str.getData();
111           
112               while (*tmp)
113           	AppendSpecialChar(out, *tmp++);
114           }
115           
116           void XmlWriter::append(Array<Sint8>& out, const String& str)
117           {
118               const Char16* tmp = str.getData();
119           
120               while (*tmp)
121           	AppendChar(out, *tmp++);
122           }
123           
124           void XmlWriter::append(Array<Sint8>& out, const Indentor& x)
125           {
126               for (Uint32 i = 0; i < 4 * x.getLevel(); i++)
127 mike  1.1 	out.append(' ');
128           }
129           
130           void XmlWriter::appendLocalNameSpaceElement(
131               Array<Sint8>& out, 
132               const String& nameSpace)
133           {
134               out << "<LOCALNAMESPACEPATH>\n";
135           
136               char* tmp = nameSpace.allocateCString();
137           
138               for (char* p = strtok(tmp, "/"); p; p = strtok(NULL, "/"))
139               {
140           	out << "<NAMESPACE NAME=\"" << p << "\"/>\n";
141               }
142           
143               out << "</LOCALNAMESPACEPATH>\n";
144           }
145           
146           static inline void AppendSpecialChar(std::ostream& os, char c)
147           {
148 mike  1.1     switch (c)
149               {
150           	case '&':
151           	    os << "&amp;";
152           	    break;
153           
154           	case '<':
155           	    os << "&lt;";
156           	    break;
157           
158           	case '>':
159           	    os << "&gt;";
160           	    break;
161           
162           	case '"':
163           	    os << "&quot;";
164           	    break;
165           
166           	case '\'':
167           	    os << "&apos;";
168           	    break;
169 mike  1.1 
170           	default:
171           	    os << c;
172               }
173           }
174           
175           static inline void AppendSpecial(std::ostream& os, const char* str)
176           {
177               while (*str)
178           	AppendSpecialChar(os, *str++);
179           }
180           
181           //------------------------------------------------------------------------------
182           //
183           // formatGetHeader()
184           //
185           //------------------------------------------------------------------------------
186           
187           Array<Sint8> XmlWriter::formatGetHeader(
188               const char* documentPath)
189           {
190 mike  1.1     Array<Sint8> out;
191               return out << "GET " << documentPath << "HTTP/1.0\r\n\r\n";
192           }
193           
194           //------------------------------------------------------------------------------
195           //
196           // formatMPostHeader()
197           //
198           //     Build HTTP request header.
199           //
200           //------------------------------------------------------------------------------
201           
202           Array<Sint8> XmlWriter::formatMPostHeader(
203               const char* host,
204               const char* cimOperation,
205               const char* cimMethod,
206               const String& cimObject,
207               const Array<Sint8>& content)
208           {
209               Array<Sint8> out;
210               out.reserve(1024);
211 mike  1.1     char nn[] = { '0' + (rand() % 10), '0' + (rand() % 10), '\0' };
212           
213               out << "M-POST /cimom HTTP/1.1\r\n";
214               out << "HOST: " << host << "\r\n";
215               out << "Content-Type: application/xml; charset=\"utf-8\"\r\n";
216               out << "Content-Length: " << content.getSize() << "\r\n";
217               out << "Man: http://www.dmtf.org/cim/mapping/http/v1.0; ns=";
218               out << nn <<"\r\n";
219               out << nn << "-CIMOperation: " << cimOperation << "\r\n";
220               out << nn << "-CIMMethod: " << cimMethod << "\r\n";
221               out << nn << "-CIMObject: " << cimObject << "\r\n\r\n";
222               out << content;
223               return out;
224           }
225           
226           //------------------------------------------------------------------------------
227           //
228           // formatMethodResponseHeader()
229           //
230           //     Build HTTP response header.
231           //
232 mike  1.1 //------------------------------------------------------------------------------
233           
234           Array<Sint8> XmlWriter::formatMethodResponseHeader(
235               const Array<Sint8>& content)
236           {
237               Array<Sint8> out;
238               out.reserve(1024);
239               char nn[] = { '0' + (rand() % 10), '0' + (rand() % 10), '\0' };
240           
241               out << "HTTP/1.1 200 OK\r\n";
242               out << "Content-Type: application/xml; charset=\"utf-8\"\r\n";
243               out << "Content-Length: " << content.getSize() << "\r\n";
244               out << "Ext:\r\n";
245               out << "Cache-Control: no-cache\r\n";
246               out << "Man: http://www.dmtf.org/cim/mapping/http/v1.0; ns=";
247               out << nn <<"\r\n";
248               out << nn << "-CIMOperation: MethodResponse\r\n\r\n";
249               out << content;
250               return out;
251           }
252           
253 mike  1.1 //------------------------------------------------------------------------------
254           //
255           // formatMessageElement()
256           //
257           //     <!ELEMENT MESSAGE (SIMPLEREQ|MULTIREQ|SIMPLERSP|MULTIRSP)>
258           //     <!ATTLIST MESSAGE
259           //         ID CDATA #REQUIRED
260           //         PROTOCOLVERSION CDATA #REQUIRED>
261           //
262           //------------------------------------------------------------------------------
263           
264           Array<Sint8> XmlWriter::formatMessageElement(
265               Uint32 messageId,
266               const Array<Sint8>& body)
267           {
268               Array<Sint8> out;
269               out.reserve(1024);
270           
271               out << "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
272               out << "<CIM CIMVERSION=\"2.0\" DTDVERSION=\"2.0\">\n";
273               out << "<MESSAGE ID=\"" << messageId << "\" PROTOCOLVERSION=\"1.0\">\n";
274 mike  1.1     out << body;
275               out << "</MESSAGE>\n";
276               out << "</CIM>\n";
277               return out;
278           }
279           
280           //------------------------------------------------------------------------------
281           //
282           // formatSimpleReqElement()
283           //
284           //     <!ELEMENT SIMPLEREQ (IMETHODCALL|METHODCALL)>
285           //
286           //------------------------------------------------------------------------------
287           
288           Array<Sint8> XmlWriter::formatSimpleReqElement(
289               const Array<Sint8>& body)
290           {
291               Array<Sint8> out;
292               return out << "<SIMPLEREQ>\n" << body << "</SIMPLEREQ>\n";
293           }
294           
295 mike  1.1 //------------------------------------------------------------------------------
296           //
297           // formatSimpleRspElement()
298           //
299           //     <!ELEMENT SIMPLERSP (METHODRESPONSE|IMETHODRESPONSE)>
300           //
301           //------------------------------------------------------------------------------
302           
303           Array<Sint8> XmlWriter::formatSimpleRspElement(
304               const Array<Sint8>& body)
305           {
306               Array<Sint8> out;
307               return out << "<SIMPLERSP>\n" << body << "</SIMPLERSP>\n";
308           }
309           
310           //------------------------------------------------------------------------------
311           //
312           // formatIMethodCallElement()
313           //
314           //     <!ELEMENT IMETHODCALL (LOCALNAMESPACEPATH,IPARAMVALUE*)>
315           //     <!ATTLIST IMETHODCALL %CIMName;>
316 mike  1.1 //
317           //------------------------------------------------------------------------------
318           
319           Array<Sint8> XmlWriter::formatIMethodCallElement(
320               const char* name,
321               const String& nameSpace,
322               const Array<Sint8>& iParamValues)
323           {
324               Array<Sint8> out;
325               out << "<IMETHODCALL NAME=\"" << name << "\">\n";
326               XmlWriter::appendLocalNameSpaceElement(out, nameSpace);
327               out << iParamValues;
328               out << "</IMETHODCALL>\n";
329               return out;
330           }
331           
332           //------------------------------------------------------------------------------
333           //
334           // formatIMethodResponseElement()
335           //
336           //     <!ELEMENT IMETHODRESPONSE (ERROR|IRETURNVALUE?)>
337 mike  1.1 //     <!ATTLIST IMETHODRESPONSE %CIMName;>
338           //
339           //------------------------------------------------------------------------------
340           
341           Array<Sint8> XmlWriter::formatIMethodResponseElement(
342               const char* name,
343               const Array<Sint8>& body)
344           {
345               Array<Sint8> out;
346               out << "<IMETHODRESPONSE NAME=\"" << name << "\">\n";
347               out << body;
348               out << "</IMETHODRESPONSE>\n";
349               return out;
350           }
351           
352           //------------------------------------------------------------------------------
353           //
354           // formatIReturnValueElement()
355           //
356           //      <!ELEMENT IRETURNVALUE (CLASSNAME*|INSTANCENAME*|VALUE*|
357           //          VALUE.OBJECTWITHPATH*|VALUE.OBJECTWITHLOCALPATH*|VALUE.OBJECT*|
358 mike  1.1 //          OBJECTPATH*|QUALIFIER.DECLARATION*|VALUE.ARRAY?|VALUE.REFERENCE?|
359           //          CLASS*|INSTANCE*|VALUE.NAMEDINSTANCE*)>
360           //
361           //------------------------------------------------------------------------------
362           
363           Array<Sint8> XmlWriter::formatIReturnValueElement(
364               const Array<Sint8>& body)
365           {
366               Array<Sint8> out;
367               return out << "<IRETURNVALUE>\n" << body << "</IRETURNVALUE>\n";
368           }
369           
370           //------------------------------------------------------------------------------
371           //
372           // formatIParamValueElement()
373           //
374           //     <!ELEMENT IPARAMVALUE (VALUE|VALUE.ARRAY|VALUE.REFERENCE
375           //         |INSTANCENAME|CLASSNAME|QUALIFIER.DECLARATION
376           //         |CLASS|INSTANCE|VALUE.NAMEDINSTANCE)?>
377           //     <!ATTLIST IPARAMVALUE %CIMName;>
378           //
379 mike  1.1 //------------------------------------------------------------------------------
380           
381           Array<Sint8>& XmlWriter::formatIParamValueElement(
382               Array<Sint8>& out,
383               const char* name,
384               const Array<Sint8>& body)
385           {
386               out << "<IPARAMVALUE NAME=\"" << name << "\">\n";
387               out << body;
388               out << "</IPARAMVALUE>\n";
389               return out;
390           }
391           
392           //------------------------------------------------------------------------------
393           //
394           // formatErrorElement()
395           //
396           //------------------------------------------------------------------------------
397           
398           Array<Sint8> XmlWriter::formatErrorElement(
399               CimException::Code code,
400 mike  1.1     const char* description)
401           {
402               Array<Sint8> out;
403               out << "<ERROR";
404               out << " CODE=\"" << Uint32(code) << "\"";
405               out << " DESCRIPTION=\"";
406               appendSpecial(out, description);
407               out << "\"/>";
408               return out;
409           }
410           
411           //------------------------------------------------------------------------------
412           //
413           // appendBooleanParameter()
414           //
415           //------------------------------------------------------------------------------
416           
417           Array<Sint8>& XmlWriter::appendBooleanParameter(
418               Array<Sint8>& out,
419               const char* name,
420               Boolean flag)
421 mike  1.1 {
422               Array<Sint8> tmp;
423               tmp << "<VALUE>" << (flag ? "TRUE" : "FALSE") << "</VALUE>\n";
424               return formatIParamValueElement(out, name, tmp);
425           }
426           
427           //------------------------------------------------------------------------------
428           //
429           // appendClassNameParameter()
430           //
431           //------------------------------------------------------------------------------
432           
433           Array<Sint8>& XmlWriter::appendClassNameParameter(
434               Array<Sint8>& out,
435               const char* name,
436               const String& className)
437           {
438               Array<Sint8> tmp;
439               appendClassNameElement(tmp, className);
440               return formatIParamValueElement(out, name, tmp);
441           }
442 mike  1.1 
443           //------------------------------------------------------------------------------
444           //
445           // appendQualifierNameParameter()
446           //
447           //------------------------------------------------------------------------------
448           
449           Array<Sint8>& XmlWriter::appendQualifierNameParameter(
450               Array<Sint8>& out,
451               const char* name,
452               const String& qualifierName)
453           {
454               // <!ELEMENT IPARAMVALUE (VALUE|VALUE.ARRAY|VALUE.REFERENCE
455               //     |INSTANCENAME|CLASSNAME|QUALIFIER.DECLARATION
456               //     |CLASS|INSTANCE|VALUE.NAMEDINSTANCE)?>
457               //
458               // ATTN: notice that there is really no way to pass a qualifier name
459               // as an IPARAMVALUE element according to the spec (look above). So we
460               // just pass it as a class name. An answer must be obtained later.
461               
462               Array<Sint8> tmp;
463 mike  1.1     appendClassNameElement(tmp, qualifierName);
464               return formatIParamValueElement(out, name, tmp);
465           }
466           
467           //------------------------------------------------------------------------------
468           //
469           // appendClassParameter()
470           //
471           //------------------------------------------------------------------------------
472           
473           Array<Sint8>& XmlWriter::appendClassParameter(
474               Array<Sint8>& out,
475               const char* parameterName,
476               const ConstClassDecl& classDecl)
477           {
478               Array<Sint8> tmp;
479               classDecl.toXml(tmp);
480               return formatIParamValueElement(out, parameterName, tmp);
481           }
482           
483           //------------------------------------------------------------------------------
484 mike  1.1 //
485           // appendClassParameter()
486           //
487           //------------------------------------------------------------------------------
488           
489           Array<Sint8>& XmlWriter::appendQualifierDeclarationParameter(
490               Array<Sint8>& out,
491               const char* parameterName,
492               const ConstQualifierDecl& qualifierDecl)
493           {
494               Array<Sint8> tmp;
495               qualifierDecl.toXml(tmp);
496               return formatIParamValueElement(out, parameterName, tmp);
497           }
498           
499           //------------------------------------------------------------------------------
500           //
501           // appendClassNameElement()
502           //
503           //------------------------------------------------------------------------------
504           
505 mike  1.1 Array<Sint8>& XmlWriter::appendClassNameElement(
506               Array<Sint8>& out,
507               const String& className)
508           {
509               return out << "<CLASSNAME NAME=\"" << className << "\"/>\n";
510           }
511           
512           //------------------------------------------------------------------------------
513           //
514           // _printAttributes()
515           //
516           //------------------------------------------------------------------------------
517           
518           static void _printAttributes(
519               std::ostream& os,
520               const XmlAttribute* attributes,
521               Uint32 attributeCount)
522           {
523               for (Uint32 i = 0; i < attributeCount; i++)
524               {
525           	os << attributes[i].name << "=";
526 mike  1.1 
527           	os << '"';
528           	AppendSpecial(os, attributes[i].value);
529           	os << '"';
530           
531           	if (i + 1 != attributeCount)
532           	    os << ' ';
533               }
534           }
535           
536           //------------------------------------------------------------------------------
537           //
538           // _indent()
539           //
540           //------------------------------------------------------------------------------
541           
542           static void _indent(std::ostream& os, Uint32 level, Uint32 indentChars)
543           {
544               Uint32 n = level * indentChars;
545           
546               for (Uint32 i = 0; i < n; i++)
547 mike  1.1 	os << ' ';
548           }
549           
550           //------------------------------------------------------------------------------
551           //
552           // indentedPrint()
553           //
554           //------------------------------------------------------------------------------
555           
556           void XmlWriter::indentedPrint(
557               std::ostream& os, 
558               const char* text, 
559               Uint32 indentChars)
560           {
561               char* tmp = strcpy(new char[strlen(text) + 1], text);
562           
563               XmlParser parser(tmp);
564               XmlEntry entry;
565               Stack<const char*> stack;
566           
567               while (parser.next(entry))
568 mike  1.1     {
569           	switch (entry.type)
570           	{
571           	    case XmlEntry::XML_DECLARATION:
572           	    {
573           		_indent(os, stack.getSize(), indentChars);
574           
575           		os << "<?" << entry.text << " ";
576           		_printAttributes(os, entry.attributes, entry.attributeCount);
577           		os << "?>";
578           		break;
579           	    }
580           
581           	    case XmlEntry::START_TAG:
582           	    {
583           		_indent(os, stack.getSize(), indentChars);
584           
585           		os << "<" << entry.text;
586           
587           		if (entry.attributeCount)
588           		    os << ' ';
589 mike  1.1 
590           		_printAttributes(os, entry.attributes, entry.attributeCount);
591           		os << ">";
592           		stack.push(entry.text);
593           		break;
594           	    }
595           
596           	    case XmlEntry::EMPTY_TAG:
597           	    {
598           		_indent(os, stack.getSize(), indentChars);
599           
600           		os << "<" << entry.text << " ";
601           		_printAttributes(os, entry.attributes, entry.attributeCount);
602           		os << "/>";
603           		break;
604           	    }
605           
606           	    case XmlEntry::END_TAG:
607           	    {
608           		if (!stack.isEmpty() && strcmp(stack.top(), entry.text) == 0)
609           		    stack.pop();
610 mike  1.1 
611           		_indent(os, stack.getSize(), indentChars);
612           
613           		os << "</" << entry.text << ">";
614           		break;
615           	    }
616           
617           	    case XmlEntry::COMMENT:
618           	    {
619           
620           		_indent(os, stack.getSize(), indentChars);
621           		os << "<!--";
622           		AppendSpecial(os, entry.text);
623           		os << "-->";
624           		break;
625           	    }
626           
627           	    case XmlEntry::CONTENT:
628           	    {
629           		_indent(os, stack.getSize(), indentChars);
630           		AppendSpecial(os, entry.text);
631 mike  1.1 		break;
632           	    }
633           
634           	    case XmlEntry::CDATA:
635           	    {
636           		_indent(os, stack.getSize(), indentChars);
637           		os << "<![CDATA[...]]>";
638           		break;
639           	    }
640           
641           	    case XmlEntry::DOCTYPE:
642           	    {
643           		_indent(os, stack.getSize(), indentChars);
644           		os << "<!DOCTYPE...>";
645           		break;
646           	    }
647           	}
648           
649           	os << std::endl;
650               }
651           
652 mike  1.1     delete [] tmp;
653           }
654           
655           //------------------------------------------------------------------------------
656           //
657           // XmlWriter::getNextMessageId()
658           //
659           //------------------------------------------------------------------------------
660           
661           Uint32 XmlWriter::getNextMessageId()
662           {
663               // ATTN: make thread-safe:
664               static Uint32 messageId = 1000;
665           
666               messageId++;
667           
668               if (messageId < 1000)
669           	messageId = 1001;
670           
671               return messageId;
672           }
673 mike  1.1 
674           //------------------------------------------------------------------------------
675           //
676           // XmlWriter::formatSimpleReqMessage()
677           //
678           //------------------------------------------------------------------------------
679           
680           Array<Sint8> XmlWriter::formatSimpleReqMessage(
681               const char* host,
682               const String& nameSpace,
683               const char* iMethodName,
684               const Array<Sint8>& body)
685           {
686               return XmlWriter::formatMPostHeader(
687           	host,
688           	"MethodCall",
689           	iMethodName,
690           	nameSpace,
691           	XmlWriter::formatMessageElement(
692           	    XmlWriter::getNextMessageId(),
693           	    XmlWriter::formatSimpleReqElement(
694 mike  1.1 		XmlWriter::formatIMethodCallElement(
695           		    iMethodName,
696           		    nameSpace, 
697           		    body))));
698           }
699           
700           Array<Sint8> XmlWriter::formatSimpleRspMessage(
701               const char* iMethodName,
702               const Array<Sint8>& body)
703           {
704               return XmlWriter::formatMethodResponseHeader(
705                   XmlWriter::formatMessageElement(
706           	    XmlWriter::getNextMessageId(),
707                       XmlWriter::formatSimpleRspElement(
708                           XmlWriter::formatIMethodResponseElement(
709                               iMethodName,
710                               XmlWriter::formatIReturnValueElement(body)))));
711           }
712           
713           PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2