From: cantor Date: Wed, 29 Mar 2006 19:10:13 +0000 (+0000) Subject: Unix porting fixes X-Git-Tag: 1.4.1~757 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fxmltooling.git;a=commitdiff_plain;h=cdae8cd771779d0c8ccc7822a74d0fcdfc3fe764 Unix porting fixes git-svn-id: https://svn.middleware.georgetown.edu/cpp-xmltooling/trunk@66 de75baf8-a10c-0410-a50a-987c0e22f00f --- diff --git a/xmltooling/AbstractXMLObject.cpp b/xmltooling/AbstractXMLObject.cpp index cdba177..bb40e91 100644 --- a/xmltooling/AbstractXMLObject.cpp +++ b/xmltooling/AbstractXMLObject.cpp @@ -1,78 +1,78 @@ -/* -* 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 "exceptions.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* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType) - : m_elementQname(nsURI, localName, prefix), m_typeQname(NULL), m_parent(NULL), - m_log(&log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".XMLObject")) -{ - addNamespace(Namespace(nsURI, prefix)); - if (schemaType) { - m_typeQname = new QName(*schemaType); - addNamespace(Namespace(m_typeQname->getNamespaceURI(), m_typeQname->getPrefix())); - } -} - -AbstractXMLObject::AbstractXMLObject(const AbstractXMLObject& src) - : m_namespaces(src.m_namespaces), m_log(src.m_log), m_parent(NULL), m_elementQname(src.m_elementQname), m_typeQname(NULL) -{ - if (src.m_typeQname) - m_typeQname=new QName(*src.m_typeQname); -} - -XMLObject* AbstractXMLObject::prepareForAssignment(XMLObject* oldValue, XMLObject* newValue) { - - if (newValue && newValue->hasParent()) - throw XMLObjectException("child XMLObject cannot be added - it is already the child of another XMLObject"); - - if (!oldValue) { - if (newValue) { - releaseThisandParentDOM(); - newValue->setParent(this); - return newValue; - } - else { - return NULL; - } - } - - if (oldValue != newValue) { - delete oldValue; - releaseThisandParentDOM(); - newValue->setParent(this); - } - - return newValue; -} +/* +* 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 "exceptions.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* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType) + : m_log(&log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".XMLObject")), + m_parent(NULL), m_elementQname(nsURI, localName, prefix), m_typeQname(NULL) +{ + addNamespace(Namespace(nsURI, prefix)); + if (schemaType) { + m_typeQname = new QName(*schemaType); + addNamespace(Namespace(m_typeQname->getNamespaceURI(), m_typeQname->getPrefix())); + } +} + +AbstractXMLObject::AbstractXMLObject(const AbstractXMLObject& src) + : m_namespaces(src.m_namespaces), m_log(src.m_log), m_parent(NULL), m_elementQname(src.m_elementQname), m_typeQname(NULL) +{ + if (src.m_typeQname) + m_typeQname=new QName(*src.m_typeQname); +} + +XMLObject* AbstractXMLObject::prepareForAssignment(XMLObject* oldValue, XMLObject* newValue) { + + if (newValue && newValue->hasParent()) + throw XMLObjectException("child XMLObject cannot be added - it is already the child of another XMLObject"); + + if (!oldValue) { + if (newValue) { + releaseThisandParentDOM(); + newValue->setParent(this); + return newValue; + } + else { + return NULL; + } + } + + if (oldValue != newValue) { + delete oldValue; + releaseThisandParentDOM(); + newValue->setParent(this); + } + + return newValue; +} diff --git a/xmltooling/Makefile.am b/xmltooling/Makefile.am index e139979..5b4e2bc 100644 --- a/xmltooling/Makefile.am +++ b/xmltooling/Makefile.am @@ -18,7 +18,6 @@ libxmltoolinginclude_HEADERS = \ AbstractAttributeExtensibleXMLObject.h \ AbstractDOMCachingXMLObject.h \ AbstractElementProxy.h \ - AbstractValidatingXMLObject.h \ AbstractXMLObject.h \ AttributeExtensibleXMLObject.h \ base.h \ @@ -29,7 +28,6 @@ libxmltoolinginclude_HEADERS = \ Namespace.h \ QName.h \ unicode.h \ - ValidatingXMLObject.h \ version.h \ XMLObject.h \ XMLObjectBuilder.h \ @@ -57,6 +55,8 @@ utilinclude_HEADERS = \ util/XMLObjectChildrenList.h valinclude_HEADERS = \ + validation/AbstractValidatingXMLObject.h \ + validation/ValidatingXMLObject.h \ validation/Validator.h noinst_HEADERS = \ @@ -66,7 +66,6 @@ noinst_HEADERS = \ if BUILD_XMLSEC xmlsec_sources = \ - signature/impl/KeyInfoImpl.cpp \ signature/impl/XMLSecSignatureImpl.cpp else xmlsec_sources = @@ -87,6 +86,7 @@ libxmltooling_la_SOURCES = \ impl/UnknownElement.cpp \ io/AbstractXMLObjectMarshaller.cpp \ io/AbstractXMLObjectUnmarshaller.cpp \ + signature/impl/KeyInfoImpl.cpp \ util/NDC.cpp \ util/ParserPool.cpp \ util/XMLConstants.cpp \ diff --git a/xmltooling/base.h b/xmltooling/base.h index d2060cb..093152e 100644 --- a/xmltooling/base.h +++ b/xmltooling/base.h @@ -74,6 +74,12 @@ #define NULL 0 #endif +#ifdef _MSC_VER + #define XMLTOOLING_DOXYGEN(desc) /##** desc */ +#else + #define XMLTOOLING_DOXYGEN(desc) +#endif + /** * Blocks copy c'tor and assignment operator for a class. */ @@ -96,11 +102,11 @@ cname() {} \ public: \ virtual ~cname() {} \ - /##** Type-specific clone method. */ \ + XMLTOOLING_DOXYGEN(Type-specific clone method.) \ virtual cname* clone##cname() const=0; \ - /##** Element prefix */ \ + XMLTOOLING_DOXYGEN(Element prefix) \ static const XMLCh PREFIX[]; \ - /##** Element local name */ \ + XMLTOOLING_DOXYGEN(Element local name) \ static const XMLCh LOCAL_NAME[] /** @@ -115,11 +121,11 @@ * @param upcased the upcased name of the attribute */ #define DECL_XMLOBJECT_ATTRIB(proper,upcased) \ - /##** proper attribute name */ \ + XMLTOOLING_DOXYGEN(proper attribute name) \ static const XMLCh upcased##_ATTRIB_NAME[]; \ - /##** Returns the proper attribute. */ \ + XMLTOOLING_DOXYGEN(Returns the proper attribute.) \ virtual const XMLCh* get##proper() const=0; \ - /##** Sets the proper attribute. */ \ + XMLTOOLING_DOXYGEN(Sets the proper attribute.) \ virtual void set##proper(const XMLCh* proper)=0 /** @@ -165,11 +171,11 @@ * @param cname the name of the XMLObject specialization */ #define BEGIN_XMLOBJECTBUILDER(cname) \ - /##** Builder for cname objects. */ \ + XMLTOOLING_DOXYGEN(Builder for cname objects.) \ class XMLTOOL_API cname##Builder : public xmltooling::XMLObjectBuilder { \ public: \ virtual ~cname##Builder() {} \ - /##** Default builder. */ \ + XMLTOOLING_DOXYGEN(Default builder.) \ virtual cname* buildObject() const=0 /** diff --git a/xmltooling/exceptions.cpp b/xmltooling/exceptions.cpp index 10e4e39..114e1ad 100644 --- a/xmltooling/exceptions.cpp +++ b/xmltooling/exceptions.cpp @@ -1,274 +1,275 @@ -/* - * 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. - */ - -/** - * exceptions.cpp - * - * Exception classes - */ - -#include "internal.h" -#include "exceptions.h" -#include "XMLToolingConfig.h" -#include "util/XMLConstants.h" -#include "util/XMLHelper.h" - -#include -#include - -using namespace xmltooling; -using namespace std; - -params::params(int count,...) -{ - va_list args; - va_start(args,count); - while (count--) - v.push_back(va_arg(args,char*)); - va_end(args); -} - -namedparams::namedparams(int count,...) -{ - count*=2; - va_list args; - va_start(args,count); - while (count--) - v.push_back(va_arg(args,char*)); - va_end(args); -} - -XMLToolingException::ExceptionFactoryMap XMLToolingException::m_factoryMap; - -XMLToolingException* XMLToolingException::getInstance(const char* exceptionClass) -{ - if (exceptionClass) { - ExceptionFactoryMap::const_iterator i=m_factoryMap.find(exceptionClass); - if (i!=m_factoryMap.end()) - return (i->second)(); - } - return new XMLToolingException(); -} - -XMLToolingException::XMLToolingException(const char* msg, const params& p) -{ - if (msg) - m_msg=msg; - addProperties(p); -} - -XMLToolingException::XMLToolingException(const char* msg, const namedparams& p) -{ - if (msg) - m_msg=msg; - addProperties(p); -} - -XMLToolingException::XMLToolingException(const std::string& msg, const params& p) : m_msg(msg) -{ - addProperties(p); -} - -XMLToolingException::XMLToolingException(const std::string& msg, const namedparams& p) : m_msg(msg) -{ - addProperties(p); -} - -void XMLToolingException::setMessage(const char* msg) -{ - if (msg) - m_msg=msg; - else - m_msg.erase(); - m_processedmsg.erase(); -} - -inline const char* get_digit_character() -{ - static const char s_characters[19] = - { - '9' - , '8' - , '7' - , '6' - , '5' - , '4' - , '3' - , '2' - , '1' - , '0' - , '1' - , '2' - , '3' - , '4' - , '5' - , '6' - , '7' - , '8' - , '9' - }; - static const char *s_mid = s_characters + 9; - - return s_mid; -} - -inline const char* unsigned_integer_to_string(char* buf, size_t cchBuf, int i) -{ - char* psz=buf + cchBuf - 1; // Set psz to last char - *psz = 0; // Set terminating null - - do { - unsigned int lsd = i % 10; // Get least significant - // digit - - i /= 10; // Prepare for next most - // significant digit - - --psz; // Move back - - *psz = get_digit_character()[lsd]; // Place the digit - - } while(i!=0 && psz>buf); - - return psz; -} - -void XMLToolingException::addProperties(const params& p) -{ - m_processedmsg.erase(); - int i=m_params.size()+1; - char buf[20]; - const vector& v=p.get(); - for (vector::const_iterator ci=v.begin(); ci!=v.end(); ci++) { - m_params[unsigned_integer_to_string(buf,sizeof(buf),i++)] = *ci; - } -} - -void XMLToolingException::addProperties(const namedparams& p) -{ - m_processedmsg.erase(); - const vector& v=p.get(); - for (vector::const_iterator ci=v.begin(); ci!=v.end(); ci++) { - m_params.erase(*ci); - m_params[*ci] = *(ci+1); - ci++; // advance past name to value, then loop will advance it again - } -} - -const char* XMLToolingException::getProperty(unsigned int index) const -{ - char buf[20]; - map::const_iterator i=m_params.find(unsigned_integer_to_string(buf,sizeof(buf),index)); - return (i==m_params.end()) ? NULL : i->second.c_str(); -} - -const char* XMLToolingException::getProperty(const char* name) const -{ - map::const_iterator i=m_params.find(name); - return (i==m_params.end()) ? NULL : i->second.c_str(); -} - -const char* XMLToolingException::getMessage() const -{ - if (!m_processedmsg.empty()) - return m_processedmsg.c_str(); - else if (m_params.empty()) - return m_msg.c_str(); - - static const char* legal="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_"; - - // Replace any parameters in the message. - string::size_type i=0,start=0; - while (start!=string::npos && startstart) - m_processedmsg += m_msg.substr(start,i-start); // append everything in between - start=i+1; // move start to the beginning of the token name - i=m_msg.find_first_not_of(legal,start); // find token delimiter - if (i==start) { // append a non legal character - m_processedmsg+=m_msg[start++]; - continue; - } - - // search for token in map - map::const_iterator param=m_params.find(m_msg.substr(start,(i==string::npos) ? i : i-start)); - if (param!=m_params.end()) { - m_processedmsg+=param->second; - start=i; - } - } - if (start!=string::npos && start"; - const char* msg=getMessage(); - if (msg) - xml=xml + "" + msg + ""; - for (map::const_iterator i=m_params.begin(); i!=m_params.end(); i++) { - xml=xml + "first + "\">" + i->second + ""; - } - xml+=""; - return xml; -} - -XMLToolingException* XMLToolingException::fromStream(std::istream& in) -{ - static const XMLCh exception[] = { chLatin_e, chLatin_x, chLatin_c, chLatin_e, chLatin_p, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull }; - static const XMLCh message[] = { chLatin_m, chLatin_e, chLatin_s, chLatin_s, chLatin_a, chLatin_g, chLatin_e, chNull }; - static const XMLCh name[] = { chLatin_n, chLatin_a, chLatin_m, chLatin_e, chNull }; - static const XMLCh param[] = { chLatin_p, chLatin_a, chLatin_r, chLatin_a, chLatin_m, chNull }; - static const XMLCh type[] = { chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull }; - - DOMDocument* doc=XMLToolingInternalConfig::getInternalConfig().m_parserPool->parse(in); - - // Check root element. - const DOMElement* root=doc->getDocumentElement(); - if (!XMLHelper::isNodeNamed(root,XMLConstants::XMLTOOLING_NS,exception)) { - doc->release(); - throw XMLToolingException("Invalid root element on serialized exception."); - } - - auto_ptr_char classname(root->getAttributeNS(NULL,type)); - auto_ptr excep(XMLToolingException::getInstance(classname.get())); - - DOMElement* child=XMLHelper::getFirstChildElement(root,XMLConstants::XMLTOOLING_NS,message); - if (child && child->hasChildNodes()) { - auto_ptr_char m(child->getFirstChild()->getNodeValue()); - excep->setMessage(m.get()); - } - - child=XMLHelper::getFirstChildElement(root,XMLConstants::XMLTOOLING_NS,param); - while (child && child->hasChildNodes()) { - auto_ptr_char n(child->getAttributeNS(NULL,name)); - char* v=toUTF8(child->getFirstChild()->getNodeValue()); - if (n.get() && v) - excep->addProperty(n.get(), v); - XMLString::release(&v); - child=XMLHelper::getNextSiblingElement(root,XMLConstants::XMLTOOLING_NS,param); - } - - doc->release(); - return excep.release(); -} - -XMLToolingException* XMLToolingException::fromString(const char* s) -{ - istringstream in(s); - return fromStream(in); -} +/* + * 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. + */ + +/** + * exceptions.cpp + * + * Exception classes + */ + +#include "internal.h" +#include "exceptions.h" +#include "XMLToolingConfig.h" +#include "util/XMLConstants.h" +#include "util/XMLHelper.h" + +#include +#include +#include + +using namespace xmltooling; +using namespace std; + +params::params(int count,...) +{ + va_list args; + va_start(args,count); + while (count--) + v.push_back(va_arg(args,char*)); + va_end(args); +} + +namedparams::namedparams(int count,...) +{ + count*=2; + va_list args; + va_start(args,count); + while (count--) + v.push_back(va_arg(args,char*)); + va_end(args); +} + +XMLToolingException::ExceptionFactoryMap XMLToolingException::m_factoryMap; + +XMLToolingException* XMLToolingException::getInstance(const char* exceptionClass) +{ + if (exceptionClass) { + ExceptionFactoryMap::const_iterator i=m_factoryMap.find(exceptionClass); + if (i!=m_factoryMap.end()) + return (i->second)(); + } + return new XMLToolingException(); +} + +XMLToolingException::XMLToolingException(const char* msg, const params& p) +{ + if (msg) + m_msg=msg; + addProperties(p); +} + +XMLToolingException::XMLToolingException(const char* msg, const namedparams& p) +{ + if (msg) + m_msg=msg; + addProperties(p); +} + +XMLToolingException::XMLToolingException(const std::string& msg, const params& p) : m_msg(msg) +{ + addProperties(p); +} + +XMLToolingException::XMLToolingException(const std::string& msg, const namedparams& p) : m_msg(msg) +{ + addProperties(p); +} + +void XMLToolingException::setMessage(const char* msg) +{ + if (msg) + m_msg=msg; + else + m_msg.erase(); + m_processedmsg.erase(); +} + +inline const char* get_digit_character() +{ + static const char s_characters[19] = + { + '9' + , '8' + , '7' + , '6' + , '5' + , '4' + , '3' + , '2' + , '1' + , '0' + , '1' + , '2' + , '3' + , '4' + , '5' + , '6' + , '7' + , '8' + , '9' + }; + static const char *s_mid = s_characters + 9; + + return s_mid; +} + +inline const char* unsigned_integer_to_string(char* buf, size_t cchBuf, int i) +{ + char* psz=buf + cchBuf - 1; // Set psz to last char + *psz = 0; // Set terminating null + + do { + unsigned int lsd = i % 10; // Get least significant + // digit + + i /= 10; // Prepare for next most + // significant digit + + --psz; // Move back + + *psz = get_digit_character()[lsd]; // Place the digit + + } while(i!=0 && psz>buf); + + return psz; +} + +void XMLToolingException::addProperties(const params& p) +{ + m_processedmsg.erase(); + int i=m_params.size()+1; + char buf[20]; + const vector& v=p.get(); + for (vector::const_iterator ci=v.begin(); ci!=v.end(); ci++) { + m_params[unsigned_integer_to_string(buf,sizeof(buf),i++)] = *ci; + } +} + +void XMLToolingException::addProperties(const namedparams& p) +{ + m_processedmsg.erase(); + const vector& v=p.get(); + for (vector::const_iterator ci=v.begin(); ci!=v.end(); ci++) { + m_params.erase(*ci); + m_params[*ci] = *(ci+1); + ci++; // advance past name to value, then loop will advance it again + } +} + +const char* XMLToolingException::getProperty(unsigned int index) const +{ + char buf[20]; + map::const_iterator i=m_params.find(unsigned_integer_to_string(buf,sizeof(buf),index)); + return (i==m_params.end()) ? NULL : i->second.c_str(); +} + +const char* XMLToolingException::getProperty(const char* name) const +{ + map::const_iterator i=m_params.find(name); + return (i==m_params.end()) ? NULL : i->second.c_str(); +} + +const char* XMLToolingException::getMessage() const +{ + if (!m_processedmsg.empty()) + return m_processedmsg.c_str(); + else if (m_params.empty()) + return m_msg.c_str(); + + static const char* legal="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_"; + + // Replace any parameters in the message. + string::size_type i=0,start=0; + while (start!=string::npos && startstart) + m_processedmsg += m_msg.substr(start,i-start); // append everything in between + start=i+1; // move start to the beginning of the token name + i=m_msg.find_first_not_of(legal,start); // find token delimiter + if (i==start) { // append a non legal character + m_processedmsg+=m_msg[start++]; + continue; + } + + // search for token in map + map::const_iterator param=m_params.find(m_msg.substr(start,(i==string::npos) ? i : i-start)); + if (param!=m_params.end()) { + m_processedmsg+=param->second; + start=i; + } + } + if (start!=string::npos && start"; + const char* msg=getMessage(); + if (msg) + xml=xml + "" + msg + ""; + for (map::const_iterator i=m_params.begin(); i!=m_params.end(); i++) { + xml=xml + "first + "\">" + i->second + ""; + } + xml+=""; + return xml; +} + +XMLToolingException* XMLToolingException::fromStream(std::istream& in) +{ + static const XMLCh exception[] = { chLatin_e, chLatin_x, chLatin_c, chLatin_e, chLatin_p, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull }; + static const XMLCh message[] = { chLatin_m, chLatin_e, chLatin_s, chLatin_s, chLatin_a, chLatin_g, chLatin_e, chNull }; + static const XMLCh name[] = { chLatin_n, chLatin_a, chLatin_m, chLatin_e, chNull }; + static const XMLCh param[] = { chLatin_p, chLatin_a, chLatin_r, chLatin_a, chLatin_m, chNull }; + static const XMLCh type[] = { chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull }; + + DOMDocument* doc=XMLToolingInternalConfig::getInternalConfig().m_parserPool->parse(in); + + // Check root element. + const DOMElement* root=doc->getDocumentElement(); + if (!XMLHelper::isNodeNamed(root,XMLConstants::XMLTOOLING_NS,exception)) { + doc->release(); + throw XMLToolingException("Invalid root element on serialized exception."); + } + + auto_ptr_char classname(root->getAttributeNS(NULL,type)); + auto_ptr excep(XMLToolingException::getInstance(classname.get())); + + DOMElement* child=XMLHelper::getFirstChildElement(root,XMLConstants::XMLTOOLING_NS,message); + if (child && child->hasChildNodes()) { + auto_ptr_char m(child->getFirstChild()->getNodeValue()); + excep->setMessage(m.get()); + } + + child=XMLHelper::getFirstChildElement(root,XMLConstants::XMLTOOLING_NS,param); + while (child && child->hasChildNodes()) { + auto_ptr_char n(child->getAttributeNS(NULL,name)); + char* v=toUTF8(child->getFirstChild()->getNodeValue()); + if (n.get() && v) + excep->addProperty(n.get(), v); + XMLString::release(&v); + child=XMLHelper::getNextSiblingElement(root,XMLConstants::XMLTOOLING_NS,param); + } + + doc->release(); + return excep.release(); +} + +XMLToolingException* XMLToolingException::fromString(const char* s) +{ + istringstream in(s); + return fromStream(in); +} diff --git a/xmltooling/exceptions.h b/xmltooling/exceptions.h index 6e82e1e..a10db9b 100644 --- a/xmltooling/exceptions.h +++ b/xmltooling/exceptions.h @@ -1,353 +1,353 @@ -/* - * 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 exceptions.h - * - * Exception classes - */ - -#ifndef __xmltooling_exceptions_h__ -#define __xmltooling_exceptions_h__ - -#include -#include -#include -#include -#include - -/** - * Declares a derived exception class - * - * @param name the exception class - * @param base the base class - * @param desc - */ -#define DECL_XMLTOOLING_EXCEPTION(name,base,desc) \ - /##** desc */ \ - class XMLTOOL_EXCEPTIONAPI(XMLTOOL_API) name : public xmltooling::base { \ - public: \ - /##** base##::##base(const char*,const xmltooling::params&) */ \ - name(const char* msg=NULL, const xmltooling::params& p=xmltooling::params()) \ - : xmltooling::base(msg,p) {} \ - /##** base##::##base(const char*,const xmltooling::namedparams&) */ \ - name(const char* msg, const xmltooling::namedparams& p) \ - : xmltooling::base(msg,p) {} \ - /##** base##::##base(const std::string&,const xmltooling::params&) */ \ - name(const std::string& msg, const xmltooling::params& p=xmltooling::params()) \ - : xmltooling::base(msg,p) {} \ - /##** base##::##base(const std::string&,const xmltooling::namedparams&) */ \ - name(const std::string& msg, const xmltooling::namedparams& p) \ - : xmltooling::base(msg,p) {} \ - virtual ~name() {} \ - virtual const char* getClassName() const { return "xmltooling::"#name; } \ - void raise() const {throw *this;} \ - } - -/** - * Declares a factory function for an exception class. - * - * @param name the exception class name - */ -#define DECL_EXCEPTION_FACTORY(name) \ - xmltooling::XMLToolingException* name##Factory() \ - { \ - return new xmltooling::name(); \ - } - -/** - * Registers a factory for an exception class. - * - * @param name the exception class name - */ -#define REGISTER_EXCEPTION_FACTORY(name) XMLToolingException::registerFactory("xmltooling::"#name,name##Factory) - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * Wrapper around a variable number of arguments. - */ - class XMLTOOL_API params - { - public: - /** - * Initializes with zero parameters. - */ - params() {} - - /** - * Initializes the parameter set. - * - * @param count the number of parameters that follow - */ - params(int count,...); - - /** - * Returns an immutable reference to the set of parameters. - * - * @return the parameter set - */ - const std::vector& get() const {return v;} - - protected: - /** Contains the parameters being passed. */ - std::vector v; - }; - - /** - * Wrapper around a variable number of name/value pairs. - */ - class XMLTOOL_API namedparams : public params - { - public: - /** - * Initializes with zero parameters. - */ - namedparams() {} - - /** - * Initializes the named parameter set. - * - * @param count the number of name/value pairs that follow (must be even) - */ - namedparams(int count,...); - }; - - class XMLTOOL_EXCEPTIONAPI(XMLTOOL_API) XMLToolingException; - - /** A factory function that returns an empty exception object of a given type. */ - typedef XMLToolingException* ExceptionFactory(); - - /** - * Base exception class, supports parametrized messages and XML serialization. - * Parameters are prefixed with a dollar sign ($) and can be positional ($1) - * or named ($info). - */ - class XMLTOOL_EXCEPTIONAPI(XMLTOOL_API) XMLToolingException - { - public: - virtual ~XMLToolingException() {} - - /** - * Constructs an exception using a message and positional parameters. - * - * @param msg error message - * @param p an ordered set of positional parameter strings - */ - XMLToolingException(const char* msg=NULL, const params& p=params()); - - /** - * Constructs an exception using a message and named parameters. - * - * @param msg error message - * @param p a set of named parameter strings - */ - XMLToolingException(const char* msg, const namedparams& p); - - /** - * Constructs an exception using a message and positional parameters. - * - * @param msg error message - * @param p an ordered set of positional parameter strings - */ - XMLToolingException(const std::string& msg, const params& p=params()); - - /** - * Constructs an exception using a message and named parameters. - * - * @param msg error message - * @param p a set of named parameter strings - */ - XMLToolingException(const std::string& msg, const namedparams& p); - - /** - * Returns the error message, after processing any parameter references. - * - * @return the processed message - */ - const char* getMessage() const; - - /** - * Returns the error message, after processing any parameter references. - * - * @return the processed message - */ - const char* what() const {return getMessage();} - - /** - * Sets the error message. - * - * @param msg the error message - */ - void setMessage(const char* msg); - - /** - * Sets the error message. - * - * @param msg the error message - */ - void setMessage(const std::string& msg) { - setMessage(msg.c_str()); - } - - /** - * Attach a set of positional parameters to the exception. - * - * @param p an ordered set of named parameter strings - */ - void addProperties(const params& p); - - /** - * Attach a set of named parameters to the exception. - * - * @param p a set of named parameter strings - */ - void addProperties(const namedparams& p); - - /** - * Attach a single positional parameter at the next available position. - * - * @param value the parameter value - */ - void addProperty(const char* value) { - addProperties(params(1,value)); - } - - /** - * Attach a single named parameter. - * - * @param name the parameter name - * @param value the parameter value - */ - void addProperty(const char* name, const char* value) { - addProperties(namedparams(1,name,value)); - } - - /** - * Returns the parameter property with the designated position (based from one). - * - * @param index position to access - * @return the parameter property or NULL - */ - const char* getProperty(unsigned int index) const; - - /** - * Returns the parameter property with the designated name. - * - * @param name named parameter to access - * @return the parameter property or NULL - */ - const char* getProperty(const char* name) const; - - /** - * Raises an exception using itself. - * Used to raise an exception of a derived type. - */ - virtual void raise() const { - throw *this; - } - - /** - * Returns a unique name for the exception class. - * - * @return class name - */ - virtual const char* getClassName() const { - return "xmltooling::XMLToolingException"; - } - - /** - * Returns a string containing a serialized representation of the exception. - * - * @return the serialization - */ - std::string toString() const; - - private: - std::string m_msg; - mutable std::string m_processedmsg; - std::map m_params; - - public: - /** - * Builds an empty exception of the given type. - * - * @param exceptionClass the name of the exception type to build - * @return an empty exception object - */ - static XMLToolingException* getInstance(const char* exceptionClass); - - /** - * Builds an exception from a serialized input stream. - * - * @param in input stream - * @return the exception object found in the stream - */ - static XMLToolingException* fromStream(std::istream& in); - - /** - * Builds an exception from a serialized input buffer. - * - * @param s input buffer - * @return the exception object found in the buffer - */ - static XMLToolingException* fromString(const char* s); - - /** - * Registers a factory to create exceptions of a given class name. - * - * @param exceptionClass name of exception type - * @param factory factory function to build exceptions with - */ - static void registerFactory(const char* exceptionClass, ExceptionFactory* factory) { - m_factoryMap[exceptionClass] = factory; - } - - /** - * Unregisters the factory for a given class name. - * - * @param exceptionClass name of exception type - */ - static void deregisterFactory(const char* exceptionClass) { - m_factoryMap.erase(exceptionClass); - } - - private: - typedef std::map ExceptionFactoryMap; - static ExceptionFactoryMap m_factoryMap; - }; - - DECL_XMLTOOLING_EXCEPTION(XMLParserException,XMLToolingException,Exceptions related to XML parsing); - DECL_XMLTOOLING_EXCEPTION(XMLObjectException,XMLToolingException,Exceptions in basic object usage); - DECL_XMLTOOLING_EXCEPTION(MarshallingException,XMLToolingException,Exceptions during object marshalling); - DECL_XMLTOOLING_EXCEPTION(UnmarshallingException,XMLToolingException,Exceptions during object unmarshalling); - DECL_XMLTOOLING_EXCEPTION(UnknownElementException,XMLToolingException,Exceptions due to processing of unknown element content); - DECL_XMLTOOLING_EXCEPTION(UnknownAttributeException,XMLToolingException,Exceptions due to processing of unknown attributes); - DECL_XMLTOOLING_EXCEPTION(ValidationException,XMLToolingException,Exceptions during object validation); - DECL_XMLTOOLING_EXCEPTION(SignatureException,XMLToolingException,Exceptions in signature processing); - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_exceptions_h__ */ +/* + * 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 exceptions.h + * + * Exception classes + */ + +#ifndef __xmltooling_exceptions_h__ +#define __xmltooling_exceptions_h__ + +#include +#include +#include +#include +#include + +/** + * Declares a derived exception class + * + * @param name the exception class + * @param base the base class + * @param desc + */ +#define DECL_XMLTOOLING_EXCEPTION(name,base,desc) \ + XMLTOOLING_DOXYGEN(desc) \ + class XMLTOOL_EXCEPTIONAPI(XMLTOOL_API) name : public xmltooling::base { \ + public: \ + XMLTOOLING_DOXYGEN(Constructor) \ + name(const char* msg=NULL, const xmltooling::params& p=xmltooling::params()) \ + : xmltooling::base(msg,p) {} \ + XMLTOOLING_DOXYGEN(Constructor) \ + name(const char* msg, const xmltooling::namedparams& p) \ + : xmltooling::base(msg,p) {} \ + XMLTOOLING_DOXYGEN(Constructor) \ + name(const std::string& msg, const xmltooling::params& p=xmltooling::params()) \ + : xmltooling::base(msg,p) {} \ + XMLTOOLING_DOXYGEN(Constructor) \ + name(const std::string& msg, const xmltooling::namedparams& p) \ + : xmltooling::base(msg,p) {} \ + virtual ~name() {} \ + virtual const char* getClassName() const { return "xmltooling::"#name; } \ + void raise() const {throw *this;} \ + } + +/** + * Declares a factory function for an exception class. + * + * @param name the exception class name + */ +#define DECL_EXCEPTION_FACTORY(name) \ + xmltooling::XMLToolingException* name##Factory() \ + { \ + return new xmltooling::name(); \ + } + +/** + * Registers a factory for an exception class. + * + * @param name the exception class name + */ +#define REGISTER_EXCEPTION_FACTORY(name) XMLToolingException::registerFactory("xmltooling::"#name,name##Factory) + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * Wrapper around a variable number of arguments. + */ + class XMLTOOL_API params + { + public: + /** + * Initializes with zero parameters. + */ + params() {} + + /** + * Initializes the parameter set. + * + * @param count the number of parameters that follow + */ + params(int count,...); + + /** + * Returns an immutable reference to the set of parameters. + * + * @return the parameter set + */ + const std::vector& get() const {return v;} + + protected: + /** Contains the parameters being passed. */ + std::vector v; + }; + + /** + * Wrapper around a variable number of name/value pairs. + */ + class XMLTOOL_API namedparams : public params + { + public: + /** + * Initializes with zero parameters. + */ + namedparams() {} + + /** + * Initializes the named parameter set. + * + * @param count the number of name/value pairs that follow (must be even) + */ + namedparams(int count,...); + }; + + class XMLTOOL_EXCEPTIONAPI(XMLTOOL_API) XMLToolingException; + + /** A factory function that returns an empty exception object of a given type. */ + typedef XMLToolingException* ExceptionFactory(); + + /** + * Base exception class, supports parametrized messages and XML serialization. + * Parameters are prefixed with a dollar sign ($) and can be positional ($1) + * or named ($info). + */ + class XMLTOOL_EXCEPTIONAPI(XMLTOOL_API) XMLToolingException + { + public: + virtual ~XMLToolingException() {} + + /** + * Constructs an exception using a message and positional parameters. + * + * @param msg error message + * @param p an ordered set of positional parameter strings + */ + XMLToolingException(const char* msg=NULL, const params& p=params()); + + /** + * Constructs an exception using a message and named parameters. + * + * @param msg error message + * @param p a set of named parameter strings + */ + XMLToolingException(const char* msg, const namedparams& p); + + /** + * Constructs an exception using a message and positional parameters. + * + * @param msg error message + * @param p an ordered set of positional parameter strings + */ + XMLToolingException(const std::string& msg, const params& p=params()); + + /** + * Constructs an exception using a message and named parameters. + * + * @param msg error message + * @param p a set of named parameter strings + */ + XMLToolingException(const std::string& msg, const namedparams& p); + + /** + * Returns the error message, after processing any parameter references. + * + * @return the processed message + */ + const char* getMessage() const; + + /** + * Returns the error message, after processing any parameter references. + * + * @return the processed message + */ + const char* what() const {return getMessage();} + + /** + * Sets the error message. + * + * @param msg the error message + */ + void setMessage(const char* msg); + + /** + * Sets the error message. + * + * @param msg the error message + */ + void setMessage(const std::string& msg) { + setMessage(msg.c_str()); + } + + /** + * Attach a set of positional parameters to the exception. + * + * @param p an ordered set of named parameter strings + */ + void addProperties(const params& p); + + /** + * Attach a set of named parameters to the exception. + * + * @param p a set of named parameter strings + */ + void addProperties(const namedparams& p); + + /** + * Attach a single positional parameter at the next available position. + * + * @param value the parameter value + */ + void addProperty(const char* value) { + addProperties(params(1,value)); + } + + /** + * Attach a single named parameter. + * + * @param name the parameter name + * @param value the parameter value + */ + void addProperty(const char* name, const char* value) { + addProperties(namedparams(1,name,value)); + } + + /** + * Returns the parameter property with the designated position (based from one). + * + * @param index position to access + * @return the parameter property or NULL + */ + const char* getProperty(unsigned int index) const; + + /** + * Returns the parameter property with the designated name. + * + * @param name named parameter to access + * @return the parameter property or NULL + */ + const char* getProperty(const char* name) const; + + /** + * Raises an exception using itself. + * Used to raise an exception of a derived type. + */ + virtual void raise() const { + throw *this; + } + + /** + * Returns a unique name for the exception class. + * + * @return class name + */ + virtual const char* getClassName() const { + return "xmltooling::XMLToolingException"; + } + + /** + * Returns a string containing a serialized representation of the exception. + * + * @return the serialization + */ + std::string toString() const; + + private: + std::string m_msg; + mutable std::string m_processedmsg; + std::map m_params; + + public: + /** + * Builds an empty exception of the given type. + * + * @param exceptionClass the name of the exception type to build + * @return an empty exception object + */ + static XMLToolingException* getInstance(const char* exceptionClass); + + /** + * Builds an exception from a serialized input stream. + * + * @param in input stream + * @return the exception object found in the stream + */ + static XMLToolingException* fromStream(std::istream& in); + + /** + * Builds an exception from a serialized input buffer. + * + * @param s input buffer + * @return the exception object found in the buffer + */ + static XMLToolingException* fromString(const char* s); + + /** + * Registers a factory to create exceptions of a given class name. + * + * @param exceptionClass name of exception type + * @param factory factory function to build exceptions with + */ + static void registerFactory(const char* exceptionClass, ExceptionFactory* factory) { + m_factoryMap[exceptionClass] = factory; + } + + /** + * Unregisters the factory for a given class name. + * + * @param exceptionClass name of exception type + */ + static void deregisterFactory(const char* exceptionClass) { + m_factoryMap.erase(exceptionClass); + } + + private: + typedef std::map ExceptionFactoryMap; + static ExceptionFactoryMap m_factoryMap; + }; + + DECL_XMLTOOLING_EXCEPTION(XMLParserException,XMLToolingException,Exceptions related to XML parsing); + DECL_XMLTOOLING_EXCEPTION(XMLObjectException,XMLToolingException,Exceptions in basic object usage); + DECL_XMLTOOLING_EXCEPTION(MarshallingException,XMLToolingException,Exceptions during object marshalling); + DECL_XMLTOOLING_EXCEPTION(UnmarshallingException,XMLToolingException,Exceptions during object unmarshalling); + DECL_XMLTOOLING_EXCEPTION(UnknownElementException,XMLToolingException,Exceptions due to processing of unknown element content); + DECL_XMLTOOLING_EXCEPTION(UnknownAttributeException,XMLToolingException,Exceptions due to processing of unknown attributes); + DECL_XMLTOOLING_EXCEPTION(ValidationException,XMLToolingException,Exceptions during object validation); + DECL_XMLTOOLING_EXCEPTION(SignatureException,XMLToolingException,Exceptions in signature processing); + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_exceptions_h__ */ diff --git a/xmltooling/io/AbstractXMLObjectUnmarshaller.cpp b/xmltooling/io/AbstractXMLObjectUnmarshaller.cpp index 465b432..fd4c9f5 100644 --- a/xmltooling/io/AbstractXMLObjectUnmarshaller.cpp +++ b/xmltooling/io/AbstractXMLObjectUnmarshaller.cpp @@ -1,177 +1,176 @@ -/* -* 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. - */ - -/** - * AbstractXMLObjectUnmarshaller.cpp - * - * A thread-safe abstract unmarshaller. - */ - -#include "internal.h" -#include "exceptions.h" -#include "XMLObjectBuilder.h" -#include "io/AbstractXMLObjectUnmarshaller.h" -#include "util/NDC.h" -#include "util/XMLConstants.h" -#include "util/XMLHelper.h" - -#include -#include - -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -#define XT_log (*static_cast(m_log)) - -XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool bindDocument) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("unmarshall"); -#endif - - if (getDOM() || hasParent()) - throw UnmarshallingException("Object already contains data, it cannot be unmarshalled at this stage."); - - if (!XMLString::equals(element->getNamespaceURI(),getElementQName().getNamespaceURI()) || - !XMLString::equals(element->getLocalName(),getElementQName().getLocalPart())) { - throw UnmarshallingException("Unrecognized element supplied to implementation for unmarshalling."); - } - - if (XT_log.isDebugEnabled()) { - auto_ptr_char dname(element->getNodeName()); - XT_log.debug("unmarshalling DOM element (%s)", dname.get()); - } - - if (element->hasAttributes()) { - unmarshallAttributes(element); - } - - unmarshallChildElements(element); - - /* TODO: Signing - if (xmlObject instanceof SignableXMLObject) { - verifySignature(domElement, xmlObject); - } - */ - - setDOM(element,bindDocument); - return this; -} - -void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domElement) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("unmarshallAttributes"); -#endif - static const XMLCh type[]={chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull}; - - if (XT_log.isDebugEnabled()) { - auto_ptr_char dname(domElement->getNodeName()); - XT_log.debug("unmarshalling attributes for DOM element (%s)", dname.get()); - } - - DOMNamedNodeMap* attributes = domElement->getAttributes(); - if (!attributes) { - XT_log.debug("no attributes to unmarshall"); - return; - } - - DOMNode* childNode; - DOMAttr* attribute; - for (XMLSize_t i=0; igetLength(); i++) { - childNode = attributes->item(i); - - // 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()); - continue; - } - - attribute = static_cast(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"); - addNamespace(Namespace(attribute->getValue(), NULL, true)); - continue; - } - else { - XT_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 (nsuri && !XMLString::equals(nsuri,XMLConstants::XML_NS)) { - XT_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"); - processAttribute(attribute); - } -} - -void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* domElement) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("unmarshallChildElements"); -#endif - - if (XT_log.isDebugEnabled()) { - auto_ptr_char dname(domElement->getNodeName()); - XT_log.debug("unmarshalling child elements of DOM element (%s)", dname.get()); - } - - DOMNodeList* childNodes = domElement->getChildNodes(); - DOMNode* childNode; - if (!childNodes || childNodes->getLength()==0) { - XT_log.debug("element had no children"); - return; - } - - XMLToolingConfig& config=XMLToolingConfig::getConfig(); - for (XMLSize_t i = 0; i < childNodes->getLength(); i++) { - childNode = childNodes->item(i); - if (childNode->getNodeType() == DOMNode::ELEMENT_NODE) { - const XMLObjectBuilder* builder = XMLObjectBuilder::getBuilder(static_cast(childNode)); - if (!builder) { - auto_ptr cname(XMLHelper::getNodeQName(childNode)); - 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()) { - auto_ptr cname(XMLHelper::getNodeQName(childNode)); - XT_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 childObject(builder->buildFromElement(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(childNode->getNodeValue()); - } - } -} +/* +* 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. + */ + +/** + * AbstractXMLObjectUnmarshaller.cpp + * + * A thread-safe abstract unmarshaller. + */ + +#include "internal.h" +#include "exceptions.h" +#include "XMLObjectBuilder.h" +#include "io/AbstractXMLObjectUnmarshaller.h" +#include "util/NDC.h" +#include "util/XMLConstants.h" +#include "util/XMLHelper.h" + +#include +#include + +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +#define XT_log (*static_cast(m_log)) + +XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool bindDocument) +{ +#ifdef _DEBUG + xmltooling::NDC ndc("unmarshall"); +#endif + + if (getDOM() || hasParent()) + throw UnmarshallingException("Object already contains data, it cannot be unmarshalled at this stage."); + + if (!XMLString::equals(element->getNamespaceURI(),getElementQName().getNamespaceURI()) || + !XMLString::equals(element->getLocalName(),getElementQName().getLocalPart())) { + throw UnmarshallingException("Unrecognized element supplied to implementation for unmarshalling."); + } + + if (XT_log.isDebugEnabled()) { + auto_ptr_char dname(element->getNodeName()); + XT_log.debug("unmarshalling DOM element (%s)", dname.get()); + } + + if (element->hasAttributes()) { + unmarshallAttributes(element); + } + + unmarshallChildElements(element); + + /* TODO: Signing + if (xmlObject instanceof SignableXMLObject) { + verifySignature(domElement, xmlObject); + } + */ + + setDOM(element,bindDocument); + return this; +} + +void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domElement) +{ +#ifdef _DEBUG + xmltooling::NDC ndc("unmarshallAttributes"); +#endif + static const XMLCh type[]={chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull}; + + if (XT_log.isDebugEnabled()) { + auto_ptr_char dname(domElement->getNodeName()); + XT_log.debug("unmarshalling attributes for DOM element (%s)", dname.get()); + } + + DOMNamedNodeMap* attributes = domElement->getAttributes(); + if (!attributes) { + XT_log.debug("no attributes to unmarshall"); + return; + } + + DOMNode* childNode; + DOMAttr* attribute; + for (XMLSize_t i=0; igetLength(); i++) { + childNode = attributes->item(i); + + // 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()); + continue; + } + + attribute = static_cast(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"); + addNamespace(Namespace(attribute->getValue(), NULL, true)); + continue; + } + else { + XT_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 (nsuri && !XMLString::equals(nsuri,XMLConstants::XML_NS)) { + XT_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"); + processAttribute(attribute); + } +} + +void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* domElement) +{ +#ifdef _DEBUG + xmltooling::NDC ndc("unmarshallChildElements"); +#endif + + if (XT_log.isDebugEnabled()) { + auto_ptr_char dname(domElement->getNodeName()); + XT_log.debug("unmarshalling child elements of DOM element (%s)", dname.get()); + } + + DOMNodeList* childNodes = domElement->getChildNodes(); + DOMNode* childNode; + if (!childNodes || childNodes->getLength()==0) { + XT_log.debug("element had no children"); + return; + } + + for (XMLSize_t i = 0; i < childNodes->getLength(); i++) { + childNode = childNodes->item(i); + if (childNode->getNodeType() == DOMNode::ELEMENT_NODE) { + const XMLObjectBuilder* builder = XMLObjectBuilder::getBuilder(static_cast(childNode)); + if (!builder) { + auto_ptr cname(XMLHelper::getNodeQName(childNode)); + 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()) { + auto_ptr cname(XMLHelper::getNodeQName(childNode)); + XT_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 childObject(builder->buildFromElement(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(childNode->getNodeValue()); + } + } +} diff --git a/xmltooling/util/ParserPool.cpp b/xmltooling/util/ParserPool.cpp index 5bec638..838c044 100644 --- a/xmltooling/util/ParserPool.cpp +++ b/xmltooling/util/ParserPool.cpp @@ -1,358 +1,357 @@ -/* - * 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. - */ - -/** - * ParserPool.cpp - * - * XML parsing - */ - -#include "internal.h" -#include "exceptions.h" -#include "util/NDC.h" -#include "util/ParserPool.h" -#include "util/XMLHelper.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace xmltooling; -using namespace std; -using namespace log4cpp; - -ParserPool::ParserPool(bool namespaceAware, bool schemaAware) - : m_namespaceAware(namespaceAware), m_schemaAware(schemaAware), m_lock(XMLPlatformUtils::makeMutex()) {} - -ParserPool::~ParserPool() -{ - while(!m_pool.empty()) { - m_pool.top()->release(); - m_pool.pop(); - } - XMLPlatformUtils::closeMutex(m_lock); -} - -DOMDocument* ParserPool::newDocument() -{ - return DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument(); -} - -DOMDocument* ParserPool::parse(DOMInputSource& domsrc) -{ - DOMBuilder* parser=checkoutBuilder(); - try { - DOMDocument* doc=parser->parse(domsrc); - parser->setFeature(XMLUni::fgXercesUserAdoptsDOMDocument,true); - checkinBuilder(parser); - return doc; - } - catch (...) { - checkinBuilder(parser); - throw; - } -} - -DOMDocument* ParserPool::parse(istream& is) -{ - StreamInputSource src(is); - Wrapper4InputSource domsrc(&src,false); - return parse(domsrc); -} - -// Functor to double its argument separated by a character and append to a buffer -template class doubleit -{ -public: - doubleit(T& t, const typename T::value_type& s) : temp(t), sep(s) {} - void operator() (const pair& s) { temp += s.first + sep + s.first + sep; } - T& temp; - const typename T::value_type& sep; -}; - -bool ParserPool::loadSchema(const XMLCh* nsURI, const XMLCh* pathname) -{ - // Just check the pathname and then directly register the pair into the map. - - auto_ptr_char p(pathname); -#ifdef WIN32 - struct _stat stat_buf; - if (_stat(p.get(), &stat_buf) != 0) -#else - struct stat stat_buf; - if (stat(p.get(), &stat_buf) != 0) -#endif - { -#if _DEBUG - xmltooling::NDC ndc("loadSchema"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".ParserPool"); - auto_ptr_char n(nsURI); - log.error("failed to load schema for (%s), file not found (%s)",n.get(),p.get()); - return false; - } - - XMLPlatformUtils::lockMutex(m_lock); -#ifdef HAVE_GOOD_STL - m_schemaLocMap[nsURI]=pathname; - m_schemaLocations.erase(); - for_each(m_schemaLocMap.begin(),m_schemaLocMap.end(),doubleit(m_schemaLocations,chSpace)); -#else - auto_ptr_char n(nsURI); - m_schemaLocMap[n.get()]=p.get(); - m_schemaLocations.erase(); - for_each(m_schemaLocMap.begin(),m_schemaLocMap.end(),doubleit(m_schemaLocations,' ')); -#endif - XMLPlatformUtils::unlockMutex(m_lock); - - return true; -} - -bool ParserPool::loadCatalog(const XMLCh* pathname) -{ -#if _DEBUG - xmltooling::NDC ndc("loadCatalog"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".ParserPool"); - - // XML constants - static const XMLCh impltype[] = { chLatin_L, chLatin_S, chNull }; - static const XMLCh catalog[] = { chLatin_c, chLatin_a, chLatin_t, chLatin_a, chLatin_l, chLatin_o, chLatin_g, chNull }; - static const XMLCh uri[] = { chLatin_u, chLatin_r, chLatin_i, chNull }; - static const XMLCh name[] = { chLatin_n, chLatin_a, chLatin_m, chLatin_e, chNull }; - static const XMLCh CATALOG_NS[] = { - chLatin_u, chLatin_r, chLatin_n, chColon, - chLatin_o, chLatin_a, chLatin_s, chLatin_i, chLatin_s, chColon, - chLatin_n, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chColon, - chLatin_t, chLatin_c, chColon, - chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_t, chLatin_y, chColon, - chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chColon, - chLatin_x, chLatin_m, chLatin_l, chColon, - chLatin_c, chLatin_a, chLatin_t, chLatin_a, chLatin_l, chLatin_o, chLatin_g, chNull - }; - - // Parse the catalog with the internal parser pool. - - if (log.isDebugEnabled()) { - auto_ptr_char temp(pathname); - log.debug("loading XML catalog from %s", temp.get()); - } - - LocalFileInputSource fsrc(NULL,pathname); - Wrapper4InputSource domsrc(&fsrc,false); - try { - DOMDocument* doc=XMLToolingInternalConfig::getInternalConfig().m_parserPool->parse(domsrc); - - // Check root element. - const DOMElement* root=doc->getDocumentElement(); - if (!XMLHelper::isNodeNamed(root,CATALOG_NS,catalog)) { - auto_ptr_char temp(pathname); - log.error("unknown root element, failed to load XML catalog from %s", temp.get()); - doc->release(); - return false; - } - - // Fetch all the elements. - DOMNodeList* mappings=root->getElementsByTagNameNS(CATALOG_NS,uri); - XMLPlatformUtils::lockMutex(m_lock); - for (XMLSize_t i=0; igetLength(); i++) { - root=static_cast(mappings->item(i)); - const XMLCh* from=root->getAttributeNS(NULL,name); - const XMLCh* to=root->getAttributeNS(NULL,uri); -#ifdef HAVE_GOOD_STL - m_schemaLocMap[from]=to; -#else - auto_ptr_char f(from); - auto_ptr_char t(to); - m_schemaLocMap[f.get()]=t.get(); -#endif - } - m_schemaLocations.erase(); -#ifdef HAVE_GOOD_STL - for_each(m_schemaLocMap.begin(),m_schemaLocMap.end(),doubleit(m_schemaLocations,chSpace)); -#else - for_each(m_schemaLocMap.begin(),m_schemaLocMap.end(),doubleit(m_schemaLocations,' ')); -#endif - XMLPlatformUtils::unlockMutex(m_lock); - doc->release(); - } - catch (XMLParserException& e) { - log.error("catalog loader caught XMLParserException: %s", e.what()); - return false; - } - - return true; -} - -DOMInputSource* ParserPool::resolveEntity(const XMLCh* const publicId, const XMLCh* const systemId, const XMLCh* const baseURI) -{ -#if _DEBUG - xmltooling::NDC ndc("resolveEntity"); -#endif - if (!systemId) - return NULL; - - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".ParserPool"); - if (log.isDebugEnabled()) { - auto_ptr_char sysId(systemId); - auto_ptr_char base(baseURI); - log.debug("asked to resolve %s with baseURI %s",sysId.get(),base.get() ? base.get() : "(null)"); - } - - // Find well-known schemas in the specified location. -#ifdef HAVE_GOOD_STL - map::const_iterator i=m_schemaLocMap.find(systemId); - if (i!=m_schemaLocMap.end()) - return new Wrapper4InputSource(new LocalFileInputSource(NULL,i->second.c_str())); -#else - auto_ptr_char temp(systemId); - map::const_iterator i=m_schemaLocMap.find(temp.get()); - auto_ptr_XMLCh temp2(i->second.c_str()); - if (i!=m_schemaLocMap.end()) - return new Wrapper4InputSource(new LocalFileInputSource(NULL,temp2.get())); -#endif - - // Shortcircuit the request. - log.warn("unauthorized entity request, blocking it"); - static const XMLByte nullbuf[] = {0}; - return new Wrapper4InputSource(new MemBufInputSource(nullbuf,0,systemId)); -} - -bool ParserPool::handleError(const DOMError& e) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("handleError"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".ParserPool"); - DOMLocator* locator=e.getLocation(); - auto_ptr_char temp(e.getMessage()); - - switch (e.getSeverity()) { - case DOMError::DOM_SEVERITY_WARNING: - log.warnStream() << "warning on line " << locator->getLineNumber() - << ", column " << locator->getColumnNumber() - << ", message: " << temp.get() << CategoryStream::ENDLINE; - return true; - - case DOMError::DOM_SEVERITY_ERROR: - log.errorStream() << "error on line " << locator->getLineNumber() - << ", column " << locator->getColumnNumber() - << ", message: " << temp.get() << CategoryStream::ENDLINE; - throw XMLParserException(string("error during XML parsing: ") + (temp.get() ? temp.get() : "no message")); - - case DOMError::DOM_SEVERITY_FATAL_ERROR: - log.critStream() << "fatal error on line " << locator->getLineNumber() - << ", column " << locator->getColumnNumber() - << ", message: " << temp.get() << CategoryStream::ENDLINE; - throw XMLParserException(string("fatal error during XML parsing: ") + (temp.get() ? temp.get() : "no message")); - } - throw XMLParserException(string("unclassified error during XML parsing: ") + (temp.get() ? temp.get() : "no message")); -} - -DOMBuilder* ParserPool::createBuilder() -{ - static const XMLCh impltype[] = { chLatin_L, chLatin_S, chNull }; - DOMImplementation* impl=DOMImplementationRegistry::getDOMImplementation(impltype); - DOMBuilder* parser=static_cast(impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS,0); - if (m_namespaceAware) - parser->setFeature(XMLUni::fgDOMNamespaces,true); - if (m_schemaAware) { - parser->setFeature(XMLUni::fgXercesSchema,true); - parser->setFeature(XMLUni::fgDOMValidation,true); - parser->setFeature(XMLUni::fgXercesCacheGrammarFromParse,true); - parser->setFeature(XMLUni::fgXercesValidationErrorAsFatal,true); - - // We build a "fake" schema location hint that binds each namespace to itself. - // This ensures the entity resolver will be given the namespace as a systemId it can check. -#ifdef HAVE_GOOD_STL - parser->setProperty(XMLUni::fgXercesSchemaExternalSchemaLocation,const_cast(m_schemaLocations.c_str())); -#else - auto_ptr_XMLCh temp(m_schemaLocations.c_str()); - parser->setProperty(XMLUni::fgXercesSchemaExternalSchemaLocation,const_cast(temp.get())); -#endif - } - parser->setFeature(XMLUni::fgXercesUserAdoptsDOMDocument,true); - parser->setEntityResolver(this); - parser->setErrorHandler(this); - return parser; -} - -DOMBuilder* ParserPool::checkoutBuilder() -{ - XMLPlatformUtils::lockMutex(m_lock); - try { - if (m_pool.empty()) { - DOMBuilder* builder=createBuilder(); - XMLPlatformUtils::unlockMutex(m_lock); - return builder; - } - DOMBuilder* p=m_pool.top(); - m_pool.pop(); - if (m_schemaAware) { -#ifdef HAVE_GOOD_STL - p->setProperty(XMLUni::fgXercesSchemaExternalSchemaLocation,const_cast(m_schemaLocations.c_str())); -#else - auto_ptr_XMLCh temp2(m_schemaLocations.c_str()); - p->setProperty(XMLUni::fgXercesSchemaExternalSchemaLocation,const_cast(temp2.get())); -#endif - } - XMLPlatformUtils::unlockMutex(m_lock); - return p; - } - catch(...) { - XMLPlatformUtils::unlockMutex(m_lock); - throw; - } -} - -void ParserPool::checkinBuilder(DOMBuilder* builder) -{ - if (builder) { - XMLPlatformUtils::lockMutex(m_lock); - m_pool.push(builder); - XMLPlatformUtils::unlockMutex(m_lock); - } -} - -unsigned int StreamInputSource::StreamBinInputStream::readBytes(XMLByte* const toFill, const unsigned int maxToRead) -{ - XMLByte* target=toFill; - unsigned int bytes_read=0,request=maxToRead; - - // Fulfill the rest by reading from the stream. - if (request && !m_is.eof()) { - try { - m_is.read(reinterpret_cast(target),request); - m_pos+=m_is.gcount(); - bytes_read+=m_is.gcount(); - } - catch(...) { - Category::getInstance(XMLTOOLING_LOGCAT".StreamInputSource").critStream() << - "XML::StreamInputSource::StreamBinInputStream::readBytes caught an exception" << CategoryStream::ENDLINE; - *toFill=0; - return 0; - } - } - return bytes_read; -} +/* + * 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. + */ + +/** + * ParserPool.cpp + * + * XML parsing + */ + +#include "internal.h" +#include "exceptions.h" +#include "util/NDC.h" +#include "util/ParserPool.h" +#include "util/XMLHelper.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace xmltooling; +using namespace std; +using namespace log4cpp; + +ParserPool::ParserPool(bool namespaceAware, bool schemaAware) + : m_namespaceAware(namespaceAware), m_schemaAware(schemaAware), m_lock(XMLPlatformUtils::makeMutex()) {} + +ParserPool::~ParserPool() +{ + while(!m_pool.empty()) { + m_pool.top()->release(); + m_pool.pop(); + } + XMLPlatformUtils::closeMutex(m_lock); +} + +DOMDocument* ParserPool::newDocument() +{ + return DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument(); +} + +DOMDocument* ParserPool::parse(DOMInputSource& domsrc) +{ + DOMBuilder* parser=checkoutBuilder(); + try { + DOMDocument* doc=parser->parse(domsrc); + parser->setFeature(XMLUni::fgXercesUserAdoptsDOMDocument,true); + checkinBuilder(parser); + return doc; + } + catch (...) { + checkinBuilder(parser); + throw; + } +} + +DOMDocument* ParserPool::parse(istream& is) +{ + StreamInputSource src(is); + Wrapper4InputSource domsrc(&src,false); + return parse(domsrc); +} + +// Functor to double its argument separated by a character and append to a buffer +template class doubleit +{ +public: + doubleit(T& t, const typename T::value_type& s) : temp(t), sep(s) {} + void operator() (const pair& s) { temp += s.first + sep + s.first + sep; } + T& temp; + const typename T::value_type& sep; +}; + +bool ParserPool::loadSchema(const XMLCh* nsURI, const XMLCh* pathname) +{ + // Just check the pathname and then directly register the pair into the map. + + auto_ptr_char p(pathname); +#ifdef WIN32 + struct _stat stat_buf; + if (_stat(p.get(), &stat_buf) != 0) +#else + struct stat stat_buf; + if (stat(p.get(), &stat_buf) != 0) +#endif + { +#if _DEBUG + xmltooling::NDC ndc("loadSchema"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".ParserPool"); + auto_ptr_char n(nsURI); + log.error("failed to load schema for (%s), file not found (%s)",n.get(),p.get()); + return false; + } + + XMLPlatformUtils::lockMutex(m_lock); +#ifdef HAVE_GOOD_STL + m_schemaLocMap[nsURI]=pathname; + m_schemaLocations.erase(); + for_each(m_schemaLocMap.begin(),m_schemaLocMap.end(),doubleit(m_schemaLocations,chSpace)); +#else + auto_ptr_char n(nsURI); + m_schemaLocMap[n.get()]=p.get(); + m_schemaLocations.erase(); + for_each(m_schemaLocMap.begin(),m_schemaLocMap.end(),doubleit(m_schemaLocations,' ')); +#endif + XMLPlatformUtils::unlockMutex(m_lock); + + return true; +} + +bool ParserPool::loadCatalog(const XMLCh* pathname) +{ +#if _DEBUG + xmltooling::NDC ndc("loadCatalog"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".ParserPool"); + + // XML constants + static const XMLCh catalog[] = { chLatin_c, chLatin_a, chLatin_t, chLatin_a, chLatin_l, chLatin_o, chLatin_g, chNull }; + static const XMLCh uri[] = { chLatin_u, chLatin_r, chLatin_i, chNull }; + static const XMLCh name[] = { chLatin_n, chLatin_a, chLatin_m, chLatin_e, chNull }; + static const XMLCh CATALOG_NS[] = { + chLatin_u, chLatin_r, chLatin_n, chColon, + chLatin_o, chLatin_a, chLatin_s, chLatin_i, chLatin_s, chColon, + chLatin_n, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chColon, + chLatin_t, chLatin_c, chColon, + chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_t, chLatin_y, chColon, + chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chColon, + chLatin_x, chLatin_m, chLatin_l, chColon, + chLatin_c, chLatin_a, chLatin_t, chLatin_a, chLatin_l, chLatin_o, chLatin_g, chNull + }; + + // Parse the catalog with the internal parser pool. + + if (log.isDebugEnabled()) { + auto_ptr_char temp(pathname); + log.debug("loading XML catalog from %s", temp.get()); + } + + LocalFileInputSource fsrc(NULL,pathname); + Wrapper4InputSource domsrc(&fsrc,false); + try { + DOMDocument* doc=XMLToolingInternalConfig::getInternalConfig().m_parserPool->parse(domsrc); + + // Check root element. + const DOMElement* root=doc->getDocumentElement(); + if (!XMLHelper::isNodeNamed(root,CATALOG_NS,catalog)) { + auto_ptr_char temp(pathname); + log.error("unknown root element, failed to load XML catalog from %s", temp.get()); + doc->release(); + return false; + } + + // Fetch all the elements. + DOMNodeList* mappings=root->getElementsByTagNameNS(CATALOG_NS,uri); + XMLPlatformUtils::lockMutex(m_lock); + for (XMLSize_t i=0; igetLength(); i++) { + root=static_cast(mappings->item(i)); + const XMLCh* from=root->getAttributeNS(NULL,name); + const XMLCh* to=root->getAttributeNS(NULL,uri); +#ifdef HAVE_GOOD_STL + m_schemaLocMap[from]=to; +#else + auto_ptr_char f(from); + auto_ptr_char t(to); + m_schemaLocMap[f.get()]=t.get(); +#endif + } + m_schemaLocations.erase(); +#ifdef HAVE_GOOD_STL + for_each(m_schemaLocMap.begin(),m_schemaLocMap.end(),doubleit(m_schemaLocations,chSpace)); +#else + for_each(m_schemaLocMap.begin(),m_schemaLocMap.end(),doubleit(m_schemaLocations,' ')); +#endif + XMLPlatformUtils::unlockMutex(m_lock); + doc->release(); + } + catch (XMLParserException& e) { + log.error("catalog loader caught XMLParserException: %s", e.what()); + return false; + } + + return true; +} + +DOMInputSource* ParserPool::resolveEntity(const XMLCh* const publicId, const XMLCh* const systemId, const XMLCh* const baseURI) +{ +#if _DEBUG + xmltooling::NDC ndc("resolveEntity"); +#endif + if (!systemId) + return NULL; + + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".ParserPool"); + if (log.isDebugEnabled()) { + auto_ptr_char sysId(systemId); + auto_ptr_char base(baseURI); + log.debug("asked to resolve %s with baseURI %s",sysId.get(),base.get() ? base.get() : "(null)"); + } + + // Find well-known schemas in the specified location. +#ifdef HAVE_GOOD_STL + map::const_iterator i=m_schemaLocMap.find(systemId); + if (i!=m_schemaLocMap.end()) + return new Wrapper4InputSource(new LocalFileInputSource(NULL,i->second.c_str())); +#else + auto_ptr_char temp(systemId); + map::const_iterator i=m_schemaLocMap.find(temp.get()); + auto_ptr_XMLCh temp2(i->second.c_str()); + if (i!=m_schemaLocMap.end()) + return new Wrapper4InputSource(new LocalFileInputSource(NULL,temp2.get())); +#endif + + // Shortcircuit the request. + log.warn("unauthorized entity request, blocking it"); + static const XMLByte nullbuf[] = {0}; + return new Wrapper4InputSource(new MemBufInputSource(nullbuf,0,systemId)); +} + +bool ParserPool::handleError(const DOMError& e) +{ +#ifdef _DEBUG + xmltooling::NDC ndc("handleError"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".ParserPool"); + DOMLocator* locator=e.getLocation(); + auto_ptr_char temp(e.getMessage()); + + switch (e.getSeverity()) { + case DOMError::DOM_SEVERITY_WARNING: + log.warnStream() << "warning on line " << locator->getLineNumber() + << ", column " << locator->getColumnNumber() + << ", message: " << temp.get() << CategoryStream::ENDLINE; + return true; + + case DOMError::DOM_SEVERITY_ERROR: + log.errorStream() << "error on line " << locator->getLineNumber() + << ", column " << locator->getColumnNumber() + << ", message: " << temp.get() << CategoryStream::ENDLINE; + throw XMLParserException(string("error during XML parsing: ") + (temp.get() ? temp.get() : "no message")); + + case DOMError::DOM_SEVERITY_FATAL_ERROR: + log.critStream() << "fatal error on line " << locator->getLineNumber() + << ", column " << locator->getColumnNumber() + << ", message: " << temp.get() << CategoryStream::ENDLINE; + throw XMLParserException(string("fatal error during XML parsing: ") + (temp.get() ? temp.get() : "no message")); + } + throw XMLParserException(string("unclassified error during XML parsing: ") + (temp.get() ? temp.get() : "no message")); +} + +DOMBuilder* ParserPool::createBuilder() +{ + static const XMLCh impltype[] = { chLatin_L, chLatin_S, chNull }; + DOMImplementation* impl=DOMImplementationRegistry::getDOMImplementation(impltype); + DOMBuilder* parser=static_cast(impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS,0); + if (m_namespaceAware) + parser->setFeature(XMLUni::fgDOMNamespaces,true); + if (m_schemaAware) { + parser->setFeature(XMLUni::fgXercesSchema,true); + parser->setFeature(XMLUni::fgDOMValidation,true); + parser->setFeature(XMLUni::fgXercesCacheGrammarFromParse,true); + parser->setFeature(XMLUni::fgXercesValidationErrorAsFatal,true); + + // We build a "fake" schema location hint that binds each namespace to itself. + // This ensures the entity resolver will be given the namespace as a systemId it can check. +#ifdef HAVE_GOOD_STL + parser->setProperty(XMLUni::fgXercesSchemaExternalSchemaLocation,const_cast(m_schemaLocations.c_str())); +#else + auto_ptr_XMLCh temp(m_schemaLocations.c_str()); + parser->setProperty(XMLUni::fgXercesSchemaExternalSchemaLocation,const_cast(temp.get())); +#endif + } + parser->setFeature(XMLUni::fgXercesUserAdoptsDOMDocument,true); + parser->setEntityResolver(this); + parser->setErrorHandler(this); + return parser; +} + +DOMBuilder* ParserPool::checkoutBuilder() +{ + XMLPlatformUtils::lockMutex(m_lock); + try { + if (m_pool.empty()) { + DOMBuilder* builder=createBuilder(); + XMLPlatformUtils::unlockMutex(m_lock); + return builder; + } + DOMBuilder* p=m_pool.top(); + m_pool.pop(); + if (m_schemaAware) { +#ifdef HAVE_GOOD_STL + p->setProperty(XMLUni::fgXercesSchemaExternalSchemaLocation,const_cast(m_schemaLocations.c_str())); +#else + auto_ptr_XMLCh temp2(m_schemaLocations.c_str()); + p->setProperty(XMLUni::fgXercesSchemaExternalSchemaLocation,const_cast(temp2.get())); +#endif + } + XMLPlatformUtils::unlockMutex(m_lock); + return p; + } + catch(...) { + XMLPlatformUtils::unlockMutex(m_lock); + throw; + } +} + +void ParserPool::checkinBuilder(DOMBuilder* builder) +{ + if (builder) { + XMLPlatformUtils::lockMutex(m_lock); + m_pool.push(builder); + XMLPlatformUtils::unlockMutex(m_lock); + } +} + +unsigned int StreamInputSource::StreamBinInputStream::readBytes(XMLByte* const toFill, const unsigned int maxToRead) +{ + XMLByte* target=toFill; + unsigned int bytes_read=0,request=maxToRead; + + // Fulfill the rest by reading from the stream. + if (request && !m_is.eof()) { + try { + m_is.read(reinterpret_cast(target),request); + m_pos+=m_is.gcount(); + bytes_read+=m_is.gcount(); + } + catch(...) { + Category::getInstance(XMLTOOLING_LOGCAT".StreamInputSource").critStream() << + "XML::StreamInputSource::StreamBinInputStream::readBytes caught an exception" << CategoryStream::ENDLINE; + *toFill=0; + return 0; + } + } + return bytes_read; +} diff --git a/xmltooling/util/XMLObjectChildrenList.h b/xmltooling/util/XMLObjectChildrenList.h index 32dd9d7..1890f97 100644 --- a/xmltooling/util/XMLObjectChildrenList.h +++ b/xmltooling/util/XMLObjectChildrenList.h @@ -194,7 +194,7 @@ namespace xmltooling { Container& sublist, typename std::list<_Ty*>* backing, typename std::list<_Ty*>::iterator ins_fence - ) : m_parent(parent), m_container(sublist), m_list(backing), m_fence(ins_fence) { + ) : m_container(sublist), m_list(backing), m_fence(ins_fence), m_parent(parent) { } /// @cond OFF diff --git a/xmltoolingtest/Makefile.am b/xmltoolingtest/Makefile.am index 65044a3..ae00257 100644 --- a/xmltoolingtest/Makefile.am +++ b/xmltoolingtest/Makefile.am @@ -16,7 +16,7 @@ endif xmltoolingtest_h = \ ComplexXMLObjectTest.h \ - ExceptionText.h \ + ExceptionTest.h \ MarshallingTest.h \ UnmarshallingTest.h \ xmltoolingtest.h \