Multi-line svn commit, see body.
[shibboleth/cpp-xmltooling.git] / xmltooling / io / AbstractXMLObjectUnmarshaller.cpp
index fd4c9f5..5a07591 100644 (file)
@@ -1,5 +1,5 @@
 /*
-*  Copyright 2001-2006 Internet2
+*  Copyright 2001-2007 Internet2
  * 
 * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include "util/XMLHelper.h"
 
 #include <xercesc/util/XMLUniDefs.hpp>
-#include <log4cpp/Category.hh>
 
+using namespace xmlconstants;
 using namespace xmltooling;
-using namespace log4cpp;
 using namespace std;
 
-#define XT_log (*static_cast<Category*>(m_log))
 
 XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool bindDocument)
 {
@@ -51,22 +49,16 @@ XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool b
         throw UnmarshallingException("Unrecognized element supplied to implementation for unmarshalling.");
     }
 
-    if (XT_log.isDebugEnabled()) {
+    if (m_log.isDebugEnabled()) {
         auto_ptr_char dname(element->getNodeName());
-        XT_log.debug("unmarshalling DOM element (%s)", dname.get());
+        m_log.debug("unmarshalling DOM element (%s)", dname.get());
     }
 
     if (element->hasAttributes()) {
         unmarshallAttributes(element);
     }
 
-    unmarshallChildElements(element);
-
-    /* TODO: Signing
-    if (xmlObject instanceof SignableXMLObject) {
-        verifySignature(domElement, xmlObject);
-    }
-    */
+    unmarshallContent(element);
 
     setDOM(element,bindDocument);
     return this;
@@ -77,16 +69,15 @@ void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domEl
 #ifdef _DEBUG
     xmltooling::NDC ndc("unmarshallAttributes");
 #endif
-    static const XMLCh type[]={chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull};
 
-    if (XT_log.isDebugEnabled()) {
+    if (m_log.isDebugEnabled()) {
         auto_ptr_char dname(domElement->getNodeName());
-        XT_log.debug("unmarshalling attributes for DOM element (%s)", dname.get());
+        m_log.debug("unmarshalling attributes for DOM element (%s)", dname.get());
     }
 
     DOMNamedNodeMap* attributes = domElement->getAttributes();
     if (!attributes) {
-        XT_log.debug("no attributes to unmarshall");
+        m_log.debug("no attributes to unmarshall");
         return;
     }
 
@@ -97,80 +88,121 @@ void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domEl
 
         // The child node should always be an attribute, but just in case
         if (childNode->getNodeType() != DOMNode::ATTRIBUTE_NODE) {
-            XT_log.debug("encountered child node of type %d in attribute list, ignoring it", childNode->getNodeType());
+            m_log.debug("encountered child node of type %d in attribute list, ignoring it", childNode->getNodeType());
             continue;
         }
 
         attribute = static_cast<DOMAttr*>(childNode);
         
         const XMLCh* nsuri=attribute->getNamespaceURI();
-        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");
+        if (XMLString::equals(nsuri,XMLNS_NS)) {
+            if (XMLString::equals(attribute->getLocalName(),XMLNS_PREFIX)) {
+                m_log.debug("found default namespace declaration, adding it to the list of namespaces on the XMLObject");
                 addNamespace(Namespace(attribute->getValue(), NULL, true));
                 continue;
             }
             else {
-                XT_log.debug("found namespace declaration, adding it to the list of namespaces on the XMLObject");
+                m_log.debug("found namespace declaration, adding it to the list of namespaces on the XMLObject");
                 addNamespace(Namespace(attribute->getValue(), attribute->getLocalName(), true));
                 continue;
             }
         }
-        else if (XMLString::equals(nsuri,XMLConstants::XSI_NS) && XMLString::equals(attribute->getLocalName(),type)) {
-            XT_log.debug("skipping xsi:type declaration");
-            continue;
+        else if (XMLString::equals(nsuri,XSI_NS)) {
+            static const XMLCh type[]= UNICODE_LITERAL_4(t,y,p,e);
+            static const XMLCh schemaLocation[]= UNICODE_LITERAL_14(s,c,h,e,m,a,L,o,c,a,t,i,o,n);
+            static const XMLCh noNamespaceSchemaLocation[]= UNICODE_LITERAL_25(n,o,N,a,m,e,s,p,a,c,e,S,c,h,e,m,a,L,o,c,a,t,i,o,n);
+            static const XMLCh _nil[]= UNICODE_LITERAL_3(n,i,l);
+            if (XMLString::equals(attribute->getLocalName(),type)) {
+                m_log.debug("skipping xsi:type declaration");
+                continue;
+            }
+            else if (XMLString::equals(attribute->getLocalName(),schemaLocation)) {
+                m_log.debug("storing off xsi:schemaLocation attribute");
+                if (m_schemaLocation)
+                    XMLString::release(&m_schemaLocation);
+                m_schemaLocation=XMLString::replicate(attribute->getValue());
+                continue;
+            }
+            else if (XMLString::equals(attribute->getLocalName(),noNamespaceSchemaLocation)) {
+                m_log.debug("storing off xsi:noNamespaceSchemaLocation attribute");
+                if (m_noNamespaceSchemaLocation)
+                    XMLString::release(&m_noNamespaceSchemaLocation);
+                m_schemaLocation=XMLString::replicate(attribute->getValue());
+                m_noNamespaceSchemaLocation=XMLString::replicate(attribute->getValue());
+                continue;
+            }
+            else if (XMLString::equals(attribute->getLocalName(), _nil)) {
+               m_log.debug("processing xsi:nil attribute");
+               setNil(attribute->getValue());
+               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");
+        else if (nsuri && !XMLString::equals(nsuri,XML_NS)) {
+            m_log.debug("found namespace-qualified attribute, adding prefix to the list of namespaces on the XMLObject");
             addNamespace(Namespace(nsuri, attribute->getPrefix()));
         }
 
-        XT_log.debug("processing generic attribute");
+        m_log.debug("processing generic attribute");
         processAttribute(attribute);
     }
 }
 
-void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* domElement)
+void AbstractXMLObjectUnmarshaller::unmarshallContent(const DOMElement* domElement)
 {
 #ifdef _DEBUG
-    xmltooling::NDC ndc("unmarshallChildElements");
+    xmltooling::NDC ndc("unmarshallContent");
 #endif
 
-    if (XT_log.isDebugEnabled()) {
+    if (m_log.isDebugEnabled()) {
         auto_ptr_char dname(domElement->getNodeName());
-        XT_log.debug("unmarshalling child elements of DOM element (%s)", dname.get());
+        m_log.debug("unmarshalling child nodes of DOM element (%s)", dname.get());
     }
 
-    DOMNodeList* childNodes = domElement->getChildNodes();
-    DOMNode* childNode;
-    if (!childNodes || childNodes->getLength()==0) {
-        XT_log.debug("element had no children");
+    DOMNode* childNode = domElement->getFirstChild();
+    if (!childNode) {
+        m_log.debug("element had no children");
         return;
     }
 
-    for (XMLSize_t i = 0; i < childNodes->getLength(); i++) {
-        childNode = childNodes->item(i);
+    unsigned int position = 0;
+    while (childNode) {
         if (childNode->getNodeType() == DOMNode::ELEMENT_NODE) {
             const XMLObjectBuilder* builder = XMLObjectBuilder::getBuilder(static_cast<DOMElement*>(childNode));
             if (!builder) {
                 auto_ptr<QName> cname(XMLHelper::getNodeQName(childNode));
-                XT_log.error("no default builder installed, found unknown child element (%s)", cname->toString().c_str());
+                m_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()) {
+            if (m_log.isDebugEnabled()) {
                 auto_ptr<QName> cname(XMLHelper::getNodeQName(childNode));
-                XT_log.debug("unmarshalling child element (%s)", cname->toString().c_str());
+                m_log.debug("unmarshalling child element (%s)", cname->toString().c_str());
             }
 
             // Retain ownership of the unmarshalled child until it's processed by the parent.
             auto_ptr<XMLObject> childObject(builder->buildFromElement(static_cast<DOMElement*>(childNode)));
             processChildElement(childObject.get(), static_cast<DOMElement*>(childNode));
             childObject.release();
+            
+            // Advance the text node position marker.
+            ++position;
         }
-        else if (childNode->getNodeType() == DOMNode::TEXT_NODE) {
-            XT_log.debug("processing element content");
-            processElementContent(childNode->getNodeValue());
+        else if (childNode->getNodeType() == DOMNode::TEXT_NODE || childNode->getNodeType() == DOMNode::CDATA_SECTION_NODE) {
+            m_log.debug("processing text content at position (%d)", position);
+            setTextContent(childNode->getNodeValue(), position);
         }
+        
+        childNode = childNode->getNextSibling();
     }
 }
+
+void AbstractXMLObjectUnmarshaller::processChildElement(XMLObject* child, const DOMElement* childRoot)
+{
+    throw UnmarshallingException("Invalid child element: $1",params(1,child->getElementQName().toString().c_str()));
+}
+
+void AbstractXMLObjectUnmarshaller::processAttribute(const DOMAttr* attribute)
+{
+    auto_ptr<QName> q(XMLHelper::getNodeQName(attribute));
+    throw UnmarshallingException("Invalid attribute: $1",params(1,q->toString().c_str()));
+}