X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=xmltooling%2Fio%2FAbstractXMLObjectMarshaller.cpp;h=c28bcbfc2edf5fb0f8bbc06c760e72c3a147e3cf;hb=a0d768778a8f5f539b909baf5b115e70ea765f0f;hp=4822fbeb812b63cba6566bcc05dc5629ef856570;hpb=c50f3cc9a47e95fc3518e61703791d098ce3253d;p=shibboleth%2Fcpp-xmltooling.git diff --git a/xmltooling/io/AbstractXMLObjectMarshaller.cpp b/xmltooling/io/AbstractXMLObjectMarshaller.cpp index 4822fbe..c28bcbf 100644 --- a/xmltooling/io/AbstractXMLObjectMarshaller.cpp +++ b/xmltooling/io/AbstractXMLObjectMarshaller.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2001-2006 Internet2 +* Copyright 2001-2010 Internet2 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ #include "exceptions.h" #include "io/AbstractXMLObjectMarshaller.h" #ifndef XMLTOOLING_NO_XMLSEC + #include "security/Credential.h" #include "signature/Signature.h" #endif #include "util/NDC.h" @@ -33,22 +34,37 @@ #include #include #include -#include #ifndef XMLTOOLING_NO_XMLSEC using namespace xmlsignature; #endif using namespace xmlconstants; using namespace xmltooling; -using namespace log4cpp; +using namespace xercesc; using namespace std; -#define XT_log (*static_cast(m_log)) +AbstractXMLObjectMarshaller::AbstractXMLObjectMarshaller() +{ +} + +AbstractXMLObjectMarshaller::~AbstractXMLObjectMarshaller() +{ +} + +void AbstractXMLObjectMarshaller::setDocumentElement(DOMDocument* document, DOMElement* element) const +{ + DOMElement* documentRoot = document->getDocumentElement(); + if (documentRoot) + document->replaceChild(element, documentRoot); + else + document->appendChild(element); +} DOMElement* AbstractXMLObjectMarshaller::marshall( DOMDocument* document #ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs + ,const vector* sigs + ,const Credential* credential #endif ) const { @@ -56,14 +72,14 @@ DOMElement* AbstractXMLObjectMarshaller::marshall( xmltooling::NDC ndc("marshall"); #endif - if (XT_log.isDebugEnabled()) { - XT_log.debug("starting to marshal %s", getElementQName().toString().c_str()); + if (m_log.isDebugEnabled()) { + m_log.debug("starting to marshal %s", getElementQName().toString().c_str()); } DOMElement* cachedDOM=getDOM(); if (cachedDOM) { if (!document || document==cachedDOM->getOwnerDocument()) { - XT_log.debug("XMLObject has a usable cached DOM, reusing it"); + m_log.debug("XMLObject has a usable cached DOM, reusing it"); if (document) setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM); releaseParentDOM(true); @@ -83,24 +99,24 @@ DOMElement* AbstractXMLObjectMarshaller::marshall( // We may need to create our own document. bool bindDocument=false; if (!document) { - document=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument(); + document=DOMImplementationRegistry::getDOMImplementation(nullptr)->createDocument(); bindDocument=true; } - XercesJanitor janitor(bindDocument ? document : NULL); + XercesJanitor janitor(bindDocument ? document : nullptr); - XT_log.debug("creating root element to marshall"); + m_log.debug("creating root element to marshall"); DOMElement* domElement = document->createElementNS( getElementQName().getNamespaceURI(), getElementQName().getLocalPart() ); setDocumentElement(document, domElement); #ifndef XMLTOOLING_NO_XMLSEC - marshallInto(domElement, sigs); + marshallInto(domElement, sigs, credential); #else marshallInto(domElement); #endif //Recache the DOM. - XT_log.debug("caching DOM for XMLObject (document is %sbound)", bindDocument ? "" : "not "); + m_log.debug("caching DOM for XMLObject (document is %sbound)", bindDocument ? "" : "not "); setDOM(domElement, bindDocument); janitor.release(); // safely transferred releaseParentDOM(true); @@ -111,7 +127,8 @@ DOMElement* AbstractXMLObjectMarshaller::marshall( DOMElement* AbstractXMLObjectMarshaller::marshall( DOMElement* parentElement #ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs + ,const vector* sigs + ,const Credential* credential #endif ) const { @@ -119,14 +136,14 @@ DOMElement* AbstractXMLObjectMarshaller::marshall( xmltooling::NDC ndc("marshall"); #endif - if (XT_log.isDebugEnabled()) { - XT_log.debug("starting to marshalling %s", getElementQName().toString().c_str()); + if (m_log.isDebugEnabled()) { + m_log.debug("starting to marshalling %s", getElementQName().toString().c_str()); } DOMElement* cachedDOM=getDOM(); if (cachedDOM) { if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) { - XT_log.debug("XMLObject has a usable cached DOM, reusing it"); + m_log.debug("XMLObject has a usable cached DOM, reusing it"); if (parentElement!=cachedDOM->getParentNode()) { parentElement->appendChild(cachedDOM); releaseParentDOM(true); @@ -144,19 +161,19 @@ DOMElement* AbstractXMLObjectMarshaller::marshall( } // 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"); + m_log.debug("creating root element to marshall"); DOMElement* domElement = parentElement->getOwnerDocument()->createElementNS( getElementQName().getNamespaceURI(), getElementQName().getLocalPart() ); parentElement->appendChild(domElement); #ifndef XMLTOOLING_NO_XMLSEC - marshallInto(domElement, sigs); + marshallInto(domElement, sigs, credential); #else marshallInto(domElement); #endif //Recache the DOM. - XT_log.debug("caching DOM for XMLObject"); + m_log.debug("caching DOM for XMLObject"); setDOM(domElement, false); releaseParentDOM(true); @@ -166,28 +183,66 @@ DOMElement* AbstractXMLObjectMarshaller::marshall( void AbstractXMLObjectMarshaller::marshallInto( DOMElement* targetElement #ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs + ,const vector* sigs + ,const Credential* credential #endif ) const { if (getElementQName().hasPrefix()) targetElement->setPrefix(getElementQName().getPrefix()); - if (m_schemaLocation) { - static const XMLCh schemaLocation[]= UNICODE_LITERAL_14(s,c,h,e,m,a,L,o,c,a,t,i,o,n); - if (targetElement->getParentNode()==NULL || targetElement->getParentNode()->getNodeType()==DOMNode::DOCUMENT_NODE) - targetElement->setAttributeNS(XSI_NS,schemaLocation,m_schemaLocation); + if (m_schemaLocation || m_noNamespaceSchemaLocation) { + static const XMLCh schemaLocation[] = { + chLatin_x, chLatin_s, chLatin_i, chColon, + chLatin_s, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, + chLatin_L, chLatin_o, chLatin_c, chLatin_a, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull + }; + static const XMLCh noNamespaceSchemaLocation[] = { + chLatin_x, chLatin_s, chLatin_i, chColon, + chLatin_n, chLatin_o, chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, + chLatin_S, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, + chLatin_L, chLatin_o, chLatin_c, chLatin_a, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull + }; + if (targetElement->getParentNode()==nullptr || targetElement->getParentNode()->getNodeType()==DOMNode::DOCUMENT_NODE) { + if (m_schemaLocation) + targetElement->setAttributeNS(XSI_NS,schemaLocation,m_schemaLocation); + if (m_noNamespaceSchemaLocation) + targetElement->setAttributeNS(XSI_NS,noNamespaceSchemaLocation,m_noNamespaceSchemaLocation); + } + } + + static const XMLCh _nil[] = { chLatin_x, chLatin_s, chLatin_i, chColon, chLatin_n, chLatin_i, chLatin_l, chNull }; + + if (m_nil != xmlconstants::XML_BOOL_NULL) { + switch (m_nil) { + case xmlconstants::XML_BOOL_TRUE: + targetElement->setAttributeNS(XSI_NS, _nil, xmlconstants::XML_TRUE); + break; + case xmlconstants::XML_BOOL_ONE: + targetElement->setAttributeNS(XSI_NS, _nil, xmlconstants::XML_ONE); + break; + case xmlconstants::XML_BOOL_FALSE: + targetElement->setAttributeNS(XSI_NS, _nil, xmlconstants::XML_FALSE); + break; + case xmlconstants::XML_BOOL_ZERO: + targetElement->setAttributeNS(XSI_NS, _nil, xmlconstants::XML_ZERO); + break; + } + m_log.debug("adding XSI namespace to list of namespaces visibly used by XMLObject"); + addNamespace(Namespace(XSI_NS, XSI_PREFIX, false, Namespace::VisiblyUsed)); } marshallElementType(targetElement); marshallNamespaces(targetElement); marshallAttributes(targetElement); - marshallContent(targetElement); #ifndef XMLTOOLING_NO_XMLSEC + marshallContent(targetElement,credential); if (sigs) { - for_each(sigs->begin(),sigs->end(),mem_fun(&Signature::sign)); + for_each(sigs->begin(),sigs->end(),bind2nd(mem_fun1_t(&Signature::sign),credential)); } +#else + marshallContent(targetElement); #endif } @@ -195,7 +250,7 @@ void AbstractXMLObjectMarshaller::marshallElementType(DOMElement* domElement) co { const QName* type = getSchemaType(); if (type) { - XT_log.debug("setting xsi:type attribute for XMLObject"); + m_log.debug("setting xsi:type attribute for XMLObject"); const XMLCh* typeLocalName = type->getLocalPart(); if (!typeLocalName || !*typeLocalName) { @@ -220,8 +275,8 @@ void AbstractXMLObjectMarshaller::marshallElementType(DOMElement* domElement) co if (xsivalue != typeLocalName) XMLString::release(&xsivalue); - XT_log.debug("Adding XSI namespace to list of namespaces used by XMLObject"); - addNamespace(Namespace(XSI_NS, XSI_PREFIX)); + m_log.debug("adding XSI namespace to list of namespaces visibly used by XMLObject"); + addNamespace(Namespace(XSI_NS, XSI_PREFIX, false, Namespace::VisiblyUsed)); } } @@ -231,6 +286,10 @@ public: const XMLCh* prefix=ns.getNamespacePrefix(); const XMLCh* uri=ns.getNamespaceURI(); + // Check for xmlns:xml. + if (XMLString::equals(prefix, XML_PREFIX) && XMLString::equals(uri, XML_NS)) + return; + // Check to see if the prefix is already declared properly above this node. if (!ns.alwaysDeclare()) { const XMLCh* declared=lookupNamespaceURI(domElement->getParentNode(),prefix); @@ -246,6 +305,7 @@ public: XMLString::catString(xmlns,colon); XMLString::catString(xmlns,prefix); domElement->setAttributeNS(XMLNS_NS, xmlns, uri); + delete[] xmlns; } else { domElement->setAttributeNS(XMLNS_NS, XMLNS_PREFIX, uri); @@ -253,12 +313,12 @@ public: } const XMLCh* lookupNamespaceURI(const DOMNode* n, const XMLCh* prefix) const { - // Return NULL if no declaration in effect. The empty string signifies the null namespace. + // Return nullptr if no declaration in effect. The empty string signifies the null namespace. if (!n || n->getNodeType()!=DOMNode::ELEMENT_NODE) { // At the root, the default namespace is set to the null namespace. if (!prefix || !*prefix) return &chNull; - return NULL; // we're done + return nullptr; // we're done } DOMNamedNodeMap* attributes = static_cast(n)->getAttributes(); if (!attributes) @@ -285,26 +345,40 @@ public: void AbstractXMLObjectMarshaller::marshallNamespaces(DOMElement* domElement) const { - XT_log.debug("marshalling namespace attributes for XMLObject"); + m_log.debug("marshalling namespace attributes for XMLObject"); const set& namespaces = getNamespaces(); for_each(namespaces.begin(),namespaces.end(),bind1st(_addns(),domElement)); } -void AbstractXMLObjectMarshaller::marshallContent(DOMElement* domElement) const +void AbstractXMLObjectMarshaller::marshallContent( + DOMElement* domElement +#ifndef XMLTOOLING_NO_XMLSEC + ,const Credential* credential +#endif + ) const { - XT_log.debug("marshalling text and child elements for XMLObject"); + m_log.debug("marshalling text and child elements for XMLObject"); - const XMLCh* val; unsigned int pos=0; + const XMLCh* val = getTextContent(pos); + if (val && *val) + domElement->appendChild(domElement->getOwnerDocument()->createTextNode(val)); + const list& children=getOrderedChildren(); - for (list::const_iterator i=children.begin(); i!=children.end(); ++i, ++pos) { - val = getTextContent(pos); - if (val && *val) - domElement->appendChild(domElement->getOwnerDocument()->createTextNode(val)); - if (*i) + for (list::const_iterator i=children.begin(); i!=children.end(); ++i) { + if (*i) { +#ifndef XMLTOOLING_NO_XMLSEC + (*i)->marshall(domElement,nullptr,credential); +#else (*i)->marshall(domElement); +#endif + val = getTextContent(++pos); + if (val && *val) + domElement->appendChild(domElement->getOwnerDocument()->createTextNode(val)); + } } - val = getTextContent(pos); - if (val && *val) - domElement->appendChild(domElement->getOwnerDocument()->createTextNode(val)); +} + +void AbstractXMLObjectMarshaller::marshallAttributes(DOMElement* domElement) const +{ }