Changeset 17362 in vbox
- Timestamp:
- Mar 4, 2009 6:10:58 PM (16 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/xml.h
r16539 r17362 139 139 { 140 140 public: 141 142 141 XmlError(xmlErrorPtr aErr); 143 142 … … 151 150 { 152 151 public: 153 154 ENotImplemented (const char *aMsg = NULL) : LogicError (aMsg) {} 155 ENotImplemented (RT_SRC_POS_DECL) : LogicError (RT_SRC_POS_ARGS) {} 152 ENotImplemented(const char *aMsg = NULL) : LogicError(aMsg) {} 153 ENotImplemented(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {} 156 154 }; 157 155 … … 159 157 { 160 158 public: 161 162 EInvalidArg (const char *aMsg = NULL) : LogicError (aMsg) {} 163 EInvalidArg (RT_SRC_POS_DECL) : LogicError (RT_SRC_POS_ARGS) {} 159 EInvalidArg(const char *aMsg = NULL) : LogicError(aMsg) {} 160 EInvalidArg(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {} 161 }; 162 163 class VBOXXML_CLASS EDocumentNotEmpty : public LogicError 164 { 165 public: 166 EDocumentNotEmpty(const char *aMsg = NULL) : LogicError(aMsg) {} 167 EDocumentNotEmpty(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {} 164 168 }; 165 169 … … 170 174 { 171 175 public: 172 173 ENoMemory (const char *aMsg = NULL) : RuntimeError (aMsg) {} 176 ENoMemory(const char *aMsg = NULL) : RuntimeError (aMsg) {} 174 177 virtual ~ENoMemory() throw() {} 175 178 }; … … 321 324 322 325 /** 323 * Destr roys the File object. If the object was created from a file name326 * Destroys the File object. If the object was created from a file name 324 327 * the corresponding file will be automatically closed. If the object was 325 328 * created from a file handle, it will remain open. … … 418 421 419 422 /* 420 * Node 421 * 423 * Node: 424 * an XML node, which represents either an element or an attribute. 425 * 426 * For elements, getName() returns the element name, and getValue() 427 * returns the text contents, if any. 428 * 429 * For attributes, getName() returns the attribute name, and getValue() 430 * returns the attribute value, if any. 431 * 432 * Since the default constructor is private, one can create new nodes 433 * only through factory methods provided by the XML classes. These are: 434 * 435 * -- xml::Document::createRootElement() 436 * -- xml::Node::createChild() 437 * -- xml::Node::setAttribute() 422 438 */ 423 439 … … 428 444 { 429 445 public: 430 Node();431 446 ~Node(); 432 447 … … 451 466 bool getAttributeValue(const char *pcszMatch, uint64_t &i) const; 452 467 453 private: 468 Node* createChild(const char *pcszElementName); 469 Node* setAttribute(const char *pcszName, const char *pcszValue); 470 471 private: 472 // hide the default constructor so people use only our factory methods 473 Node(); 474 454 475 friend class Document; 455 476 friend class XmlFileParser; … … 477 498 478 499 private: 500 /* Obscure class data */ 479 501 struct Data; 480 502 Data *m; … … 491 513 Document(); 492 514 ~Document(); 515 493 516 Document(const Document &x); 494 517 Document& operator=(const Document &x); … … 496 519 const Node* getRootElement() const; 497 520 521 Node* createRootElement(const char *pcszRootElementName); 522 498 523 private: 499 524 friend class XmlFileParser; 525 friend class XmlFileWriter; 500 526 501 527 void refreshInternals(); … … 539 565 540 566 static int ReadCallback(void *aCtxt, char *aBuf, int aLen); 541 542 567 static int CloseCallback (void *aCtxt); 543 568 }; 544 569 545 570 /* 571 * XmlFileWriter 572 * 573 */ 574 575 class VBOXXML_CLASS XmlFileWriter 576 { 577 public: 578 XmlFileWriter(Document &doc); 579 ~XmlFileWriter(); 580 581 void write(const char *pcszFilename); 582 583 static int WriteCallback(void *aCtxt, const char *aBuf, int aLen); 584 static int CloseCallback (void *aCtxt); 585 586 private: 587 /* Obscure class data */ 588 struct Data; 589 Data *m; 590 }; 546 591 547 592 #if defined(_MSC_VER) -
trunk/src/VBox/Main/ApplianceImpl.cpp
r17343 r17362 115 115 struct Appliance::Data 116 116 { 117 Bstr bstrPath;117 Utf8Str strPath; // file name last given to either read() or write() 118 118 119 119 DiskImagesMap mapDisks; // map of DiskImage structs, sorted by DiskImage.strDiskId … … 938 938 AutoReadLock alock(this); 939 939 940 m->bstrPath.cloneTo(aPath); 940 Bstr bstrPath(m->strPath); 941 bstrPath.cloneTo(aPath); 941 942 942 943 return S_OK; … … 1226 1227 1227 1228 AutoWriteLock alock(this); 1228 m->bstrPath = path;1229 1229 1230 1230 // see if we can handle this file; for now we insist it has an ".ovf" extension 1231 Utf8Str utf8Path(path);1232 const char *pcszLastDot = strrchr( utf8Path, '.');1231 m->strPath = path; 1232 const char *pcszLastDot = strrchr(m->strPath, '.'); 1233 1233 if ( (!pcszLastDot) 1234 1234 || ( strcmp(pcszLastDot, ".ovf") … … 1243 1243 xml::XmlFileParser parser; 1244 1244 xml::Document doc; 1245 parser.read( utf8Path.raw(),1245 parser.read(m->strPath.raw(), 1246 1246 doc); 1247 1247 … … 1267 1267 1268 1268 // now go though the sections 1269 if (!(SUCCEEDED(rc = LoopThruSections( utf8Path.raw(), pReferencesElem, pRootElem))))1269 if (!(SUCCEEDED(rc = LoopThruSections(m->strPath.raw(), pReferencesElem, pRootElem)))) 1270 1270 return rc; 1271 1271 } … … 1654 1654 { 1655 1655 uint32_t opCount = calcMaxProgress(); 1656 Bstr progressDesc = BstrFmt(tr("Import appliance '% ls'"),1657 m-> bstrPath.raw());1656 Bstr progressDesc = BstrFmt(tr("Import appliance '%s'"), 1657 m->strPath.raw()); 1658 1658 /* Create the progress object */ 1659 1659 progress.createObject(); … … 1695 1695 if (FAILED(rc = autoCaller.rc())) return rc; 1696 1696 1697 AutoReadLock(this); 1697 AutoWriteLock(this); 1698 1699 // see if we can handle this file; for now we insist it has an ".ovf" extension 1700 m->strPath = path; 1701 const char *pcszLastDot = strrchr(m->strPath, '.'); 1702 if ( (!pcszLastDot) 1703 || ( strcmp(pcszLastDot, ".ovf") 1704 && strcmp(pcszLastDot, ".OVF") 1705 ) 1706 ) 1707 return setError(VBOX_E_FILE_ERROR, 1708 tr("Appliance file must have .ovf extension")); 1698 1709 1699 1710 ComObjPtr<Progress> progress; … … 1701 1712 { 1702 1713 uint32_t opCount = calcMaxProgress(); 1703 Bstr progressDesc = BstrFmt(tr("Write appliance '% ls'"),1704 m-> bstrPath.raw());1714 Bstr progressDesc = BstrFmt(tr("Write appliance '%s'"), 1715 m->strPath.raw()); 1705 1716 /* Create the progress object */ 1706 1717 progress.createObject(); … … 2103 2114 /* The disk image has to be on the same place as the OVF file. So 2104 2115 * strip the filename out of the full file path. */ 2105 Utf8Str strSrcDir = stripFilename( Utf8Str(pAppliance->m->bstrPath).raw());2116 Utf8Str strSrcDir = stripFilename(pAppliance->m->strPath); 2106 2117 2107 2118 /* Iterate over all given disk images */ … … 2443 2454 try 2444 2455 { 2456 xml::Document doc; 2457 doc.createRootElement("Envelope"); 2458 2459 xml::XmlFileWriter writer(doc); 2460 writer.write(pAppliance->m->strPath.c_str()); 2445 2461 } 2446 2462 catch(HRESULT aRC) -
trunk/src/VBox/Main/xml/xml.cpp
r16538 r17362 4 4 5 5 /* 6 * Copyright (C) 2007-200 8Sun Microsystems, Inc.6 * Copyright (C) 2007-2009 Sun Microsystems, Inc. 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 42 42 #include "VBox/xml.h" 43 43 44 //////////////////////////////////////////////////////////////////////////////// 45 // 46 // globals 47 // 48 //////////////////////////////////////////////////////////////////////////////// 44 49 45 50 /** … … 94 99 { 95 100 96 ////////////////////////////////////////////////////////////////////////////// 101 //////////////////////////////////////////////////////////////////////////////// 102 // 97 103 // Exceptions 98 ////////////////////////////////////////////////////////////////////////////// 104 // 105 //////////////////////////////////////////////////////////////////////////////// 99 106 100 107 LogicError::LogicError(RT_SRC_POS_DECL) … … 111 118 { 112 119 if (!aErr) 113 throw EInvalidArg 120 throw EInvalidArg(RT_SRC_POS); 114 121 115 122 char *msg = Format(aErr); … … 148 155 } 149 156 150 ////////////////////////////////////////////////////////////////////////////// 157 //////////////////////////////////////////////////////////////////////////////// 158 // 151 159 // File Class 160 // 152 161 ////////////////////////////////////////////////////////////////////////////// 153 162 … … 283 292 } 284 293 285 ////////////////////////////////////////////////////////////////////////////// 294 //////////////////////////////////////////////////////////////////////////////// 295 // 286 296 // MemoryBuf Class 297 // 287 298 ////////////////////////////////////////////////////////////////////////////// 288 299 … … 349 360 } 350 361 351 / *352 * GlobalLock 353 * 354 * 355 */362 //////////////////////////////////////////////////////////////////////////////// 363 // 364 // GlobalLock class 365 // 366 //////////////////////////////////////////////////////////////////////////////// 356 367 357 368 struct GlobalLock::Data … … 392 403 } 393 404 394 / *395 * Node 396 * 397 * 398 */405 //////////////////////////////////////////////////////////////////////////////// 406 // 407 // Node class 408 // 409 //////////////////////////////////////////////////////////////////////////////// 399 410 400 411 struct Node::Data 401 412 { 402 413 xmlNode *plibNode; // != NULL if this is an element 403 xmlAttr *plibAttr; // != NULL if this is an element404 405 Node *pParent;// NULL only for the root element414 xmlAttr *plibAttr; // != NULL if this is an attribute 415 416 Node *pParent; // NULL only for the root element 406 417 const char *pcszName; // points either into plibNode or plibAttr 407 418 … … 790 801 } 791 802 792 / *793 * Document 794 * 795 * 796 */803 //////////////////////////////////////////////////////////////////////////////// 804 // 805 // Document class 806 // 807 //////////////////////////////////////////////////////////////////////////////// 797 808 798 809 struct Document::Data 799 810 { 800 xmlDocPtr p Document;801 Node *pRootElement;811 xmlDocPtr plibDocument; 812 Node *pRootElement; 802 813 803 814 Data() 804 815 { 805 p Document = NULL;816 plibDocument = NULL; 806 817 pRootElement = NULL; 807 818 } … … 814 825 void reset() 815 826 { 816 if (p Document)827 if (plibDocument) 817 828 { 818 xmlFreeDoc(p Document);819 p Document = NULL;829 xmlFreeDoc(plibDocument); 830 plibDocument = NULL; 820 831 } 821 832 if (pRootElement) … … 828 839 void copyFrom(const Document::Data *p) 829 840 { 830 if (p->p Document)841 if (p->plibDocument) 831 842 { 832 p Document = xmlCopyDoc(p->pDocument,833 1); // recursive == copy all843 plibDocument = xmlCopyDoc(p->plibDocument, 844 1); // recursive == copy all 834 845 } 835 846 } … … 867 878 { 868 879 m->pRootElement = new Node(); 869 m->pRootElement->m->plibNode = xmlDocGetRootElement(m->p Document);880 m->pRootElement->m->plibNode = xmlDocGetRootElement(m->plibDocument); 870 881 m->pRootElement->m->pcszName = (const char*)m->pRootElement->m->plibNode->name; 871 882 … … 873 884 } 874 885 886 /** 887 * Returns the root element of the document, or NULL if the document is empty. 888 * @return 889 */ 875 890 const Node* Document::getRootElement() const 876 891 { … … 878 893 } 879 894 880 /* 881 * XmlParserBase 882 * 883 * 884 */ 895 /** 896 * Creates a new element node and sets it as the root element. This will 897 * only work if the document is empty; otherwise EDocumentNotEmpty is thrown. 898 */ 899 Node* Document::createRootElement(const char *pcszRootElementName) 900 { 901 if (m->pRootElement) 902 throw EDocumentNotEmpty(RT_SRC_POS); 903 904 m->plibDocument = xmlNewDoc((const xmlChar*)"1.0"); 905 if (!(m->pRootElement = new Node())) 906 throw ENoMemory(); 907 Node::Data *pNodeData = m->pRootElement->m; 908 if (!(pNodeData->plibNode = xmlNewNode(NULL, // namespace 909 (const xmlChar*)pcszRootElementName))) 910 throw ENoMemory(); 911 pNodeData->pcszName = (const char*)pNodeData->plibNode->name; 912 913 return m->pRootElement; 914 } 915 916 //////////////////////////////////////////////////////////////////////////////// 917 // 918 // XmlParserBase class 919 // 920 //////////////////////////////////////////////////////////////////////////////// 885 921 886 922 XmlParserBase::XmlParserBase() … … 897 933 } 898 934 899 / *900 * XmlFileParser 901 * 902 * 903 */935 //////////////////////////////////////////////////////////////////////////////// 936 // 937 // XmlFileParser class 938 // 939 //////////////////////////////////////////////////////////////////////////////// 904 940 905 941 struct XmlFileParser::Data … … 931 967 } 932 968 933 struct Read Context969 struct ReadWriteContext 934 970 { 935 971 File file; 936 972 com::Utf8Str error; 937 973 938 Read Context(const char *pcszFilename)939 : file(File::Mode_Read, pcszFilename) 974 ReadWriteContext(const char *pcszFilename) 975 : file(File::Mode_Read, pcszFilename) // @todo must be write for writer 940 976 { 941 977 } … … 969 1005 m->strXmlFilename = pcszFilename; 970 1006 971 Read Context context(pcszFilename);1007 ReadWriteContext context(pcszFilename); 972 1008 doc.m->reset(); 973 if (!(doc.m->p Document = xmlCtxtReadIO(m->ctxt,974 ReadCallback,975 CloseCallback,976 &context,977 pcszFilename,978 NULL, // encoding = auto979 XML_PARSE_NOBLANKS)))1009 if (!(doc.m->plibDocument = xmlCtxtReadIO(m->ctxt, 1010 ReadCallback, 1011 CloseCallback, 1012 &context, 1013 pcszFilename, 1014 NULL, // encoding = auto 1015 XML_PARSE_NOBLANKS))) 980 1016 throw XmlError(xmlCtxtGetLastError(m->ctxt)); 981 1017 … … 986 1022 int XmlFileParser::ReadCallback(void *aCtxt, char *aBuf, int aLen) 987 1023 { 988 Read Context *pContext = static_cast<ReadContext*>(aCtxt);1024 ReadWriteContext *pContext = static_cast<ReadWriteContext*>(aCtxt); 989 1025 990 1026 /* To prevent throwing exceptions while inside libxml2 code, we catch … … 1010 1046 } 1011 1047 1048 //////////////////////////////////////////////////////////////////////////////// 1049 // 1050 // XmlFileWriter class 1051 // 1052 //////////////////////////////////////////////////////////////////////////////// 1053 1054 struct XmlFileWriter::Data 1055 { 1056 Document *pDoc; 1057 }; 1058 1059 XmlFileWriter::XmlFileWriter(Document &doc) 1060 { 1061 m = new Data(); 1062 m->pDoc = &doc; 1063 } 1064 1065 XmlFileWriter::~XmlFileWriter() 1066 { 1067 delete m; 1068 } 1069 1070 int XmlFileWriter::WriteCallback(void *aCtxt, const char *aBuf, int aLen) 1071 { 1072 ReadWriteContext *pContext = static_cast<ReadWriteContext*>(aCtxt); 1073 1074 /* To prevent throwing exceptions while inside libxml2 code, we catch 1075 * them and forward to our level using a couple of variables. */ 1076 try 1077 { 1078 return pContext->file.write(aBuf, aLen); 1079 } 1080 catch (const xml::EIPRTFailure &err) { pContext->setError(err); } 1081 catch (const xml::Error &err) { pContext->setError(err); } 1082 catch (const std::exception &err) { pContext->setError(err); } 1083 catch (...) { pContext->setError(xml::LogicError(RT_SRC_POS)); } 1084 1085 return -1 /* failure */; 1086 } 1087 1088 int XmlFileWriter::CloseCallback(void *aCtxt) 1089 { 1090 /// @todo to be written 1091 1092 return -1; 1093 } 1094 1095 void XmlFileWriter::write(const char *pcszFilename) 1096 { 1097 ReadWriteContext context(pcszFilename); 1098 1099 GlobalLock lock(); 1100 1101 /* serialize to the stream */ 1102 xmlIndentTreeOutput = 1; 1103 xmlTreeIndentString = " "; 1104 xmlSaveNoEmptyTags = 0; 1105 1106 xmlSaveCtxtPtr saveCtxt; 1107 if (!(saveCtxt = xmlSaveToIO(WriteCallback, 1108 CloseCallback, 1109 &context, 1110 NULL, 1111 XML_SAVE_FORMAT))) 1112 throw xml::LogicError(RT_SRC_POS); 1113 1114 long rc = xmlSaveDoc(saveCtxt, m->pDoc->m->plibDocument); 1115 if (rc == -1) 1116 { 1117 /* look if there was a forwared exception from the lower level */ 1118 // if (m->trappedErr.get() != NULL) 1119 // m->trappedErr->rethrow(); 1120 1121 /* there must be an exception from the Output implementation, 1122 * otherwise the save operation must always succeed. */ 1123 throw xml::LogicError(RT_SRC_POS); 1124 } 1125 1126 xmlSaveClose(saveCtxt); 1127 } 1128 1012 1129 1013 1130 } // end namespace xml
Note:
See TracChangeset
for help on using the changeset viewer.