VirtualBox

Changeset 17362 in vbox


Ignore:
Timestamp:
Mar 4, 2009 6:10:58 PM (16 years ago)
Author:
vboxsync
Message:

OVF: partial implementation of write support in XML classes.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/xml.h

    r16539 r17362  
    139139{
    140140public:
    141 
    142141    XmlError(xmlErrorPtr aErr);
    143142
     
    151150{
    152151public:
    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) {}
    156154};
    157155
     
    159157{
    160158public:
    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
     163class VBOXXML_CLASS EDocumentNotEmpty : public LogicError
     164{
     165public:
     166    EDocumentNotEmpty(const char *aMsg = NULL) : LogicError(aMsg) {}
     167    EDocumentNotEmpty(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
    164168};
    165169
     
    170174{
    171175public:
    172 
    173     ENoMemory (const char *aMsg = NULL) : RuntimeError (aMsg) {}
     176    ENoMemory(const char *aMsg = NULL) : RuntimeError (aMsg) {}
    174177    virtual ~ENoMemory() throw() {}
    175178};
     
    321324
    322325    /**
    323      * Destrroys the File object. If the object was created from a file name
     326     * Destroys the File object. If the object was created from a file name
    324327     * the corresponding file will be automatically closed. If the object was
    325328     * created from a file handle, it will remain open.
     
    418421
    419422/*
    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()
    422438 */
    423439
     
    428444{
    429445public:
    430     Node();
    431446    ~Node();
    432447
     
    451466    bool getAttributeValue(const char *pcszMatch, uint64_t &i) const;
    452467
    453 private:
     468    Node* createChild(const char *pcszElementName);
     469    Node* setAttribute(const char *pcszName, const char *pcszValue);
     470
     471private:
     472    // hide the default constructor so people use only our factory methods
     473    Node();
     474
    454475    friend class Document;
    455476    friend class XmlFileParser;
     
    477498
    478499private:
     500    /* Obscure class data */
    479501    struct Data;
    480502    Data *m;
     
    491513    Document();
    492514    ~Document();
     515
    493516    Document(const Document &x);
    494517    Document& operator=(const Document &x);
     
    496519    const Node* getRootElement() const;
    497520
     521    Node* createRootElement(const char *pcszRootElementName);
     522
    498523private:
    499524    friend class XmlFileParser;
     525    friend class XmlFileWriter;
    500526
    501527    void refreshInternals();
     
    539565
    540566    static int ReadCallback(void *aCtxt, char *aBuf, int aLen);
    541 
    542567    static int CloseCallback (void *aCtxt);
    543568};
    544569
    545 
     570/*
     571 * XmlFileWriter
     572 *
     573 */
     574
     575class VBOXXML_CLASS XmlFileWriter
     576{
     577public:
     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
     586private:
     587    /* Obscure class data */
     588    struct Data;
     589    Data *m;
     590};
    546591
    547592#if defined(_MSC_VER)
  • trunk/src/VBox/Main/ApplianceImpl.cpp

    r17343 r17362  
    115115struct Appliance::Data
    116116{
    117     Bstr bstrPath;
     117    Utf8Str                 strPath;            // file name last given to either read() or write()
    118118
    119119    DiskImagesMap           mapDisks;           // map of DiskImage structs, sorted by DiskImage.strDiskId
     
    938938    AutoReadLock alock(this);
    939939
    940     m->bstrPath.cloneTo(aPath);
     940    Bstr bstrPath(m->strPath);
     941    bstrPath.cloneTo(aPath);
    941942
    942943    return S_OK;
     
    12261227
    12271228    AutoWriteLock alock(this);
    1228     m->bstrPath = path;
    12291229
    12301230    // 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, '.');
    12331233    if (    (!pcszLastDot)
    12341234         || (    strcmp(pcszLastDot, ".ovf")
     
    12431243        xml::XmlFileParser parser;
    12441244        xml::Document doc;
    1245         parser.read(utf8Path.raw(),
     1245        parser.read(m->strPath.raw(),
    12461246                    doc);
    12471247
     
    12671267
    12681268        // now go though the sections
    1269         if (!(SUCCEEDED(rc = LoopThruSections(utf8Path.raw(), pReferencesElem, pRootElem))))
     1269        if (!(SUCCEEDED(rc = LoopThruSections(m->strPath.raw(), pReferencesElem, pRootElem))))
    12701270            return rc;
    12711271    }
     
    16541654    {
    16551655        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());
    16581658        /* Create the progress object */
    16591659        progress.createObject();
     
    16951695    if (FAILED(rc = autoCaller.rc())) return rc;
    16961696
    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"));
    16981709
    16991710    ComObjPtr<Progress> progress;
     
    17011712    {
    17021713        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());
    17051716        /* Create the progress object */
    17061717        progress.createObject();
     
    21032114                    /* The disk image has to be on the same place as the OVF file. So
    21042115                     * 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);
    21062117
    21072118                    /* Iterate over all given disk images */
     
    24432454    try
    24442455    {
     2456        xml::Document doc;
     2457        doc.createRootElement("Envelope");
     2458
     2459        xml::XmlFileWriter writer(doc);
     2460        writer.write(pAppliance->m->strPath.c_str());
    24452461    }
    24462462    catch(HRESULT aRC)
  • trunk/src/VBox/Main/xml/xml.cpp

    r16538 r17362  
    44
    55/*
    6  * Copyright (C) 2007-2008 Sun Microsystems, Inc.
     6 * Copyright (C) 2007-2009 Sun Microsystems, Inc.
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4242#include "VBox/xml.h"
    4343
     44////////////////////////////////////////////////////////////////////////////////
     45//
     46// globals
     47//
     48////////////////////////////////////////////////////////////////////////////////
    4449
    4550/**
     
    9499{
    95100
    96 //////////////////////////////////////////////////////////////////////////////
     101////////////////////////////////////////////////////////////////////////////////
     102//
    97103// Exceptions
    98 //////////////////////////////////////////////////////////////////////////////
     104//
     105////////////////////////////////////////////////////////////////////////////////
    99106
    100107LogicError::LogicError(RT_SRC_POS_DECL)
     
    111118{
    112119    if (!aErr)
    113         throw EInvalidArg (RT_SRC_POS);
     120        throw EInvalidArg(RT_SRC_POS);
    114121
    115122    char *msg = Format(aErr);
     
    148155}
    149156
    150 //////////////////////////////////////////////////////////////////////////////
     157////////////////////////////////////////////////////////////////////////////////
     158//
    151159// File Class
     160//
    152161//////////////////////////////////////////////////////////////////////////////
    153162
     
    283292}
    284293
    285 //////////////////////////////////////////////////////////////////////////////
     294////////////////////////////////////////////////////////////////////////////////
     295//
    286296// MemoryBuf Class
     297//
    287298//////////////////////////////////////////////////////////////////////////////
    288299
     
    349360}
    350361
    351 /*
    352  * GlobalLock
    353  *
    354  *
    355  */
     362////////////////////////////////////////////////////////////////////////////////
     363//
     364// GlobalLock class
     365//
     366////////////////////////////////////////////////////////////////////////////////
    356367
    357368struct GlobalLock::Data
     
    392403}
    393404
    394 /*
    395  * Node
    396  *
    397  *
    398  */
     405////////////////////////////////////////////////////////////////////////////////
     406//
     407// Node class
     408//
     409////////////////////////////////////////////////////////////////////////////////
    399410
    400411struct Node::Data
    401412{
    402413    xmlNode     *plibNode;          // != NULL if this is an element
    403     xmlAttr     *plibAttr;          // != NULL if this is an element
    404 
    405     Node     *pParent;       // NULL only for the root element
     414    xmlAttr     *plibAttr;          // != NULL if this is an attribute
     415
     416    Node        *pParent;           // NULL only for the root element
    406417    const char  *pcszName;          // points either into plibNode or plibAttr
    407418
     
    790801}
    791802
    792 /*
    793  * Document
    794  *
    795  *
    796  */
     803////////////////////////////////////////////////////////////////////////////////
     804//
     805// Document class
     806//
     807////////////////////////////////////////////////////////////////////////////////
    797808
    798809struct Document::Data
    799810{
    800     xmlDocPtr   pDocument;
    801     Node     *pRootElement;
     811    xmlDocPtr   plibDocument;
     812    Node        *pRootElement;
    802813
    803814    Data()
    804815    {
    805         pDocument = NULL;
     816        plibDocument = NULL;
    806817        pRootElement = NULL;
    807818    }
     
    814825    void reset()
    815826    {
    816         if (pDocument)
     827        if (plibDocument)
    817828        {
    818             xmlFreeDoc(pDocument);
    819             pDocument = NULL;
     829            xmlFreeDoc(plibDocument);
     830            plibDocument = NULL;
    820831        }
    821832        if (pRootElement)
     
    828839    void copyFrom(const Document::Data *p)
    829840    {
    830         if (p->pDocument)
     841        if (p->plibDocument)
    831842        {
    832             pDocument = xmlCopyDoc(p->pDocument,
    833                                    1);      // recursive == copy all
     843            plibDocument = xmlCopyDoc(p->plibDocument,
     844                                      1);      // recursive == copy all
    834845        }
    835846    }
     
    867878{
    868879    m->pRootElement = new Node();
    869     m->pRootElement->m->plibNode = xmlDocGetRootElement(m->pDocument);
     880    m->pRootElement->m->plibNode = xmlDocGetRootElement(m->plibDocument);
    870881    m->pRootElement->m->pcszName = (const char*)m->pRootElement->m->plibNode->name;
    871882
     
    873884}
    874885
     886/**
     887 * Returns the root element of the document, or NULL if the document is empty.
     888 * @return
     889 */
    875890const Node* Document::getRootElement() const
    876891{
     
    878893}
    879894
    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 */
     899Node* 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////////////////////////////////////////////////////////////////////////////////
    885921
    886922XmlParserBase::XmlParserBase()
     
    897933}
    898934
    899 /*
    900  * XmlFileParser
    901  *
    902  *
    903  */
     935////////////////////////////////////////////////////////////////////////////////
     936//
     937// XmlFileParser class
     938//
     939////////////////////////////////////////////////////////////////////////////////
    904940
    905941struct XmlFileParser::Data
     
    931967}
    932968
    933 struct ReadContext
     969struct ReadWriteContext
    934970{
    935971    File file;
    936972    com::Utf8Str error;
    937973
    938     ReadContext(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
    940976    {
    941977    }
     
    9691005    m->strXmlFilename = pcszFilename;
    9701006
    971     ReadContext context(pcszFilename);
     1007    ReadWriteContext context(pcszFilename);
    9721008    doc.m->reset();
    973     if (!(doc.m->pDocument = xmlCtxtReadIO(m->ctxt,
    974                                            ReadCallback,
    975                                            CloseCallback,
    976                                            &context,
    977                                            pcszFilename,
    978                                            NULL,       // encoding = auto
    979                                            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)))
    9801016        throw XmlError(xmlCtxtGetLastError(m->ctxt));
    9811017
     
    9861022int XmlFileParser::ReadCallback(void *aCtxt, char *aBuf, int aLen)
    9871023{
    988     ReadContext *pContext = static_cast<ReadContext*>(aCtxt);
     1024    ReadWriteContext *pContext = static_cast<ReadWriteContext*>(aCtxt);
    9891025
    9901026    /* To prevent throwing exceptions while inside libxml2 code, we catch
     
    10101046}
    10111047
     1048////////////////////////////////////////////////////////////////////////////////
     1049//
     1050// XmlFileWriter class
     1051//
     1052////////////////////////////////////////////////////////////////////////////////
     1053
     1054struct XmlFileWriter::Data
     1055{
     1056    Document *pDoc;
     1057};
     1058
     1059XmlFileWriter::XmlFileWriter(Document &doc)
     1060{
     1061    m = new Data();
     1062    m->pDoc = &doc;
     1063}
     1064
     1065XmlFileWriter::~XmlFileWriter()
     1066{
     1067    delete m;
     1068}
     1069
     1070int 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
     1088int XmlFileWriter::CloseCallback(void *aCtxt)
     1089{
     1090    /// @todo to be written
     1091
     1092    return -1;
     1093}
     1094
     1095void 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
    10121129
    10131130} // end namespace xml
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette