From c5183613326e3d36a544b2941654d0667a29b836 Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Fri, 17 Mar 2006 05:45:33 +0000 Subject: [PATCH] Merged marshalling/unmarshalling methods into core interface. --- xmltooling/AbstractDOMCachingXMLObject.cpp | 25 +-- xmltooling/AbstractDOMCachingXMLObject.h | 25 +-- xmltooling/AbstractXMLObject.cpp | 41 +++++ xmltooling/AbstractXMLObject.h | 22 ++- xmltooling/DOMCachingXMLObject.h | 10 +- xmltooling/Makefile.am | 8 +- xmltooling/XMLObject.h | 87 +++++++++- xmltooling/XMLObjectBuilder.h | 8 +- xmltooling/XMLToolingConfig.cpp | 9 +- xmltooling/impl/UnknownElement.cpp | 51 +++--- xmltooling/impl/UnknownElement.h | 80 ++-------- xmltooling/io/AbstractXMLObjectMarshaller.cpp | 167 ++++++++------------ xmltooling/io/AbstractXMLObjectMarshaller.h | 55 ++++--- xmltooling/io/AbstractXMLObjectUnmarshaller.cpp | 61 +++---- xmltooling/io/AbstractXMLObjectUnmarshaller.h | 62 +++----- xmltooling/io/Marshaller.cpp | 73 --------- xmltooling/io/Marshaller.h | 201 ------------------------ xmltooling/io/Unmarshaller.cpp | 74 --------- xmltooling/io/Unmarshaller.h | 156 ------------------ xmltooling/signature/Signature.h | 34 ++-- xmltooling/signature/SigningContext.h | 8 +- xmltooling/signature/impl/XMLSecSignature.cpp | 130 ++++++++------- xmltooling/signature/impl/XMLSecSignature.h | 64 ++------ xmltooling/xmltooling.vcproj | 20 +-- xmltoolingtest/ComplexXMLObjectTest.h | 13 +- xmltoolingtest/Makefile.am | 1 - xmltoolingtest/MarshallingTest.h | 20 +-- xmltoolingtest/SignatureTest.h | 36 +++-- xmltoolingtest/UnknownTest.h | 83 ---------- xmltoolingtest/UnmarshallingTest.h | 35 +++-- xmltoolingtest/XMLObjectBaseTestCase.h | 161 ++++++------------- xmltoolingtest/xmltoolingtest.h | 63 +++++++- xmltoolingtest/xmltoolingtest.vcproj | 26 --- 33 files changed, 618 insertions(+), 1291 deletions(-) create mode 100644 xmltooling/AbstractXMLObject.cpp delete mode 100644 xmltooling/io/Marshaller.cpp delete mode 100644 xmltooling/io/Marshaller.h delete mode 100644 xmltooling/io/Unmarshaller.cpp delete mode 100644 xmltooling/io/Unmarshaller.h delete mode 100644 xmltoolingtest/UnknownTest.h diff --git a/xmltooling/AbstractDOMCachingXMLObject.cpp b/xmltooling/AbstractDOMCachingXMLObject.cpp index 7ffc58c..fb4c0f5 100644 --- a/xmltooling/AbstractDOMCachingXMLObject.cpp +++ b/xmltooling/AbstractDOMCachingXMLObject.cpp @@ -21,9 +21,9 @@ */ #include "internal.h" -#include "exceptions.h" #include "AbstractDOMCachingXMLObject.h" -#include "io/Unmarshaller.h" +#include "exceptions.h" +#include "XMLObjectBuilder.h" #include "util/XMLHelper.h" #include @@ -40,7 +40,7 @@ AbstractDOMCachingXMLObject::~AbstractDOMCachingXMLObject() m_document->release(); } -void AbstractDOMCachingXMLObject::setDOM(DOMElement* dom, bool bindDocument) +void AbstractDOMCachingXMLObject::setDOM(DOMElement* dom, bool bindDocument) const { m_dom=dom; if (dom) { @@ -50,7 +50,7 @@ void AbstractDOMCachingXMLObject::setDOM(DOMElement* dom, bool bindDocument) } } -void AbstractDOMCachingXMLObject::releaseDOM() +void AbstractDOMCachingXMLObject::releaseDOM() const { if (m_dom) { Category& log=Category::getInstance(XMLTOOLING_LOGCAT".DOM"); @@ -62,7 +62,7 @@ void AbstractDOMCachingXMLObject::releaseDOM() } } -void AbstractDOMCachingXMLObject::releaseParentDOM(bool propagateRelease) +void AbstractDOMCachingXMLObject::releaseParentDOM(bool propagateRelease) const { DOMCachingXMLObject* domCachingParent = dynamic_cast(getParent()); if (domCachingParent) { @@ -90,7 +90,7 @@ public: } }; -void AbstractDOMCachingXMLObject::releaseChildrenDOM(bool propagateRelease) +void AbstractDOMCachingXMLObject::releaseChildrenDOM(bool propagateRelease) const { if (hasChildren()) { Category::getInstance(XMLTOOLING_LOGCAT".DOM").debug( @@ -117,20 +117,23 @@ XMLObject* AbstractDOMCachingXMLObject::clone() const DOMElement* domCopy=cloneDOM(); if (domCopy) { // Seemed to work, so now we unmarshall the DOM to produce the clone. - const Unmarshaller* u=Unmarshaller::getUnmarshaller(domCopy); - if (!u) { + const XMLObjectBuilder* b=XMLObjectBuilder::getBuilder(domCopy); + if (!b) { auto_ptr q(XMLHelper::getNodeQName(domCopy)); Category::getInstance(XMLTOOLING_LOGCAT".DOM").error( - "DOM clone failed, unable to locate unmarshaller for element (%s)", q->toString().c_str() + "DOM clone failed, unable to locate builder for element (%s)", q->toString().c_str() ); domCopy->getOwnerDocument()->release(); - throw UnmarshallingException("Unable to locate unmarshaller for cloned element."); + throw UnmarshallingException("Unable to locate builder for cloned element."); } try { - return u->unmarshall(domCopy, true); // bind document + auto_ptr objCopy(b->buildObject(domCopy)); + objCopy->unmarshall(domCopy, true); // bind document + return objCopy.release(); } catch (...) { domCopy->getOwnerDocument()->release(); + throw; } } return NULL; diff --git a/xmltooling/AbstractDOMCachingXMLObject.h b/xmltooling/AbstractDOMCachingXMLObject.h index 501f039..70f7890 100644 --- a/xmltooling/AbstractDOMCachingXMLObject.h +++ b/xmltooling/AbstractDOMCachingXMLObject.h @@ -37,7 +37,7 @@ namespace xmltooling { * Extension of AbstractXMLObject that implements a DOMCachingXMLObject. * This is the primary base class for XMLObject implementation classes to use. */ - class XMLTOOL_API AbstractDOMCachingXMLObject : public AbstractXMLObject, public DOMCachingXMLObject + class XMLTOOL_API AbstractDOMCachingXMLObject : public AbstractXMLObject, public virtual DOMCachingXMLObject { public: virtual ~AbstractDOMCachingXMLObject(); @@ -52,12 +52,12 @@ namespace xmltooling { /** * @see DOMCachingXMLObject::setDOM() */ - void setDOM(DOMElement* dom, bool bindDocument=false); + void setDOM(DOMElement* dom, bool bindDocument=false) const; /** * @see DOMCachingXMLObject::setDocument() */ - void setDocument(DOMDocument* doc) { + void setDocument(DOMDocument* doc) const { if (m_document) m_document->release(); m_document=doc; @@ -66,22 +66,22 @@ namespace xmltooling { /** * @see DOMCachingXMLObject::releaseDOM() */ - virtual void releaseDOM(); + virtual void releaseDOM() const; /** * @see DOMCachingXMLObject::releaseParentDOM() */ - virtual void releaseParentDOM(bool propagateRelease=true); + virtual void releaseParentDOM(bool propagateRelease=true) const; /** * @see DOMCachingXMLObject::releaseChildrenDOM() */ - virtual void releaseChildrenDOM(bool propagateRelease=true); + virtual void releaseChildrenDOM(bool propagateRelease=true) const; /** * A convenience method that is equal to calling releaseDOM() then releaseParentDOM(true). */ - void releaseThisandParentDOM() { + void releaseThisandParentDOM() const { if (m_dom) { releaseDOM(); releaseParentDOM(true); @@ -91,7 +91,7 @@ namespace xmltooling { /** * A convenience method that is equal to calling releaseChildrenDOM(true) then releaseDOM(). */ - void releaseThisAndChildrenDOM() { + void releaseThisAndChildrenDOM() const { if (m_dom) { releaseChildrenDOM(true); releaseDOM(); @@ -111,8 +111,9 @@ namespace xmltooling { * @param elementLocalName the local name of the XML element this Object represents * @param namespacePrefix the namespace prefix to use */ - AbstractDOMCachingXMLObject(const XMLCh* namespaceURI=NULL, const XMLCh* elementLocalName=NULL, const XMLCh* namespacePrefix=NULL) - : AbstractXMLObject(namespaceURI,elementLocalName, namespacePrefix), m_dom(NULL), m_document(NULL) {} + AbstractDOMCachingXMLObject( + const XMLCh* namespaceURI=NULL, const XMLCh* elementLocalName=NULL, const XMLCh* namespacePrefix=NULL + ) : AbstractXMLObject(namespaceURI,elementLocalName, namespacePrefix), m_dom(NULL), m_document(NULL) {} /** * If a DOM representation exists, this clones it into a new document. @@ -160,8 +161,8 @@ namespace xmltooling { XMLObject* prepareForAssignment(XMLObject* oldValue, XMLObject* newValue); private: - DOMElement* m_dom; - DOMDocument* m_document; + mutable DOMElement* m_dom; + mutable DOMDocument* m_document; }; }; diff --git a/xmltooling/AbstractXMLObject.cpp b/xmltooling/AbstractXMLObject.cpp new file mode 100644 index 0000000..cc9381a --- /dev/null +++ b/xmltooling/AbstractXMLObject.cpp @@ -0,0 +1,41 @@ +/* +* Copyright 2001-2006 Internet2 + * +* Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * AbstractXMLObject.cpp + * + * An abstract implementation of XMLObject. + */ + +#include "internal.h" +#include "AbstractXMLObject.h" + +#include +#include + +using namespace xmltooling; + +AbstractXMLObject::~AbstractXMLObject() { + delete m_typeQname; + std::for_each(m_children.begin(), m_children.end(), cleanup()); +} + +AbstractXMLObject::AbstractXMLObject(const XMLCh* namespaceURI, const XMLCh* elementLocalName, const XMLCh* namespacePrefix) + : m_elementQname(namespaceURI,elementLocalName, namespacePrefix), m_typeQname(NULL), m_parent(NULL), + m_log(&log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".XMLObject")) +{ + addNamespace(Namespace(namespaceURI, namespacePrefix)); +} diff --git a/xmltooling/AbstractXMLObject.h b/xmltooling/AbstractXMLObject.h index 9a00401..e72f3eb 100644 --- a/xmltooling/AbstractXMLObject.h +++ b/xmltooling/AbstractXMLObject.h @@ -23,7 +23,6 @@ #if !defined(__xmltooling_abstractxmlobj_h__) #define __xmltooling_abstractxmlobj_h__ -#include #include #if defined (_MSC_VER) @@ -39,10 +38,7 @@ namespace xmltooling { class XMLTOOL_API AbstractXMLObject : public virtual XMLObject { public: - virtual ~AbstractXMLObject() { - delete m_typeQname; - std::for_each(m_children.begin(), m_children.end(), cleanup()); - } + virtual ~AbstractXMLObject(); /** * @see XMLObject::getElementQName() @@ -68,7 +64,7 @@ namespace xmltooling { /** * @see XMLObject::addNamespace() */ - void addNamespace(const Namespace& ns) { + void addNamespace(const Namespace& ns) const { if (ns.alwaysDeclare() || m_namespaces.find(ns)==m_namespaces.end()) { m_namespaces.insert(ns); } @@ -143,10 +139,7 @@ namespace xmltooling { * @param elementLocalName the local name of the XML element this Object represents * @param namespacePrefix the namespace prefix to use */ - AbstractXMLObject(const XMLCh* namespaceURI=NULL, const XMLCh* elementLocalName=NULL, const XMLCh* namespacePrefix=NULL) - : m_elementQname(namespaceURI,elementLocalName, namespacePrefix), m_typeQname(NULL), m_parent(NULL) { - addNamespace(Namespace(namespaceURI, namespacePrefix)); - } + AbstractXMLObject(const XMLCh* namespaceURI=NULL, const XMLCh* elementLocalName=NULL, const XMLCh* namespacePrefix=NULL); /** * Underlying list of child objects. @@ -157,8 +150,13 @@ namespace xmltooling { /** * Set of namespaces associated with the object. */ - std::set m_namespaces; - + mutable std::set m_namespaces; + + /** + * Logging object. + */ + void* m_log; + private: XMLObject* m_parent; QName m_elementQname; diff --git a/xmltooling/DOMCachingXMLObject.h b/xmltooling/DOMCachingXMLObject.h index 84f33e2..895527d 100644 --- a/xmltooling/DOMCachingXMLObject.h +++ b/xmltooling/DOMCachingXMLObject.h @@ -52,7 +52,7 @@ namespace xmltooling { * @param dom DOM representation of this XMLObject * @param bindDocument true if the object should take ownership of the associated Document */ - virtual void setDOM(DOMElement* dom, bool bindDocument=false)=0; + virtual void setDOM(DOMElement* dom, bool bindDocument=false) const=0; /** * Assigns ownership of a DOM document to the XMLObject. @@ -60,26 +60,26 @@ namespace xmltooling { * * @param doc DOM document bound to this object */ - virtual void setDocument(DOMDocument* doc)=0; + virtual void setDocument(DOMDocument* doc) const=0; /** * Releases the DOM representation of this XMLObject, if there is one. */ - virtual void releaseDOM()=0; + virtual void releaseDOM() const=0; /** * Releases the DOM representation of this XMLObject's parent. * * @param propagateRelease true if all ancestors of this element should release their DOM */ - virtual void releaseParentDOM(bool propagateRelease=true)=0; + virtual void releaseParentDOM(bool propagateRelease=true) const=0; /** * Releases the DOM representation of this XMLObject's children. * * @param propagateRelease true if all descendants of this element should release their DOM */ - virtual void releaseChildrenDOM(bool propagateRelease=true)=0; + virtual void releaseChildrenDOM(bool propagateRelease=true) const=0; }; }; diff --git a/xmltooling/Makefile.am b/xmltooling/Makefile.am index a26eb12..e90aca3 100644 --- a/xmltooling/Makefile.am +++ b/xmltooling/Makefile.am @@ -34,12 +34,11 @@ libxmltoolinginclude_HEADERS = \ ioinclude_HEADERS = \ io/AbstractXMLObjectUnmarshaller.h \ - io/Marshaller.h \ - io/Unmarshaller.h siginclude_HEADERS = \ signature/Signature.h \ - signature/SigningContext.h + signature/SigningContext.h \ + signature/VerifyingContext.h utilinclude_HEADERS = \ util/NDC.h \ @@ -67,6 +66,7 @@ libxmltooling_la_SOURCES = \ AbstractAttributeExtensibleXMLObject.cpp \ AbstractDOMCachingXMLObject.cpp \ AbstractElementProxy.cpp \ + AbstractXMLObject.cpp \ Namespace.cpp \ QName.cpp \ unicode.cpp \ @@ -75,8 +75,6 @@ libxmltooling_la_SOURCES = \ impl/UnknownElement.cpp \ io/AbstractXMLObjectMarshaller.cpp \ io/AbstractXMLObjectUnmarshaller.cpp \ - io/Marshaller.cpp \ - io/Unmarshaller.cpp \ util/NDC.cpp \ util/ParserPool.cpp \ util/XMLConstants.cpp \ diff --git a/xmltooling/XMLObject.h b/xmltooling/XMLObject.h index 1ff2ce7..b613e50 100644 --- a/xmltooling/XMLObject.h +++ b/xmltooling/XMLObject.h @@ -25,11 +25,46 @@ #include #include +#include +#include #include #include +using namespace xercesc; + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + namespace xmltooling { +#ifndef XMLTOOLING_NO_XMLSEC + class XMLTOOL_API Signature; + class XMLTOOL_API SigningContext; +#endif + + /** + * Supplies additional information to the marshalling process. + * Currently this only consists of signature related information. + */ + class XMLTOOL_API MarshallingContext + { + MAKE_NONCOPYABLE(MarshallingContext); + public: + MarshallingContext() {} + ~MarshallingContext() {} + +#ifndef XMLTOOLING_NO_XMLSEC + MarshallingContext(Signature* sig, const SigningContext* ctx) { + m_signingContexts.push_back(std::make_pair(sig,ctx)); + } + + /** Array of signing contexts, keyed off of the associated Signature */ + std::vector< std::pair > m_signingContexts; +#endif + }; + /** * Object that represents an XML Element that has been unmarshalled into this C++ object. */ @@ -79,7 +114,7 @@ namespace xmltooling { * * @param ns the namespace to add */ - virtual void addNamespace(const Namespace& ns)=0; + virtual void addNamespace(const Namespace& ns) const=0; /** * Removes a namespace from this element @@ -143,10 +178,60 @@ namespace xmltooling { */ virtual const std::list& getOrderedChildren() const=0; + /** + * Marshalls the XMLObject, and its children, into a DOM element. + * If a document is supplied, then it will be used to create the resulting elements. + * If the document does not have a Document Element set, then the resulting + * element will be set as the Document Element. If no document is supplied, then + * a new document will be created and bound to the lifetime of the root object being + * marshalled, unless an existing DOM can be reused without creating a new document. + * + * @param document the DOM document the marshalled element will be placed in, or NULL + * @param ctx optional marshalling context + * @return the DOM element representing this XMLObject + * + * @throws MarshallingException thrown if there is a problem marshalling the given object + * @throws SignatureException thrown if a problem occurs during signature creation + */ + virtual DOMElement* marshall(DOMDocument* document=NULL, MarshallingContext* ctx=NULL) const=0; + + /** + * Marshalls the XMLObject and appends it as a child of the given parent element. + * + * NOTE: The given Element must be within a DOM tree rooted in + * the Document owning the given Element. + * + * @param parentElement the parent element to append the resulting DOM tree + * @param ctx optional marshalling context + * @return the marshalled element tree + + * @throws MarshallingException thrown if the given XMLObject can not be marshalled. + * @throws SignatureException thrown if a problem occurs during signature creation + */ + virtual DOMElement* marshall(DOMElement* parentElement, MarshallingContext* ctx=NULL) const=0; + + /** + * Unmarshalls the given W3C DOM element into the XMLObject. + * The root of a given XML construct should be unmarshalled with the bindDocument parameter + * set to true. + * + * @param element the DOM element to unmarshall + * @param bindDocument true iff the resulting XMLObject should take ownership of the DOM's Document + * + * @return the unmarshalled XMLObject + * + * @throws UnmarshallingException thrown if an error occurs unmarshalling the DOM element into the XMLObject + */ + virtual XMLObject* unmarshall(DOMElement* element, bool bindDocument=false)=0; + protected: XMLObject() {} }; +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + }; #endif /* __xmltooling_xmlobj_h__ */ diff --git a/xmltooling/XMLObjectBuilder.h b/xmltooling/XMLObjectBuilder.h index de34c89..0c9f069 100644 --- a/xmltooling/XMLObjectBuilder.h +++ b/xmltooling/XMLObjectBuilder.h @@ -50,19 +50,21 @@ namespace xmltooling { /** * Creates an empty XMLObject. * + * @param e a construction hint based on the eventual unmarshalling source * @return the empty XMLObject */ - virtual XMLObject* buildObject() const=0; + virtual XMLObject* buildObject(const DOMElement* e=NULL) const=0; /** * Creates an empty XMLObject using the default build method, if a builder can be found. * * @param key the key used to locate a builder + * @param e a construction hint based on the eventual unmarshalling source * @return the empty object or NULL if no builder is available */ - static XMLObject* buildObject(const QName& key) { + static XMLObject* buildObject(const QName& key, const DOMElement* e=NULL) { const XMLObjectBuilder* b=getBuilder(key); - return b ? b->buildObject() : NULL; + return b ? b->buildObject(e) : NULL; } /** diff --git a/xmltooling/XMLToolingConfig.cpp b/xmltooling/XMLToolingConfig.cpp index 9bd8b3e..23c4146 100644 --- a/xmltooling/XMLToolingConfig.cpp +++ b/xmltooling/XMLToolingConfig.cpp @@ -140,13 +140,8 @@ bool XMLToolingInternalConfig::init() // default registrations XMLObjectBuilder::registerDefaultBuilder(new UnknownElementBuilder()); - Marshaller::registerDefaultMarshaller(new UnknownElementMarshaller()); - Unmarshaller::registerDefaultUnmarshaller(new UnknownElementUnmarshaller()); #ifndef XMLTOOLING_NO_XMLSEC - QName dsig(XMLConstants::XMLSIG_NS,Signature::LOCAL_NAME); - XMLObjectBuilder::registerBuilder(dsig,new XMLSecSignatureBuilder()); - Marshaller::registerMarshaller(dsig,new XMLSecSignatureMarshaller()); - Unmarshaller::registerUnmarshaller(dsig,new XMLSecSignatureUnmarshaller()); + XMLObjectBuilder::registerBuilder(QName(XMLConstants::XMLSIG_NS,Signature::LOCAL_NAME),new XMLSecSignatureBuilder()); #endif } catch (const xercesc::XMLException&) { @@ -161,8 +156,6 @@ bool XMLToolingInternalConfig::init() void XMLToolingInternalConfig::term() { XMLObjectBuilder::destroyBuilders(); - Marshaller::destroyMarshallers(); - Unmarshaller::destroyUnmarshallers(); for (vector::reverse_iterator i=m_libhandles.rbegin(); i!=m_libhandles.rend(); i++) { #if defined(WIN32) diff --git a/xmltooling/impl/UnknownElement.cpp b/xmltooling/impl/UnknownElement.cpp index 3d638ae..dd8e303 100644 --- a/xmltooling/impl/UnknownElement.cpp +++ b/xmltooling/impl/UnknownElement.cpp @@ -70,7 +70,7 @@ void UnknownElementImpl::serialize(string& s) const XMLHelper::serialize(getDOM(),s); } -DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMDocument* document, MarshallingContext* ctx) const +DOMElement* UnknownElementImpl::marshall(DOMDocument* document, MarshallingContext* ctx) const { #ifdef _DEBUG xmltooling::NDC ndc("marshall"); @@ -79,17 +79,13 @@ DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMDocument Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Marshaller"); log.debug("marshalling unknown content"); - UnknownElementImpl* unk=dynamic_cast(xmlObject); - if (!unk) - throw MarshallingException("Only objects of class UnknownElementImpl can be marshalled."); - - DOMElement* cachedDOM=unk->getDOM(); + DOMElement* cachedDOM=getDOM(); if (cachedDOM) { if (!document || document==cachedDOM->getOwnerDocument()) { log.debug("XMLObject has a usable cached DOM, reusing it"); if (document) setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM); - unk->releaseParentDOM(true); + releaseParentDOM(true); return cachedDOM; } @@ -100,15 +96,15 @@ DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMDocument // Recache the DOM. setDocumentElement(document, cachedDOM); log.debug("caching imported DOM for XMLObject"); - unk->setDOM(cachedDOM, false); - unk->releaseParentDOM(true); + setDOM(cachedDOM, false); + releaseParentDOM(true); return cachedDOM; } // If we get here, we didn't have a usable DOM. // We need to reparse the XML we saved off into a new DOM. bool bindDocument=false; - MemBufInputSource src(reinterpret_cast(unk->m_xml.c_str()),unk->m_xml.length(),"UnknownElementImpl"); + MemBufInputSource src(reinterpret_cast(m_xml.c_str()),m_xml.length(),"UnknownElementImpl"); Wrapper4InputSource dsrc(&src,false); log.debug("parsing XML back into DOM tree"); DOMDocument* internalDoc=XMLToolingInternalConfig::getInternalConfig().m_parserPool->parse(dsrc); @@ -129,13 +125,13 @@ DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMDocument // Recache the DOM and clear the serialized copy. setDocumentElement(document, cachedDOM); log.debug("caching DOM for XMLObject (document is %sbound)", bindDocument ? "" : "not "); - unk->setDOM(cachedDOM, bindDocument); - unk->releaseParentDOM(true); - unk->m_xml.erase(); + setDOM(cachedDOM, bindDocument); + releaseParentDOM(true); + m_xml.erase(); return cachedDOM; } -DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMElement* parentElement, MarshallingContext* ctx) const +DOMElement* UnknownElementImpl::marshall(DOMElement* parentElement, MarshallingContext* ctx) const { #ifdef _DEBUG xmltooling::NDC ndc("marshall"); @@ -144,16 +140,12 @@ DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMElement* Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Marshaller"); log.debug("marshalling unknown content"); - UnknownElementImpl* unk=dynamic_cast(xmlObject); - if (!unk) - throw MarshallingException("Only objects of class UnknownElementImpl can be marshalled."); - - DOMElement* cachedDOM=unk->getDOM(); + DOMElement* cachedDOM=getDOM(); if (cachedDOM) { if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) { log.debug("XMLObject has a usable cached DOM, reusing it"); parentElement->appendChild(cachedDOM); - unk->releaseParentDOM(true); + releaseParentDOM(true); return cachedDOM; } @@ -164,14 +156,14 @@ DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMElement* // Recache the DOM. parentElement->appendChild(cachedDOM); log.debug("caching imported DOM for XMLObject"); - unk->setDOM(cachedDOM, false); - unk->releaseParentDOM(true); + setDOM(cachedDOM, false); + releaseParentDOM(true); return cachedDOM; } // If we get here, we didn't have a usable DOM (and/or we flushed the one we had). // We need to reparse the XML we saved off into a new DOM. - MemBufInputSource src(reinterpret_cast(unk->m_xml.c_str()),unk->m_xml.length(),"UnknownElementImpl"); + MemBufInputSource src(reinterpret_cast(m_xml.c_str()),m_xml.length(),"UnknownElementImpl"); Wrapper4InputSource dsrc(&src,false); log.debug("parsing XML back into DOM tree"); DOMDocument* internalDoc=XMLToolingInternalConfig::getInternalConfig().m_parserPool->parse(dsrc); @@ -183,15 +175,14 @@ DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMElement* // Recache the DOM and clear the serialized copy. parentElement->appendChild(cachedDOM); log.debug("caching DOM for XMLObject"); - unk->setDOM(cachedDOM, false); - unk->releaseParentDOM(true); - unk->m_xml.erase(); + setDOM(cachedDOM, false); + releaseParentDOM(true); + m_xml.erase(); return cachedDOM; } -XMLObject* UnknownElementUnmarshaller::unmarshall(DOMElement* element, bool bindDocument) const +XMLObject* UnknownElementImpl::unmarshall(DOMElement* element, bool bindDocument) { - UnknownElementImpl* ret=new UnknownElementImpl(); - ret->setDOM(element, bindDocument); - return ret; + setDOM(element, bindDocument); + return this; } diff --git a/xmltooling/impl/UnknownElement.h b/xmltooling/impl/UnknownElement.h index 1afb6e1..7ac3103 100644 --- a/xmltooling/impl/UnknownElement.h +++ b/xmltooling/impl/UnknownElement.h @@ -15,7 +15,7 @@ */ /** - * @file UnknownElement.h + * UnknownElement.h * * Basic implementations suitable for use as defaults for unrecognized content */ @@ -24,10 +24,9 @@ #define __xmltooling_unkelement_h__ #include "internal.h" -#include "AbstractDOMCachingXMLObject.h" #include "XMLObjectBuilder.h" -#include "io/Marshaller.h" -#include "io/Unmarshaller.h" +#include "io/AbstractXMLObjectMarshaller.h" +#include "io/AbstractXMLObjectUnmarshaller.h" #include @@ -38,69 +37,19 @@ namespace xmltooling { - /** - * Implementation class for unrecognized DOM elements. - * Purpose is to wrap the DOM and do any necessary caching/reconstruction - * when a DOM has to cross into a new document. - */ class XMLTOOL_DLLLOCAL UnknownElementImpl : public AbstractDOMCachingXMLObject { public: UnknownElementImpl(const XMLCh* namespaceURI=NULL, const XMLCh* elementLocalName=NULL, const XMLCh* namespacePrefix=NULL) : AbstractDOMCachingXMLObject(namespaceURI, elementLocalName, namespacePrefix) {} - /** - * Overridden to ensure XML content of DOM isn't lost. - * - * @see DOMCachingXMLObject::releaseDOM() - */ void releaseDOM(); - /** - * @see XMLObject::clone() - */ XMLObject* clone() const; - protected: - /** - * When needed, we can serialize the DOM into XML form and preserve it here. - */ - std::string m_xml; - - void serialize(std::string& s) const; - private: - friend class XMLTOOL_DLLLOCAL UnknownElementMarshaller; - }; - - /** - * Factory for UnknownElementImpl objects - */ - class XMLTOOL_DLLLOCAL UnknownElementBuilder : public virtual XMLObjectBuilder - { - public: - /** - * @see XMLObjectBuilder::buildObject() - */ - XMLObject* buildObject() const { - return new UnknownElementImpl(); - } - }; - - /** - * Marshaller for UnknownElementImpl objects - */ - class XMLTOOL_DLLLOCAL UnknownElementMarshaller : public virtual Marshaller - { - public: - /** - * @see Marshaller::marshall(XMLObject*,DOMDocument*, const MarshallingContext*) - */ - DOMElement* marshall(XMLObject* xmlObject, DOMDocument* document=NULL, MarshallingContext* ctx=NULL) const; - - /** - * @see Marshaller::marshall(XMLObject*,DOMElement*, const MarshallingContext* ctx) - */ - DOMElement* marshall(XMLObject* xmlObject, DOMElement* parentElement, MarshallingContext* ctx=NULL) const; + DOMElement* marshall(DOMDocument* document=NULL, MarshallingContext* ctx=NULL) const; + DOMElement* marshall(DOMElement* parentElement, MarshallingContext* ctx=NULL) const; + XMLObject* unmarshall(DOMElement* element, bool bindDocument=false); protected: void setDocumentElement(DOMDocument* document, DOMElement* element) const { @@ -110,19 +59,20 @@ namespace xmltooling { else document->appendChild(element); } + + mutable std::string m_xml; + + void serialize(std::string& s) const; }; - /** - * Unmarshaller for UnknownElementImpl objects - */ - class XMLTOOL_DLLLOCAL UnknownElementUnmarshaller : public virtual Unmarshaller + class XMLTOOL_DLLLOCAL UnknownElementBuilder : public XMLObjectBuilder { public: - /** - * @see Unmarshaller::unmarshall() - */ - XMLObject* unmarshall(DOMElement* element, bool bindDocument=false) const; + XMLObject* buildObject(const DOMElement* e=NULL) const { + return new UnknownElementImpl(); + } }; + }; #if defined (_MSC_VER) diff --git a/xmltooling/io/AbstractXMLObjectMarshaller.cpp b/xmltooling/io/AbstractXMLObjectMarshaller.cpp index 8a718a7..e0f7856 100644 --- a/xmltooling/io/AbstractXMLObjectMarshaller.cpp +++ b/xmltooling/io/AbstractXMLObjectMarshaller.cpp @@ -21,9 +21,11 @@ */ #include "internal.h" -#include "DOMCachingXMLObject.h" #include "exceptions.h" #include "io/AbstractXMLObjectMarshaller.h" +#ifndef XMLTOOLING_NO_XMLSEC + #include "signature/Signature.h" +#endif #include "util/NDC.h" #include "util/XMLConstants.h" #include "util/XMLHelper.h" @@ -39,39 +41,33 @@ using namespace std; #define XT_log (*static_cast(m_log)) -AbstractXMLObjectMarshaller::AbstractXMLObjectMarshaller() - : m_log(&Category::getInstance(XMLTOOLING_LOGCAT".Marshaller")) {} - -DOMElement* AbstractXMLObjectMarshaller::marshall(XMLObject* xmlObject, DOMDocument* document, MarshallingContext* ctx) const +DOMElement* AbstractXMLObjectMarshaller::marshall(DOMDocument* document, MarshallingContext* ctx) const { #ifdef _DEBUG xmltooling::NDC ndc("marshall"); #endif if (XT_log.isDebugEnabled()) { - XT_log.debug("starting to marshalling %s", xmlObject->getElementQName().toString().c_str()); + XT_log.debug("starting to marshal %s", getElementQName().toString().c_str()); } - DOMCachingXMLObject* dc=dynamic_cast(xmlObject); - if (dc) { - DOMElement* cachedDOM=dc->getDOM(); - if (cachedDOM) { - if (!document || document==cachedDOM->getOwnerDocument()) { - XT_log.debug("XMLObject has a usable cached DOM, reusing it"); - if (document) - setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM); - dc->releaseParentDOM(true); - return cachedDOM; - } - - // We have a DOM but it doesn't match the document we were given. This both sucks and blows. - // Without an adoptNode option to maintain the child pointers, we have to either import the - // DOM while somehow reassigning all the nested references (which amounts to a complete - // *unmarshall* operation), or we just release the existing DOM and hope that we can get - // it back. This depends on all objects being able to preserve their DOM at all costs. - dc->releaseChildrenDOM(true); - dc->releaseDOM(); + DOMElement* cachedDOM=getDOM(); + if (cachedDOM) { + if (!document || document==cachedDOM->getOwnerDocument()) { + XT_log.debug("XMLObject has a usable cached DOM, reusing it"); + if (document) + setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM); + releaseParentDOM(true); + return cachedDOM; } + + // We have a DOM but it doesn't match the document we were given. This both sucks and blows. + // Without an adoptNode option to maintain the child pointers, we have to either import the + // DOM while somehow reassigning all the nested references (which amounts to a complete + // *unmarshall* operation), or we just release the existing DOM and hope that we can get + // it back. This depends on all objects being able to preserve their DOM at all costs. + releaseChildrenDOM(true); + releaseDOM(); } // If we get here, we didn't have a usable DOM (and/or we released the one we had). @@ -85,17 +81,15 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(XMLObject* xmlObject, DOMDocum try { XT_log.debug("creating root element to marshall"); DOMElement* domElement = document->createElementNS( - xmlObject->getElementQName().getNamespaceURI(), xmlObject->getElementQName().getLocalPart() + getElementQName().getNamespaceURI(), getElementQName().getLocalPart() ); setDocumentElement(document, domElement); - marshallInto(*xmlObject, domElement, ctx); + marshallInto(domElement, ctx); //Recache the DOM. - if (dc) { - XT_log.debug("caching DOM for XMLObject (document is %sbound)", bindDocument ? "" : "not "); - dc->setDOM(domElement, bindDocument); - dc->releaseParentDOM(true); - } + XT_log.debug("caching DOM for XMLObject (document is %sbound)", bindDocument ? "" : "not "); + setDOM(domElement, bindDocument); + releaseParentDOM(true); return domElement; } @@ -108,53 +102,48 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(XMLObject* xmlObject, DOMDocum } } -DOMElement* AbstractXMLObjectMarshaller::marshall(XMLObject* xmlObject, DOMElement* parentElement, MarshallingContext* ctx) const +DOMElement* AbstractXMLObjectMarshaller::marshall(DOMElement* parentElement, MarshallingContext* ctx) const { #ifdef _DEBUG xmltooling::NDC ndc("marshall"); #endif if (XT_log.isDebugEnabled()) { - XT_log.debug("starting to marshalling %s", xmlObject->getElementQName().toString().c_str()); + XT_log.debug("starting to marshalling %s", getElementQName().toString().c_str()); } - DOMCachingXMLObject* dc=dynamic_cast(xmlObject); - if (dc) { - DOMElement* cachedDOM=dc->getDOM(); - if (cachedDOM) { - if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) { - XT_log.debug("XMLObject has a usable cached DOM, reusing it"); - if (parentElement!=cachedDOM->getParentNode()) { - parentElement->appendChild(cachedDOM); - dc->releaseParentDOM(true); - } - return cachedDOM; + DOMElement* cachedDOM=getDOM(); + if (cachedDOM) { + if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) { + XT_log.debug("XMLObject has a usable cached DOM, reusing it"); + if (parentElement!=cachedDOM->getParentNode()) { + parentElement->appendChild(cachedDOM); + releaseParentDOM(true); } - - // We have a DOM but it doesn't match the document we were given. This both sucks and blows. - // Without an adoptNode option to maintain the child pointers, we have to either import the - // DOM while somehow reassigning all the nested references (which amounts to a complete - // *unmarshall* operation), or we just release the existing DOM and hope that we can get - // it back. This depends on all objects being able to preserve their DOM at all costs. - dc->releaseChildrenDOM(true); - dc->releaseDOM(); + return cachedDOM; } + + // We have a DOM but it doesn't match the document we were given. This both sucks and blows. + // Without an adoptNode option to maintain the child pointers, we have to either import the + // DOM while somehow reassigning all the nested references (which amounts to a complete + // *unmarshall* operation), or we just release the existing DOM and hope that we can get + // it back. This depends on all objects being able to preserve their DOM at all costs. + releaseChildrenDOM(true); + releaseDOM(); } // If we get here, we didn't have a usable DOM (and/or we released the one we had). XT_log.debug("creating root element to marshall"); DOMElement* domElement = parentElement->getOwnerDocument()->createElementNS( - xmlObject->getElementQName().getNamespaceURI(), xmlObject->getElementQName().getLocalPart() + getElementQName().getNamespaceURI(), getElementQName().getLocalPart() ); parentElement->appendChild(domElement); - marshallInto(*xmlObject, domElement, ctx); + marshallInto(domElement, ctx); //Recache the DOM. - if (dc) { - XT_log.debug("caching DOM for XMLObject"); - dc->setDOM(domElement, false); - dc->releaseParentDOM(true); - } + XT_log.debug("caching DOM for XMLObject"); + setDOM(domElement, false); + releaseParentDOM(true); return domElement; } @@ -163,22 +152,20 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(XMLObject* xmlObject, DOMEleme class _signit : public unary_function&, void> { public: void operator()(const pair& p) const { - p.first->sign(p.second); + p.first->sign(*(p.second)); } }; #endif -void AbstractXMLObjectMarshaller::marshallInto( - XMLObject& xmlObject, DOMElement* targetElement, MarshallingContext* ctx - ) const +void AbstractXMLObjectMarshaller::marshallInto(DOMElement* targetElement, MarshallingContext* ctx) const { - if (xmlObject.getElementQName().hasPrefix()) - targetElement->setPrefix(xmlObject.getElementQName().getPrefix()); - marshallElementType(xmlObject, targetElement); - marshallNamespaces(xmlObject, targetElement); - marshallAttributes(xmlObject, targetElement); - marshallChildElements(xmlObject, targetElement); - marshallElementContent(xmlObject, targetElement); + if (getElementQName().hasPrefix()) + targetElement->setPrefix(getElementQName().getPrefix()); + marshallElementType(targetElement); + marshallNamespaces(targetElement); + marshallAttributes(targetElement); + marshallChildElements(targetElement); + marshallElementContent(targetElement); #ifndef XMLTOOLING_NO_XMLSEC if (ctx) { @@ -187,9 +174,9 @@ void AbstractXMLObjectMarshaller::marshallInto( #endif } -void AbstractXMLObjectMarshaller::marshallElementType(XMLObject& xmlObject, DOMElement* domElement) const +void AbstractXMLObjectMarshaller::marshallElementType(DOMElement* domElement) const { - const QName* type = xmlObject.getSchemaType(); + const QName* type = getSchemaType(); if (type) { XT_log.debug("setting xsi:type attribute for XMLObject"); @@ -217,7 +204,7 @@ void AbstractXMLObjectMarshaller::marshallElementType(XMLObject& xmlObject, DOME XMLString::release(&xsivalue); XT_log.debug("Adding XSI namespace to list of namespaces used by XMLObject"); - xmlObject.addNamespace(Namespace(XMLConstants::XSI_NS, XMLConstants::XSI_PREFIX)); + addNamespace(Namespace(XMLConstants::XSI_NS, XMLConstants::XSI_PREFIX)); } } @@ -279,40 +266,24 @@ public: } }; -void AbstractXMLObjectMarshaller::marshallNamespaces(const XMLObject& xmlObject, DOMElement* domElement) const +void AbstractXMLObjectMarshaller::marshallNamespaces(DOMElement* domElement) const { XT_log.debug("marshalling namespace attributes for XMLObject"); - const set& namespaces = xmlObject.getNamespaces(); + const set& namespaces = getNamespaces(); for_each(namespaces.begin(),namespaces.end(),bind1st(_addns(),domElement)); } -class _marshallchild : public binary_function { - void* m_log; +class _marshallit : public binary_function { public: - _marshallchild(void* log) : m_log(log) {} - void operator()(XMLObject* obj, DOMElement* element) const { - if (!obj) - return; - if (XT_log.isDebugEnabled()) { - XT_log.debug("getting marshaller for child XMLObject: %s", obj->getElementQName().toString().c_str()); - } - - const Marshaller* marshaller = Marshaller::getMarshaller(obj); - if (!marshaller) { - XT_log.error( - "no default unmarshaller installed, unknown child object: %s", - obj->getElementQName().toString().c_str() - ); - throw MarshallingException("Marshaller found unknown child element, but no default marshaller was found."); - } - marshaller->marshall(obj, element); + void operator()(const XMLObject* xo, DOMElement* e) const { + if (xo) xo->marshall(e); } }; -void AbstractXMLObjectMarshaller::marshallChildElements(const XMLObject& xmlObject, DOMElement* domElement) const +void AbstractXMLObjectMarshaller::marshallChildElements(DOMElement* domElement) const { XT_log.debug("marshalling child elements for XMLObject"); - const list& children=xmlObject.getOrderedChildren(); - for_each(children.begin(),children.end(),bind2nd(_marshallchild(m_log),domElement)); + const list& children=getOrderedChildren(); + for_each(children.begin(),children.end(),bind2nd(_marshallit(),domElement)); } diff --git a/xmltooling/io/AbstractXMLObjectMarshaller.h b/xmltooling/io/AbstractXMLObjectMarshaller.h index 7d1928d..e7c6647 100644 --- a/xmltooling/io/AbstractXMLObjectMarshaller.h +++ b/xmltooling/io/AbstractXMLObjectMarshaller.h @@ -23,30 +23,35 @@ #if !defined(__xmltooling_xmlmarshaller_h__) #define __xmltooling_xmlmarshaller_h__ -#include +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif namespace xmltooling { /** * A thread-safe abstract marshaller. */ - class XMLTOOL_API AbstractXMLObjectMarshaller : public virtual Marshaller + class XMLTOOL_API AbstractXMLObjectMarshaller : public virtual AbstractDOMCachingXMLObject { public: virtual ~AbstractXMLObjectMarshaller() {} /** - * @see Marshaller::marshall(XMLObject*,DOMDocument*,const MarshallingContext*) + * @see XMLObject::marshall(DOMDocument*,const MarshallingContext*) */ - DOMElement* marshall(XMLObject* xmlObject, DOMDocument* document=NULL, MarshallingContext* ctx=NULL) const; + DOMElement* marshall(DOMDocument* document=NULL, MarshallingContext* ctx=NULL) const; /** - * @see Marshaller::marshall(XMLObject*,DOMElement*,const MarshallingContext*) + * @see XMLObject::marshall(DOMElement*,const MarshallingContext*) */ - DOMElement* marshall(XMLObject* xmlObject, DOMElement* parentElement, MarshallingContext* ctx=NULL) const; + DOMElement* marshall(DOMElement* parentElement, MarshallingContext* ctx=NULL) const; protected: - AbstractXMLObjectMarshaller(); + AbstractXMLObjectMarshaller() {} /** * Sets the given element as the Document Element of the given Document. @@ -64,70 +69,64 @@ namespace xmltooling { } /** - * Marshalls the given XMLObject into the given DOM Element. + * Marshalls the XMLObject into the given DOM Element. * The DOM Element must be within a DOM tree rooted in the owning Document. * - * @param xmlObject the XMLObject to marshall * @param targetElement the Element into which the XMLObject is marshalled into * @param ctx optional marshalling context * * @throws MarshallingException thrown if there is a problem marshalling the object * @throws SignatureException thrown if a problem occurs during signature creation */ - void marshallInto(XMLObject& xmlObject, DOMElement* targetElement, MarshallingContext* ctx) const; + void marshallInto(DOMElement* targetElement, MarshallingContext* ctx) const; /** * Creates an xsi:type attribute, corresponding to the given type of the XMLObject, on the DOM element. * - * @param xmlObject the XMLObject * @param domElement the DOM element * * @throws MarshallingException thrown if the type on the XMLObject is doesn't contain * a local name, prefix, and namespace URI */ - void marshallElementType(XMLObject& xmlObject, DOMElement* domElement) const; + void marshallElementType(DOMElement* domElement) const; /** - * Creates the xmlns attributes for any namespaces set on the given XMLObject. + * Creates the xmlns attributes for any namespaces set on the XMLObject. * - * @param xmlObject the XMLObject * @param domElement the DOM element the namespaces will be added to */ - void marshallNamespaces(const XMLObject& xmlObject, DOMElement* domElement) const; + void marshallNamespaces(DOMElement* domElement) const; /** - * Marshalls the child elements of the given XMLObject. + * Marshalls the child elements of the XMLObject. * - * @param xmlObject the XMLObject whose children will be marshalled * @param domElement the DOM element that will recieved the marshalled children * * @throws MarshallingException thrown if there is a problem marshalling a child element */ - void marshallChildElements(const XMLObject& xmlObject, DOMElement* domElement) const; + void marshallChildElements(DOMElement* domElement) const; /** - * Marshalls the attributes from the given XMLObject into the given DOM element. - * The XMLObject passed to this method is guaranteed to be of the target name - * specified during this marshaller's construction. + * Marshalls the attributes from the XMLObject into the given DOM element. * - * @param xmlObject the XMLObject being marshalled * @param domElement the DOM Element into which attributes will be marshalled * - * @throws UnmarshallingException thrown if there is a problem unmarshalling an attribute + * @throws MarshallingException thrown if there is a problem marshalling an attribute */ - virtual void marshallAttributes(const XMLObject& xmlObject, DOMElement* domElement) const=0; + virtual void marshallAttributes(DOMElement* domElement) const=0; /** * Marshalls data from the XMLObject into content of the DOM Element. * - * @param xmlObject the XMLObject * @param domElement the DOM element recieving the content */ - virtual void marshallElementContent(const XMLObject& xmlObject, DOMElement* domElement) const=0; - - void* m_log; + virtual void marshallElementContent(DOMElement* domElement) const=0; }; }; +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + #endif /* __xmltooling_xmlmarshaller_h__ */ diff --git a/xmltooling/io/AbstractXMLObjectUnmarshaller.cpp b/xmltooling/io/AbstractXMLObjectUnmarshaller.cpp index e3ae471..701494b 100644 --- a/xmltooling/io/AbstractXMLObjectUnmarshaller.cpp +++ b/xmltooling/io/AbstractXMLObjectUnmarshaller.cpp @@ -21,7 +21,6 @@ */ #include "internal.h" -#include "DOMCachingXMLObject.h" #include "exceptions.h" #include "XMLObjectBuilder.h" #include "io/AbstractXMLObjectUnmarshaller.h" @@ -38,10 +37,7 @@ using namespace std; #define XT_log (*static_cast(m_log)) -AbstractXMLObjectUnmarshaller::AbstractXMLObjectUnmarshaller() - : m_log(&Category::getInstance(XMLTOOLING_LOGCAT".Unmarshaller")) {} - -XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool bindDocument) const +XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool bindDocument) { #ifdef _DEBUG xmltooling::NDC ndc("unmarshall"); @@ -52,13 +48,11 @@ XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool b XT_log.debug("unmarshalling DOM element (%s)", dname.get()); } - auto_ptr xmlObject(buildXMLObject(element)); - if (element->hasAttributes()) { - unmarshallAttributes(element, *(xmlObject.get())); + unmarshallAttributes(element); } - unmarshallChildElements(element, *(xmlObject.get())); + unmarshallChildElements(element); /* TODO: Signing if (xmlObject instanceof SignableXMLObject) { @@ -66,24 +60,11 @@ XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool b } */ - DOMCachingXMLObject* dc=dynamic_cast(xmlObject.get()); - if (dc) - dc->setDOM(element,bindDocument); - else if (bindDocument) - throw UnmarshallingException("Unable to bind document to non-DOM caching XMLObject instance."); - - return xmlObject.release(); -} - -XMLObject* AbstractXMLObjectUnmarshaller::buildXMLObject(const DOMElement* domElement) const -{ - const XMLObjectBuilder* xmlObjectBuilder = XMLObjectBuilder::getBuilder(domElement); - if (xmlObjectBuilder) - return xmlObjectBuilder->buildObject(); - throw UnmarshallingException("Failed to locate XMLObjectBuilder for element."); + setDOM(element,bindDocument); + return this; } -void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domElement, XMLObject& xmlObject) const +void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domElement) { #ifdef _DEBUG xmltooling::NDC ndc("unmarshallAttributes"); @@ -118,32 +99,32 @@ void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domEl if (XMLString::equals(nsuri,XMLConstants::XMLNS_NS)) { if (XMLString::equals(attribute->getLocalName(),XMLConstants::XMLNS_PREFIX)) { XT_log.debug("found default namespace declaration, adding it to the list of namespaces on the XMLObject"); - xmlObject.addNamespace(Namespace(attribute->getValue(), NULL, true)); + addNamespace(Namespace(attribute->getValue(), NULL, true)); continue; } else { XT_log.debug("found namespace declaration, adding it to the list of namespaces on the XMLObject"); - xmlObject.addNamespace(Namespace(attribute->getValue(), attribute->getLocalName(), true)); + addNamespace(Namespace(attribute->getValue(), attribute->getLocalName(), true)); continue; } } else if (XMLString::equals(nsuri,XMLConstants::XSI_NS) && XMLString::equals(attribute->getLocalName(),type)) { XT_log.debug("found xsi:type declaration, setting the schema type of the XMLObject"); auto_ptr xsitype(XMLHelper::getAttributeValueAsQName(attribute)); - xmlObject.setSchemaType(xsitype.get()); + setSchemaType(xsitype.get()); continue; } else if (nsuri && !XMLString::equals(nsuri,XMLConstants::XML_NS)) { XT_log.debug("found namespace-qualified attribute, adding prefix to the list of namespaces on the XMLObject"); - xmlObject.addNamespace(Namespace(nsuri, attribute->getPrefix())); + addNamespace(Namespace(nsuri, attribute->getPrefix())); } XT_log.debug("processing generic attribute"); - processAttribute(xmlObject, attribute); + processAttribute(attribute); } } -void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* domElement, XMLObject& xmlObject) const +void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* domElement) { #ifdef _DEBUG xmltooling::NDC ndc("unmarshallChildElements"); @@ -156,7 +137,6 @@ void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* do DOMNodeList* childNodes = domElement->getChildNodes(); DOMNode* childNode; - const Unmarshaller* unmarshaller; if (!childNodes || childNodes->getLength()==0) { XT_log.debug("element had no children"); return; @@ -166,13 +146,11 @@ void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* do for (XMLSize_t i = 0; i < childNodes->getLength(); i++) { childNode = childNodes->item(i); if (childNode->getNodeType() == DOMNode::ELEMENT_NODE) { - unmarshaller = Unmarshaller::getUnmarshaller(static_cast(childNode)); - if (!unmarshaller) { + const XMLObjectBuilder* builder = XMLObjectBuilder::getBuilder(static_cast(childNode)); + if (!builder) { auto_ptr cname(XMLHelper::getNodeQName(childNode)); - XT_log.error( - "no default unmarshaller installed, found unknown child element (%s)", cname->toString().c_str() - ); - throw UnmarshallingException("Unmarshaller found unknown child element, but no default unmarshaller was found."); + XT_log.error("no default builder installed, found unknown child element (%s)", cname->toString().c_str()); + throw UnmarshallingException("Unmarshaller found unknown child element, but no default builder was found."); } if (XT_log.isDebugEnabled()) { @@ -181,13 +159,14 @@ void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* do } // Retain ownership of the unmarshalled child until it's processed by the parent. - auto_ptr childObject(unmarshaller->unmarshall(static_cast(childNode))); - processChildElement(xmlObject, childObject.get(), static_cast(childNode)); + auto_ptr childObject(builder->buildObject(static_cast(childNode))); + childObject->unmarshall(static_cast(childNode)); + processChildElement(childObject.get(), static_cast(childNode)); childObject.release(); } else if (childNode->getNodeType() == DOMNode::TEXT_NODE) { XT_log.debug("processing element content"); - processElementContent(xmlObject, childNode->getNodeValue()); + processElementContent(childNode->getNodeValue()); } } } diff --git a/xmltooling/io/AbstractXMLObjectUnmarshaller.h b/xmltooling/io/AbstractXMLObjectUnmarshaller.h index f7d05aa..b85ce01 100644 --- a/xmltooling/io/AbstractXMLObjectUnmarshaller.h +++ b/xmltooling/io/AbstractXMLObjectUnmarshaller.h @@ -23,98 +23,84 @@ #if !defined(__xmltooling_xmlunmarshaller_h__) #define __xmltooling_xmlunmarshaller_h__ -#include +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif namespace xmltooling { /** * A thread-safe abstract unmarshaller. */ - class XMLTOOL_API AbstractXMLObjectUnmarshaller : public virtual Unmarshaller + class XMLTOOL_API AbstractXMLObjectUnmarshaller : public virtual AbstractDOMCachingXMLObject { public: virtual ~AbstractXMLObjectUnmarshaller() {} /** - * @see Unmarshaller::unmarshall() + * @see XMLObject::unmarshall() */ - XMLObject* unmarshall(DOMElement* element, bool bindDocument=false) const; + XMLObject* unmarshall(DOMElement* element, bool bindDocument=false); protected: - AbstractXMLObjectUnmarshaller(); + AbstractXMLObjectUnmarshaller() {} /** - * Constructs the XMLObject that the given DOM Element will be unmarshalled into. If the DOM element has an XML - * Schema type defined this method will attempt to retrieve an XMLObjectBuilder using the schema type. If no - * schema type is present or no builder is registered for the schema type, the element's QName is used. Once - * the builder is found the XMLObject is created by invoking XMLObjectBuilder::buildObject(). - * Extending classes may wish to override this logic if more than just schema type or element name - * (e.g. element attributes or content) need to be used to determine how to create the XMLObject. - * - * @param domElement the DOM Element the created XMLObject will represent - * @return the empty XMLObject that DOM Element can be unmarshalled into - * - * @throws UnmarshallingException thrown if there is now XMLObjectBuilder registered for the given DOM Element - */ - virtual XMLObject* buildXMLObject(const DOMElement* domElement) const; - - /** - * Unmarshalls the attributes from the given DOM Element into the given XMLObject. If the attribute is an XML - * namespace declaration the namespace is added to the given element via XMLObject::addNamespace(). - * If it is a schema type (xsi:type) the schema type is added to the element via XMLObject::setSchemaType(). + * Unmarshalls the attributes from the given DOM Element into the XMLObject. If the attribute + * is an XML namespace declaration the namespace is added via XMLObject::addNamespace(). + * If it is a schema type (xsi:type) the schema type is added via XMLObject::setSchemaType(). * All other attributes are passed to the processAttribute hook. * * @param domElement the DOM Element whose attributes will be unmarshalled - * @param xmlObject the XMLObject that will recieve information from the DOM attribute * * @throws UnmarshallingException thrown if there is a problem unmarshalling an attribute */ - virtual void unmarshallAttributes(const DOMElement* domElement, XMLObject& xmlObject) const; + virtual void unmarshallAttributes(const DOMElement* domElement); /** - * Unmarshalls a given Element's children. For each child an unmarshaller is retrieved using - * getUnmarshaller(). The unmarshaller is then used to unmarshall the child element and the - * resulting XMLObject is passed to processChildElement() for further processing. + * Unmarshalls a given Element's children. The resulting XMLObject child is passed to + * processChildElement() for further processing. * * @param domElement the DOM Element whose children will be unmarshalled - * @param xmlObject the parent object of the unmarshalled children * * @throws UnmarshallingException thrown if an error occurs unmarshalling the child elements */ - virtual void unmarshallChildElements(const DOMElement* domElement, XMLObject& xmlObject) const; + virtual void unmarshallChildElements(const DOMElement* domElement); /** * Called after a child element has been unmarshalled so that it can be added to the parent XMLObject. * - * @param parent the parent XMLObject * @param child pointer to the child XMLObject * @param childRoot root element of the child (must not be stored, just a hint) * * @throws UnmarshallingException thrown if there is a problem adding the child to the parent */ - virtual void processChildElement(XMLObject& parent, XMLObject* child, const DOMElement* childRoot) const=0; + virtual void processChildElement(XMLObject* child, const DOMElement* childRoot)=0; /** * Called after an attribute has been unmarshalled so that it can be added to the XMLObject. * - * @param xmlObject the XMLObject * @param attribute the attribute being unmarshalled * * @throws UnmarshallingException thrown if there is a problem adding the attribute to the XMLObject */ - virtual void processAttribute(XMLObject& xmlObject, const DOMAttr* attribute) const=0; + virtual void processAttribute(const DOMAttr* attribute)=0; /** * Called if the element being unmarshalled contained textual content so that it can be added to the XMLObject. * - * @param xmlObject XMLObject the content will be given to * @param elementContent the Element's text content */ - virtual void processElementContent(XMLObject& xmlObject, const XMLCh* elementContent) const=0; - - void* m_log; + virtual void processElementContent(const XMLCh* elementContent)=0; }; }; +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + #endif /* __xmltooling_xmlunmarshaller_h__ */ diff --git a/xmltooling/io/Marshaller.cpp b/xmltooling/io/Marshaller.cpp deleted file mode 100644 index 2ed9d16..0000000 --- a/xmltooling/io/Marshaller.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2001-2006 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Marshaller.cpp - * - * Transforms XMLObjects into DOM trees - */ - -#include "internal.h" -#include "Marshaller.h" -#include "util/NDC.h" -#include "util/XMLHelper.h" - -#include - -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -map Marshaller::m_map; - -Marshaller* Marshaller::m_default=NULL; - -const Marshaller* Marshaller::getMarshaller(const XMLObject* xmlObject) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("getMarshaller"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Marshaller"); - - const QName* type=xmlObject->getSchemaType(); - const Marshaller* m = type ? getMarshaller(*type) : NULL; - if (m) { - if (log.isDebugEnabled()) { - log.debug("located Marshaller for schema type: %s", type->toString().c_str()); - } - return m; - } - - m = getMarshaller(xmlObject->getElementQName()); - if (m) { - if (log.isDebugEnabled()) { - log.debug("located Marshaller for element name: %s", xmlObject->getElementQName().toString().c_str()); - } - return m; - } - if (log.isDebugEnabled()) { - string qname=xmlObject->getElementQName().toString().c_str(); - log.debug("no Marshaller registered for element (%s), returning default", qname.empty() ? "unknown" : qname.c_str()); - } - return m_default; -} - -void Marshaller::destroyMarshallers() -{ - for_each(m_map.begin(),m_map.end(),cleanup_pair()); - m_map.clear(); - deregisterDefaultMarshaller(); -} diff --git a/xmltooling/io/Marshaller.h b/xmltooling/io/Marshaller.h deleted file mode 100644 index ba334c4..0000000 --- a/xmltooling/io/Marshaller.h +++ /dev/null @@ -1,201 +0,0 @@ -/* -* Copyright 2001-2006 Internet2 - * -* Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file Marshaller.h - * - * Transforms XMLObjects into DOM trees - */ - -#if !defined(__xmltooling_marshaller_h__) -#define __xmltooling_marshaller_h__ - -#include -#include -#include -#include -#ifndef XMLTOOLING_NO_XMLSEC - #include -#endif - -using namespace xercesc; - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * Supplies additional information to the marshalling process. - * Currently this only consists of signature related information. - */ - class XMLTOOL_API MarshallingContext - { - MAKE_NONCOPYABLE(MarshallingContext); - public: - MarshallingContext() {} - ~MarshallingContext() {} - -#ifndef XMLTOOLING_NO_XMLSEC - MarshallingContext(Signature* sig, const SigningContext* ctx) { - m_signingContexts.push_back(std::make_pair(sig,ctx)); - } - - /** Array of signing contexts, keyed off of the associated Signature */ - std::vector< std::pair > m_signingContexts; -#endif - }; - - /** - * Marshallers are used to marshall an XMLObject into a W3C DOM element. - */ - class XMLTOOL_API Marshaller - { - MAKE_NONCOPYABLE(Marshaller); - public: - Marshaller() {} - virtual ~Marshaller() {} - - /** - * Marshalls an object, and its children, into a DOM element. - * If a document is supplied, then it will be used to create the resulting elements. - * If the document does not have a Document Element set, then the resulting - * element will be set as the Document Element. If no document is supplied, then - * a new document will be created and bound to the lifetime of the root object being - * marshalled, unless an existing DOM can be reused without creating a new document. - * - * @param xmlObject the object to marshall - * @param document the DOM document the marshalled element will be placed in, or NULL - * @param ctx optional marshalling context - * @return the DOM element representing this XMLObject - * - * @throws MarshallingException thrown if there is a problem marshalling the given object - * @throws SignatureException thrown if a problem occurs during signature creation - */ - virtual DOMElement* marshall(XMLObject* xmlObject, DOMDocument* document=NULL, MarshallingContext* ctx=NULL) const=0; - - /** - * Marshall the given XMLObject and append it as a child of the given parent element. - * - * NOTE: The given Element must be within a DOM tree rooted in - * the Document owning the given Element. - * - * @param xmlObject the XMLObject to be marshalled - * @param parentElement the parent element to append the resulting DOM tree - * @param ctx optional marshalling context - * @return the marshalled element tree - - * @throws MarshallingException thrown if the given XMLObject can not be marshalled. - * @throws SignatureException thrown if a problem occurs during signature creation - */ - virtual DOMElement* marshall(XMLObject* xmlObject, DOMElement* parentElement, MarshallingContext* ctx=NULL) const=0; - - /** - * Retrieves a Marshaller using the key it was registered with. - * - * @param key the key used to register the marshaller - * @return the marshaller or NULL - */ - static const Marshaller* getMarshaller(const QName& key) { - std::map::const_iterator i=m_map.find(key); - return (i==m_map.end()) ? NULL : i->second; - } - - /** - * Retrieves a Marshaller for an XML object - * If no match is found, the default marshaller is returned, if any. - * - * @param xmlObject the object for which to return a marshaller - * @return the marshaller or NULL - */ - static const Marshaller* getMarshaller(const XMLObject* xmlObject); - - /** - * Retrieves default Marshaller for DOM elements - * - * @return the default marshaller or NULL - */ - static const Marshaller* getDefaultMarshaller() { - return m_default; - } - - /** - * Gets an immutable list of all the marshallers currently registered. - * - * @return list of all the marshallers currently registered - */ - static const std::map& getMarshallers() { - return m_map; - } - - /** - * Registers a new marshaller for the given key. - * - * @param key the key used to retrieve this marshaller later - * @param marshaller the marshaller - */ - static void registerMarshaller(const QName& key, Marshaller* marshaller) { - deregisterMarshaller(key); - m_map[key]=marshaller; - } - - /** - * Registers default marshaller - * - * @param marshaller the default marshaller - */ - static void registerDefaultMarshaller(Marshaller* marshaller) { - deregisterDefaultMarshaller(); - m_default=marshaller; - } - - /** - * Deregisters a marshaller. - * - * @param key the key for the marshaller to be deregistered - */ - static void deregisterMarshaller(const QName& key) { - delete getMarshaller(key); - m_map.erase(key); - } - - /** - * Deregisters default marshaller. - */ - static void deregisterDefaultMarshaller() { - delete m_default; - m_default=NULL; - } - - /** - * Unregisters and destroys all registered marshallers. - */ - static void destroyMarshallers(); - - private: - static std::map m_map; - static Marshaller* m_default; - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_marshaller_h__ */ diff --git a/xmltooling/io/Unmarshaller.cpp b/xmltooling/io/Unmarshaller.cpp deleted file mode 100644 index 4c3aef4..0000000 --- a/xmltooling/io/Unmarshaller.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2001-2006 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Unmarshaller.cpp - * - * Transforms DOM trees into XMLObjects - */ - -#include "internal.h" -#include "Unmarshaller.h" -#include "util/NDC.h" -#include "util/XMLHelper.h" - -#include - -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -map Unmarshaller::m_map; - -Unmarshaller* Unmarshaller::m_default=NULL; - -const Unmarshaller* Unmarshaller::getUnmarshaller(const DOMElement* domElement) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("getUnmarshaller"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Unmarshaller"); - - auto_ptr schemaType(XMLHelper::getXSIType(domElement)); - const Unmarshaller* m = schemaType.get() ? getUnmarshaller(*(schemaType.get())) : NULL; - if (m) { - if (log.isDebugEnabled()) { - log.debug("located Unmarshaller for schema type: %s", schemaType->toString().c_str()); - } - return m; - } - - auto_ptr elementName(XMLHelper::getNodeQName(domElement)); - m = getUnmarshaller(*(elementName.get())); - if (m) { - if (log.isDebugEnabled()) { - log.debug("located Unmarshaller for element name: %s", elementName->toString().c_str()); - } - return m; - } - - if (log.isDebugEnabled()) { - log.debug("no Unmarshaller registered for element (%s), returning default", elementName->toString().c_str()); - } - return m_default; -} - -void Unmarshaller::destroyUnmarshallers() -{ - for_each(m_map.begin(),m_map.end(),cleanup_pair()); - m_map.clear(); - deregisterDefaultUnmarshaller(); -} diff --git a/xmltooling/io/Unmarshaller.h b/xmltooling/io/Unmarshaller.h deleted file mode 100644 index 4e99a8d..0000000 --- a/xmltooling/io/Unmarshaller.h +++ /dev/null @@ -1,156 +0,0 @@ -/* -* Copyright 2001-2006 Internet2 - * -* Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file Unmarshaller.h - * - * Transforms DOM trees into XMLObjects - */ - -#if !defined(__xmltooling_unmarshaller_h__) -#define __xmltooling_unmarshaller_h__ - -#include -#include -#include - -using namespace xercesc; - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * Unmarshallers are used to unmarshall a W3C DOM element into an XMLObject. - */ - class XMLTOOL_API Unmarshaller - { - MAKE_NONCOPYABLE(Unmarshaller); - public: - Unmarshaller() {} - virtual ~Unmarshaller() {} - - /** - * Unmarshalls the given W3C DOM element into an XMLObject. - * The root of a given XML construct should be unmarshalled with the bindDocument parameter - * set to true. - * - * @param element the DOM element to unmarshall - * @param bindDocument true iff the resulting XMLObject should take ownership of the DOM's Document - * - * @return the unmarshalled XMLObject - * - * @throws UnmarshallingException thrown if an error occurs unmarshalling the DOM element into the XMLObject - */ - virtual XMLObject* unmarshall(DOMElement* element, bool bindDocument=false) const=0; - - /** - * Retrieves an unmarshaller using the key it was registered with. - * - * @param key the key used to register the unmarshaller - * @return the unmarshaller - */ - static const Unmarshaller* getUnmarshaller(const QName& key) { - std::map::const_iterator i=m_map.find(key); - return (i==m_map.end()) ? NULL : i->second; - } - - /** - * Retrieves an Unmarshaller for a DOM element. - * If no match is found, the default unmarshaller is returned, if any. - * - * @param element the element for which to return an unmarshaller - * @return the unmarshaller or NULL - */ - static const Unmarshaller* getUnmarshaller(const DOMElement* element); - - /** - * Retrieves the default Unmarshaller for an unknown DOM element - * - * @return the default unmarshaller or NULL - */ - static const Unmarshaller* getDefaultUnmarshaller() { - return m_default; - } - - /** - * Gets an immutable list of all the unmarshallers currently registered. - * - * @return list of all the unmarshallers currently registered - */ - static const std::map& getUnmarshallers() { - return m_map; - } - - /** - * Registers a new unmarshaller for the given key. - * - * @param key the key used to retrieve this unmarshaller later - * @param unmarshaller the unmarshaller - */ - static void registerUnmarshaller(const QName& key, Unmarshaller* unmarshaller) { - deregisterUnmarshaller(key); - m_map[key]=unmarshaller; - } - - /** - * Registers a new default unmarshaller - * - * @param unmarshaller the default unmarshaller - */ - static void registerDefaultUnmarshaller(Unmarshaller* unmarshaller) { - deregisterDefaultUnmarshaller(); - m_default=unmarshaller; - } - - /** - * Deregisters a unmarshaller. - * - * @param key the key for the unmarshaller to be deregistered - */ - static void deregisterUnmarshaller(const QName& key) { - delete getUnmarshaller(key); - m_map.erase(key); - } - - /** - * Deregisters the default unmarshaller. - */ - static void deregisterDefaultUnmarshaller() { - delete m_default; - m_default=NULL; - } - - /** - * Unregisters and destroys all registered unmarshallers. - */ - static void destroyUnmarshallers(); - - private: - static std::map m_map; - static Unmarshaller* m_default; - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_unmarshaller_h__ */ diff --git a/xmltooling/signature/Signature.h b/xmltooling/signature/Signature.h index 9a8838a..c1031da 100644 --- a/xmltooling/signature/Signature.h +++ b/xmltooling/signature/Signature.h @@ -25,6 +25,7 @@ #include #include +#include namespace xmltooling { @@ -45,29 +46,6 @@ namespace xmltooling { static const XMLCh LOCAL_NAME[]; /** - * Gets the canonicalization method for the ds:SignedInfo element. - * - * @return the canonicalization method - */ - virtual const XMLCh* getCanonicalizationMethod() const=0; - - /** - * Gets the signing algorithm for the signature. - * - * @return the signature algorithm - */ - virtual const XMLCh* getSignatureAlgorithm() const=0; - - /** - * Returns the ds:KeyInfo information attached to the signature. - * The Signature object must be marshalled before this will return anything. - * The caller MUST NOT mutate the information through the provided pointer. - * - * @return the ds:KeyInfo information - */ - virtual DSIGKeyInfoList* getKeyInfo() const=0; - - /** * Sets the canonicalization method for the ds:SignedInfo element * * @param c14n the canonicalization method @@ -87,8 +65,16 @@ namespace xmltooling { * @param ctx the signing context that determines the signature's content * @throws SignatureException thrown if the signing operation fails */ - virtual void sign(const SigningContext* ctx)=0; + virtual void sign(const SigningContext& ctx)=0; + /** + * Verifies an XML signature based on the supplied context. + * + * @param ctx the verifying context that validates the signature's content + * @throws SignatureException thrown if the verifying operation fails + */ + virtual void verify(const VerifyingContext& ctx) const=0; + protected: Signature() {} }; diff --git a/xmltooling/signature/SigningContext.h b/xmltooling/signature/SigningContext.h index 72648d6..2e6d249 100644 --- a/xmltooling/signature/SigningContext.h +++ b/xmltooling/signature/SigningContext.h @@ -47,7 +47,9 @@ namespace xmltooling { * appropriate signature transforms, references, etc. * This method MAY attach ds:KeyInfo information, or a set of X.509 * certificates can be returned from the SigningContext::getX509Certificates() - * method instead. + * method instead. + * + * @param sig native signature interface */ virtual void createSignature(DSIGSignature* sig) const=0; @@ -56,6 +58,8 @@ namespace xmltooling { * the ds:KeyInfo element in a ds:X509Data chain. * The certificate corresponding to the signing key SHOULD be * first, followed by any additional intermediates to append. + * + * @return an immutable collection of certificates to embed */ virtual const std::vector& getX509Certificates() const=0; @@ -63,6 +67,8 @@ namespace xmltooling { * Gets the signing key to use. * Must be compatible with the intended signature algorithm. Ownership of the key * MUST be transferred to the caller. + * + * @return pointer to a signing key, will be freed by caller */ virtual XSECCryptoKey* getSigningKey() const=0; diff --git a/xmltooling/signature/impl/XMLSecSignature.cpp b/xmltooling/signature/impl/XMLSecSignature.cpp index 5221329..eb01345 100644 --- a/xmltooling/signature/impl/XMLSecSignature.cpp +++ b/xmltooling/signature/impl/XMLSecSignature.cpp @@ -97,7 +97,7 @@ public: } }; -void XMLSecSignatureImpl::sign(const SigningContext* ctx) +void XMLSecSignatureImpl::sign(const SigningContext& ctx) { Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature"); log.debug("applying signature"); @@ -107,15 +107,15 @@ void XMLSecSignatureImpl::sign(const SigningContext* ctx) try { log.debug("creating signature content"); - ctx->createSignature(m_signature); - const std::vector& certs=ctx->getX509Certificates(); + ctx.createSignature(m_signature); + const std::vector& certs=ctx.getX509Certificates(); if (!certs.empty()) { DSIGKeyInfoX509* x509Data=m_signature->appendX509Data(); for_each(certs.begin(),certs.end(),bind1st(_addcert(),x509Data)); } log.debug("computing signature"); - m_signature->setSigningKey(ctx->getSigningKey()); + m_signature->setSigningKey(ctx.getSigningKey()); m_signature->sign(); } catch(XSECException& e) { @@ -127,26 +127,42 @@ void XMLSecSignatureImpl::sign(const SigningContext* ctx) } } -DOMElement* XMLSecSignatureMarshaller::marshall(XMLObject* xmlObject, DOMDocument* document, MarshallingContext* ctx) const +void XMLSecSignatureImpl::verify(const VerifyingContext& ctx) const +{ + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature"); + log.debug("verifying signature"); + + if (!m_signature) + throw SignatureException("Only a marshalled Signature object can be verified."); + + try { + ctx.verifySignature(m_signature); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + throw SignatureException(string("Caught an XMLSecurity exception verifying signature: ") + temp.get()); + } + catch(XSECCryptoException& e) { + throw SignatureException(string("Caught an XMLSecurity exception verifying signature: ") + e.getMsg()); + } +} + +DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, MarshallingContext* ctx) const { #ifdef _DEBUG xmltooling::NDC ndc("marshall"); #endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Marshaller"); + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature"); log.debug("marshalling ds:Signature"); - XMLSecSignatureImpl* sig=dynamic_cast(xmlObject); - if (!sig) - throw MarshallingException("Only objects of class XMLSecSignatureImpl can be marshalled."); - - DOMElement* cachedDOM=sig->getDOM(); + DOMElement* cachedDOM=getDOM(); if (cachedDOM) { if (!document || document==cachedDOM->getOwnerDocument()) { log.debug("Signature has a usable cached DOM, reusing it"); if (document) setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM); - sig->releaseParentDOM(true); + releaseParentDOM(true); return cachedDOM; } @@ -155,11 +171,12 @@ DOMElement* XMLSecSignatureMarshaller::marshall(XMLObject* xmlObject, DOMDocumen cachedDOM=static_cast(document->importNode(cachedDOM, true)); try { - XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(sig->m_signature); - sig->m_signature=NULL; - sig->m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( + XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature); + m_signature=NULL; + m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( document, cachedDOM ); + m_signature->load(); } catch(XSECException& e) { auto_ptr_char temp(e.getMsg()); @@ -172,29 +189,27 @@ DOMElement* XMLSecSignatureMarshaller::marshall(XMLObject* xmlObject, DOMDocumen // Recache the DOM. setDocumentElement(document, cachedDOM); log.debug("caching imported DOM for Signature"); - sig->setDOM(cachedDOM, false); - sig->releaseParentDOM(true); + setDOM(cachedDOM, false); + releaseParentDOM(true); return cachedDOM; } // If we get here, we didn't have a usable DOM. bool bindDocument=false; - if (sig->m_xml.empty()) { + if (m_xml.empty()) { // Fresh signature, so we just create an empty one. log.debug("creating empty Signature element"); if (!document) { document=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument(); bindDocument=true; } - sig->m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature(); - sig->m_signature->setDSIGNSPrefix(Signature::PREFIX); - cachedDOM=sig->m_signature->createBlankSignature( - document, sig->getCanonicalizationMethod(), sig->getSignatureAlgorithm() - ); + m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature(); + m_signature->setDSIGNSPrefix(Signature::PREFIX); + cachedDOM=m_signature->createBlankSignature(document, getCanonicalizationMethod(), getSignatureAlgorithm()); } else { // We need to reparse the XML we saved off into a new DOM. - MemBufInputSource src(reinterpret_cast(sig->m_xml.c_str()),sig->m_xml.length(),"XMLSecSignatureImpl"); + MemBufInputSource src(reinterpret_cast(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl"); Wrapper4InputSource dsrc(&src,false); log.debug("parsing Signature XML back into DOM tree"); DOMDocument* internalDoc=XMLToolingInternalConfig::getInternalConfig().m_parserPool->parse(dsrc); @@ -214,9 +229,10 @@ DOMElement* XMLSecSignatureMarshaller::marshall(XMLObject* xmlObject, DOMDocumen // Now reload the signature from the DOM. try { - sig->m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( + m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( document, cachedDOM ); + m_signature->load(); } catch(XSECException& e) { if (bindDocument) @@ -234,31 +250,27 @@ DOMElement* XMLSecSignatureMarshaller::marshall(XMLObject* xmlObject, DOMDocumen // Recache the DOM and clear the serialized copy. setDocumentElement(document, cachedDOM); log.debug("caching DOM for Signature (document is %sbound)", bindDocument ? "" : "not "); - sig->setDOM(cachedDOM, bindDocument); - sig->releaseParentDOM(true); - sig->m_xml.erase(); + setDOM(cachedDOM, bindDocument); + releaseParentDOM(true); + m_xml.erase(); return cachedDOM; } -DOMElement* XMLSecSignatureMarshaller::marshall(XMLObject* xmlObject, DOMElement* parentElement, MarshallingContext* ctx) const +DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, MarshallingContext* ctx) const { #ifdef _DEBUG xmltooling::NDC ndc("marshall"); #endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Marshaller"); + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature"); log.debug("marshalling ds:Signature"); - XMLSecSignatureImpl* sig=dynamic_cast(xmlObject); - if (!sig) - throw MarshallingException("Only objects of class XMLSecSignatureImpl can be marshalled."); - - DOMElement* cachedDOM=sig->getDOM(); + DOMElement* cachedDOM=getDOM(); if (cachedDOM) { if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) { log.debug("Signature has a usable cached DOM, reusing it"); parentElement->appendChild(cachedDOM); - sig->releaseParentDOM(true); + releaseParentDOM(true); return cachedDOM; } @@ -267,11 +279,12 @@ DOMElement* XMLSecSignatureMarshaller::marshall(XMLObject* xmlObject, DOMElement cachedDOM=static_cast(parentElement->getOwnerDocument()->importNode(cachedDOM, true)); try { - XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(sig->m_signature); - sig->m_signature=NULL; - sig->m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( + XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature); + m_signature=NULL; + m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( parentElement->getOwnerDocument(), cachedDOM ); + m_signature->load(); } catch(XSECException& e) { auto_ptr_char temp(e.getMsg()); @@ -284,36 +297,37 @@ DOMElement* XMLSecSignatureMarshaller::marshall(XMLObject* xmlObject, DOMElement // Recache the DOM. parentElement->appendChild(cachedDOM); log.debug("caching imported DOM for Signature"); - sig->setDOM(cachedDOM, false); - sig->releaseParentDOM(true); + setDOM(cachedDOM, false); + releaseParentDOM(true); return cachedDOM; } // If we get here, we didn't have a usable DOM. - if (sig->m_xml.empty()) { + if (m_xml.empty()) { // Fresh signature, so we just create an empty one. log.debug("creating empty Signature element"); - sig->m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature(); - sig->m_signature->setDSIGNSPrefix(Signature::PREFIX); - cachedDOM=sig->m_signature->createBlankSignature( - parentElement->getOwnerDocument(), sig->getCanonicalizationMethod(), sig->getSignatureAlgorithm() + m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature(); + m_signature->setDSIGNSPrefix(Signature::PREFIX); + cachedDOM=m_signature->createBlankSignature( + parentElement->getOwnerDocument(), getCanonicalizationMethod(), getSignatureAlgorithm() ); } else { - MemBufInputSource src(reinterpret_cast(sig->m_xml.c_str()),sig->m_xml.length(),"XMLSecSignatureImpl"); + MemBufInputSource src(reinterpret_cast(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl"); Wrapper4InputSource dsrc(&src,false); log.debug("parsing XML back into DOM tree"); DOMDocument* internalDoc=XMLToolingInternalConfig::getInternalConfig().m_parserPool->parse(dsrc); log.debug("reimporting new DOM into caller-supplied document"); - cachedDOM=static_cast(parentElement->getOwnerDocument()->importNode(internalDoc->getDocumentElement(), true)); + cachedDOM=static_cast(parentElement->getOwnerDocument()->importNode(internalDoc->getDocumentElement(),true)); internalDoc->release(); // Now reload the signature from the DOM. try { - sig->m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( + m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( parentElement->getOwnerDocument(), cachedDOM ); + m_signature->load(); } catch(XSECException& e) { auto_ptr_char temp(e.getMsg()); @@ -327,21 +341,21 @@ DOMElement* XMLSecSignatureMarshaller::marshall(XMLObject* xmlObject, DOMElement // Recache the DOM and clear the serialized copy. parentElement->appendChild(cachedDOM); log.debug("caching DOM for Signature"); - sig->setDOM(cachedDOM, false); - sig->releaseParentDOM(true); - sig->m_xml.erase(); + setDOM(cachedDOM, false); + releaseParentDOM(true); + m_xml.erase(); return cachedDOM; } -XMLObject* XMLSecSignatureUnmarshaller::unmarshall(DOMElement* element, bool bindDocument) const +XMLObject* XMLSecSignatureImpl::unmarshall(DOMElement* element, bool bindDocument) { - Category::getInstance(XMLTOOLING_LOGCAT".Unmarshaller").debug("unmarshalling ds:Signature"); + Category::getInstance(XMLTOOLING_LOGCAT".Signature").debug("unmarshalling ds:Signature"); - auto_ptr ret(new XMLSecSignatureImpl()); try { - ret->m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( + m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( element->getOwnerDocument(), element ); + m_signature->load(); } catch(XSECException& e) { auto_ptr_char temp(e.getMsg()); @@ -351,6 +365,6 @@ XMLObject* XMLSecSignatureUnmarshaller::unmarshall(DOMElement* element, bool bin throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg()); } - ret->setDOM(element, bindDocument); - return ret.release(); + setDOM(element, bindDocument); + return this; } diff --git a/xmltooling/signature/impl/XMLSecSignature.h b/xmltooling/signature/impl/XMLSecSignature.h index c196be5..d97fd81 100644 --- a/xmltooling/signature/impl/XMLSecSignature.h +++ b/xmltooling/signature/impl/XMLSecSignature.h @@ -15,7 +15,7 @@ */ /** - * @file XMLSecSignature.h + * XMLSecSignature.h * * Signature classes for XMLSec-based signature-handling */ @@ -37,10 +37,6 @@ namespace xmltooling { - /** - * XMLObject representing XML Digital Signature, version 20020212, Signature element. - * Manages an Apache XML Signature object and the associated DOM. - */ class XMLTOOL_DLLLOCAL XMLSecSignatureImpl : public UnknownElementImpl, public virtual Signature { public: @@ -51,6 +47,10 @@ namespace xmltooling { void releaseDOM(); XMLObject* clone() const; + DOMElement* marshall(DOMDocument* document=NULL, MarshallingContext* ctx=NULL) const; + DOMElement* marshall(DOMElement* parentElement, MarshallingContext* ctx=NULL) const; + XMLObject* unmarshall(DOMElement* element, bool bindDocument=false); + // Getters const XMLCh* getCanonicalizationMethod() const { return m_c14n ? m_c14n : DSIGConstants::s_unicodeStrURIEXC_C14N_NOC; } const XMLCh* getSignatureAlgorithm() const { return m_sm ? m_sm : DSIGConstants::s_unicodeStrURIRSA_SHA1; } @@ -60,69 +60,23 @@ namespace xmltooling { void setCanonicalizationMethod(const XMLCh* c14n) { m_c14n = prepareForAssignment(m_c14n,c14n); } void setSignatureAlgorithm(const XMLCh* sm) { m_sm = prepareForAssignment(m_sm,sm); } - void sign(const SigningContext* ctx); + void sign(const SigningContext& ctx); + void verify(const VerifyingContext& ctx) const; private: - DSIGSignature* m_signature; + mutable DSIGSignature* m_signature; XMLCh* m_c14n; XMLCh* m_sm; - - friend class XMLTOOL_DLLLOCAL XMLSecSignatureMarshaller; - friend class XMLTOOL_DLLLOCAL XMLSecSignatureUnmarshaller; }; - /** - * Factory for XMLSecSignatureImpl objects - */ class XMLTOOL_DLLLOCAL XMLSecSignatureBuilder : public virtual XMLObjectBuilder { public: - /** - * @see XMLObjectBuilder::buildObject() - */ - XMLObject* buildObject() const { + XMLObject* buildObject(const DOMElement* e=NULL) const { return new XMLSecSignatureImpl(); } }; - /** - * Marshaller for XMLSecSignatureImpl objects - */ - class XMLTOOL_DLLLOCAL XMLSecSignatureMarshaller : public virtual Marshaller - { - public: - /** - * @see Marshaller::marshall(XMLObject*,DOMDocument*, const MarshallingContext*) - */ - DOMElement* marshall(XMLObject* xmlObject, DOMDocument* document=NULL, MarshallingContext* ctx=NULL) const; - - /** - * @see Marshaller::marshall(XMLObject*,DOMElement*, const MarshallingContext* ctx) - */ - DOMElement* marshall(XMLObject* xmlObject, DOMElement* parentElement, MarshallingContext* ctx=NULL) const; - - protected: - void setDocumentElement(DOMDocument* document, DOMElement* element) const { - DOMElement* documentRoot = document->getDocumentElement(); - if (documentRoot) - document->replaceChild(documentRoot, element); - else - document->appendChild(element); - } - }; - - /** - * Unmarshaller for XMLSecSignatureImpl objects - */ - class XMLTOOL_DLLLOCAL XMLSecSignatureUnmarshaller : public virtual Unmarshaller - { - public: - /** - * @see Unmarshaller::unmarshall() - */ - XMLObject* unmarshall(DOMElement* element, bool bindDocument=false) const; - }; - }; #if defined (_MSC_VER) diff --git a/xmltooling/xmltooling.vcproj b/xmltooling/xmltooling.vcproj index deafcaa..11c0f60 100644 --- a/xmltooling/xmltooling.vcproj +++ b/xmltooling/xmltooling.vcproj @@ -194,6 +194,10 @@ > + + @@ -244,14 +248,6 @@ RelativePath=".\io\AbstractXMLObjectUnmarshaller.cpp" > - - - - - - - - parse(fs); TS_ASSERT(doc!=NULL); - const Unmarshaller* u = Unmarshaller::getUnmarshaller(doc->getDocumentElement()); - TS_ASSERT(u!=NULL); + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); - auto_ptr wcObject(dynamic_cast(u->unmarshall(doc->getDocumentElement(),true))); + auto_ptr wcObject( + dynamic_cast(b->buildObject(doc->getDocumentElement())->unmarshall(doc->getDocumentElement(),true)) + ); TS_ASSERT(wcObject.get()!=NULL); ListOf(XMLObject) kids=wcObject->getXMLObjects(); TSM_ASSERT_EQUALS("Number of child elements was not expected value", 2, kids.size()); - WildcardXMLObject* wc1=dynamic_cast(*(++kids.begin())); WildcardXMLObject* wc2=dynamic_cast(*(++(wc1->getXMLObjects().begin()))); TSM_ASSERT_EQUALS("Number of child elements was not expected value", 3, wc2->getXMLObjects().size()); diff --git a/xmltoolingtest/Makefile.am b/xmltoolingtest/Makefile.am index 0e26bc0..448e160 100644 --- a/xmltoolingtest/Makefile.am +++ b/xmltoolingtest/Makefile.am @@ -17,7 +17,6 @@ endif xmltoolingtest_h = \ ComplexXMLObjectTest.h \ MarshallingTest.h \ - UnknownTest.h \ UnmarshallingTest.h \ xmltoolingtest.h \ ${xmlsec_sources} diff --git a/xmltoolingtest/MarshallingTest.h b/xmltoolingtest/MarshallingTest.h index b5f0814..79dfaf1 100644 --- a/xmltoolingtest/MarshallingTest.h +++ b/xmltoolingtest/MarshallingTest.h @@ -25,14 +25,10 @@ public: void setUp() { XMLObjectBuilder::registerBuilder(m_qname, new SimpleXMLObjectBuilder()); - Marshaller::registerMarshaller(m_qname, new SimpleXMLObjectMarshaller()); - Unmarshaller::registerUnmarshaller(m_qname, new SimpleXMLObjectUnmarshaller()); } void tearDown() { XMLObjectBuilder::deregisterBuilder(m_qname); - Marshaller::deregisterMarshaller(m_qname); - Unmarshaller::deregisterUnmarshaller(m_qname); } void testMarshallingWithAttributes() { @@ -43,7 +39,7 @@ public: TS_ASSERT(sxObject.get()!=NULL); sxObject->setId(expected.get()); - DOMElement* rootElement = Marshaller::getMarshaller(sxObject.get())->marshall(sxObject.get()); + DOMElement* rootElement = sxObject->marshall(); string path=data_path + "SimpleXMLObjectWithAttribute.xml"; ifstream fs(path.c_str()); @@ -62,7 +58,7 @@ public: TS_ASSERT(sxObject.get()!=NULL); sxObject->setValue(expected.get()); - DOMElement* rootElement = Marshaller::getMarshaller(sxObject.get())->marshall(sxObject.get()); + DOMElement* rootElement = sxObject->marshall(); string path=data_path + "SimpleXMLObjectWithContent.xml"; ifstream fs(path.c_str()); @@ -76,15 +72,15 @@ public: void testMarshallingWithChildElements() { TS_TRACE("testMarshallingWithChildElements"); - const XMLObjectBuilder* b=XMLObjectBuilder::getBuilder(m_qname); + const SimpleXMLObjectBuilder* b=dynamic_cast(XMLObjectBuilder::getBuilder(m_qname)); TS_ASSERT(b!=NULL); - auto_ptr sxObject(dynamic_cast(b->buildObject())); + auto_ptr sxObject(b->buildObject()); TS_ASSERT(sxObject.get()!=NULL); VectorOf(SimpleXMLObject) kids=sxObject->getSimpleXMLObjects(); - kids.push_back(dynamic_cast(b->buildObject())); - kids.push_back(dynamic_cast(b->buildObject())); - kids.push_back(dynamic_cast(b->buildObject())); + kids.push_back(b->buildObject()); + kids.push_back(b->buildObject()); + kids.push_back(b->buildObject()); // Test some collection stuff auto_ptr_XMLCh foo("Foo"); @@ -94,7 +90,7 @@ public: kids.erase(kids.begin()+1); TS_ASSERT_SAME_DATA(kids.back()->getValue(), bar.get(), XMLString::stringLen(bar.get())); - DOMElement* rootElement = Marshaller::getMarshaller(sxObject.get())->marshall(sxObject.get()); + DOMElement* rootElement = sxObject->marshall(); string path=data_path + "SimpleXMLObjectWithChildren.xml"; ifstream fs(path.c_str()); diff --git a/xmltoolingtest/SignatureTest.h b/xmltoolingtest/SignatureTest.h index 2087c4e..2582b15 100644 --- a/xmltoolingtest/SignatureTest.h +++ b/xmltoolingtest/SignatureTest.h @@ -20,10 +20,11 @@ #include #include #include +#include #include #include -class TestContext : public SigningContext +class TestContext : public SigningContext, public VerifyingContext { XSECCryptoKey* m_key; vector m_certs; @@ -69,6 +70,14 @@ public: ref->appendEnvelopedSignatureTransform(); ref->appendCanonicalizationTransform(CANON_C14NE_NOC); } + + void verifySignature(DSIGSignature* sig) const { + const XMLCh* uri=sig->getReferenceList()->item(0)->getURI(); + TSM_ASSERT_SAME_DATA("Reference URI does not match.",uri,m_uri,XMLString::stringLen(uri)); + XSECKeyInfoResolverDefault resolver; + sig->setKeyInfoResolver(&resolver); // It will clone the resolver for us. + sig->verify(); + } const std::vector& getX509Certificates() const { return m_certs; } XSECCryptoKey* getSigningKey() const { return m_key->clone(); } @@ -81,27 +90,23 @@ public: void setUp() { XMLObjectBuilder::registerBuilder(m_qname, new SimpleXMLObjectBuilder()); - Marshaller::registerMarshaller(m_qname, new SimpleXMLObjectMarshaller()); - Unmarshaller::registerUnmarshaller(m_qname, new SimpleXMLObjectUnmarshaller()); } void tearDown() { XMLObjectBuilder::deregisterBuilder(m_qname); - Marshaller::deregisterMarshaller(m_qname); - Unmarshaller::deregisterUnmarshaller(m_qname); } void testSignature() { TS_TRACE("testSignature"); - const XMLObjectBuilder* b=XMLObjectBuilder::getBuilder(m_qname); + const SimpleXMLObjectBuilder* b=dynamic_cast(XMLObjectBuilder::getBuilder(m_qname)); TS_ASSERT(b!=NULL); - auto_ptr sxObject(dynamic_cast(b->buildObject())); + auto_ptr sxObject(b->buildObject()); TS_ASSERT(sxObject.get()!=NULL); VectorOf(SimpleXMLObject) kids=sxObject->getSimpleXMLObjects(); - kids.push_back(dynamic_cast(b->buildObject())); - kids.push_back(dynamic_cast(b->buildObject())); + kids.push_back(b->buildObject()); + kids.push_back(b->buildObject()); // Test some collection stuff auto_ptr_XMLCh foo("Foo"); @@ -116,7 +121,7 @@ public: // Signing context for the whole document. TestContext tc(&chNull); MarshallingContext mctx(sig,&tc); - DOMElement* rootElement = Marshaller::getMarshaller(sxObject.get())->marshall(sxObject.get(),(DOMDocument*)NULL,&mctx); + DOMElement* rootElement = sxObject->marshall((DOMDocument*)NULL,&mctx); string buf; XMLHelper::serialize(rootElement, buf); @@ -124,10 +129,17 @@ public: istringstream in(buf); DOMDocument* doc=nonvalidatingPool->parse(in); - const Unmarshaller* u = Unmarshaller::getUnmarshaller(doc->getDocumentElement()); - auto_ptr sxObject2(dynamic_cast(u->unmarshall(doc->getDocumentElement(),true))); + auto_ptr sxObject2(dynamic_cast(b->buildObject()->unmarshall(doc->getDocumentElement(),true))); TS_ASSERT(sxObject2.get()!=NULL); TS_ASSERT(sxObject2->getSignature()!=NULL); + + try { + sxObject2->getSignature()->verify(tc); + } + catch (SignatureException& e) { + TS_TRACE(e.what()); + throw; + } } }; diff --git a/xmltoolingtest/UnknownTest.h b/xmltoolingtest/UnknownTest.h deleted file mode 100644 index 31dbec9..0000000 --- a/xmltoolingtest/UnknownTest.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2001-2005 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "XMLObjectBaseTestCase.h" - -#include - - -class UnknownTest : public CxxTest::TestSuite { -public: - - void testUnknown() { - ifstream fs("../xmltoolingtest/data/SimpleXMLObjectWithChildren.xml"); - DOMDocument* doc=nonvalidatingPool->parse(fs); - TS_ASSERT(doc!=NULL); - - string buf1; - XMLHelper::serialize(doc->getDocumentElement(), buf1); - - const Unmarshaller* u=Unmarshaller::getUnmarshaller(doc->getDocumentElement()); - TS_ASSERT(u!=NULL); - - auto_ptr xmlObject(u->unmarshall(doc->getDocumentElement(),true)); // bind document - TS_ASSERT(xmlObject.get()!=NULL); - - auto_ptr clonedObject(xmlObject->clone()); - TS_ASSERT(clonedObject.get()!=NULL); - - const Marshaller* m=Marshaller::getMarshaller(clonedObject.get()); - TS_ASSERT(m!=NULL); - - DOMElement* rootElement=m->marshall(clonedObject.get()); - TS_ASSERT(rootElement!=NULL); - - rootElement=m->marshall(clonedObject.get()); // should reuse DOM - TS_ASSERT(rootElement!=NULL); - - string buf2; - XMLHelper::serialize(rootElement, buf2); - TS_ASSERT_EQUALS(buf1,buf2); - } - - void testUnknownWithDocChange() { - ifstream fs("../xmltoolingtest/data/SimpleXMLObjectWithChildren.xml"); - DOMDocument* doc=nonvalidatingPool->parse(fs); - TS_ASSERT(doc!=NULL); - - string buf1; - XMLHelper::serialize(doc->getDocumentElement(), buf1); - - const Unmarshaller* u=Unmarshaller::getUnmarshaller(doc->getDocumentElement()); - TS_ASSERT(u!=NULL); - - auto_ptr xmlObject(u->unmarshall(doc->getDocumentElement(),true)); // bind document - TS_ASSERT(xmlObject.get()!=NULL); - - const Marshaller* m=Marshaller::getMarshaller(xmlObject.get()); - TS_ASSERT(m!=NULL); - - DOMDocument* newDoc=nonvalidatingPool->newDocument(); - DOMElement* rootElement=m->marshall(xmlObject.get(), newDoc); - TS_ASSERT(rootElement!=NULL); - - string buf2; - XMLHelper::serialize(rootElement, buf2); - TS_ASSERT_EQUALS(buf1,buf2); - - newDoc->release(); - } -}; diff --git a/xmltoolingtest/UnmarshallingTest.h b/xmltoolingtest/UnmarshallingTest.h index f361266..cc7c25c 100644 --- a/xmltoolingtest/UnmarshallingTest.h +++ b/xmltoolingtest/UnmarshallingTest.h @@ -48,14 +48,10 @@ public: void setUp() { XMLObjectBuilder::registerBuilder(m_qname, new SimpleXMLObjectBuilder()); - Marshaller::registerMarshaller(m_qname, new SimpleXMLObjectMarshaller()); - Unmarshaller::registerUnmarshaller(m_qname, new SimpleXMLObjectUnmarshaller()); } void tearDown() { XMLObjectBuilder::deregisterBuilder(m_qname); - Marshaller::deregisterMarshaller(m_qname); - Unmarshaller::deregisterUnmarshaller(m_qname); } void testUnmarshallingWithAttributes() { @@ -66,10 +62,12 @@ public: DOMDocument* doc=nonvalidatingPool->parse(fs); TS_ASSERT(doc!=NULL); - const Unmarshaller* u = Unmarshaller::getUnmarshaller(doc->getDocumentElement()); - TS_ASSERT(u!=NULL); + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); - auto_ptr sxObject(dynamic_cast(u->unmarshall(doc->getDocumentElement(),true))); + auto_ptr sxObject( + dynamic_cast(b->buildObject()->unmarshall(doc->getDocumentElement(),true)) + ); TS_ASSERT(sxObject.get()!=NULL); auto_ptr_XMLCh expected("Firefly"); @@ -84,10 +82,12 @@ public: DOMDocument* doc=nonvalidatingPool->parse(fs); TS_ASSERT(doc!=NULL); - const Unmarshaller* u = Unmarshaller::getUnmarshaller(doc->getDocumentElement()); - TS_ASSERT(u!=NULL); + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); - auto_ptr sxObject(dynamic_cast(u->unmarshall(doc->getDocumentElement(),true))); + auto_ptr sxObject( + dynamic_cast(b->buildObject()->unmarshall(doc->getDocumentElement(),true)) + ); TS_ASSERT(sxObject.get()!=NULL); auto_ptr_XMLCh expected("Sample Content"); @@ -102,10 +102,12 @@ public: DOMDocument* doc=nonvalidatingPool->parse(fs); TS_ASSERT(doc!=NULL); - const Unmarshaller* u = Unmarshaller::getUnmarshaller(doc->getDocumentElement()); - TS_ASSERT(u!=NULL); + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); - auto_ptr sxObject(dynamic_cast(u->unmarshall(doc->getDocumentElement(),true))); + auto_ptr sxObject( + dynamic_cast(b->buildObject()->unmarshall(doc->getDocumentElement(),true)) + ); TS_ASSERT(sxObject.get()!=NULL); VectorOf(SimpleXMLObject) kids=sxObject->getSimpleXMLObjects(); @@ -120,10 +122,11 @@ public: DOMDocument* doc=nonvalidatingPool->parse(fs); TS_ASSERT(doc!=NULL); - const Unmarshaller* u = Unmarshaller::getUnmarshaller(doc->getDocumentElement()); - TS_ASSERT(u!=NULL); + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); - TS_ASSERT_THROWS(u->unmarshall(doc->getDocumentElement(),true),UnmarshallingException); + auto_ptr sxObject(b->buildObject()); + TS_ASSERT_THROWS(sxObject->unmarshall(doc->getDocumentElement(),true),UnmarshallingException); doc->release(); } }; diff --git a/xmltoolingtest/XMLObjectBaseTestCase.h b/xmltoolingtest/XMLObjectBaseTestCase.h index 18d02d5..f36c032 100644 --- a/xmltoolingtest/XMLObjectBaseTestCase.h +++ b/xmltoolingtest/XMLObjectBaseTestCase.h @@ -16,7 +16,6 @@ #include #include -#include #include #include #include @@ -43,7 +42,7 @@ extern string data_path; #pragma warning( disable : 4250 4251 ) #endif -class SimpleXMLObject : public AbstractDOMCachingXMLObject +class SimpleXMLObject : public AbstractXMLObjectMarshaller, public AbstractXMLObjectUnmarshaller { public: static const XMLCh NAMESPACE[]; @@ -99,88 +98,61 @@ public: return ret; } -private: - XMLCh* m_id; - XMLCh* m_value; - vector m_simples; -#ifndef XMLTOOLING_NO_XMLSEC - list::iterator m_signature; -#endif -}; - -class SimpleXMLObjectBuilder : public XMLObjectBuilder -{ -public: - SimpleXMLObject* buildObject() const { - return new SimpleXMLObject(); - } -}; - -class SimpleXMLObjectMarshaller : public AbstractXMLObjectMarshaller -{ -public: - SimpleXMLObjectMarshaller() {} - -private: - void marshallAttributes(const XMLObject& xmlObject, DOMElement* domElement) const { - const SimpleXMLObject& simpleXMLObject = dynamic_cast(xmlObject); - - if(simpleXMLObject.getId()) { - domElement->setAttributeNS(NULL, SimpleXMLObject::ID_ATTRIB_NAME, simpleXMLObject.getId()); + void marshallAttributes(DOMElement* domElement) const { + if(getId()) { + domElement->setAttributeNS(NULL, SimpleXMLObject::ID_ATTRIB_NAME, getId()); domElement->setIdAttributeNS(NULL, SimpleXMLObject::ID_ATTRIB_NAME); } } - void marshallElementContent(const XMLObject& xmlObject, DOMElement* domElement) const { - const SimpleXMLObject& simpleXMLObject = dynamic_cast(xmlObject); - - if(simpleXMLObject.getValue()) { - domElement->setTextContent(simpleXMLObject.getValue()); + void marshallElementContent(DOMElement* domElement) const { + if(getValue()) { + domElement->setTextContent(getValue()); } } -}; - -class SimpleXMLObjectUnmarshaller : public AbstractXMLObjectUnmarshaller -{ -public: - SimpleXMLObjectUnmarshaller() {} - -private: - void processChildElement(XMLObject& parentXMLObject, XMLObject* childXMLObject, const DOMElement* root) const { - SimpleXMLObject& simpleXMLObject = dynamic_cast(parentXMLObject); + void processChildElement(XMLObject* childXMLObject, const DOMElement* root) { if (XMLHelper::isNodeNamed(root, SimpleXMLObject::NAMESPACE, SimpleXMLObject::LOCAL_NAME)) - simpleXMLObject.getSimpleXMLObjects().push_back(dynamic_cast(childXMLObject)); + getSimpleXMLObjects().push_back(dynamic_cast(childXMLObject)); #ifndef XMLTOOLING_NO_XMLSEC else if (XMLHelper::isNodeNamed(root, XMLConstants::XMLSIG_NS, Signature::LOCAL_NAME)) - simpleXMLObject.setSignature(dynamic_cast(childXMLObject)); + setSignature(dynamic_cast(childXMLObject)); #endif else throw UnmarshallingException("Unknown child element cannot be added to parent object."); } - void processAttribute(XMLObject& xmlObject, const DOMAttr* attribute) const { - SimpleXMLObject& simpleXMLObject = dynamic_cast(xmlObject); - + void processAttribute(const DOMAttr* attribute) { if (XMLHelper::isNodeNamed(attribute, NULL, SimpleXMLObject::ID_ATTRIB_NAME)) - simpleXMLObject.setId(attribute->getValue()); + setId(attribute->getValue()); else throw UnmarshallingException("Unknown attribute cannot be processed by parent object."); } - void processElementContent(XMLObject& xmlObject, const XMLCh* elementContent) const { - SimpleXMLObject& simpleXMLObject = dynamic_cast(xmlObject); - - simpleXMLObject.setValue(elementContent); + void processElementContent(const XMLCh* elementContent) { + setValue(elementContent); } +private: + XMLCh* m_id; + XMLCh* m_value; + vector m_simples; +#ifndef XMLTOOLING_NO_XMLSEC + list::iterator m_signature; +#endif }; -class WildcardXMLObjectMarshaller; +class SimpleXMLObjectBuilder : public XMLObjectBuilder +{ +public: + SimpleXMLObject* buildObject(const DOMElement* e=NULL) const { + return new SimpleXMLObject(); + } +}; -class WildcardXMLObject : public AbstractElementProxy, public AbstractAttributeExtensibleXMLObject +class WildcardXMLObject : public AbstractElementProxy, public AbstractAttributeExtensibleXMLObject, + public AbstractXMLObjectMarshaller, public AbstractXMLObjectUnmarshaller { - friend class WildcardXMLObjectMarshaller; public: WildcardXMLObject(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix) : AbstractDOMCachingXMLObject(nsURI, localName, prefix), @@ -207,30 +179,9 @@ public: xmltooling::clone(m_children, ret->m_children); return ret; } -}; - -class WildcardXMLObjectBuilder : public XMLObjectBuilder -{ -public: - XMLObject* buildObject() const { - throw XMLObjectException("No default builder available."); - } - - WildcardXMLObject* buildObject(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix) const { - return new WildcardXMLObject(nsURI,localName,prefix); - } -}; - -class WildcardXMLObjectMarshaller : public AbstractXMLObjectMarshaller -{ -public: - WildcardXMLObjectMarshaller() : AbstractXMLObjectMarshaller() {} -private: - void marshallAttributes(const XMLObject& xmlObject, DOMElement* domElement) const { - const WildcardXMLObject& wcXMLObject = dynamic_cast(xmlObject); - - for (map::const_iterator i=wcXMLObject.m_attributeMap.begin(); i!=wcXMLObject.m_attributeMap.end(); i++) { + void marshallAttributes(DOMElement* domElement) const { + for (map::const_iterator i=m_attributeMap.begin(); i!=m_attributeMap.end(); i++) { DOMAttr* attr=domElement->getOwnerDocument()->createAttributeNS(i->first.getNamespaceURI(),i->first.getLocalPart()); if (i->first.hasPrefix()) attr->setPrefix(i->first.getPrefix()); @@ -239,48 +190,32 @@ private: } } - void marshallElementContent(const XMLObject& xmlObject, DOMElement* domElement) const { - const WildcardXMLObject& wcXMLObject = dynamic_cast(xmlObject); - - if(wcXMLObject.getTextContent()) { - domElement->appendChild(domElement->getOwnerDocument()->createTextNode(wcXMLObject.getTextContent())); + void marshallElementContent(DOMElement* domElement) const { + if(getTextContent()) { + domElement->appendChild(domElement->getOwnerDocument()->createTextNode(getTextContent())); } } -}; -class WildcardXMLObjectUnmarshaller : public AbstractXMLObjectUnmarshaller -{ -public: - WildcardXMLObjectUnmarshaller() {} - -private: - XMLObject* buildXMLObject(const DOMElement* domElement) const { - const WildcardXMLObjectBuilder* builder = - dynamic_cast(XMLObjectBuilder::getBuilder(domElement)); - if (builder) - return builder->buildObject(domElement->getNamespaceURI(),domElement->getLocalName(),domElement->getPrefix()); - throw UnmarshallingException("Failed to locate WildcardObjectBuilder for element."); + void processChildElement(XMLObject* childXMLObject, const DOMElement* root) { + getXMLObjects().push_back(childXMLObject); } - void processChildElement(XMLObject& parentXMLObject, XMLObject* childXMLObject, const DOMElement* root) const { - WildcardXMLObject& wcXMLObject = dynamic_cast(parentXMLObject); - - wcXMLObject.getXMLObjects().push_back(childXMLObject); - } - - void processAttribute(XMLObject& xmlObject, const DOMAttr* attribute) const { - WildcardXMLObject& wcXMLObject = dynamic_cast(xmlObject); - + void processAttribute(const DOMAttr* attribute) { QName q(attribute->getNamespaceURI(),attribute->getLocalName(),attribute->getPrefix()); - wcXMLObject.setAttribute(q,attribute->getNodeValue()); + setAttribute(q,attribute->getNodeValue()); } - void processElementContent(XMLObject& xmlObject, const XMLCh* elementContent) const { - WildcardXMLObject& wcXMLObject = dynamic_cast(xmlObject); - - wcXMLObject.setTextContent(elementContent); + void processElementContent(const XMLCh* elementContent) { + setTextContent(elementContent); } +}; +class WildcardXMLObjectBuilder : public XMLObjectBuilder +{ +public: + WildcardXMLObject* buildObject(const DOMElement* e=NULL) const { + return new WildcardXMLObject(e->getNamespaceURI(),e->getLocalName(),e->getPrefix()); + } }; #if defined (_MSC_VER) diff --git a/xmltoolingtest/xmltoolingtest.h b/xmltoolingtest/xmltoolingtest.h index 42c21c9..50a66d3 100644 --- a/xmltoolingtest/xmltoolingtest.h +++ b/xmltoolingtest/xmltoolingtest.h @@ -14,14 +14,13 @@ * limitations under the License. */ -#include -#include +#include "XMLObjectBaseTestCase.h" +#include +#include #include #include -using namespace xmltooling; - ParserPool* validatingPool=NULL; ParserPool* nonvalidatingPool=NULL; std::string data_path = "../xmltoolingtest/data/"; @@ -60,7 +59,7 @@ public: static ToolingFixture globalFixture; -class CatalogTest : public CxxTest::TestSuite +class GlobalTest : public CxxTest::TestSuite { public: void testCatalog(void) { @@ -68,4 +67,58 @@ public: auto_ptr_XMLCh temp(path.c_str()); TS_ASSERT(validatingPool->loadCatalog(temp.get())); } + + void testUnknown() { + ifstream fs("../xmltoolingtest/data/SimpleXMLObjectWithChildren.xml"); + DOMDocument* doc=nonvalidatingPool->parse(fs); + TS_ASSERT(doc!=NULL); + + string buf1; + XMLHelper::serialize(doc->getDocumentElement(), buf1); + + const XMLObjectBuilder* b=XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + + auto_ptr xmlObject(b->buildObject(doc->getDocumentElement())->unmarshall(doc->getDocumentElement(),true)); // bind document + TS_ASSERT(xmlObject.get()!=NULL); + + auto_ptr clonedObject(xmlObject->clone()); + TS_ASSERT(clonedObject.get()!=NULL); + + DOMElement* rootElement=clonedObject->marshall(); + TS_ASSERT(rootElement!=NULL); + + // should reuse DOM + TS_ASSERT(rootElement==clonedObject->marshall()); + + string buf2; + XMLHelper::serialize(rootElement, buf2); + TS_ASSERT_EQUALS(buf1,buf2); + } + + void testUnknownWithDocChange() { + ifstream fs("../xmltoolingtest/data/SimpleXMLObjectWithChildren.xml"); + DOMDocument* doc=nonvalidatingPool->parse(fs); + TS_ASSERT(doc!=NULL); + + string buf1; + XMLHelper::serialize(doc->getDocumentElement(), buf1); + + const XMLObjectBuilder* b=XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + + auto_ptr xmlObject(b->buildObject(doc->getDocumentElement())->unmarshall(doc->getDocumentElement(),true)); // bind document + TS_ASSERT(xmlObject.get()!=NULL); + + DOMDocument* newDoc=nonvalidatingPool->newDocument(); + DOMElement* rootElement=xmlObject->marshall(newDoc); + TS_ASSERT(rootElement!=NULL); + + string buf2; + XMLHelper::serialize(rootElement, buf2); + TS_ASSERT_EQUALS(buf1,buf2); + + newDoc->release(); + } }; + diff --git a/xmltoolingtest/xmltoolingtest.vcproj b/xmltoolingtest/xmltoolingtest.vcproj index 5703d4c..294fe85 100644 --- a/xmltoolingtest/xmltoolingtest.vcproj +++ b/xmltoolingtest/xmltoolingtest.vcproj @@ -192,10 +192,6 @@ > - - @@ -276,28 +272,6 @@ - - - - - - - -