2 * Copyright 2001-2006 Internet2
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
18 * AbstractXMLObjectUnmarshaller.cpp
\r
20 * A thread-safe abstract unmarshaller.
\r
23 #include "internal.h"
\r
24 #include "exceptions.h"
\r
25 #include "XMLObjectBuilder.h"
\r
26 #include "io/AbstractXMLObjectUnmarshaller.h"
\r
27 #include "util/NDC.h"
\r
28 #include "util/XMLConstants.h"
\r
29 #include "util/XMLHelper.h"
\r
31 #include <xercesc/util/XMLUniDefs.hpp>
\r
32 #include <log4cpp/Category.hh>
\r
34 using namespace xmltooling;
\r
35 using namespace log4cpp;
\r
36 using namespace std;
\r
38 #define XT_log (*static_cast<Category*>(m_log))
\r
40 XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool bindDocument)
\r
43 xmltooling::NDC ndc("unmarshall");
\r
46 if (XT_log.isDebugEnabled()) {
\r
47 auto_ptr_char dname(element->getNodeName());
\r
48 XT_log.debug("unmarshalling DOM element (%s)", dname.get());
\r
51 if (element->hasAttributes()) {
\r
52 unmarshallAttributes(element);
\r
55 unmarshallChildElements(element);
\r
58 if (xmlObject instanceof SignableXMLObject) {
\r
59 verifySignature(domElement, xmlObject);
\r
63 setDOM(element,bindDocument);
\r
67 void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domElement)
\r
70 xmltooling::NDC ndc("unmarshallAttributes");
\r
72 static const XMLCh type[]={chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull};
\r
74 if (XT_log.isDebugEnabled()) {
\r
75 auto_ptr_char dname(domElement->getNodeName());
\r
76 XT_log.debug("unmarshalling attributes for DOM element (%s)", dname.get());
\r
79 DOMNamedNodeMap* attributes = domElement->getAttributes();
\r
81 XT_log.debug("no attributes to unmarshall");
\r
87 for (XMLSize_t i=0; i<attributes->getLength(); i++) {
\r
88 childNode = attributes->item(i);
\r
90 // The child node should always be an attribute, but just in case
\r
91 if (childNode->getNodeType() != DOMNode::ATTRIBUTE_NODE) {
\r
92 XT_log.debug("encountered child node of type %d in attribute list, ignoring it", childNode->getNodeType());
\r
96 attribute = static_cast<DOMAttr*>(childNode);
\r
98 const XMLCh* nsuri=attribute->getNamespaceURI();
\r
99 if (XMLString::equals(nsuri,XMLConstants::XMLNS_NS)) {
\r
100 if (XMLString::equals(attribute->getLocalName(),XMLConstants::XMLNS_PREFIX)) {
\r
101 XT_log.debug("found default namespace declaration, adding it to the list of namespaces on the XMLObject");
\r
102 addNamespace(Namespace(attribute->getValue(), NULL, true));
\r
106 XT_log.debug("found namespace declaration, adding it to the list of namespaces on the XMLObject");
\r
107 addNamespace(Namespace(attribute->getValue(), attribute->getLocalName(), true));
\r
111 else if (XMLString::equals(nsuri,XMLConstants::XSI_NS) && XMLString::equals(attribute->getLocalName(),type)) {
\r
112 XT_log.debug("found xsi:type declaration, setting the schema type of the XMLObject");
\r
113 auto_ptr<QName> xsitype(XMLHelper::getAttributeValueAsQName(attribute));
\r
114 setSchemaType(xsitype.get());
\r
117 else if (nsuri && !XMLString::equals(nsuri,XMLConstants::XML_NS)) {
\r
118 XT_log.debug("found namespace-qualified attribute, adding prefix to the list of namespaces on the XMLObject");
\r
119 addNamespace(Namespace(nsuri, attribute->getPrefix()));
\r
122 XT_log.debug("processing generic attribute");
\r
123 processAttribute(attribute);
\r
127 void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* domElement)
\r
130 xmltooling::NDC ndc("unmarshallChildElements");
\r
133 if (XT_log.isDebugEnabled()) {
\r
134 auto_ptr_char dname(domElement->getNodeName());
\r
135 XT_log.debug("unmarshalling child elements of DOM element (%s)", dname.get());
\r
138 DOMNodeList* childNodes = domElement->getChildNodes();
\r
139 DOMNode* childNode;
\r
140 if (!childNodes || childNodes->getLength()==0) {
\r
141 XT_log.debug("element had no children");
\r
145 XMLToolingConfig& config=XMLToolingConfig::getConfig();
\r
146 for (XMLSize_t i = 0; i < childNodes->getLength(); i++) {
\r
147 childNode = childNodes->item(i);
\r
148 if (childNode->getNodeType() == DOMNode::ELEMENT_NODE) {
\r
149 const XMLObjectBuilder* builder = XMLObjectBuilder::getBuilder(static_cast<DOMElement*>(childNode));
\r
151 auto_ptr<QName> cname(XMLHelper::getNodeQName(childNode));
\r
152 XT_log.error("no default builder installed, found unknown child element (%s)", cname->toString().c_str());
\r
153 throw UnmarshallingException("Unmarshaller found unknown child element, but no default builder was found.");
\r
156 if (XT_log.isDebugEnabled()) {
\r
157 auto_ptr<QName> cname(XMLHelper::getNodeQName(childNode));
\r
158 XT_log.debug("unmarshalling child element (%s)", cname->toString().c_str());
\r
161 // Retain ownership of the unmarshalled child until it's processed by the parent.
\r
162 auto_ptr<XMLObject> childObject(builder->buildObject(static_cast<DOMElement*>(childNode)));
\r
163 childObject->unmarshall(static_cast<DOMElement*>(childNode));
\r
164 processChildElement(childObject.get(), static_cast<DOMElement*>(childNode));
\r
165 childObject.release();
\r
167 else if (childNode->getNodeType() == DOMNode::TEXT_NODE) {
\r
168 XT_log.debug("processing element content");
\r
169 processElementContent(childNode->getNodeValue());
\r