Multi-line svn commit, see body.
[shibboleth/cpp-xmltooling.git] / xmltooling / io / AbstractXMLObjectMarshaller.cpp
index a17476e..a33016c 100644 (file)
 #include <xercesc/util/XMLUniDefs.hpp>\r
 #include <log4cpp/Category.hh>\r
 \r
-using namespace xmlsignature;\r
+#ifndef XMLTOOLING_NO_XMLSEC\r
+    using namespace xmlsignature;\r
+#endif\r
 using namespace xmltooling;\r
 using namespace log4cpp;\r
 using namespace std;\r
 \r
 #define XT_log (*static_cast<Category*>(m_log))\r
 \r
-DOMElement* AbstractXMLObjectMarshaller::marshall(DOMDocument* document, MarshallingContext* ctx) const\r
+DOMElement* AbstractXMLObjectMarshaller::marshall(\r
+    DOMDocument* document\r
+#ifndef XMLTOOLING_NO_XMLSEC\r
+    ,const std::vector<xmlsignature::Signature*>* sigs\r
+#endif\r
+    ) const\r
 {\r
 #ifdef _DEBUG\r
     xmltooling::NDC ndc("marshall");\r
@@ -78,32 +85,34 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(DOMDocument* document, Marshal
         document=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument();\r
         bindDocument=true;\r
     }\r
+    \r
+    XercesJanitor<DOMDocument> janitor(bindDocument ? document : NULL);\r
 \r
-    try {\r
-        XT_log.debug("creating root element to marshall");\r
-        DOMElement* domElement = document->createElementNS(\r
-            getElementQName().getNamespaceURI(), getElementQName().getLocalPart()\r
-            );\r
-        setDocumentElement(document, domElement);\r
-        marshallInto(domElement, ctx);\r
-\r
-        //Recache the DOM.\r
-        XT_log.debug("caching DOM for XMLObject (document is %sbound)", bindDocument ? "" : "not ");\r
-        setDOM(domElement, bindDocument);\r
-        releaseParentDOM(true);\r
+    XT_log.debug("creating root element to marshall");\r
+    DOMElement* domElement = document->createElementNS(\r
+        getElementQName().getNamespaceURI(), getElementQName().getLocalPart()\r
+        );\r
+    setDocumentElement(document, domElement);\r
+#ifndef XMLTOOLING_NO_XMLSEC\r
+    marshallInto(domElement, sigs);\r
+#else\r
+    marshallInto(domElement);\r
+#endif\r
+    //Recache the DOM.\r
+    XT_log.debug("caching DOM for XMLObject (document is %sbound)", bindDocument ? "" : "not ");\r
+    setDOM(domElement, bindDocument);\r
+    janitor.release();  // safely transferred\r
+    releaseParentDOM(true);\r
 \r
-        return domElement;\r
-    }\r
-    catch (...) {\r
-        // Delete the document if need be, and rethrow.\r
-        if (bindDocument) {\r
-            document->release();\r
-        }\r
-        throw;\r
-    }\r
+    return domElement;\r
 }\r
 \r
-DOMElement* AbstractXMLObjectMarshaller::marshall(DOMElement* parentElement, MarshallingContext* ctx) const\r
+DOMElement* AbstractXMLObjectMarshaller::marshall(\r
+    DOMElement* parentElement\r
+#ifndef XMLTOOLING_NO_XMLSEC\r
+    ,const std::vector<xmlsignature::Signature*>* sigs\r
+#endif\r
+    ) const\r
 {\r
 #ifdef _DEBUG\r
     xmltooling::NDC ndc("marshall");\r
@@ -139,7 +148,11 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(DOMElement* parentElement, Mar
         getElementQName().getNamespaceURI(), getElementQName().getLocalPart()\r
         );\r
     parentElement->appendChild(domElement);\r
-    marshallInto(domElement, ctx);\r
+#ifndef XMLTOOLING_NO_XMLSEC\r
+    marshallInto(domElement, sigs);\r
+#else\r
+    marshallInto(domElement);\r
+#endif\r
 \r
     //Recache the DOM.\r
     XT_log.debug("caching DOM for XMLObject");\r
@@ -149,28 +162,30 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(DOMElement* parentElement, Mar
     return domElement;\r
 }\r
 \r
+void AbstractXMLObjectMarshaller::marshallInto(\r
+    DOMElement* targetElement\r
 #ifndef XMLTOOLING_NO_XMLSEC\r
-    class _signit : public unary_function<const pair<Signature*,const SigningContext*>&, void> {\r
-    public:\r
-        void operator()(const pair<Signature*,const SigningContext*>& p) const {\r
-            p.first->sign(*(p.second));\r
-        }\r
-    };\r
+    ,const std::vector<xmlsignature::Signature*>* sigs\r
 #endif\r
-\r
-void AbstractXMLObjectMarshaller::marshallInto(DOMElement* targetElement, MarshallingContext* ctx) const\r
+    ) const\r
 {\r
     if (getElementQName().hasPrefix())\r
         targetElement->setPrefix(getElementQName().getPrefix());\r
+\r
+    if (m_schemaLocation) {\r
+        static const XMLCh schemaLocation[]= UNICODE_LITERAL_14(s,c,h,e,m,a,L,o,c,a,t,i,o,n);\r
+        if (targetElement->getParentNode()==NULL || targetElement->getParentNode()->getNodeType()==DOMNode::DOCUMENT_NODE)\r
+            targetElement->setAttributeNS(XMLConstants::XSI_NS,schemaLocation,m_schemaLocation); \r
+    }\r
+\r
     marshallElementType(targetElement);\r
     marshallNamespaces(targetElement);\r
     marshallAttributes(targetElement);\r
-    marshallChildElements(targetElement);\r
-    marshallElementContent(targetElement);\r
-\r
+    marshallContent(targetElement);\r
+    \r
 #ifndef XMLTOOLING_NO_XMLSEC\r
-    if (ctx) {\r
-        for_each(ctx->m_signingContexts.begin(),ctx->m_signingContexts.end(),_signit());\r
+    if (sigs) {\r
+        for_each(sigs->begin(),sigs->end(),mem_fun<void,Signature>(&Signature::sign));\r
     }\r
 #endif\r
 }\r
@@ -274,17 +289,21 @@ void AbstractXMLObjectMarshaller::marshallNamespaces(DOMElement* domElement) con
     for_each(namespaces.begin(),namespaces.end(),bind1st(_addns(),domElement));\r
 }\r
 \r
-class _marshallit : public binary_function<const XMLObject*,DOMElement*,void> {\r
-public:\r
-    void operator()(const XMLObject* xo, DOMElement* e) const {\r
-        if (xo) xo->marshall(e);\r
-    }\r
-};\r
-\r
-void AbstractXMLObjectMarshaller::marshallChildElements(DOMElement* domElement) const\r
+void AbstractXMLObjectMarshaller::marshallContent(DOMElement* domElement) const\r
 {\r
-    XT_log.debug("marshalling child elements for XMLObject");\r
-\r
+    XT_log.debug("marshalling text and child elements for XMLObject");\r
+    \r
+    const XMLCh* val;\r
+    unsigned int pos=0;\r
     const list<XMLObject*>& children=getOrderedChildren();\r
-    for_each(children.begin(),children.end(),bind2nd(_marshallit(),domElement));\r
+    for (list<XMLObject*>::const_iterator i=children.begin(); i!=children.end(); ++i, ++pos) {\r
+        val = getTextContent(pos);\r
+        if (val && *val)\r
+            domElement->appendChild(domElement->getOwnerDocument()->createTextNode(val));\r
+        if (*i)\r
+            (*i)->marshall(domElement);\r
+    }\r
+    val = getTextContent(pos);\r
+    if (val && *val)\r
+        domElement->appendChild(domElement->getOwnerDocument()->createTextNode(val));\r
 }\r